Jails
1. chroot weaknesses
I guess everyone will have heard about chroot and that you “chroot” a program so that it cannot interferer with other programs. For example a web server: If a web server is compromised, not your full server is compromised, too. That's the theory about chroot.
So how does it manage to do that? Chroot is a system call which changes your root directory “/”. Chroot doesn't do a lot more. And guess what chroot is by far not secure. I think, it was back in 1998, when it was widely publicized how easy it can be to break out of a chroot environment. You “only” needed to obtain root privileges in the chroot environment and call chroot without a chdir a few 100 times and you're in the base system. Of, course, a lot of more advanced ways exists: like creating a own device in the chroot environment and using this to break out.
You can definitely prevent this kind of attack by removing any compiler and interpret from the environment and make sure that no one can gain root privileges.
But chroot still misses too much, like it has never given a thought about network security, because in a chroot environment you can still access the really ethernet interface and change its IP and MAC address. And a process from the chroot environment can't be distinguished between a process from the main system in kernel space!
2. FreeBSD jail system: The theory
So what does a FreeBSD jail do different?
- A process started in a jail gets not only a UID and GID, but a JID (jail ID), too. So, if an attacker becomes uid 0 in a jail, he cannot influence processes from another jail or the main system, because the JIDs do not match.
- After the start of a jail, it is not possible to create new devices in this jail. All devices must have been created before a jail starts!
- The IP for the jail is specified at startup of the jail. It is not possible to change the IP in a jail or even change a MAC of an ethernet device.
- Protocols which do not support JIDs are disabled by default, but you can activate them, which lowers the security level!
I would recommend build a fat jail first, because it is much easier, to remove stuff from the jail until the services doesn't work anymore than to add stuff to a jail until if finally works.
You definitely want to have a fat jail, too, to build packages for your other jails. I have a jail which just builds packages and doesn't do anything else, because you can only build packages from the ports system with make package after(!) you have installed the port with make install. So if you don't want to mess up your main system, it's a good idea to create a jail for packaging!
3. Building a jail
You have two ways of building a jail: either compiling base or just installing a binary set. I will cover the latter one first, because I personally, don't want to wait an hour or two until it is compiled.
3.1 binary setup
So you only need the first FreeBSD cdrom or the iso does the job, too. So mount the cdrom or iso file (I will use /mnt/cdrom as the mount point and /jail/package as the Path to the jail):
sh install.sh DESTDIR=/jail/package
And your done!
3.2 source setup
Please, make sure you have the freebsd sources installed, otherwise take a look here (first note).
Now build the jail with
mkdir /jail/package
make world DESTDIR=/jail/package
cd etc
make distribution DESTDIR=/jail/package
mount_devfs devfs /jail/package/dev
cd /jail/package
ln -sf dev/null kernel
And your done ;)
3.3 the first startup
Before starting a jail we need to make sure that you have the right network settings in the jail. Therefore, copy /etc/resolv.conf into /jail/package/etc/.
You start a jail with
Because I don't want to run my jail(s) on my main IP, I use VLans. You can add an additional IP to an interface by
ifconfig DEVICE aliasX inet IP
where X stands for the alias number. For example:
You can add this to your rc.conf so that the VLan is active after every boot:
The last thing we need to make sure is that all the services which are running in your main system just bind to the ip of the main system and not to one of the jails. A good list where the config file for each server can be found is here.
Because I just run services in my jails, I don't wan't to start them by hand, therefore, I just setup an rc.conf inside the jail and then run
jail /jail/web WEB 192.168.1.4 /etc/rc
to start up the jail including all necessary services.
My rc.conf of my webserver jail looks like this:
ifconfig_em0="inet 192.168.178.3 netmask 255.255.255.0"
defaultrouter="192.168.178.1" # Set to default gateway (or NO).
clear_tmp_enable="YES" # Clear /tmp at startup.
# Once you set your jail up you may want to consider adding a good securelevel:
# Same as sysctl -w kern.securelevel=3
kern_securelevel_enable="YES" # kernel security level (see init(8)),
kern_securelevel="3"
lighttpd_enable="YES"
mysql_enable="YES"
4. Working with jails
So after starting a jail and not using a shell as the executable how can I still work in a jail?
You have several different “jail” tools.
jls: lists all running jails and their according jids
jexec: executes the command in the jail with jid
So this should be everything you need to work with jails on a daily basis.
5. What can't be done with jails.
Of course, jails are not “perfect”. You can't jail any service you want. For example: An openvpn server, because it tries to create an tun interface (which isn't allowed in an jail) and, additionally, tries to set the ip for that interface (which isn't allowed either).
So, whatever you want to jail, you need to make sure that the service doesn't preform any of the outlawed task like
- changing an IP after startup
- creating an interface or device
- If you don't activate it, you can't use protocols which don't support jids.
