Rsync

rsync is a fast, powerful, and network-capable filesystem synchronization tool. It is useful for transferring files across a variety of mediums, can resume partial or interrupted transfers, perform its own user authentication, and can be run in numerous flexible configurations. Numerous utilities are built atop rsync, such as the Duplicity backup tool, making rsync an important infrastructural technology.

Installing

The rsync package available in most distribution’s package repositories contains everything needed for a basic client and/or server configuration. You likely already have rsync installed on your system. If you do not, on Debian-derived GNU/Linux distributions, install rsync with:

sudo apt install rsync

Configuring

There are numerous ways to set up rsync infrastructure for various collaborative purposes. This page describes the configurations useful for and familiar to the Tech Autonomy Infrastructure committee needs.

Socket-activated systemd service unit made available via Tor

A “socket-activated service” is systemd jargon for an on-demand server invoked by the systemd service manager process itself. (For the purposes of this guide, systemd replaces the xinetd process, which itself obsoleted the even older inetd process, which may be familiar to seasoned system administrators.) We prefer to use on-demand server processes for rsync for performance and resource conservation reasons.

The transfer’s data itself must be protected when in motion by a transport layer protection mechanism. This can be a TLS or SSH tunnel or, arguably more usefully, a Tor Onion service ("hidden service"). This section’s examples showcase how one might configure a socket-activated rsync server that is made available only over a Tor Onion service. See the Tor page for information about configuring authenticated Onion services, themselves.

Do this to configure rsync as a server:

  1. First, we’ll need to configure the rsync daemon process itself. This is done by writing a configuration file and placing it in a conventional place, which is usually /etc/rsyncd.conf for most GNU/Linux systems. Paste the following configuration file, being careful to change the values of MODULE_NAME, YOUR_USER_NAME, YOUR_GROUP_NAME, RSYNC_USER_NAME, and specific pathnames to sensible values given the data you intend to make available to rsync clients:
    # File: rsyncd.conf
    #
    # This is the configuration file for the rsync daemon process.
    # It provides a default set of options for rsync transfers and
    # offers a fallback for situations when rsync is not invoked
    # using a socket-activated incoming network connection. That is,
    # some options configured here are ignored when rsync is started
    # by inetd, xinetd, or a systemd socket unit. See rsnycd.conf(5)
    # for more details.
    
    #####################
    # Global directives #
    #####################
    
    # Runtime files.
    lock file = /var/run/rsync/rsyncd.lock
    pid file = /var/run/rsync/rsyncd.pid
    
    # Send any and all logging performed by rsync to a black hole.
    log file = /dev/null
    transfer logging = no
    
    # Only listen on the loopback interface; use Tor for remote connectivity.
    address = 127.0.0.1
    
    # Don't use a default port on the LAN; the authenticated Onion
    # service can expose the default on the WAN side, if you want.
    # See `/etc/services` for your system's default rsync port.
    #port = 8873
    
    # Restrict transfers to (but not connections from) IP ranges.
    hosts allow = 127.0.0.1
    
    # Don't do any DNS lookups or hostname matching.
    reverse lookup = no
    forward lookup = no
    
    # Don't offer a list of exported modules.
    list = no
    
    # Wait no more than five minutes (300 seconds) for client data.
    timeout = 300
    
    # chroot(2) to an exported module's `path`.
    # This requires the parent `rsync` process to be run as root.
    # The default setting is `true`.
    #use chroot = true
    
    # The default for all modules is to be read only.
    # Set this to `false` on a module level to make that one module
    # writable, or using `auth users` to set this on a per-user per-module
    # level to grant specific users write access while defaulting to read only
    # access for the remainder of users not explicitly granted write permission.
    #read only = true
    
    # Provide application-level user access control.
    secrets file = /etc/rsyncd.secrets
    
    ####################
    # Exported modules #
    ####################
    
    #
    # Define your exports here.
    #
    
    [MODULE_NAME]
    comment = A human-readable description of the module.
    path = /path/to/whatever/you/want/to/share
    uid = YOUR_USER_NAME
    gid = YOUR_GROUP_NAME
    auth users = RSYNC_USER_NAME
    
  2. The above configuration uses application-level user access control, so we’ll need to define users and their passwords in the secrets file location. In the snippet above, this location is /etc/rsyncd.secrets. Paste the following in a file at that path:
    # FILE: /etc/rsyncd.secrets
    #
    # Username and password database for rsync daemon.
    # This file is described by rsyncd.conf(5).
    #
    # The format of this file is:
    #
    #     user_name:password
    #
    # where `user_name` is an rsync user name, and `password` is
    # the given user's password. Lines containing only whitespace
    # or lines that begin with a `#` character are ignored.
    #
    # Users defined here do not need to exist as Operating System
    # user accounts, although they can be. Again, see the manual
    # page for rsyncd.conf(5) for additional details.
    
    RSYNC_USER_NAME:RSYNC_PASSWORD
    
  3. The rsync daemon will refuse to authenticate users against the secrets file unless its filesystem permission bits are set to 600:
    sudo chown root:root /etc/rsyncd.secrets
    sudo chmod 600 /etc/rsyncd.secrets
    
  4. Next, we’ll need to create two systemd files. The first is a socket unit that provides inetd-style backwards compatibility. Paste the following into /etc/systemd/system/rsyncd.socket:
    # FILE: /etc/systemd/system/rsyncd.socket
    #
    # rsync daemon socket activation unit
    #
    # This file is a systemd socket unit (see systemd.socket(5))
    # that offers inetd-style equivalency for starting the rsync
    # daemon when an incoming connection is detected.
    # 
    # Without this socket unit started, the rsync daemon is
    # not available over a network connection. Tor handles all
    # other parts of the network connection and connectivity.
    #
    [Unit]
    Description=rsync socket for per-connection servers
    After=tor.service
    
    [Socket]
    ListenStream=127.0.0.1:873
    Accept=yes
    
    [Install]
    WantedBy=sockets.target
    
  5. Finally, write the `rsyncd@.service` unit file, placing it into the /etc/systemd/system directory:
    # FILE: /etc/systemd/system/rsyncd@.service
    #
    # On-demand per-connection socket-activated rsync server.
    #
    # This file is a systemd service unit (see systemd.service(5))
    # offering a hand-off from systemd to `rsync` when an incoming
    # connection bound to the ListenStream address (defined in the
    # rsyncd.socket unit file) is detected.
    
    [Unit]
    Description=rsync per-connection server
    
    [Service]
    Type=simple
    ExecStart=-/usr/bin/rsync --daemon
    StandardInput=socket
    RuntimeDirectory=rsync
    # Extra security precautions
    MemoryDenyWriteExecute=true
    NoNewPrivileges=true
    PrivateDevices=true
    PrivateTmp=true
    # On some systems, the `PrivateUsers` directive causes errors of the form:
    #
    #     @ERROR: setgid failed
    #
    # If that happens for your system, comment out the `PrivateUsers` line.
    PrivateUsers=true
    ProtectControlGroups=true
    ProtectHome=true
    ProtectKernelModules=true
    ProtectKernelTunables=true
    ProtectSystem=full
    LockPersonality=true
    RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
    RestrictRealtime=true
    
  6. Once the configuration files are in place, invoke them with the following systemctl commands:
    systemctl daemon-reload        # Tell systemd to look at the new files we added.
    systemctl enable rsyncd.socket # Load the socket-activation unit.
    systemctl start rsyncd.socket  # Manually start the socket unit.
    

