You can bind-mount directories into your chroot root with:
mount -o bind /x/y /chroot/x/y
(see man mount
, section "The bind mounts"). Any access to /chroot/x/y
from now on acts exactly like an access to /x/y
: same file listings, same contents, same inodes.
Note, however, that this puts the entire directory in as-is: a process inside the chroot that can write to the directory will be able to write to the "real" directory outside. If you want to make the mount inside the chroot read-only you need to remount explicitly read-only after the bind:
mount -o remount,ro /chroot/x/y
The original /x/y will remain read-write, but the copy will now be read-only.
To prefer internal copies of files, or to allow writing in some existing files or directories without affecting the originals, you can use a union file system. These let you overlay multiple directory trees on one another, specifying where writes go to and the order that reads are resolved. Common union filesystems for Linux include aufs, Unionfs, and unionfs-fuse. The first two of those are kernel modules, while the last uses FUSE to run a filesystem in user space. The kernel modules are generally faster, but the FUSE version may be easier to set up, although you may want to avoid using external user-space tools from your chroot anyway. You can prepare the union filesystems you want and then chroot into them.
In each case the basic approach is the same, something like:
unionfs-fuse -o cow /jail/bin:/other/bin:/bin /chroot/bin
This creates a union mount in /chroot/bin
which gives the files from /jail/bin
priority if they exist, then try /other/bin/
, and otherwise shows the files from /bin
. -o cow
makes it copy-on-write: attempts to write to, say, /chroot/bin/foo
will copy /bin/foo
to /jail/bin/foo
and save the modifications there. If you don't want that behaviour, leave the option out. The other filesystems have slightly different configurations, but the principle is the same.
Whichever way you set it up, you could then:
chroot /chroot
and have everything work the way you wanted.
This is an interesting differentiation:
I'm NOT talking about preventing people from logging in. I'm talking about removing the parts of the system that even make it possible to log in.
I'm not entirely sure there is actually anything other than a semantic difference. If I were to remove /bin/login
then you would not be able to log in (on the physical terminal) because I had made it impossible to log in. But I would not have removed the entire login subsystem.
My suggestion would be to leave as much intact as possible because there may be unforeseen dependencies. Leave users in place, so that your web server runs as a different account than root
. Prevent interactive and non-interactive logins by modifying the PAM subsystem. Optionally prevent sudo
type access in a similar manner.
Prepare a "denied" PAM definition
Create /etc/pam.d/denied
containing the following two lines:
auth requisite pam_deny.so
session requisite pam_deny.so
Prevent logins from the terminal/screen
Replace /etc/pam.d/login
with a copy of /etc/pam.d/denied
Prevent network logins with ssh
Replace /etc/pam.d/sshd
with a copy of /etc/pam.d/denied
Edit /etc/ssh/sshd_config
and ensure that UsePam yes
is set.
Optionally, disable at attempt at sudo
Replace /etc/pam.d/sudo
with a copy of /etc/pam.d/denied
Actually, rather than denying all logins, it might be better to permit root logins from the physical terminal/screen and deny everything else. This could also be done via PAM but is outside the specific scope of the question.
Best Answer
It provides reasonable filesystem isolation for non-root processes. However, chroot has several limitations. Mainly, the root user can easily escape from the environment. It would be better to use an isolated environment that provides root privilege isolation, such FreeBSD jails, Linux containers, or Docker.
If a hacker finds a way to exploit the web application in a way that allows him/her to run some code as root, chroot only provides the protection that the hacker may not know he/she is in a chrooted environment. If discovered, the hacker could run some trivial code to chroot into the system that you are trying to protect. This is not so much the case with the other technologies mentioned above, where a root escape would be considered a vulnerability in that technology rather than expected behavior.
The answer to your question comes down to what is enough for you given the specific services and web applications being exposed.