Secure File Synchronisation with SSH and rsync
Quite often I want to be able to do a backup of some files / folders on a remote server. So far I have been doing this quite successfully using public/private key authentication with scp and then entering my passphrase when prompted.
This has worked pretty well for me but now I want to automate this with a cron job. Since I am human and quite forgetful automating this will ensure that I never again fail to complete a backup of some critical data. A problem now arises however in how to secure this. I don't want to have to store a password or passphrase in the crontab so I need to find a new way.
After some googling and some experimentation I finally have working something which I am sure real sysadmins have been aware of for a while and that is the ability to restrict a ssh via public/private key to specific commands.
In order to get this to work for myself I did the following steps.
Firstly I created a new passphrase-less rsa key
ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/username/.ssh/id_rsa): /home/username/.ssh/rsync_backup Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/username/.ssh/rsync_backup. Your public key has been saved in /home/username/.ssh/rsync_backup.pub.
Next I copied the public key to the server I wanted to backup and added this to the /home/remoteuser/.ssh/authorized_keys
I then tested to make sure that I could login to the remote server using ssh
ssh -i /home/username/.ssh/rsync_backup remoteuser@remotehost
Once I had confirmed that it was all working with ssh the next step was to lock down the key to a specific IP address. Since this was an internal system I knew which IP address would be used to connect.
I edited the /home/remoteuser/.ssh/authorized_keys to look like the following
from="192.168.1.50" ssh-rsa <public key>
I then tested ssh login again to make sure I didn't mess anything up
ssh -i /home/username/.ssh/rsync_backup remoteuser@remotehost
All was still working. To play devils advocate I also tried to connect from a different IP and my connection was denied successfully.
Next up I needed to check on connection what command was being called to ensure that only rsync was permitted. After a lot of googling around I came across the following
#!/bin/sh logfile=/var/log/rsync_backup.log case "$SSH_ORIGINAL_COMMAND" in *\&*) echo `date` "- SSH connection rejected" >> $logfile ;; *\(*) echo `date` "- SSH connection rejected" >> $logfile ;; *\{*) echo `date` "- SSH connection rejected" >> $logfile ;; *\;*) echo `date` "- SSH connection rejected" >> $logfile ;; *\<*) echo `date` "- SSH connection rejected" >> $logfile ;; *\`*) echo `date` "- SSH connection rejected" >> $logfile ;; *\|*) echo `date` "- SSH connection rejected" >> $logfile ;; rsync\ --server*) { echo `date` "- SSH connection accepted" >> $logfile $SSH_ORIGINAL_COMMAND } ;; *) echo `date` "- SSH connection rejected" >> $logfile ;; esac
This script checks the SSH command to be run and rejects it if anything other than rsync is being used.
I once again edited the /home/remoteuser/.ssh/authorized_keys to add the command restriction so that it looked like the following
from="192.168.1.50", command="/home/remoteuser/check-rsync.sh" ssh-rsa <public key>
I then checked to see what would happen if I tried to login using ssh
ssh -i /home/username/.ssh/rsync_backup remoteuser@remotehost
This time my connection was denied. Checking my logfile I saw the following entry
Sun Feb 6 00:51:58 GMT 2011 - SSH connection rejected
Now the final test... could I use the public/private key to connect and run the rsync command. To do this I ran
rsync -avz -e "ssh -i /home/username/.ssh/rsync_backup" remoteuser@remotehost:/home/remoteuser/datatobackup /home/username/remotehost
And low and behold my files were downloaded
receiving file list ... done home/remoteuser/datatobackup/file1.txt home/remoteuser/datatobackup/file7.txt sent 98 bytes received 2331 bytes 1619.33 bytes/sec total size is 32663 speedup is 13.45
Job Completed. I can now just set this up as a cron job to run every night and sleep easy in the knowledge that all the valuable data I need is safely backed up.
I would love to hear any feedback on this solution and any tips for ways to improve it.
