Configuring a Server to Operate in a chroot Jail
Once you've set up the chroot jail, you can begin using it. This involves configuring the server to operate in the jail, starting the server so that it runs in the jail, and controlling outside access to the jail. This section describes how to do these things, and it concludes with an example of running a name server in a chroot jail.
Running a Server in a chroot Jail
If you're running a server with explicit chroot() support, chances are it includes one or more configuration options relating to chroot operation. For instance, ProFTPd's <Anonymous> directive automatically sets up the server to operate from the specified directory as a chroot jail. You should consult your server's documentation to learn what configuration options invoke chroot operation, and set them appropriately.
If you're configuring a server that lacks explicit chroot support, you should begin with a working configuration from the main Linux environment. Test the server outside of its jail to be sure the basic configuration works. You can then copy the configuration files to a chroot jail, and that configuration should continue working with few or no changes. Once the environment is correctly configured, you should be able to run the server by using the chroot command, which has the following syntax:
chroot /new/root server-name [ server-options ]
The /new/root directory is the chroot jail directory, server-name is the name of the server (complete with path , if necessary), and server-options is any options the server needs. Note that you specify the path to server-name relative to its new root. For instance, if the program file is /opt/chroot/bin/server , with /opt/chroot as the jail directory, you'd type the following to launch the server:
# chroot /opt/chroot /bin/server
If your server normally starts through a SysV startup script or a local startup script, you'll have to modify the startup script to include the chroot command, or disable the startup script and find some other way to start the server. If the server normally runs from a super server, you'll need to set up the super server within the chroot environment along with the target server, alter the super server launch command to incorporate a chroot call, or change the server startup method to use a SysV or local startup script.
Controlling Local Access to the chroot Environment
The chroot jail sets up one-way protections ”programs within the chroot jail cannot influence the system outside of the jail. You might want to limit access in the other direction, as well. For instance, you might want to set up a server in a chroot jail and use restrictive permissions on the chroot jail directories to prevent unauthorized users from reading the files in those directories. You can do this by setting the ownership on the chroot jail to root , setting the group ownership to a special group , and using 0640 ( rw-r ” ”- ) permissions on the files in the directory tree. You can then run the server as a user in the special group you create for this purpose. The result is that the server can read but not write files within the chroot jail, and outside of the jail, only root can read or write files within the tree. Of course, you may need to loosen some of these permissions if the server must be able to write files.
An Example: Running BIND in a chroot Jail
The preceding description may be helpful in setting up a chroot jail, but it may be even more helpful to ground the topic with a more concrete example. Therefore, this section describes the installation of the Berkeley Internet Name Domain (BIND) in a chroot jail. You may want to read, or at least skim, Chapter 18, Administering a Domain via DNS, before proceeding. This example doesn't change the default BIND configuration except to move it to a chroot jail, though, so you don't need to be familiar with the intricacies of name server configuration. This section uses a Debian 2.2 installation as an example. The procedures used will differ slightly for other distributions because of different package management systems and different default configuration files.
To begin the process, we need the standard BIND package installed. This can be done in many ways with Debian, but for this example, I used apt-get :
# apt-get install bind
This installs the standard Debian BIND package in the normal way. The installation script runs, and asks if you want to add the local machine as a name server to /etc/resolv.conf . For testing purposes, I did not do this, but this detail is unimportant for demonstration purposes. When done, Debian runs BIND, which you can verify as follows :
# ps aux grep named root 7656 0.0 1.5 2184 1492 ? S 13:29 0:00 \ /usr/sbin/named # host awl.com localhost awl.com A 126.96.36.199
The second command serves to verify that BIND is installed and working; it calls the host command to locate the IP address of awl.com using the server on localhost . You can substitute any other hostname you like for awl.com , or use your server's true name or IP address instead of localhost . If you get a command not found error, you must install the dnsutils package in Debian to get the host program. (This program may be in a package of another name, such as bind- utils , in other distributions.)
Now that you've verified that the server is working, you can shut it down:
# /etc/init.d/bind stop
After shutting down the server, the next step is creating a chroot directory tree. This example uses /opt/chroot as the chroot jail directory. Thus, we begin by creating the jail directory tree and moving the BIND files into that tree:
# mkdir -p /opt/chroot/usr/sbin /opt/chroot/var/cache/bind # mkdir /opt/chroot/lib /opt/chroot/etc # cp /usr/sbin/named /opt/chroot/usr/sbin # cp -rp /etc/bind/ /opt/chroot/etc
These commands set up the basics of the BIND directory tree and copy the named server and configuration files in /etc/bind to the appropriate directories in the chroot jail. If you were installing a server from scratch, you would probably have to do some investigation to learn precisely what files you'd need to copy, and you might end up creating these files and directories in a piecemeal fashion. One particularly important bit of detective work is locating the support libraries upon which the server relies. You can do this, and copy the libraries, using ldd , as follows:
# ldd /usr/sbin/named libc.so.6 => /lib/libc.so.6 (0x40017000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) # cp /lib/libc.so.6 /lib/ld-linux.so.2 /opt/chroot/lib
At this point, you can test your configuration:
# chroot /opt/chroot /usr/sbin/named # host awl.com localhost awl.com A 188.8.131.52
If this doesn't work, check that only one instance of named is running, and that you created or copied all the necessary files. You can then modify the BIND startup script ( /etc/init.d/bind in Debian) to start the server via the chroot command, or disable the SysV startup script and start the server in some other way. Many SysV startup scripts use wrapper programs (such as start-stop-daemon and ndc in Debian) to do their work, and these programs may create files in still more directories, such as /var/run , so you must copy these files and directories to within the chroot jail:
# mkdir -p /opt/chroot/sbin /opt/chroot/var/run # cp /usr/sbin/ndc /opt/chroot/usr/sbin # cp /sbin/start-stop-daemon /opt/chroot/sbin
You can edit the SysV startup script by adding chroot /opt/chroot before every instance of both start-stop-daemon and ndc . Unfortunately, your work still isn't done, because start-stop-daemon relies on the /proc filesystem, which isn't available in the chroot directory tree. You can edit your /etc/fstab file to make it available ”copy the existing line for /proc and rename it so that it mounts at /opt/chroot/proc . You must then type mount -a to mount the duplicate /proc within the chroot jail.
At this point, you should be able to start the server using the SysV startup script and test it in its final configuration:
# /etc/init.d/bind start # host awl.com localhost awl.com A 184.108.40.206
If you want to be sure the server is running from the chroot environment, you can delete the original program file (in /usr/sbin ) and its configuration files (in /etc/bind ), then restart the server. If your tests still work, you can be confident that the server is running from its chroot jail.
As an alternative to running BIND with the chroot command, you can use the -t option to named , which activates named 's internal chroot() call. For instance, you can launch the server in this way:
# /usr/sbin/named -t /opt/chroot
This approach is simpler than the preceding one because you don't need to copy as many files to the chroot jail directory; you can omit named and the libraries upon which it depends. You must still copy the named configuration files, though (in /etc/bind in this example), because named 's -t option causes it to lock itself in its chroot jail before reading its configuration file. (This contrasts with the usual FTP server configuration, described in Chapter 21, which reads the configuration file first and then locks the server in the chroot jail.) Using named 's -t option also has the advantage of requiring fewer changes to the SysV startup scripts; you need only pass the -t /opt/chroot option through to the server by placing this option at the end of the start-stop-daemon call, preceded by a double dash ( -- ). There's then no need to duplicate the /proc filesystem within the chroot jail.
Of course, the exact procedures you use will be different for other servers or other distributions. Nonetheless, the basic outline should be similar to what's described here. You might also want to make some further changes to the chroot environment, such as changing the permissions on the directories or reconfiguring the server to run as a user other than root (the default for BIND under Debian).