FreeBSD Jails

Deploying jail

A jail is simply a chroot with strong isolation. So, if you want to create jail, you simply need to create an alternative root and starting a new jail in it.

Simple jail deployment from binaries

# create our alternative root path
JAILROOT="/path/to/my/jail"
mkdir -p "${JAILROOT}"
cd "${JAILROOT}"

# get distribution from freebsd repository
fetch http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/11.0-RELEASE/base.txz

# extract it in our alternative root
tar xJvf base.txz

# now we can launch our jail
jail -c name=simplejail path=${JAILROOT} 

# to check if jail is up and running we use jls
jls

# now we can enter in our new jail
jexec simplejail sh

Simple jail deployment from source

# create our alternative root path
JAILROOT="/path/to/my/jail"
mkdir -p "${JAILROOT}"

# we need to build binaries from source...
cd /usr/src
make buildworld

# ... and install it in our alternative path
make installworld DESTDIR=${JAILROOT}

# now we can launch our jail
jail -c name=simplejail path=${JAILROOT} 

# to check if jail is up and running we use jls
jls

# now we can enter in our new jail
jexec simplejail sh

Simple thin jail deployment

Thin jail is simply a jail with shared read-only alternative root mounted with nullfs.

Initializing our environment

# making our shared alternative root
SHARED_ROOT=/path/to/your/shared/root
mkdir -p "${SHARED_ROOT}"

# making our jail root
JAIL_ROOT=/path/to/your/jail/root
mkdir -p "${JAIL_ROOT}"

downloading sources

# to initialize our shared root, we can use 
# all method described above. Here, we will use
# simple binary initialization from official
# repository
cd "${SHARED_ROOT}"

# get distribution from freebsd repository
fetch http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/11.0-RELEASE/base.txz

# extract it in our alternative root
tar xJvf base.txz

Initializing our thin jail

# now we need to initialize our dedicated
# jail root
cd "${JAIL_ROOT}"
mkdir base

# we make symbolic link pointing to 
# files stored in read-only directory
for link in bin boot lib libexec rescue sbin
do
  ln -s ${link} /base/${link}
done

# we do same thing with directory in /usr
for link in bin include lib lib32 libdata libexec sbin share
do
  ln -s usr/${link} /base/usr/${link}
done

# now we are ready to start our jail!
jail -c name=thinjail path="${JAIL_ROOT}" \
        mount="${SHARED_ROOT} ${JAIL_ROOT} nullfs ro 0 0"

# check if our thin jail is ok...
jls

# we can now grab in it!
jexec thinjail sh

Networking and Jails

FreeBSD jails can have fine grained networking configuration. By default, every jails use the same network configuration than host.

Removing network support

jail -c name="nonetwork" path="/path/to/your/jail" ip4=disable ip6=disable

Allowing only IPv4 networking

jail -c name="onlyipv4" path="/path/to/your/jail" ip4=inherit ip6=disable

Allowing only IPv6 networking

jail -c name="onlyipv6" path="/path/to/your/jail" ip4=disable ip6=inherit

Dedicated network stack (VNET)

VNET is recent feature allowing jail to have its own network stack. Doing this configuration need to add routing feature to the host. VIMAGE option is required in host kernel.

# starting our own jail with vnet
jail -c name="vnetjail" path="/path/to/your/jail" vnet=new

# we need a bridge...
ifconfig bridge0 create

# a pair of ethernet interface...
ifconfig epair0 create

# and interconnecting epair, jail and bridge
ifconfig epair0b vnet vnetjail
ifconfig bridge0 add epair0a
ifconfig bridge0 add ${your_external_interface}