Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

rsync in Go! implements client and server, which can send or receive files (upload, download, all directions supported)

License

NotificationsYou must be signed in to change notification settings

gokrazy/rsync

Repository files navigation

testsSourcegraph

This repository contains a native Go rsync implementation: thegokr-rsynccommand implements an rsync client and server, which can send or receive files(all directions supported). Daemon mode is supported, meaning you can deploygokr-rsync behind SSH (anonymous or authorized), as command or daemon, orlistening directly on the network (on port 873/tcp by default).

The following known improvements are not yet implemented:

  • Makinggokr-rsync chroot (and/or Linux mount namespaces when available?)into the destination directory to reduce chances of accidental file systemmanipulation in case of bugs.

This project accepts contributions as time permits to merge them (best effort).

How do I know this project won’t eat my data?

This rsync implementation is very fresh. It was started in 2021 and doesn’t havemany users yet.

With that warning out of the way, the rsync protocol uses MD4 checksums overfile contents, so at least your file contents should never be able to becorrupted.

There is enough other functionality (delta transfers, file metadata, specialfiles like symlinks or devices, directory structures, etc.) in the rsyncprotocol that provides opportunities for bugs to hide.

I recommend you carefully check that your transfers work, and please do reportany issues you run into!

Existing rsync implementation survey

LanguageURLNoteMax ProtocolServer mode?
CRsyncProject/rsync (formerly WayneD/rsync)original “tridge” implementation; I foundolder versions easier to study31✔ yes
Ckristapsdz/openrsyncOpenBSD, good docs27✔ yes
Gogokrazy/rsync→ you are here ←27✔ yes 🎉
Gojbreiding/rsync-gorsync algorithm❌ no
Gokaiakz/rsync-osonly client/receiver27❌ no
Goknight42proxy❌ no
Goc4milo/gsync❌ no
JavaAPNIC-net/repositorydarchived✔ yes
JavaJohannesBuchner/Jarsyncarchived,internet draft RFC “The rsync Network Protocol”✔ yes
Javaperlundq/yajsync✔ yes
C++gilbertchen/acrosync-librarycommercial❌ no
Rustsourcefrog/rsynarchived, client, “rsyn is rsync with no c”27❌ no

Getting started

To serve the current directory via rsync onlocalhost:8730, use:

go install github.com/gokrazy/rsync/cmd/gokr-rsync@latestgokr-rsync --daemon --gokr.listen=localhost:8730 --gokr.modulemap=pwd=$PWD

You can then copy the contents of the current directory with clients such asrsync(1):

% rsync -v --archive --port 8730 rsync://localhost/pwd/ quinereceiving file list ... donecreated directory quine./.git/[…].github/workflows/main.ymlLICENSEMakefileREADME.mdcmd/gokr-rsyncd/rsyncd.godoc.gogo.modgo.suminternal/rsyncd/connection.gointernal/rsyncd/rsyncd.gointerop_test.gosent 1,234 bytes  received 5,678 bytes  13,824.00 bytes/sectotal size is 666  speedup is 0.10

…oropenrsync(1), shown doing adifferential update:

% openrsync -v --archive --port 8730 rsync://localhost/pwd/ quinesocket.c:109: warning: connect refused: ::1, localhostTransfer starting: 369 files.git/index (1.1 KB, 100.0% downloaded)Transfer complete: 5.5 KB sent, 1.2 KB read, 666 B file size

Usage / Setup

setupencryptedauthenticatedprivate files?privilegesprotocol versionconfig required
1. rsync daemon protocol (TCP port 873)❌ no⚠ rsync (insecure)❌ only world-readable✔ dropped +namespace✔ negotiatedconfig required
2. anon SSH (daemon)✔ yes✔ rsync❌ only world-readable✔ dropped +namespace✔ negotiatedconfig required
3. SSH (command)✔ yes✔ SSH✔ yes⚠ full user⚠ assumedno config
4. SSH (daemon)✔ yes✔ SSH (+ rsync)✔ yes⚠ full user✔ negotiated~/.config/gokr-rsyncd.toml required

Regarding protocol version “assumed”: the flags to send over the network arecomputedbefore starting SSH and hence the remote rsync process. You mightneed to specify--protocol=27 explicitly on the client. Once the connection isestablished, both sidesdo negotiate the protocol, though.

Setup 1: rsync daemon protocol (TCP port 873)

Serving rsync daemon protocol on TCP port 873 is only safe where the networklayer ensures trusted communication, e.g. in a local network (LAN), or whenusingTailscale or similar. In untrusted networks,attackers can eavesdrop on file transfers and possibly even modify filecontents.

Prefer setup 2 instead.

Example:

  • Server:gokr-rsync --daemon --gokr.modulemap=module=/srv/rsync-module
  • Client:rsync rsync://webserver/module/path

