FreeBSD + Jail. Short Notes.

The short notes with step by step instructions how to configure FreeBSD and setup jails with public network access from newly created container.

Mike Gavrilov
3 min readAug 3, 2022

FreeBSD was installed on Raspberry PI 4 with 8GB of Ram. I am using it like a board for CI/CD and QA machine for testing pet projects. In this article I will configure jail container for RabbitMQ.

First of all need enable jail feature on rc.conf

# sysrc jail_enable=”YES”

I prefer install separate user land for the rabbit jail.

# bsdinstall jail /home/rabbitmq_jail

After several minutes the user land will be installed into the folder /home/rabbitmq_jail

Networking is a heaviest part in a jail. For communication between jails, host system and outside world FreeBSD offer several powerful instruments:

  • tun/tap interfaces
  • physical Ethernet interfaces
  • epair. It is a feature where two interfaces was created, A and B, and one of them moved to the jail. It’s look like a patch cord where side B inserted to the Ethernet card and side B inserted to the switch
  • SR-IOV
  • Virtual-Interface (driver specific)
  • VLAN

I chose epair feature for my setup. bridge0 should be created for making communication between different jail and host system.

Initial configuration for Host system Network. (Restart host system needed)

  • create bridge0
  • configure IP address for bridge0. This IP will be default gateway for all jails

sysrc cloned_interfaces=”bridge0"
sysrc ifconfig_bridge0=”inet 192.168.0.254/24 addm genet0 up”

In the next step /etc/jail.conf should be configured.

allow.nomount;

# need enable this option for made ping and traceroute workable
allow.raw_sockets;
mount.devfs;

exec.clean;

# Start command
exec.start = “/bin/sh /etc/rc”;

# Stop command
exec.stop = “/bin/sh /etc/rc.shutdown”;

rabbitmq {
host.hostname = rabbitmq;

# enable virtual network infrastructure
vnet = new;

# epait interface for the jail
vnet.interface = “epair0b”;

# create epair infrastructure for the jail on runtime
exec.prestart = “ifconfig epair0 create up”;
exec.prestart += “ifconfig epair0a up”;

# add one side of patch cord to the bridge0
exec.prestart += “ifconfig bridge0 addm epair0a”;

# configure IP address for jail network interface
exec.start += “ifconfig epair0b inet 192.168.0.2/24”;

# add default route for the jail
exec.start += “route add default 192.168.0.254”;

# destroy epair infrastructure before jail shutdown
exec.poststop = “ifconfig epair0b -vnet rabbitmq”;
exec.poststop += “ifconfig bridge0 deletem epair0a”;
exec.poststop += “sleep 2”;
exec.poststop += “ifconfig epair0a destroy”;

# Path to the jail
path = “/home/rabbitmq_jail”;
persist;
}

Initial jail configuration was complete.

Start all configured jails

# service jail start

If everything was Ok, jail will be up and traffic will go from jail to host machine.

# jls # list of jails

# jexec 2 ping -c 192.168.0.254

Configure jail access to the outside world.

Here we need nat for masquerading traffic between jail network and public network. pf or ipfw can do what we need.

Example of the /etc/pf.conf file.

# sysrc pf_enable=”YES”

ext_if=”genet0"

# jail network
jailnet=”192.168.0.0/24"

# nat rule for masquerading traffic

nat pass on $ext_if inet from $jailnet to any -> ($ext_if)

# port forwarding rule. Forward port from public interface to the specific jail IP
rdr pass on $ext_if proto tcp from any to 192.168.88.203 port { 15672 } -> 192.168.0.2 port 15672

set skip on { lo0, bridge0 }
pass inet proto icmp
pass out all keep state

# Don’t forget about SSH to the host machine :)
pass in inet proto tcp from any to any port ssh flags S/SA modulate state

Start the pf.

# service pf start

Now you can ping whatever you want from the outside of the world.

# jexec 2 ping -c 4 8.8.8.8

Don’t forget restart the whole system. Everything should work as needed.

Enjoy.

Useful links

P.S. Hope this article will save your time.

Enjoy.

--

--