Chroot-ed ssh shell in ramdisk on OpenBSD 6.8
Memory File System (a.k.a. "ramdisk")
OpenBSD provides the wonderful option to mount a memory file system, called "mfs file system", with the -P switch.
Think of this -P switch as "prototype". The option -P has to be followed by either a directorypath ("file") or a block device. When -P is followed by a directorypath, the mfs file system will be created with the contents of that path.
If followed by a block device, the mfs file system will be created with the contents of the FFS file system contained on the device.
See the example below how to add a mfs file system to
The contents are copied into the mfs file system at the time of creation. So, any changes of the prototype directory will only be reflected in the mfs file system after it has been umounted and mounted again.
See man mount_mfs.
When the chrooted environment is small enough, it can easily run in ram. So we can create a script that populates a directory, and mount a mfs file system filled with the contents of that directory.
We start with adding a group and some users. By making the users member of the group, we can tell sshd that they belong to the chroot-users, and we can build a script based on the fact that these users are member of the group.
We use the group "chroot" for this.
The users must be member of this group and no home directory in /etc/passwd.
useradd -g chroot [username]
Replace [username] with the username of the user.
Building the chroot environment
First, think about what utilities are necessary for the user. The less the better, in this case.
We need some basic infrastructure (some directories, some device-files in /dev, /etc/resolv.conf, et cetera) and some utilities (programs to run). To make this easy adaptable it is best to do this with a script.
In the example build script, there are some utilities from /bin (like "date") and from /usr/bin ("ssh") that will be put into the chroot. These are just examples, use what you need.
Every utility takes up space, and perhaps also one or more extra library files.
The script builds the chroot environment in
I use several mfs file system mounts, and for each I have a directory in /proto to populate them with.
The script doesn't delete user home directories, so it can be run several times, rebuilding the chroot environment, without impact for the users.
The script finds the users that are member of the group 'chroot' and creates a home-directory for these users. The script touches the authorized_keys file for each user in it's $HOME/.ssh directory, but the actual public key of the user have to be copied into this file. This can be done after the script has run.
Mounting the mfs file system
When the /proto/chroot directory is complete, we can mount the mfs file system.
Add the mfs file system to your /etc/fstab;
swap /chroot mfs ro,nosuid,-P=/proto/chroot,-s=48000 0 0
In this example the mfs filesytem will be mounted read only. Depending on your needs, you could also mount it read-write, sshd will check that the directory tree is owned by root and can not be over written by other users.
The -s option sets the size of the mfs filesystem. This is the maximum size, stating to how much you can fill it up.
If you make this bigger, there will be less memory left for your system. The required size of the mfs file system depends on the size of the actual chroot environment.
We use key authentication to get access to the chroot.
The chrooted ssh shell is made easy by the features sshd offers. We only need to add some chroot configuration to sshd.
Add these lines to sshd_config:
Match Group chroot ChrootDirectory /chroot AuthorizedKeysFile /chroot/home/%u/.ssh/authorized_keys PasswordAuthentication no
The example build script mentioned above is based on
the work on arnor.org, see