Setup 2: anon SSH (daemon)

This setup is well suited for serving world-readable files withoutauthentication.

Example:

  • Server:gokr-rsync --daemon --gokr.modulemap=module=/srv/rsync-module --gokr.anonssh_listen=:22873
  • Client:rsync -e ssh rsync://webserver/module/path

Setup 3: SSH (command)

This setup is well suited for interactive one-off transfers or regular backups,and uses SSH for both encryption and authentication.

Note that becausegokr-rsync is invoked with user privileges (not rootprivileges), it cannot donamespacingand hence retains more privileges. When serving public data, it is generallypreferable to use setup 2 instead.

Note thatrsync(1) assumes the server process understands all flags that itsends, i.e. is running the same version on client and server, or at least acompatible-enough version. You can either specify--protocol=27 on the client,or use setup 4, which negotiates the protocol version, side-stepping possiblecompatibility gaps between rsync clients andgokr-rsync.

Example:

  • Server will be started via SSH
  • Client:rsync --rsync-path=gokr-rsync webserver:path

Setup 4: SSH (daemon)

This setup is more reliable than setup 3 because the rsync protocol version willbe negotiated between client and server. This setup is slightly inconvenientbecause it requires a config file to be present on the server in~/.config/gokr-rsyncd.toml.

Note that this mode of operation is only implemented by the original “trigde”rsync, not in openrsync. Apple started shipping openrsync with macOS 15 Sequoia,so you might need to explicitly start /usr/libexec/rsync/rsync.samba on Macs.

Example:

  • Server will be started via SSH
  • Client:rsync -e ssh --rsync-path=gokr-rsync rsync://webserver/module/path

Limitations

Bandwidth

In my tests,gokr-rsync can easily transfer data at > 6 Gbit/s. The currentbottleneck is the MD4 algorithm itself (not sure whether in the “tridge” rsyncclient, or ingokr-rsync). Implementing support for more recent protocolversions would help here, as these include hash algorithm negotiation with morerecent choices.

Protocol related limitations

  • xattrs (including acls) was introduced in rsync protocol 30, so is currentlynot supported.

Supported environments and privilege dropping

Supported environments:

  1. systemd (Linux)
  2. Docker (Linux)
  3. privileged Linux
  4. privileged non-Linux

In all environments, the default instructions will take care that:

  • (On Linux only) Only configured rsync modules from the host file system aremountedread-only into a Linux mount namespace forgokr-rsync, to guardagainst data modification and data exfiltration.
  • gokr-rsync is running without privileges, as usernobody, to limit thescope of what an attacker can do when exploiting a vulnerability.

Known gaps:

  • gokr-rsync does not guard against denial of service attacks, i.e. consumingtoo many resources (connections, bandwidth, CPU, …).

systemd (unprivileged)

We provideagokr-rsyncd.socket andgokr-rsyncd.servicefile for systemd. Thesefiles enables most of systemd’s security features. You can check by runningsystemd-analyze security gokr-rsyncd.service, which should result in anexposure level of “0.2 SAFE” as of systemd 249 (September 2021).

First, configure your server flags by creating a systemd service override file:

systemctl edit gokr-rsyncd.service

In the opened editor, change the file to:

[Service]ExecStart=ExecStart=/usr/bin/gokr-rsync --daemon --gokr.modulemap=pwd=/etc/tmpfiles.d

Close the editor and install the service using:

systemctlenable --now gokr-rsyncd.socket

Additional hardening recommendations:

Docker (unprivileged)

We provideaDockerfile forgokr-rsyncd.

docker run \  --read-only \  -p 127.0.0.1:8730:8730 \  -v /etc/tmpfiles.d:/srv/rsync:ro \  stapelberg/gokrazy-rsync:latest \    --gokr.modulemap=pwd=/srv/rsync

Additional hardening recommendations:

privileged Linux (including gokrazy.org)

When started asroot on Linux,gokr-rsync will create aLinux mountnamespace, mount all configuredrsync modules read-only into the namespace, then change into the namespace usingchroot(2) and drop privileges usingsetuid(2).

Tip: you can verify which file system objects the daemon process can see byusingls -l /proc/$(pidof gokr-rsync)/root/.

Additional hardening recommendations:

privileged non-Linux (e.g. Mac)

When started asroot on non-Linux (e.g. Mac),gokr-rsync will dropprivileges usingsetuid(2).

unprivileged with write permission (e.g. from a shell)

To prevent accidental misconfiguration,gokr-rsync refuses to start when itdetects that it has write permission in any configured rsync module.

About

rsync in Go! implements client and server, which can send or receive files (upload, download, all directions supported)

Topics

Resources

License

Stars

Watchers

Forks

Languages


[8]ページ先頭

©2009-2025 Movatter.jp