Using rsnapshot for remote backups

In the previous section we investigated how we could perform local backups using the rsnapshot application. We also developed a method of working around the main shortcoming of rsnapshot allowing us to store unified backups from different backup points on different backup rotations organised by machine name.

Performing a backup of a computer system to itself is of limited value however. A failure of a major system component could still result in total data loss as could any number of software malfunctions or malicious actions. A more secure backup strategy would be to backup the contents of one machine to another, preferably in a different physical location.

In this section we shall examine how we can implement such a system using the rsnapshot application. We shall be making use of the scripts and configurations we developed in the previous section so if you have not followed that section of the guide you will need to refer to it now.

Configuring password-less login over SSH

Before the rsnapshot application can backup the contents of a remote computer we need to make those contents available. We could simply do this by exposing the entire filesystem using the rsync daemon. On a trusted network this may be acceptable but should still be strongly discouraged as read access to all files would be essentially granted to everyone.

A better approach is to use rsync over ssh so that the files are encrypted in transit and the access control features of ssh can be leveraged instead of using the far less suitable access control features provided by rsync itself. As the ssh application usually requires a password to login the first step is therefore to configure password-less login for a new user, called backup, which shall be used to perform remote backups.

The first step in this process is to create a new ssh key pair on the backup server as shown in the example below. This key pair will be used to log in to all the client machines we will be backing up without using a password.

backup ssh-keygen -t dsa -N "" -f ~/.ssh/backup_key_dsa

Next we need to create a new user on each of the client machines we shall be backing up so that we can log in using the same login details. In the example below we have called this user backup. As you can see we have specified that they will have a predefined user id, in this case 900, will not have a corresponding group created and will only be a member of the nogroup group. We have also created them a home directory automatically which is critical if we are to log in without a password.

client useradd --create-home --no-user-group --gid nogroup --uid 900 backup

Now that we have created the backup user accounts on all of our client machines we can copy the public part of the key pair we created earlier to the ~/.ssh/authorized_keys file for those user accounts. This will enable us to log-in to that account using the private part of the key pair which we still have only on the backup server.

backup scp ~/.ssh/backup_key_dsa.pub root@client:/home/backup/.ssh/authorized_keys

We can test that the configuration is correct and that password-less log-in is working for the backup user when connecting from the backup server to the clients by using the command shown in the example below.

backup ssh backup@client -i ~/.ssh/backup_key_dsa
backup@client exit

Restricting the backup user's abilities

Whilst granting the backup user the ability to log-in without a password is very convenient it does pose a certain security risk. Should the private part of the key pair we have configured for password-less log-in be compromised anyone could log-in to any of our clients and have full run of the system as if they were the backup user. Clearly we cannot prevent anyone with the private key from logging-in, they are as legitimate as anyone else as far as we can tell, but we can restrict where they connect from and what they can do once connected.

The modifications to the ~/.ssh/authorized_keys file shown below will restrict the use of password-less log-in to the machine at 10.0.1.10 and will then further restrict the abilities of that connection by automatically running the command specified instead of providing full shell access.

/home/backup/.ssh/authorized_keys
ssh-dss AAAAB3NzaC1kc3MAAACBANmhP/Q19dajVhWDfqe1GSpXZ4sTlLZBYHr85u9mqdd+tj1a/hP9AUjs8vWwrrQYZFgsQnPjQco+Q+BhRc7KcU4ESG+qrJ
from="10.0.1.10",command="/home/backup/validate-backup-cmd.sh" ssh-dss AAAAB3NzaC1kc3MAAACBANmhP/Q19dajVhWDfqe1GSpXZ4sTlLZBYHr8

Clearly we now need to create the script we specified in the command parameter when we made our modification above. The example below, which we shall be using for testing purposes, simply runs the original command that we attempted to execute.

/home/backup/validate-backup-cmd.sh
#! /bin/bash

$SSH_ORIGINAL_COMMAND

We also need to make the script we just created executable as shown below.

client chmod +x /home/backup/validate-backup-cmd.sh

We can now test that our password-less log-in is still functioning as expected using the example command shown below. We have specified that the hostname command should be executed on the remote machine which should provide a good indication that things worked.

backup ssh backup@client -i /root/.ssh/backup_key_dsa hostname
client 

