Skip to content

Instantly share code, notes, and snippets.

@biochemie
Forked from hiway/README.md
Created April 23, 2024 13:12
Show Gist options
  • Save biochemie/f7b6a297a0dcb3fb39b2584ff8786aa2 to your computer and use it in GitHub Desktop.
Save biochemie/f7b6a297a0dcb3fb39b2584ff8786aa2 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