Using SSH in a chroot environment
Table of Contents
Overview
This document describes how to set up a server with chroot accounts where
these accounts are able to connect to the server via ssh, scp and
sftp. This is not as trivial as it may sound since at least scp and
sftp won't work in a chroot environment by default.
The setup described here is tested with Linux 2.2.x, 2.4.x, 2.6.x and any version of OpenSSH between 3.1p1 and 5.5p1. You should not use any older OpenSSH versions due to several security issues.
Furthermore the setup should work with AIX 4.3.3 (tested) and 5.1 (tested) as long as you use the patch adapted for AIX and OpenSSH 3.4 or higher (thanks to Akos Domjan <a_domjan@hotmail.com>).
Since version 4.9 OpenSSH comes with native chroot support. However, I've never tried this one. Further information can be found on the sshd_config man page.
Setting up the chroot environment
First you’ll have to set up a prototypical home directory for the chroot
accounts. This home directory should contain all necessary files a
chroot’ed user needs. Typical contents would be a bin directory with a
statically compiled shell and other statically compiled tools like GNU
filetools and the like. Furthermore you’ll probably need a lib directory
for some basic libs (like libc).
Once finished with that you can chroot to this directory and verify that
anything works as desired. To find out what’s needed by a certain program
ldd and strace come in handy.
Creating User Accounts
After that you can start to create the “real” chroot accounts. To simplify this task I’d recommend to write your own setup script. The following needs to be done.
- Create the necessary directories with the appropriate permissions as root, e.g.
mkdir -m 755 $HOME/bin mkdir -m 755 $HOME/lib # ...
-
Create the
/devdirectory and necessary devices, e.g.
mkdir -m 755 $HOME/dev mknod $HOME/dev/null c 1 3 -m 666 # ...
-
Create the
/etcdirectory and add the necessary entries topasswdandgroup, e.g.
mkdir -m 755 $HOME/etc echo "root:x:0:0:root:/root:*" > $HOME/etc/passwd echo "user:x:500:500:A Chroot User:/home/user:/bin/bash" >> $HOME/etc/passwd echo "root:x:0:root" > $HOME/etc/group echo "usergroup::500:" >> $HOME/etc/group chmod 444 $HOME/etc/passwd $HOME/etc/group
- Hard link the files from you prototypical directory to the new home directory (this will save you disk space), e.g.
ln /home/typical/bin/* $HOME/bin/ ln /home/typical/lib/* $HOME/lib/ # ...
Installing OpenSSH systemwide
Before you build OpenSSH you should apply a patch that enables chroot with OpenSSH. There are various patches around, although the following works with 3.1p1 - 5.5p1 (at least for me and not for AIX; see below):
--- session.c.orig 2009-01-28 06:29:49.000000000 +0100 +++ session.c 2009-02-23 09:01:33.000000000 +0100 @@ -261,6 +261,11 @@ } } +/* CHROOT patch start */ +char *user_dir; +char *new_root; +/* CHROOT patch end */ + void do_authenticated(Authctxt *authctxt) { @@ -1496,6 +1501,27 @@ if (setlogin(pw->pw_name) < 0) error("setlogin failed: %s", strerror(errno)); + /* CHROOT patch start */ + user_dir = xstrdup(pw->pw_dir); + new_root = user_dir + 1; + + while((new_root = strchr(new_root, '.')) != NULL) { + new_root--; + if(strncmp(new_root, "/./", 3) == 0) { + *new_root = '\0'; + new_root += 2; + debug("chrooting to user directory %s", user_dir); + if(chroot(user_dir) != 0) + fatal("Couldn't chroot to user directory %s", user_dir); + pw->pw_dir = new_root; + if (chdir("/") < 0) + fatal("Couldn't cd to / after chroot to user directory %s: %s", + user_dir, strerror(errno)); + break; + } + new_root += 2; + } + /* CHROOT patch end */ if (setgid(pw->pw_gid) < 0) { perror("setgid"); exit(1);
The diff file is available here. (Older versions of this patch with different offsets are still available: diff for OpenSSH 3.x, diff for OpenSSH 3.1, diff for OpenSSH 4.x.)
Note that the above patch requires that OpenSSH must not be compiled statically. (Thanks to Oliver Gorzellik for the hint.)
Since this patch won’t work on AIX systems due to privilege problems when
calling the chroot() function, you will have to use the patch for AIX
provided by Akos Domjan <a_domjan@hotmail.com> if you’re running such a
system.
Now configure OpenSSH as desired and run make; make install.
Installing OpenSSH inside chroot cages
To install OpenSSH inside your cages copy ssh, scp, sftp and
sftp-server to your prototypical directory and hardlink it to the cages
bin directory. Note that you might need to create some Symlinks inside your
cages because OpenSSH needs to find it’s binaries inside the cage exactly
where they’re found systemwide. If you installed OpenSSH (systemwide) to
/usr/local you’ll need to do the following:
mkdir -p -m 755 $HOME/usr/local/bin cd $HOME/usr/local/bin ln -s ../../bin/ssh . ln -s ../../bin/scp . ln -s ../../bin/sftp . mkdir -p -m 755 $HOME/usr/local/libexec cd $HOME/usr/local/libexec ln -s ../../bin/sftp-server .
Once again: Do not compile OpenSSH statically.
The chroot patch to OpenSSH requires a “magic token” in /etc/passwd (you
might know this from other servers). Only if that token is found OpenSSH
will chroot. So you’ll have to alter the home directory field in
/etc/passwd for the appropriate users like that:
# old -> :$HOME: # new -> :$HOME/./: # e.g. # :/home/user: -> :/home/user/./:
At this point ssh, scp and sftp to the chroot box should work.
ssh, scp and sftp from the box seem to work, too, as long as you
make sure that host name can be resolved within the cage (Alternatively,
you can use IP numbers).
Aftermath
Note that X11-Forwarding with OpenSSH is not yet possible with this setup,
users have to invoke ssh with the -x option. Since I don’t require this
feature I haven’t explored the problem further.
Also note that users might have to upgrade their SSH-Clients on the machine
they use to connect to the server. I noticed that this setup using OpenSSH
3.1p1 won’t work with clients using scp or sftp form OpenSSH 2.x.
Please keep in mind that chroot with this setup is performed for SSH connects only. Other services must be configured separately to do a chroot on login. As for telnet I recommend to disable this service. However, you can use changeroot to perform a chroot on telnet logins. This works well with the chroot patch for OpenSSH. Several FTP-Servers are capable of performing a chroot, as well. If you really need FTP (also SFTP obsoletes that) you should have a look at the appropriate documentation.
If you provide SSH for Microsoft Windows™ users, take a look at http://support.zeitform.info/en/server_access/ssh.html.
If you have comments, questions, further hints or whatever don’t hesitate to contact me. You’ll find my e-mail address below.
Date: 2010-04-27 16:10:12
HTML generated by org-mode 6.35trans in emacs 23