SSH is a secure way to run tar or rsync on a backup client to extract the data. SSH provides strong authentication and encryption of the network data.
Note that if you run rsyncd (rsync daemon), ssh is not used. In this case, rsyncd provides its own authentication, but there is no encryption of network data. If you want encryption of network data you can use ssh to create a tunnel, or use a program like stunnel. If someone submits instructions I will include them.
Depending upon your OpenSSH installation, many of these steps can be
replaced by running the scripts ssh-user-config
and ssh-host-config
included with OpenSSH. You still need to manually exchange the public
keys.
As root on the client machine, use ssh-keygen
to generate a
public/private key pair:
ssh-keygen -t rsa
This will save the public key in ~/.ssh/id_rsa.pub
and the private
key in ~/.ssh/id_rsa
, if you don't specify another location. As a
password, you would type nothing (just enter) if you wish BackupPC to
start automatically; alternatively, you could set a password on the
private key as stored in the file system, and use an agent as described
below to store the private key without password only in memory.
Repeat the above steps for the BackupPC user (__BACKUPPCUSER__) on the server. Make a copy of the public key to make it recognizable, eg:
ssh-keygen -t rsa cp ~/.ssh/id_rsa.pub ~/.ssh/BackupPC_id_rsa.pub
See the ssh
and sshd
manual pages for extra configuration information.
To allow BackupPC to ssh to the client as root, you need to place
BackupPC's public key into root's authorized list on the client.
Append BackupPC's public key (BackupPC_id_rsa.pub
) to root's
~/.ssh/authorized_keys2
file on the client:
touch ~/.ssh/authorized_keys2 cat BackupPC_id_rsa.pub >> ~/.ssh/authorized_keys2
You should edit ~/.ssh/authorized_keys2
and add further specifiers,
eg: from, to limit which hosts can login using this key. For example,
if your BackupPC host is called backuppc.my.com
, there should be
one line in ~/.ssh/authorized_keys2
that looks like:
from="backuppc.my.com" ssh-rsa [base64 key, eg: ABwBCEAIIALyoqa8....]
Also, you need to place the client's public key into backuppc's ~/.ssh/known_hosts
file, otherwise you will get a
Host key verification failed.
error, and backuppc will not be able to log into the client.
To place the client key into the ~/.ssh/known_hosts
file,
you need to do this (make sure ~/.ssh/client_id_rsa.pub
is the client's public key,
which needs to be copied from the client):
touch ~/.ssh/known_hosts cat ~/.ssh/client_id_rsa.pub >> ~/.ssh/known_hosts
Repeat this step for every client.
You will probably need to make sure that all the files
in ~/.ssh
have no group or other read/write permission:
chmod -R go-rwx ~/.ssh
You should do the same thing for the BackupPC user on the server.
As the BackupPC user on the server, verify that this command:
ssh -l root clientHostName whoami
prints
root
You might be prompted the first time to accept the client's host key and
you might be prompted for root's password on the client. Make sure that
this command runs cleanly with no prompts after the first time. You
might need to check /etc/hosts.equiv
on the client. Look at the
man pages for more information. The -v
option to ssh is a good way
to get detailed information about what fails.
As root on the client machine, use ssh-keygen2
to generate a
public/private key pair:
ssh-keygen2 -t rsa
or, because this command is sometimes renamed to ssh-keygen
:
ssh-keygen -t rsa
This will save the public key in ~/.ssh2/id_rsa_1024_a.pub
and the
private key in ~/.ssh2/id_rsa_1024_a
. As a password, you would
type nothing (just enter) if you wish BackupPC to start automatically;
alternatively, you could set a password on the private key as stored
in the file system, and use an agent as described below to store the
private key without password only in memory.
Create the identification file ~/.ssh2/identification
:
echo "IdKey id_rsa_1024_a" > ~/.ssh2/identification
Repeat the above steps for the BackupPC user (__BACKUPPCUSER__) on the server. Rename the key files to recognizable names, eg:
ssh-keygen2 -t rsa mv ~/.ssh2/id_rsa_1024_a.pub ~/.ssh2/BackupPC_id_rsa_1024_a.pub mv ~/.ssh2/id_rsa_1024_a ~/.ssh2/BackupPC_id_rsa_1024_a echo "IdKey BackupPC_id_rsa_1024_a" > ~/.ssh2/identification
Based on your ssh2
configuration, you might also need to turn off
StrictHostKeyChecking
and PasswordAuthentication
:
touch ~/.ssh2/ssh2_config echo "StrictHostKeyChecking ask" >> ~/.ssh2/ssh2_config echo "PasswordAuthentication no" >> ~/.ssh2/ssh2_config
To allow BackupPC to ssh to the client as root, you need to place
BackupPC's public key into root's authorized list on the client.
Copy BackupPC's public key (BackupPC_id_rsa_1024_a.pub
) to the
~/.ssh2
directory on the client. Add the following line to the
~/.ssh2/authorization
file on the client (as root):
touch ~/.ssh2/authorization echo "Key BackupPC_id_rsa_1024_a.pub" >> ~/.ssh2/authorization
You will probably need to make sure that all the files
in ~/.ssh2
have no group or other read/write permission:
chmod -R go-rwx ~/.ssh2
You should do the same thing for the BackupPC user on the server.
As the BackupPC user on the server, verify that this command:
ssh2 -l root clientHostName whoami
prints
root
You might be prompted the first time to accept the client's host key and
you might be prompted for root's password on the client. Make sure that
this command runs cleanly with no prompts after the first time. You
might need to check /etc/hosts.equiv
on the client. Look at the
man pages for more information. The -v
option to ssh2 is a good way
to get detailed information about what fails.
The concept is identical and the steps are similar, but the specific commands and file names are slightly different.
First, run ssh-keygen
on the client (as root) and server (as the BackupPC
user) and simply hit enter when prompted for the pass-phrase:
ssh-keygen
This will save the public key in ~/.ssh/identity.pub
and the private
key in ~/.ssh/identity
.
Next, append BackupPC's ~/.ssh/identity.pub
(from the server) to root's
~/.ssh/authorized_keys
file on the client. It's a single long line that
you can cut-and-paste with an editor (make sure it remains a single line).
Next, force protocol version 1 by adding:
Protocol 1
to BackupPC's ~/.ssh/config
on the server.
Next, run chmod -R go-rwx ~/.ssh
on the server and
chmod -R go-rwx ~/.ssh
on the client.
Finally, test using:
ssh -l root clientHostName whoami
Using ssh is quite secure, but the security is only as good as the protection of ssh's private keys. If an attacker can devise a way to run a shell as the BackupPC user then they will have access to BackupPC's private ssh keys. They can then, in turn, ssh to any client machine as root (or whichever user you have configured BackupPC to use). This represents a serious compromise of your entire network.
So in vulnerable networks, think carefully about how to protect the machine running BackupPC and how to prevent attackers from gaining shell access (as the BackupPC user) to the machine.
An agent is a background program that stores your private keys in memory, without password protection on them. If your memory is well-protected and swapping is not going to give problems, then your agent is a safe place to store the private keys. The long-term storage of the private keys can be in a password-protected file in the file system.
When you create your keys with ssh-keygen
or ssh-keygen2
you
are prompted for a password. If you would type nothing, the file
system version of the keys is not protected with a password, which
makes their security quite fragile. An agent is a better idea.
To start the agent in the background, run the following command once:
eval `ssh-agent`
or, on commercial SSH systems:
eval `ssh-agent2`
The agent will determine what shell you are using and will send properly
formatted statements to eval
, which sets a few environment variables
that SSH will recognise as hooks to the agent.
The next step is uploading your keys to the agent. During this process you will be prompted for the password so that the agent can store the decrypted passwords. You can upload keys simply by doing:
ssh-add
or, on commercial SSH systems:
ssh-add2
The installation of the public key at the client machines remains the same, since this key is never protected with a password -- it is public. If you now try to connect from the server to a client you will not be asked for a password, since the agent is used to bypass that.
At this point, you can start BackupPC -d
. BackupPC's children inherit
the environment variables, which in turn are passed onto ssh
,
can then contact ssh-agent
to get the private keys. This allows
BackupPC to run ssh
without unprotected private keys being
available on the file system.
It is possible to forward an agent over an SSH connection, so you can even decide to take the private key store out of the BackupPC server, at the cost of having to log in there from a trusted (desktop) machine.
Finally, there are options to store the private key in a specialised
token, such as a smart card or a cryptographic USB device. This can be
done, for example, with the experimental -I
option to OpenSSH (see
http://www.openbsd.org/cgi-bin/man.cgi) or with a
replacement of the agent (see http://openfortress.nl/product/shaman)
-- the former would only work on the machine and thus keep the
credentials for accessing the smart card on the BackupPC server, while
the latter can be forwarded from a trusted machine like any other agent.
However, even the use of ssh-agent
doesn't provide complete
protection. If an attacker can run a shell as the BackupPC user,
they can access the agent to get the keys. However, using ssh-agent
does provide an extra layer of protection since no unprotected private
keys are stored anywhere on the file system.
[This section was contributed by Rick van Rein.]
Rather than ssh as root, you can create a low-privileged backuppc user
on the client, and use sudo
on the client to run the backup command
(eg: tar or rsync) as root.
Josh Marshall reports he uses ssh with a non-root user (e.g. backuppc) and use sudo as part of the rsync command on the remote end.
Configure sudo using visudo on the client like this:
backuppc ALL=NOPASSWD: /usr/bin/rsync
This means that the only command that backuppc can run is rsync. Then set the RsyncClientCmd to be something like:
$Conf{RsyncClientCmd} = '$sshPath -l backup $host nice -n 19 sudo $rsyncPath $argList+';
In this case Josh nices the backup so that it doesn't give such a performance hit on the client. The same setup works for tar.
Note that an attacker who can become the backuppc user on the
server can then ssh
to the client and use sudo
to run /bin/tar
as root. Importantly, this means they can write files anywhere on
the file system by doing tar -x
or using rsync
to copy files.
This is sufficient to allow an attacker to become root on the
client machine.
This is better than the default setup above, since getting the ssh key on the server immediately allows an attacker to ssh to the client as root.
If you want to be more cautious, you could create a short shell script
(eg: rsyncSend
) that includes the --sender
argument argument from
$Conf{RsyncClientCmd}, eg:
#!/bin/sh -f exec /usr/bin/rsync --server --sender "$@"
Make sure this script and all parent directories have no write
permission. Then change the $rsyncPath
in $Conf{RsyncClientCmd}
to rsyncSend
:
$Conf{RsyncClientCmd} = '$sshPath -l backup $host nice -n 19 sudo /path/to/rsyncSend $argList+';
and finally use visudo
to change the allowed command to
/path/to/rsyncSend
.
A similar setup for tar would ensure that an attacker can only run
tar -c
(create), and not be able to write files on the client.
Create a short script, eg, tarCreate
:
#!/bin/sh -f exec /bin/tar -c "$@"
Make sure this script and all parent directories have no write
permission. Then remove the -c
from $Conf{TarClientCmd} and change
the tar path:
$Conf{TarClientCmd} = '/usr/bin/sudo /path/to/tarCreate -v -f - -C $shareName+ --totals';
Finally, run visudo
to change the allowed command to /path/to/tarCreate
.
Martin Hansen notes that a simpler alternative to using a script is to enforce the arguments directly with sudo, eg:
backuppc ALL=NOPASSWD: /usr/bin/rsync --server --sender *
This causes sudo to only accept the /usr/bin/rsync
command with those
arguments, the *
at the end tells sudo to accept more arguments
after --sender
.
In the cases above, a compromise of the backuppc user on the server
still allows the attacker to ssh
to the client and run tar -c
or rsync --sender
via sudo
. But this only allows them read access
to files on the client, which they already have access to simply
by inspecting the BackupPC backup data directories on the server.