Enabling the backup user to rsync as root

Although the backup user can now connect to our clients from our server without using a password and can run, at the moment at least, any command they choose they still cannot access all the files that might be required to backup a complete system. To enable the backup user to access these files we must first install the sudo application, if it is not already installed, as shown below.

client emerge -pv sudo
These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild      ] app-admin/sudo-1.7.4_p5  USE="pam -ldap -offensive -skey"
 
client emerge sudo

We can now modify the script we created earlier to validate the passed command to ensure that it is in fact an rsync command and contains no suspicious shell characters which could be used to execute additional commands. We also execute the passed command using the sudo application we installed above so that the command will be executed as the root user thus enabling access to all files.

/home/backup/validate-backup-cmd.sh
#! /bin/bash

$SSH_ORIGINAL_COMMAND
case "$SSH_ORIGINAL_COMMAND" in
*\&*|*\|*|*\;*|*\>*|*\<*|*\!*)
exit 1
;;
/usr/bin/rsync\ --server\ --sender*)
sudo $SSH_ORIGINAL_COMMAND
;;
*)
exit 1
;;
esac

The script can be tested before we configure sudo to allow the backup user to execute rsync with root privileges using the command below.

backup ssh backup@client -i /root/.ssh/backup_key_dsa /usr/bin/rsync --server --sender --someargs
sudo: no tty present and no askpass program specified 

Assuming that all goes well, and we see the above error message from sudo indicating that we have neither a tty available or an askpass program specified, we can edit the sudoers file on the client using the visudo command as shown below.

client visudo

The example entry below will allow the backup user to execute the /usr/bin/rsync application as the root user with no password.

/etc/sudoers.tmp
# User privilege specification
root ALL=(ALL) ALL

backup ALL=(root) NOPASSWD: /usr/bin/rsync

We can test that our configuration is correct using the command below. As you can see the rsync application does not actually start in server mode as we have intentionally added the unknown command line option --someargs to prevent this.

backup ssh backup@client -i /root/.ssh/backup_key_dsa /usr/bin/rsync --server --sender --someargs
rsync: on remote machine: --someargs: unknown option 
rsync error: syntax or usage error (code 1) at main.c(1422) [server=3.0.6] 

Reconfiguring rsnapshot

Now that we know our configuration is correct, and the backup user can connect from the server to the clients using ssh with no password and run the rsync application as the root user, we can reconfigure the rsnapshot application as shown below.

The first addition instructs the rsnapshot application to use the ssh key we created earlier when using rsync over ssh. The second entry specifies the long arguments which should be passed to rsync when performing the backup, the most important part being the --rsync-path= entry as the default location is incorrect when used on Gentoo Linux.

/etc/rsnapshot/rsnapshot.base
# ssh has no args passed by default, but you can specify some here.
#
ssh_args -p 22 -i /root/.ssh/backup_key_dsa

# Default rsync args. All rsync commands have at least these options set.
#
#rsync_short_args -a
rsync_long_args --delete --numeric-ids --relative --delete-excluded --rsync-path=/usr/bin/rsync

Example configuration for remote snapshots

The three example files below implement a remote backup strategy for the host named client exactly the same as the backup configuration we created for localhost in the previous section. As you can see the only real difference is the addition of backup@client: to the beginning of every backup point to indicate that the backup should be performed using rsync over ssh with the host client as the target host and that the backup user should be used to log-in.

/etc/rsnapshot/client.common
# Include the base configuration file.
include_conf /etc/rsnapshot/rsnapshot.base

# Set the snapshot_root for this host
snapshot_root /mnt/snapshots/client
/etc/rsnapshot/client.1
# Include the common configuration for this host
include_conf /etc/rsnapshot/client.common

# Configure the retention period for daily backups
retain daily 14

# Configure the backup source locations
backup backup@client:/etc/ ./
/etc/rsnapshot/client.2
# Include the common configuration for this host
include_conf /etc/rsnapshot/client.common

# Configure the retention period for weekly and monthly backups
retain weekly 8
retain monthly 12

# Configure the backup source locations
backup backup@client:/var/lib/portage/ ./

# Merge the daily backup from one week ago with the weekly backup from the same time
backup_script /usr/local/bin/merge-snapshots client daily.7 weekly.1 .merge/