Secure rsync over SSH without shell access

From lxadm | Linux administration tips, tutorials, HOWTOs and articles
Jump to: navigation, search


Rsync is one of the best local and remote syncing programs. However, there is one problem with it: it's unsecure when used over internet:

  • rsync protocol transfers data in plain text - meaning, it can be easily listened to by a middleman
  • rsync credential exchange is encrypted using a weak RC4/ARC4/ARCFOUR cipher)

Traditionally, this has been worked around by running rsync over SSH, which provides proper and secure encryption. Unfortunately it leads us to additional problems:

  • it requires giving shell access to the system
  • you're no longer able to use the rsync server with its versatile configuration options (chroot, read-only, different modules with different paths etc.)

Is there a way to have the best of two systems, meaning:

  • rsync runs as a proper daemon
  • rsync is only accessible over encrypted channel, without having to access any exotic software
  • no SSH shell access


Yes, there is - read on.

rsync config

The following will start rsync as a daemon with "all" module having access to everything on the server (/), read only, listening on localhost only.

address = localhost

    comment = the whole server
    path = /
    use chroot = yes
    read only = yes
    list = no
    uid = root
    gid = root
    auth users = backup
    secrets file = /etc/rsync/rsyncd-backup.secrets
    hosts allow =
    log file = /var/log/rsyncd.log

Secrets file is a username:password pair, for example:


Make sure to chmod 600 /etc/rsync/rsyncd-backup.secrets - otherwise, rsync will refuse to use it.

SSH user with no shell access

  • create a normal user first:
useradd -m -s /bin/bash backupuser
  • add a key to user's .ssh/authorized_keys with the following content:
no-port-forwarding,no-agent-forwarding,no-X11-forwarding,command="/bin/nc localhost 873" ssh-rsa aaaabbbbb-user-key-goes-here-yyyzzzz root@server

Explanation of terms:

no-port-forwarding - don't allow port forwarding no-agent-forwarding - don't allow agent forwarding no-X11-forwarding - don't allow X11 forwarding command="/bin/nc localhost 873" - force netcat to localhost on port 873 as an executed command

This way, SSH user will have no access to the shell.

Connecting from remote

export RSYNC_USERNAME=user1
export RSYNC_PASSWORD=password1
export RSYNC_CONNECT_PROG="ssh -i /etc/snapbackup/keys/id_rsa backupuser@remoteserver -p 6253 nc localhost 873"
rsync --exclude=/proc/ --exclude=/mnt/ --exclude=/tmp/ --exclude=/media/ --exclude=/sys/ --exclude=/swapfile --exclude=/var/lib/mysql/ --exclude=/run/ --delete --inplace --partial -z --compress-level=9 -a -H -v --stats user1@remoteserver::all /mnt/backup/remoteserver/latest/all