Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Setup SSH chroot jail

profile picture
Author
Johannes Heidelbach
Published
2021-04-30
Time to read
5 minutes reading time

Introduction

This tutorial shows you how to setup a minimal working chroot jail restricting some user logging in via SSH to just the login shell.

Besides having an already installed and running SSH server we will start from scratch.

Prerequisites

  • SSH service based on OpenSSH installed

Step 1 - Provide chroot environment

Step 1.1 - Minimal setup

All binaries that shall be executed in the chroot environment along with their dependencies on the shared linked objects must be part of the chroot environment.

First create a new directory which will be root for the chroot environment. For this tutorial the directory /chroot-jail-root will be used. As the login shell is minimal required it must be copied at least.

mkdir -p /chroot-jail-root/usr/bin && cp /usr/bin/bash /chroot-jail-root/usr/bin/bash

When you try to chroot into this directory you will see an error saying that bin/bash is not found. In reality the binary exists but required libraries are not yet part of the chroot environment.

ldd does the job of printing the dependencies:

  • Archlinux:
$ ldd /usr/bin/bash
	linux-vdso.so.1 (0x00007ffeeddfc000)
	libreadline.so.8 => /usr/lib/libreadline.so.8 (0x00007f806dfb9000)
	libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f806dfb2000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f806dde5000)
	libncursesw.so.6 => /usr/lib/libncursesw.so.6 (0x00007f806dd74000)
	/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f806e118000)
  • Debian
$ ldd /usr/bin/bash
	linux-vdso.so.1 (0x00007ffc6cfa4000)
	libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f864f0f3000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f864f0ee000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f864ef2d000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f864f250000)

The linux-vdso.so.1 is virtual so you can ignore this dependency.

So we create the directory for the library and copy the required shared object files into the newly created directory:

mkdir -p /chroot-jail-root/usr/lib
ln -rs /chroot-jail-root/usr/lib /chroot-jail-root/lib
ln -rs /chroot-jail-root/usr/lib /chroot-jail-root/lib64
cp /usr/lib/libreadline.so.8 /usr/lib/libdl.so.2 /usr/lib/libc.so.6 /usr/lib/libncursesw.so.6 /usr/lib64/ld-linux-x86-64.so.2 /chroot-jail-root/usr/lib/

If you did everything correctly chroot /chroot-jail-root/ /usr/bin/bash should work now.

Step 1.2 - Provide functionality of binaries

As the chroot command works now, we can provide some basic configuration and files which will be most likely required.

Copy minimal set of configuration files:

mkdir -p /chroot-jail-root/etc /chroot-jail-root/usr/share
cp /etc/{group,passwd,shadow,hosts} etc/
cp -r /usr/share/terminfo /chroot-jail-root/usr/share/

Other files that might be desired:

  • /etc/bash.bashrc
  • /etc/inputrc

Provide the special files in directories in /dev:

mkdir /chroot-jail-root/dev
mknod /chroot-jail-root/dev/null c 1 3
mknod /chroot-jail-root/dev/zero c 1 5
mknod /chroot-jail-root/dev/tty c 5 0
mknod /chroot-jail-root/dev/random c 1 8
mknod /chroot-jail-root/dev/urandom c 1 9
chmod 0666 /chroot-jail-root/dev/{null,tty,zero}
chown root:tty /chroot-jail-root/dev/tty

In case you want to translate the user and group ids into readable strings you will need to setup the NSS by copying the following files into the chroot environment:

  • /etc/nsswitch.conf
  • libnss_systemd.so
  • libnss_files.so
  • libcrypt.so

Continue copying desired binaries and libraries.

You can copy ldd into the chroot to check binaries inside the chroot environment if all required shared object files are present.

Tip: Play around with whoami and strace (look out for openat() calls resulting in ENOENT) to identify the required files.

Step 1.3 - Optional extensions to the chroot environment

Here are some ideas you could apply to the chroot environment, which won't be described within this tutorial but might give you a starting point for internet research:

  • Maintain files within chroot environment by package manager
    • archlinux: pacman --dbpath <db_path> --cachedir <cache_dir> --config <config_file> --root <chroot root directory> where root is /chroot-jail-root/ and all other files and directories are located outside of the chroot directory

Step 2 - Create user

Create the user that shall jailed into the chroot environment.

The user name used in this tutorial will be called prisoner and use the bash as login shell.

Move or create the home directory of the prisoner user into the chroot environment.

mkdir -p /chroot-jail-root/home
useradd --base-dir /chroot-jail-root/home --create-home --shell /usr/bin/bash prisoner

Copy the changed /etc/passwd, /etc/shadow, /etc/group into the chroot environment.

Step 3 - Configure SSH to chroot

Edit the configuration /etc/ssh/sshd_config as required to jail a user, group, host, local address, local port, address.

For more details see man sshd_config.

Match User prisoner
    ChrootDirectory /chroot-jail-root
    PasswordAuthentication no

To apply the changes restart the sshd daemon or trigger a reload of the configuration.

systemctl reload sshd.service

Step 4 - Configure SSH login (Optional)

We want to allow the prisoner user to login with a SSH key, as SSH employs a strict check of the access level to ~/.ssh directory and authorized_keys file, make sure to set comply with the rules (.ssh owned by the user and authorized_keys file only readable (and writable) for the user).

su prisoner
mkdir -p ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit

Copy the desired public keys into the authorized_keys file (absolute path is /chroot-jail-root/home/prisoner/.ssh/authorized_keys).

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue
Try Hetzner Cloud

Get €20/$20 free credit!

Valid until: 31 December 2025 Valid for: 3 months and only for new customers
Get started
Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more