Steelmon's tech stuff

Create a secure backup solution with chrooted SFTP

Posted in Howto, Linux, Security, SFTP, SSH by steelmon on April 15, 2010

Secure Shell (SSH) is a very versatile tool that allows you to connect remotely in a secure manner. One of its most common uses is to transfer files and in these cases it can be confusing for users to see the entire host file system. It also makes the host system more vunerable when exposed to all users. In *NIX systems, however, there is a possibility to change the root of the file system so that a user for example sees their own home directory as a virtual root. Up until version 4.9 of OpenSSH it has been quite complex to setup a chrooted environment, but with later versions of OpenSSH it has become a lot easier, provided you only need to be able to transfer files over the SSH protocol (i.e. SFTP, no shell access). This article provides step by step instructions on how to set up a chrooted SFTP solution.

Assumptions

I have been using Ubuntu 8.04 to set up the solution. Any Debian based distribution should propably work the same way provided there are reasonably new versions of OpenSSH available. It should also be quite simple to translate the instructions into any other *NIX flavour. I have access to two machines – one acting as the server and the other as the client. If you would like to try it out on a single machine first, it works equally well using virtual hosts.

1. Install OpenSSH Server

In Ubuntu, OpenSSH does not come installed by default, so the first step is to install the OpenSSH server from the repositories. On the server host, run the following command:

server$ sudo apt-get install openssh-server

2. Setup chroot jail for sftp

Next, we are going to restrict SFTP access to a certain directory that will act as a virtual root of the file system – much like what many are used with from regular FTP. Start with creating a user, bkuser, that will be used to access the server remotely:

server$ sudo adduser bkuser

You will be asked to enter a number of information about the user. Just follow the instructions, providing at least a password for the newly created user.

Next, we are going to modify the file /etc/ssh/sshd_config, so that users belonging to the sftpusers group will be restricted to a chrooted directory without access to the rest of the host file system:

server$ sudo nano /etc/ssh/sshd_config

include the following lines:

# Make sure you replace any existing 'Subsystem sftp' line with this
Subsystem sftp internal-sftp

# Add these lines at the end of sshd_config
# Put users in the sftpusers group in a chroot jail
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no

This means that all users you add to the sftpusers group will be chrooted to their home directory, and will only be able to run the internal SFTP process.

In order for the changes to take effect, restart the ssh daemon:

server$ sudo /etc/init.d/ssh restart
* Restarting OpenBSD Secure Shell server sshd [ OK ]

Create a directory structure for the virtual SFTP server root:

server$ sudo mkdir /var/sftp
server$ sudo mkdir /var/sftp/.ssh

Create a new group for SFTP-only users. Membership of this group determines whether a user is chrooted or not:

server$ sudo groupadd sftpusers

Next, we will configure the SFTP users as follows:

  • Assign them to the sftpusers group
  • Deny any shell access by setting their shell to /bin/false
  • Reassign their home directory to the desired chroot directory. This directory and any directories over it must be owned by root

For the user bkuser created earlier, start by assigning the user to the sftpusers group:

server$ sudo usermod -g sftpusers bkuser

Make sure the user does not have any shell access:

server$ sudo usermod -s /bin/false bkuser

Remove the old home directory and create a new directory for the user under the virtual root:

server$ sudo rm -r /home/bkuser
server$ sudo mkdir /var/sftp/bkuser

Make bkuser the owner of the bkuser subdirectory under the virtual root:

server$ sudo chown bkuser:bkuser /var/sftp/bkuser

Assign /var/sftp as the new home directory for bkuser:

server$ sudo usermod -d /var/sftp/ bkuser

3. Configure RSA key authentication

This section describes how to set up public key based authentication for the SFTP access. In order to do this, we need to head over to the client and start with creating the bkuser account here as well:

client$ sudo adduser bkuser

Follow the instructions to create the new user. Next, as the newly created user, we are going to ttpare an RSA keypair consisting of a private and public key:

client$ sudo su - bkuser
client$ mkdir ~/.ssh
client$ chmod 700 ~/.ssh
client$ ssh-keygen -q -f ~/.ssh/id_rsa -t rsa

When asked for a passphrase for the private key, we simply ttss enter in order to set a blank passphrase. This will allow us to connect later without being prompted for authentication.

