Published on (
 See this if you're having trouble printing code examples

FreeBSD Jails

by Mike DeGraw-Bertsch

What is a Jail?

Those familiar with Java recognize the security concept of a sandbox. For those that aren't, it's the concept that everyone gets a unique, well-equipped sandbox to play in, and a person in one sandbox isn't allowed into anyone else's sandbox, not even to share anything with anyone else. On FreeBSD, jails implement this concept — they keep processes in their own part of the system, denying access to anything else. A jail requires its own dedicated IP address, though, which can make life difficult for those with limited address space. If this presents you with a hardship, consider at least using chroot. It won't afford you as much security, but it does help.

How does this help security? Take, for example, a box with an external FTP server and the company extranet. An exploit for the server is discovered, and a cracker manages to gain root access through the FTP daemon. If the FTP server is not run in a sandbox or jail, the cracker will have access to everything on the machine, including sensitive information destined for the company's partners through the extranet. If, however, the FTP server is run in a jail, the cracker will only have access to the FTP files.

There are, of course, still potential risks. If you run at secure level 0, the cracker can simply access the raw disk device and read data from there. The solution is obvious — on a box sensitive enough to require jails, use appropriate secure levels as well. This will eliminate a cracker's ability to read from or write to raw disk devices.

Configuring a Jail

Configuring a jail is pleasantly simple.

First, ensure that your system environment is jail-friendly. Because each jail requires its own IP address, the services on your box must be configured to listen to specific addresses, not just every available address. For example, if the box's addresses are (main) and (jail), to get inetd to listen only on, add inetd_flags="-wW -a" to /etc/rc.conf. If you fail to do this, conflicts may occur over the aliased IP address.

For some daemons, this is not an easy process — sendmail and rpcbind are two examples. If you're using these services on your box, you might consider simply running them inside of a jail of their own. After configuring all of the non-jailed daemons to listen to a specific address, reboot the machine. This will put everything into a known state, eliminating any potential for confusion.

With the proper host environment in place, create the directory that will house the jail. In this example, it's /usr/jail/ftp. Now go to /usr/src and run:

# make world DESTDIR=/usr/jail/ftp
# cd etc
# make distribution DESTDIR=/usr/jail/ftp
# cd /usr/jail/ftp/dev
# sh
# MAKEDEV jail

# cd ..
# ln -sf /dev/null kernel

These commands build the jail and populate it with all of the tools that your processes will need to run. Actually, they put in a lot more than just what your processes will need. For example, perl, gcc, and sendmail will all be installed, but you probably don't need them in your jail. Keep in mind, though, that it's a lot easier to take stuff out until something breaks than it is to put stuff back in until everything works.

To configure the jail environment, you might want to copy /stand/sysinstall into /usr/jail/ftp/stand, to provide you with an easy configuration interface. I'll show you how to use it in just a second.

With the system rebooted, you're now ready to configure the jail environment. Start the jail for the first time by running:

# jail /usr/jail/ftp /bin/sh

This will put you at a shell prompt in your jail environment. From here, you can run /stand/sysinstall (literally, since / now refers to the jail's root directory, not the system's.)

There are several configuration tasks to perform, such as setting the root password (don't make it the same as the main system root password!), adding user accounts, and configuring /etc/resolv.conf. Read man 8 jail for more configuration tasks that you'll need to perform. Keep in mind that you want to be able to log in to the environment, so consider running an SSH daemon inside the jail.

Once you're done configuring the jail environment, exit the shell and the jail will be shut down.

You're almost ready to start the jail "for real." First, add the appropriate IP address alias. For our example, this is done via:

ifconfig fxp0 inet alias

You can configure this in /etc/rc.conf to be done automatically at boot.

Now, let's start the jail! This is done with two commands:

# mount -t procfs proc /usr/jail/ftp/proc
# jail /usr/jail/ftp /bin/sh /etc/rc

You'll see some warning messages scroll by, but don't worry about them. You can now see all the daemons running inside the jail, as indicated by the J flag shown in the ps output. If you enabled SSH within the jail, you can ssh to the jail environment.

Since normal shutdown commands like halt don't work in the jail, you must take a special measure to shut the jail down. First, log in to the environment and become root. You can then kill all the processes inside the jail via kill -TERM -1 or kill t -KILL -1. You can also do this from outside the jail by manually killing any PID within the jail.

You should now be able comfortably to create and use jails to secure everything from FTP daemons to DNS servers. Before we finish, there's just one more note.

The security.jail.set_hostname_allowed (or jail.set_hostname_allowed on pre-5.0 machines) sysctl variable determines whether or not the superuser within the jail can set the hostname. This is enabled by default, and you might consider disabling it by placing security.jail.set_hostname_allowed=0 in /usr/jail/ftp/etc/sysctl.conf. Remember that it's jail.set_hostname_allowed=0 on machines running FreeBSD-4.x!


You've now seen both how jails work and how to set one up. Whether you're running multiple public services from the same box, providing login shells to untrusted users, or offering a public service on an otherwise private machine, using jails properly will help you sleep at night.

Mike DeGraw-Bertsch is a security and Unix system administration consultant in the Boston, Mass. area. When he's not at a job, writing, hacking with Perl, or playing with his wireless network, he can usually be found playing goal in ice hockey.

Return to the BSD DevCenter.

Copyright © 2009 O'Reilly Media, Inc.