To confirm that this is working, use the ss command to check for listening ports:

sudo ss --listening --tcp --numeric --processes | grep 873
LISTEN     0      128               127.0.0.1:873                      *:*      users:(("systemd",pid=1,fd=25))

This rsync server is only accepting connections from 127.0.0.1, which makes it unavailable to remote clients unless something like an SSH tunnel or Tor Onion service is exposing it.

Restricted rsync over restricted SSH login (optionally over Tor)

TK-TODO: See the rrsync (“restricted rsync”) script in the rsync distribution. See also Restricting SSH Access to rsync and Allow the restricted rsync (rrsync) script for arbitrary directories with authorized_keys.

Connecting from a client

Clients can make connections as normal:

rsync rsync://RSYNC_USER_NAME@server.example.com/MODULE_NAME /tmp/foo

To make a connection over Tor, you will need to Torify your rsync invocation; consider using torsocks(1) for this purpose. (Another option if the torsocks package is unavailable to you is socksify(1), available as part of the dante-client package on most Debian-derived systems.) See the Tor project’s guides to torification with torsocks for more details. In brief, though, all you should have to do is prepend the rsync command with torsocks and change the server address to the service’s .onion address:

torsocks rsync rsync://RSYNC_USER_NAME@abcdef0123456789.onion/MODULE_NAME /tmp/foo

If the Onion service to which you are connecting requires clients to authenticate themselves, see also Connecting to an authenticated Onion service for instructions on configuring your Tor client, which will be necessary for the torsocks command above to succeed.

Hardening

If you have configured rsync on your own (rather than following this guide), take some care to secure your system by ensuring no unintended access to your rsync server is possible, and that your rsync server is protecting your own and your user’s privacy by not retaining more data than necessary. To do so, check (and double-check) the following configuration options:

  • Use the hosts allow directive to restrict which remote IP addresses (or hostnames) can upload or download files.
  • Set a non-default port number.
  • Set the log file path to /dev/null to stop rsync from logging connection details, which contain IP addresses by default.
  • Set the list value to no or false for any module you do not want visible to clients, or globally if you do not want clients to be able to ask for a listing of exported modules.
  • Set the read only value to yes or true for any exported module that you don’t want clients making changes to.
  • If you do not need hostname matching for the hosts allow directive or similar, set reverse lookup and/or forward lookup to no or false to disable rsync’s DNS requests, especially if you have not secured your network’s DNS servers or clients.
  • Use rsync’s own application-level authentication by using a secrets file and an auth users directive for sensitive modules.
  • When making a connection to an rsync-authenticated server from a client, use the --password-file option to avoid exposing your rsync user’s password on the command line, where it is visible in process listings (ps -ef and similar).