This guide is directed to using OpenSSH for enabling secure file transfer from a file server. The level of this guide is directed at people who already know the basics of OpenSSH server & client usage for its more typical uses like logging into a remote server. Please see the bottom of the guide for some resources in case you are new to SSH and want to know more.
OpenSSH is an extremely popular program for doing all sorts of things in the world of UNIX-like operating systems. Most SSH users are well familiar with using the SSH server for logging into a remote system. OpenSSH can actually be used for quite a few other purposes beyond simply logging into a remote box, and this guide is directed to just one of them: secure file transfer.
Many of you are no doubt familiar with programs like sftp, scp, rsync (using an SSH transport), or WinSCP under Windows that let you transfer files back and forth from a remote box. Here's a little issue that some of us may encounter: You need to transfer files with an outside party in a secure manner. Of course services like Dropbox exist, but let's say that for one reason or another you don't want your data residing on Dropbox. Now, let's also assume that while you like this outside party well enough to exchange data, you certainly don't want the outside party having full-blown login access to your server via SSH. That's a bit of an issue because, by default, SSH gives users to your system access to a shell, which means that the user can run many programs that have user-level access and can also gather quite a bit of information about your system.
So here's the $64 question: How can I grant access to an outside party to upload and download data from an approved directory with all the security benefits of SSH without handing them the keys to running any old program they want? Let's take it a step further: Say you want to share files with party A (Alice) and party B (Bob) without Alice and Bob being able to see each other's files. How about another setup: Alice and Bob want to use your server to exchange data, but they don't want party C (call him Chuckula) seeing their data. This guide presents options for configuring OpenSSH to provide these types of secure file sharing.
The Server Side
Most of the complexity of setting up this server is on the server side. As you will see, it's not incredibly difficult but following the correct procedures will make sure that your system works and that it is secure. Please note that this portion of the guide assumes you have administrative access to the server that is running OpenSSH. Please add "sudo" or login as root as needed to make sure these commands complete successfully without permission denied errors. I also recommend making a backup of the sshd_config file before adding these changes just in case they don't work out.
The top-level directory is /mnt/share, which is the file path that we are using for the home directories of one or more remote users. I am keeping it separate from the more traditional "/home" directory to emphasize the difference between ordinary users who login vs. those who are just given access for file transfer purposes.
The superuser ("root") should own this directory and it should have r+x permissions for at least the users who will access this share. You can accomplish this by setting global r+x directory permissions or by making a special group just for outside users who can access this directory while potentially preventing other users on your system from accessing . We will make home directories under this path. Of course, in your system the top-level directory can be different depending on where you want to store files for the server.
One-time setup task
We will be giving our file-transfer only users a special shell program to use. The "/etc/shells" file in many distros includes a list of approved shell programs. Add the following entry into the /etc/shells file in case it isn't already there. Please note that the exact path may be different on your distribution so please confirm that this file exists or use a different path:
You only have to do this setup one time.
Give Alice & Bob separate upload directories that are each only accessible to one user
There are major two phases to the setup. First is adding in the users to your overall system since SSH relies on user accounts. Second is configuring OpenSSH to restrict access to these users.
Phase 1: Setup your users on your Server box:
Here's a command line to add user "Alice" to the system (change the name as needed and repeat for "Bob", "Chuckula" and other users):
useradd -p 12345 -s /usr/lib/ssh/sftp-server -d /mnt/share/alice/home -M alice
To those of you familiar with UNIX administration, this command is pretty straightforward, but I have an explanation of the options below:
-p: password for this user, obviously 12345 is not what you want. OpenSSH in some configurations will use this password as a login, but you
can setup a secure certificate for Alice instead.
-s: The shell for Alice. Normally the shell is a Unix shell like Bash, csh, zsh, etc. However, we don't want Alice to be able to login either through SSH or even through a direct login (if Alice were ever physically present at your server). Setting the shell to '/usr/lib/ssh/sftp-server' means that Alice can only access the approved sftp server program. If Alice tries to login locally, then the login will fail, and the only remote access that Alice will get will be for transferring files from the approved directories we setup.
-d: The home directory for Alice, which we have set to: /mnt/share/alice/home (instead of the more usual /home/alice).
-M: do not create the home directory if it does not already exist. You can omit this option to have the home directory created.
The above command is by no means the only way to add the user, for example you can change the password for the user separately using the 'passwd' command.
Now setup the home directory for Alice. Note that there are two levels here: the "alice" subdirectory and the "home" subdirectory under alice. Both are needed: the Chroot directive we detail below has to point to the higher level "alice" directory (that is actually owned by the superuser) and the "home" directory needs to be owned by alice herself. This is an unfortunate complication of the security model that is used by the "Chroot" directives.
chown root:root /mnt/share/alice # note that root actually owns the "alice" directory
chmod 755 /mnt/share/alice # alice can descend into this directory but not write to it directly
# using group permissions can restrict local access to this directory to
# allow alice in while keeping other local users out if you like.
mkdir /mnt/share/alice/home # alice's real home directory
chown alice:alice /mnt/share/alice/home
chmod 700 /mnt/share/alice/home # alice has complete control under her 'home' directory. Other users are blocked
These commands setup Alice's home directory and set permissions so that Alice (and only Alice) can access the directory. You will see that we make some changes to ownership and permissions below if we want two users to share a directory.
Perform the same command sequence with a different username, password, and home directory path for 'Bob' (or any other user you want).
Phase 2: Setup OpenSSH when keeping Alice & Bob Separate:
Add the following section to your SSH server configuration file (/etc/ssh/sshd_config):
Match user alice
# The following two directives force Alice to become chrooted
# and only have sftp (file transfer) available.
# Alice sees her home directory as "/home" and can't name other directories
# IMPORTANT: Leave off the "home" in this path. We point to the directory immediately above
# alice's home directory for the chroot.
ChrootDirectory /mnt/share/alice directories
# make sure Alice can't run arbitrary programs (even ones in her chrooted directory)
# For additional security, disallow all types of port forwardings.
Simply add another section that includes a similar set of directives for the user "bob" and points to Bob's home directory to your sshd_config file to setup Bob with his own home directory that is isolated from Alice's directory.
So what do the above configurations accomplish? Well, the "ChrootDirectory" directive means that when Alice or Bob logs in, each of them sees only her or his own "home" directory directly under the "root" directory of the filesystem. They literally can't even try to change into each other's directories or other directories on your system because they have no ability to name the paths outside of the Chrooted environment. Chroot stands for "Change Root" and chrooting a login or program is often referred to as putting a program in a "jail" that it cannot escape.
The next directive "ForceCommand internal-sftp" prevents your user from being able to execute any commands on the the computer other than the sftp command that handles file transfer responsibilities. Just in case somebody uploads executable programs to the chroot jail, it will prevent them from running by an attacker who might try to execute these programs using the "ssh <login> <command>" syntax.
The next set of three directives turn off port forwarding for Alice. As many of you may know, SSH can be used to tunnel traffic through an SSH host to another network (like an internal network). We don't want Alice doing that, so these directives disable that capability.
One last step: Restart your ssh server after you update your sshd_config file. Different distros do this in different ways, but the systemd method is:
systemctl restart sshd
Let Alice & Bob share a directory but don't let in Chuckula
Please refer to the directions above for more explanation. This set of directions lets Alice & Bob share a directory for transferred files.
Phase 1: Setup Alice & Bob with different accounts that share the same group on your Server box:
Add a new group that both Alice & Bob will belong to:
Setup the user accounts for Alice & Bob in the same way you did above with the following exceptions:
1. Both Alice & Bob get the same home directory.
2. Both Alice & Bob get added to the group "alice-n-bob" with the -G directive
useradd -p 12345 -s /usr/lib/ssh/sftp-server -d /mnt/share/alice-n-bob/home -G alice-n-bob -M alice
useradd -p 12345 -s /usr/lib/ssh/sftp-server -d /mnt/share/alice-n-bob/home -G alice-n-bob -M bob
Finally, setup their shared home directory with permissions that let both Alice and Bob access it:
mkdir /mnt/share/alice-n-bob # top-level chrooted directory not accessible to Chuckula
chown root:root /mnt/share/alice
chmod 755 /mnt/share/alice-n-bob
mkdir /mnt/share/alice-n-bob/home # new home directory that is shared by alice and bob's group
chown root:alice-n-bob /mnt/share/alice-n-bob/home
chmod 770 /mnt/share/alice-n-bob/home
Note that another system user, Chuckula, will be locked out of this directory since Chuckula is not a member of the group!
Phase 2: Setup OpenSSH with Alice & Bob having access to a single directory:
The sshd_config file will be setup in a similar manner, but now Alice and Bob get to be put together in a single group directive where they share a single directory:
Match group alice-n-bob
# The following two directives forces alice-n-bob group members to become chrooted
# and only have sftp (file transfer) available.
# Shared directory as "/" the "home" directory is directly below this
# make sure Alice & Bob can't run arbitrary programs (even ones in her chrooted directory)
# For additional security, disallow all types of port forwardings.
A few substantive updates to the instructions above (thanks to the ever shifting underlying architectures for setting up SSH):
1. Removed the references to /bin/false as the shell and put in /usr/lib/ssh/sftp-server as the replacement shell.
2. Updated the home directory vs. the chrooted directory since the Chrooted directory has to be one level higher than the user's home directory.
3. Please feel free to contact me if you encounter other setup issues!
The Client Side
This is actually a much simpler than the server side: Just have your users transfer data using sftp, scp, rysnc, WinSCP (for you windows users), or any other suitable file transfer program that interacts with SSH. Each user will be restricted to his or her chrooted directory for transferring data. These users won't be able to jump up to the real root directory or otherwise escape the chrooted file path that you setup on the SSH server. As we discussed above, if you setup the chroot and group permissions for multiple users, then they can have access to each other's files.
Just in case you completely new to SSH (it stands for Secure SHell), the following links have a great deal of information about the basics of SSH using the very-common OpenSSH client and server:
http://www.ibm.com/developerworks/aix/l ... hsecurity/