Tuesday, April 1, 2014

ssh chroot jail

This post shows step by step how to create minimalistic ssh chroot jail. I use this for sharing files via scp/WinSCP.

In general, ssh chroot jail is a directory, where user matching criteria (username or group) is chrooted after login.
My chroot contains only files necessary to create user's session. You can add other binaries to chroot jail, I don't need them bacause I use my chroot jail only to remotely copy files via scp.

First step is to create new user "share" in your system and set ChrootDirectory for this user in sshd_config:
useradd -d /home/share -m -s /bin/bash share

Add Public key to authorized_keys for key-based authentication:
su - share
[share@RPi-TA ~]$ mkdir ~/.ssh
[share@RPi-TA ~]$ vim ~/.ssh/authorized_keys
[share@RPi-TA ~]$ chmod 700 ~/.ssh
[share@RPi-TA ~]$ chmod 600 ~/.ssh/authorized_keys
[share@RPi-TA ~]$ exit

Add to sshd_config:
vim /etc/ssh/sshd_config
    Match User share
      ChrootDirectory /mnt/jail/
      X11Forwarding no
      AllowTcpForwarding no

systemctl restart sshd
Next step is to create chroot jail directory structure and copy all necessary files:
Create directory structure:
export JAIL=/mnt/jail
mkdir -p $JAIL/{dev,etc,home/share,usr/lib/ssh,usr/bin}
chown share:share $JAIL/home/share

Create /dev files:
mknod -m 0666 $JAIL/dev/null c 1 3
mknod -m 0666 $JAIL/dev/random c 1 8
mknod -m 0444 $JAIL/dev/urandom c 1 9

Create links:
cd $JAIL
ln -s usr/bin bin
ln -s usr/lib lib

Copy binaries:
cp /bin/{bash,scp,sftp} $JAIL/bin/

Now copy all libraries needed for binaries:
ldd $JAIL/bin/{bash,scp,sftp}
    /mnt/jail/bin/bash:
        libreadline.so.6 => /usr/lib/libreadline.so.6 (0xb6f79000)
        libncursesw.so.5 => /usr/lib/libncursesw.so.5 (0xb6f22000)
        libdl.so.2 => /usr/lib/libdl.so.2 (0xb6f17000)
        libc.so.6 => /usr/lib/libc.so.6 (0xb6de0000)
        /lib/ld-linux-armhf.so.3 (0xb6fce000)
    /mnt/jail/bin/scp:
        libc.so.6 => /usr/lib/libc.so.6 (0xb6e08000)
        /lib/ld-linux-armhf.so.3 (0xb6f53000)
    /mnt/jail/bin/sftp:
        libedit.so.0 => /usr/lib/libedit.so.0 (0xb6f75000)
        libc.so.6 => /usr/lib/libc.so.6 (0xb6e3e000)
        /lib/ld-linux-armhf.so.3 (0xb6fb5000)
        libncursesw.so.5 => /usr/lib/libncursesw.so.5 (0xb6de7000)

Copy all libraries from /usr/lib:
cp $(ldd $JAIL/bin/{bash,scp,sftp} | grep /usr/lib | awk '{print $3}' | sort | uniq) $JAIL/usr/lib/

Copy other libraries:
ldd $JAIL/bin/{bash,scp,sftp} | grep -v /usr/lib
    /mnt/jail/bin/bash:
        /lib/ld-linux-armhf.so.3 (0xb6eda000)
    /mnt/jail/bin/scp:
        /lib/ld-linux-armhf.so.3 (0xb6f08000)
    /mnt/jail/bin/sftp:
        /lib/ld-linux-armhf.so.3 (0xb6f33000)
cp /lib/ld-linux-armhf.so.3 $JAIL/usr/lib/

Copy libraries needed for user identification:
cp /usr/lib/libnss* $JAIL/usr/lib/

Copy sftp binary to enable sftp copy mode (used by WinSCP):
cp /usr/lib/ssh/sftp-server $JAIL/usr/lib/ssh/
Last step is to create/copy few files in etc folder in chroot:
cp /etc/hosts /etc/ld.so.{cache,conf} /etc/nsswitch.conf $JAIL/etc/

Edit hosts file, remove unneeded entries:
vim $JAIL/etc/hosts

Add newly created user (share) to chroot files:
for file in /etc/{group,gshadow,passwd,shadow}; do tail -1 $file >> $JAIL/$file; done
chmod 600 $JAIL/etc/{gshadow,shadow}

Now you should be able to use scp with user share.  

Troubleshooting:
If you get I have no name! or unknown user error, check if you have copied all /usr/lib/libnss* files to chroot jail.
Cannot initialize SFTP protocol. Is the host running a SFTP server?: WinSCP uses sftp-server, check if you have /usr/lib/ssh/sftp-server in your chroot jail.
If you've accidentally deleted some library from your system instead of chroot and you getting missing library errors, copy the missing library from chroot jail like this:
(export LD_LIBRARY_PATH=$JAIL/usr/lib:$LD_LIBRARY_PATH && cp $JAIL/usr/lib/libcap.so.2 /usr/lib/)
NOTE: file /usr/lib/libcap.so.2 might be symbolic link to library, so instead of copying file, you should create link:
(export LD_LIBRARY_PATH=$JAIL/usr/lib:$LD_LIBRARY_PATH && cd /usr/lib/ && ln -s libcap.so.2.24 /usr/lib/libcap.so.2)

3 comments:

  1. This is the simplest, clearest explanation of this topic I have found. Thanks!
    linux scp

    ReplyDelete
  2. Thank you for libnss :-)
    I have just copied libnss_files.so.2

    ReplyDelete
  3. This was helpful, thank you for documenting.

    FYI, for CentOS 7 the libnss* files are in /usr/lib64

    ReplyDelete