Now, we need to copy the public key to server:

client$ sftp server

enter password to get to the sftp> prompt. Then:

sftp> cd bkuser
sftp> put .ssh/id_rsa.pub
Uploading .ssh/id_rsa.pub to /bkuser/id_rsa.pub
.ssh/id_rsa.pub 100% 395 0.4KB/s 00:00
sftp> exit

Now, we need set up the public key based authentication over at the server. Issue the following commands in order to copy the public key to the list of authorized keys that the SFTP server will accept for authentication:

server$ sudo -i
server$ cd /var/sftp
server$ cat bkuser/id_rsa.pub >> .ssh/authorized_keys
server$ rm bkuser/id_rsa.pub
server$ exit

Now, lets try it out, back on the client:

client$ sftp server

If successful, there should be no prompt for password…

4. Install sshfs file system and mount sftp to a local directory

In order to simplify file transfer, this step allows us to mount the SFTP directory locally, where it acts just as an ordinary directory even though the contents are pushed over the network to the SFTP server. The tool used for this purpose is SSHFS (SSH File System) which operates in user space, so there is no need for escalated privileges in order to mount the remote file system. First, install SSHFS by issuing the following command:

client$ sudo apt-get install sshfs

Next, we will su into bkuser and set up the local mount point:

client$ sudo su - bkuser
client$ mkdir mnt
client$ mkdir mnt/backup

And then, mount the remote SFTP file system to the newly created mount point:

client$ sshfs server:/bkuser ~/mnt/backup

Test to add/remove files in ~/mnt/backup, and when verified, unmount by issuing the fusermount command:

client$ fusermount -u ~/mnt/backup

5. Use rsync to perform backup

There are tons of guides available on how to use rsync, so this will be kept at a bare minimum. The goal here is just to simply create a backup copy of a single directory structure:

client$ sshfs server:/bkuser ~/mnt/backup
client$ rsync -a -v /path/to/files/ ~/mnt/backup/
client$ fusermount -u ~/mnt/backup

The above commands first mount the remote SFTP server, and then uses rsync in order to copy the contents in /path/to/files/ to the server. The flag -a stands for archive and is a convience flag that makes sure to ttserve ownership, time stamps and other attributes of the transferred files. Finally the file system is unmounted. After being unmounted, the ~/mnt/backup/ directory should be empty.

6. Combine it all into a scheduled backup

In order to work as a backup solution, it is convenient to set up the rsync operation as a scheduled task. In *NIX systems, the most straight forward way of doing this is by setting up a cron job. Cron schedules a single command, so in order to perform multiple operations, we need to set up a simple shell script that in turn gets called by the scheduler. First of all, we are going to create a directory for the scrip:

client$ mkdir ~/bin

Create a shell script called backup-files.sh in the ~/bin directory, for example with nano:

client$ nano ~/bin/backup-files.sh

Enter the following contents:

#!/bin/sh
sshfs server:/bkuser ~/mnt/backup
rsync -a -v /path/to/files/ ~/backup/
fusermount -u ~/backup

Make sure the script is runnable by setting the eXecutable flag:

client$ chmod +x ~/bin/backup-files.sh

In order to set up the scheduled task, we need to edit the crontab for bkuser:

client$ crontab -e

This will bring up an editor, where the following should be entered:

# m h dom mon dow command
0 3 * * * /home/bkuser/bin/backup-files.sh

The five first columns in the crontab specifies the schedule:

  • Minute of hour
  • Hour of day
  • Day of month
  • Month
  • Day of week

The last column specifies the command to run when the scheduled time occurs. So for our case, the backup-files.sh command is called at 03:00 every day of the month, every month and every day of the week.

Thats it! You now have a simple but working, secure backup solution.

References

Advertisement

One Response

Subscribe to comments with RSS.

  1. Narcis Garcia said, on October 14, 2010 at 11:56

    I’ve seen this guide for chrooted SFTP, and I’ve learnt from a lot of tutorials as this one. Here my compendium for optimal configuration in both clients and servers:

    http://wiki.lapipaplena.org/index.php/How_to_mount_SFTP_accesses

    (special care of users and permissions)


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.