CHRoot Jail on CentOS & RedHat

Another geeky “unloading the brain” post.

Setting Up chroot jail for SFTP on CentOS 5.x

Update: While these instructions were intended originally for RedHat-based flavors of Linux, I found that it could also be used with Debian-based Linuxes and even OSX. For OSX, skip all of the compiling information and go right to the sshd_config section below.

FTP is insecure in that the data sent over it is not encrypted. Login IDs, passwords, commands, and the raw data could be intercepted by malicious third parties through whom the traffic travels.

The solution is to use a natively secure protocol, like SSH. Or, more specifically SFTP, which is a subprotocol of the SSH encryption suite. The benefit of SSH is that at no time is data sent in an unencrypted manner. There are also built-in provisions to detect potentially malicious attacks. And as a fringe benefit, only one port needs to be open instead of FTP, which may require several.

There are drawbacks, though. By default, a user who has an SSH account, which is required for SFTP to function, can also run commands on your server. Also, any SSH user will, by default, have visibility to your entire filesystem.

Those issuse are by default. We can change those defaults by locking them in their own home folder and jailing them to the SFTP protocol only.

Here’s how to do it in RedHat and CentOS versions 5.x

First, become root — everything you’ll do for the next few minutes will be as root.

sudo su –

Now, install the GCC compiler:

yum -y install gcc

We’ll need newer versions of ZLIB, OpenSSH, and OpenSSL. We’ll be compiling these from source.

cd /tmp

Now, build some target directories and temporary directories:

mkdir -p /{opt,tmp}/{zlib,openssl,openssh}

Fetch all of the needed source packages.

wget -o /tmp/zlib/

wget -o /tmp/openssl/openssl-0.9.8k.tar.gz

wget -o /tmp/openssh/openssh-5.3p1.tar.gz

Decompress the packages:

cd /tmp/zlib


cd /tmp/openssl

tar xfvz openssl-0.9.8k.tar.gz

cd /tmp/openssh

tar xfvz openssh-5.3p1.tar.gz

Now, we drop into each source directory to configure, compile, and install each package to a new destination:

cd /tmp/zlib/zlib-1.2.5

We’ll just use all of the defaults for configuration — so just do:


And compile:


Then install. Here, though, we’re telling it to install to /opt/zlib/

make install prefix=/opt/zlib/

Now OpenSSL, the encryption suite:

cd /tmp/openssl/openssl-0.9.8k

For OpenSSL, we need to specify at configuration that it will live in /opt/openssl:

./config –prefix=/opt/openssl –openssldir=/opt/openssl

Compile, test, and install:


make test

make install

Be sure to wait for each command to finish before moving on to the next.

And, finally, OpenSSH, which is the SSH suite:

cd /tmp/openssh/openssh-5.3p1

With OpenSSH, we need to define several items at configuration: Installation directory, location of the new SSL libraries to use, where xauth lives, and where our new zlib libraries are:

./configure –prefix=/opt/openssh –with-ssl-dir=/opt/openssl –with-xauth=/usr/bin/xauth –with-zlib=/opt/zlib

Make and install:


make install

Now that it’s installed, we need to edit our existing SSH startup script in /etc/init.d/sshd to point to the new binaries. Edit /etc/init.d/sshd with your favorite editor and replace the following variables with the values shown:






Edit /opt/openssh/etc/sshd_config — the new configuration file for SSH — and throw out anything starting with “^Subsystem” then add a new Subsystem section to the end of the file. Here’s one way:

cat /opt/openssh/etc/sshd_config | grep -v “^Subsystem” > /opt/openssh/etc/

cat <> /opt/openssh/etc/



Subsystem sftp internal-sftp

Match Group jailedsftp

  ChrootDirectory /var/sftp/%u

  ForceCommand internal-sftp

  AllowTcpForwarding no



cat /opt/openssh/etc/ > /opt/openssh/etc/sshd_config

rm -f /opt/openssh/etc/

Restart the SSH daemon to make sure it starts up correctly:

/etc/init.d/sshd restart

You’ll notice in our chroot jail additions that we specify a ChrootDirectory of /var/sftp/%u, so let’s create that now and assign permissions to it.

mkdir -p /var/sftp

chown root:root /var/sftp 

chmod 755 /var/sftp

We’re limiting access through SSH to SFTP only for users that are members of a local group called jailedsftp:

groupadd jailedsftp

Because of the way the sftp jail works, we need to adjust our skel so the user has a couple of important directories. First is the .ssh directory so the user can drop off his own authorized_keys file:
mkdir /etc/skel/.ssh

It needs particular permissions:

chmod 700 /etc/skel/.ssh

And, we’ll need a data directory in the user’s home directory so they have somewhere to work. The reason for this is because with this method, the user’s home directory is owned by root, not the user himself. Because of that, the user can’t, by default, create any objects. You could call this anything — public_html for example. I use ‘data’.

mkdir /etc/skel/data

That’s it. SSH will now limit user access to SFTP for anyone in the jailedsftp group.

Adding New Users

Collect some important information to drop into some variables.

fullname=”Full Name Here”



You may want to wrap that collection in some appropriate scripting to validate all of the inputs. For example, a password should not have !, \, or spaces unless you know how to delimit those. A username cannot have any spaces. An email address should have an “@” and a valid domain, etc. Standard Unix rules apply — and, on that note, Full Name and UserEmail are entirely optional.

Now, we add the user:

useradd -c “${fullname} (${useremail})” -b /var/sftp -g jailedsftp -p `perl -e ‘print crypt(“${userpass}”,”FF”),”\n”‘` ${username}

Look up the man page for useradd to understand what’s going on there. Essentially, we’re specifying where home should be, what the user’s primary group is, the password, and actual login ID.

And, finally, we need to change ownership of the user’s home directory to root with correct permissions:

chmod 755 /var/sftp/${username} && chown root:root /var/sftp/${username}

Don’t propogate those permissions though. The .ssh and data directories in the user’s home need to be owned by the user and need to have the permissions we built into the skel.


Grab your favorite SSH program and try to connect as a user that is not a member of jailedsftp. It should work fine. If it doesn’t something is broken.

Now, try your new user through SSH. It should fail.

Try your regular user through SFTP. It should work fine with the regular user’s real home directory.

Now try your jailedsftp user through SFTP only. It should log in and you should see the appropriate directories. The user should not be able to change to any parent directories, nor create (or delete) any objects in his home directory except for those that we create for him. In this case, .ssh and data.