Not long ago we rebuilt a number of servers within our production environment at work, migrating from FreeBSD to CentOS. One of the requirements in this migration was that we needed a server that would act as an SSH-only Jail on the new platform. This meant I needed to setup a system where users could SSH into a machine but the only thing they could do on that machine was SSH back out again. We used this as our “bounce” machine. Users would have outside access to their Desktops or other machines only by way of this secured SSH-only machine.
The solution I found was a tool called “JailKit“, which allows you to create chroot jails is a very simple way. Below I’ll outline the requirements for installing JailKit and using it to create an SSH chrooted “Jail”.
Step 1: Install JailKit
I was unable to find an up to date package for JailKit on CentOS, so I did the following to install from source:
yum install gcc make<br /> wget -c http://olivier.sessink.nl/jailkit/jailkit-2.7.tar.bz2<br /> tar xf jailkit-*.tar.bz2<br /> cd jailkit-*<br /> ./configure<br /> make<br /> make install<br />
Step 2: Configuration
Once you have JailKit built and installed you’ll need to configure it to provide the needed libraries and devices for your chroot SSH setup. Below is an example configuration I used for a JailKit setup on CentOS 5 x86_64 (using JailKit 2.5 at the time). Note: This is not the entire configuration. These three sections,
basicshell required minor changes and this was the end-product of those changes:
[uidbasics]<br /> comment = common files for all jails that need user/group information<br /> libraries = /lib/libnsl.so.1, /lib64/libnsl.so.1, /lib/libnss*.so.2, /lib64/libnss*.so.2<br /> regularfiles = /etc/nsswitch.conf<br /> emptydirs = /home
[ssh]<br /> comment = ssh secure shell<br /> executables = /usr/bin/ssh<br /> includesections = netbasics, uidbasics<br /> devices = /dev/urandom, /dev/tty, /dev/null
comment = bash based shell with several basic utilities executables = /bin/sh, /bin/bash, /bin/ls, /bin/cat, /bin/chmod, /bin/mkdir, /bin/cp, /bin/cpio, /bin/date, /bin/dd, /bin/echo, /bin/egrep, /bin/false, /bin/fgrep, /bin/grep, /bin/gunzip, /bin/gzip, /bin/ln, /bin/ls, /bin/mkdir, /bin/mktemp, /bin/more, /bin/mv, /bin/pwd, /bin/rm, /bin/rmdir, /bin/sed, /bin/sleep, /bin/sync, /bin/tar, /bin/touch, /bin/true, /bin/uncompress, /bin/zcat, /usr/bin/id regularfiles = /etc/motd, /etc/issue, /etc/bash.bashrc, /etc/bashrc, /etc/profile directories = /usr/lib/locale/en_US.utf8 users = root groups = root includesections = uidbasics `
Step 3: Populate The Jail Environment
Once these changes are made JailKit should be configured to provide the needed libraries and devices to your SSH chroot. You can now generate the chroot by using these two commands:
jk_init -v -f /home/chrootusers/ ssh<br /> jk_init -v -f /home/chrootusers/ basicshell<br />
Step 4: Generate Users
The final step in an SSH-chroot Jail setup is the creation of users. This step is a bit more complicated due to the fact that the users need to be created within the chroot setup and on the host system itself. The users will never have access to the host system, but that is where the initial authentication happens. Once they are authenticated they are pushed into the chroot jail and have limited permissions.
This script assumes two things that you should be aware of. If your configuration doesn’t match you’ll need to update the script accordingly:
- This script assumes your chrooted jail home directories will be in
- This script assumes group-based SSH restrictions using a system group called
- This script also attempts to create storage restrictions using filesystem quotas, but succeeds if quotas are not enabled. (See Appendix for information on enabling quotas.)
Here is the script:
This code is released under the Public Domain.
create jailed ssh accounts
usage: ./chroot-jail username ‘passwdhash’
## sanity checks<br /> if [ $# -ne 2 ]; then<br /> echo "This application requires two arguments: username 'passwdhash' (single-quotes required)"<br /> exit 1<br /> fi
if [ ! -d /home/chrootusers/./home/ ]; then<br /> echo "This application assumes installation to /home/chrootusers"<br /> exit 1<br /> fi
getent passwd $1 &>/dev/null<br /> if [ $? -eq 0 ]; then<br /> echo "User $1 already exists on host system. Please remove and re-create using this tool."<br /> exit 1<br /> fi
`getent group sshaccess &>/dev/null if [ $? -ne 0 ]; then echo “This application assumes ‘AllowGroups sshaccess’ restriction in /etc/ssh/sshd_config. sshaccess group missing” exit 1 fi
If you create all of your users using this script you should save yourself a fair amount of headache. Between the user-creation script and the JailKit tools, creating SSH chrooted jails becomes a very simple task.
Appendix: Enabling Quotas
When I first implemented this JailKit setup in production I invited a few of the users to do their worst to break out of the jail or otherwise interfere with the system and other users. One of the potential problems that we found was that of drive space. Because there were no storage limitations for the chrooted users, one user could create large files and interfere with the others (or the host system) by filling up the drive. Below I’ve outlined how to activate filesystem quotas on Red Hat Enterprise or CentOS machines and apply a 15M hard limit to your chrooted users:
Quotas are a filesystem-based feature that needs to be activated within the fstab. To activate the use of persistent quotas append the term “usrquota” to the mount options of /home/ in your fstab. Example:
/dev/LocalVol/HOME /home ext3 defaults,usrquota 1 2
Once this is configured the following four commands will install, configure and activate quotas.
yum install quota<br /> mount -o remount /home/<br /> quotacheck -cmu /home/<br /> quotaon /home/
At this point you aren’t applying any limits to the user (yet), but the quota management system is on and active. If you create your users using the script above they will be given a 10M soft limit (after 10M they will be given a warning) and a 15M hard limit (absolutely no more disk writes). You can change these values (last line in the script) based on your needs.