Skip to content

Instantly share code, notes, and snippets.

@andrew-azarov
Forked from hiway/README.md
Created February 12, 2022 20:42
Show Gist options
  • Save andrew-azarov/dfe38e17ab3becb8f5fd247f8f41a27f to your computer and use it in GitHub Desktop.
Save andrew-azarov/dfe38e17ab3becb8f5fd247f8f41a27f to your computer and use it in GitHub Desktop.
Creating a single process FreeBSD (12.1) Jail

How to jail a single process web server on FreeBSD 12.1

You may have found many great resources on how to set up jails on latest FreeBSD, however there is scant information on how to go about creating a barebones jail with nothing but the one process that you want to isolate.

I was curious if I could contain a statically compiled web server that I wrote while learning Rust all by itself in a jail instead of having a full userland.

The benefits are:

  • Storage space requirement is trivial: 5MB
  • No need to update the jail separately since there is only one additional binary to daemonize the web app
  • Updating the web app is as simple as stopping the jail, replacing the binary and restarting, with a shell script on the host, that's fast.
  • If an intruder does manage to break in, there is no shell, utility programs or interpreters to leverage

Pre-requisites

  • Working FreeBSD 12.1 machine (this should work on older versions, but I have not tested)
  • Working internet connection to download a package (daemonize)
  • Static-linked binary web app (with Rust, use cargo build --release)
  • A bit of patience

Setup the Jail

First, create directories for the jail.

  • mkdir -p /usr/local/jail/www/{app,dev,lib,libexec,var}
  • mkdir -p /usr/local/jail/www/var/{log,run}

This will create the following tree structure:

[/usr/local/jail/www]# tree
.
├── app
├── dev
├── lib
├── libexec
└── var
    ├── log
    └── run

6 directories, 0 files

Now copy a few required binaries to the jail:

  • cp /libexec/ld-elf.so.1 /usr/local/jail/www/libexec/
  • cp /lib/{libc.so.7,libgcc_s.so.1,libm.so.5,libthr.so.3} /usr/local/jail/www/lib/

The directory tree should look like this:

[/usr/local/jail/www]# tree
.
├── app
├── dev
├── lib
│   ├── libc.so.7
│   ├── libgcc_s.so.1
│   ├── libm.so.5
│   └── libthr.so.3
├── libexec
│   └── ld-elf.so.1
└── var
    ├── log
    └── run

7 directories, 5 files

Install the package daemonize on host:

pkg install daemonize

Copy the daemonize binary to jail:

cp /usr/local/bin/daemonize /usr/local/jail/www/app/

Now copy your static-linked web app to jail. Here I'm copying the Rust web app created using Rocket.rs and compiled for release (cargo build --release)

cp /home/hiway/source/webapp/target/release/webapp /usr/local/jail/www/app/

The directory tree should look like this now:

[/usr/local/jail/www]# tree
.
├── app
│   ├── daemonize
│   └── webapp
├── dev
├── lib
│   ├── libc.so.7
│   ├── libgcc_s.so.1
│   ├── libm.so.5
│   └── libthr.so.3
├── libexec
│   └── ld-elf.so.1
└── var
    ├── log
    └── run

Next, we will set up jails service.

Edit or create /etc/jail.conf using your preferred text editor and append the following to it: Remember to review the values such as ip4.addr and replace with appropriate values for the interface, ip address and subnet.

www {
  host.hostname = "www";
  ip4.addr = "wlan0|192.168.0.99/24";
  path = "/usr/local/jail/www";
  mount.devfs;
  exec.start = "/app/daemonize -v -a \
                -o /var/log/www.stdout \
                -e /var/log/www.stderr \
                -p /var/run/www.pid /app/webapp";
  exec.stop = "";
}

Enable jail service:

sysrc jail_enable=YES

And finally, start the jail:

service jail start www

Visit http://192.168.0.99:8000/ from your browser and verify that it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment