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
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
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.