Tim's blah blah blah

Passwordless secure rsync backups over ssh

I mirror my backups remotely on a server with as few privileges as possible, while ensuring the confidentiality of my backup. I build on David Obdržálek’s (A), Guy Rutenberg’s (A) and Shakko’s (A) guides.

Setup

I have a TimeMachine backup to my server which I want to mirror remotely. On the remote server I want to ensure the account has as few credentials as possible (because I offer the reciprocal service to a friend). This is achieved in 2 layers:

I achieved this as follows:

  1. First we create a backup user without password (thereby preventing bruteforece ssh login).
    NEWUSER="user"
    sudo useradd --home-dir /home/${NEWUSER} --shell /usr/bin/sh ${NEWUSER}
    
  2. Prepare the target directory to receive backups, in this case through a zfs pool.
    sudo zfs create pool0/backup${NEWUSER}
    sudo zfs set quota=1500G pool0/backup${NEWUSER}
    sudo mkdir -p /pool0/backup${NEWUSER}
    
  3. Next we chroot SSH access for this user. N.B./TODO I didn’t get the ssh config to work in the separate .conf file so in reality I appended this to /etc/ssh/sshd_config.
    cat << EOF | sudo tee /etc/ssh/sshd_config.d/backup${NEWUSER}.conf
    Match User ${NEWUSER}
           ChrootDirectory /pool0/backup${NEWUSER}
    EOF
    
  4. Prepare chroot jail. Note that we recreate an empty homedir here which the shell will cd to upon login.
    cd /pool0/backup${NEWUSER}
    sudo mkdir etc log backup
    sudo mkdir -p home/${NEWUSER}
    sudo chown --recursive ${NEWUSER}:${NEWUSER} ./*
    
  5. Populate with minimal binaries and libraries (or download the script and execute yourself line by line). Alternatively you can setup a ‘minimal’ Ubuntu environment at ~500MB using debootstrap and schroot, see e.g. this guide
    bash <(curl -s "http://web.archive.org/web/20201129094849/https://tools.deltazero.cz/server/setup.chroot.for.rsync.sh")
    
  6. Copy rrsync & perl + libraries to chroot as well to use dynamic automated (rsync remote command)[https://unix.stackexchange.com/questions/117555/rsync-over-ssh-with-authorized-keys-but-run-2-rsync-commands]. Alternatively you can use a hard-coded server-side rsync command like /usr/bin/rsync --server -vvlogDtprze.iLsf . /backup, but I prefer the versatility of the rrsync script. The drawback is that you need perl + libs in your chroot, eating up 100x more space than if you use a hard-coded command.
    copies=$((ldd `which perl`) | awk '/\// { print ($3 ? $3 : $1) }' | sort | uniq)
    copies+=" $(which rrsync) $(which perl)"
    for f in $copies; do
      d=$(dirname ${f})
      [[ ! -d ".$d" ]] && sudo mkdir -p ".$d"
      [[ ! -f ".$f" ]] && sudo cp -v "$f" ".$f"
    done
    sudo mkdir -p /pool0/backup${NEWUSER}/usr/share
    sudo cp -r /usr/share/perl /pool0/backup${NEWUSER}/usr/share
    # sudo cp -r /usr/share/perl5  /pool0/backup${NEWUSER}/usr/share # optional - I did not need this
    sudo mkdir -p /pool0/backup${NEWUSER}/usr/lib/x86_64-linux-gnu
    sudo cp -r /usr/lib/x86_64-linux-gnu/perl /pool0/backup${NEWUSER}/usr/lib/x86_64-linux-gnu
    # sudo cp -r /usr/lib/x86_64-linux-gnu/perl5 /pool0/backup${NEWUSER}/usr/lib/x86_64-linux-gnu # optional - I did not need this
    
  7. Make passwordless ssh key using RSA key type. While elliptic curves are nice, their primary benefit (smaller keys) is irrelevant for my use case. Also, RSA is slightly more resistant to quantum computing attacks, and there are no widely adoptied post-quantum schemes yet. We use a paranoid large key totally overkill for our situation.
    ssh-keygen -b 4096 -t rsa -f ~/.ssh/id_rsa_backup
    
  8. Copy ssh key to home directory outside chroot jail, give reduced permissions (use restrict instead of iterating (and potentially forgetting) all options) and only allow rsync.
    scp ~/.ssh/id_rsa_backup.pub admin@remoteserver.tld:
    ssh admin@remoteserver.tld
    sudo mkdir -p /home/${NEWUSER}/.ssh/
    sudo chown ${NEWUSER}:${NEWUSER} --recursive /home/${NEWUSER}/.ssh
    echo 'restrict,command="/usr/bin/rrsync /backup/"' | sudo tee --append /home/${NEWUSER}/.ssh/authorized_keys
    cat ~/id_rsa_backup.pub | sudo tee --append /home/${NEWUSER}/.ssh/authorized_keys
    
  9. Done. Do magic
    rsync -e "ssh -i ~/.ssh/id_rsa_backup" --checksum --hard-links --xattrs --archive --human-readable --verbose --info=progress2 /src/ ${NEWUSER}@remoteserver.tld:target/
    
  10. Error “protocol version mismatch – is your shell clean?”
    1. Ensure output of ssh user@remoteserver.tld /bin/true is nothing
    2. Ensure the directory rsync points to works
    3. Try something without the command= prefix in authorized_keys

Alternatives

Some other methods to set up a limited access rsync server:

  1. Use a restricted shell, see e.g. this guide - I opted for a stronger chroot jail instead.
  2. Use only restricted rsync (rrsync), see e.g. this guide - I opted for a stronger additional chroot jail instead

#unix #security #server