FreeBSD jails configuration
Contents
Set up ezjail
Follow this doc:
clone lo0
to lo1
in /etc/rc.conf
:
cloned_interfaces="lo1"
To create it without reboot: service netif cloneup
.
Install ezjail
cd /usr/ports/sysutils/ezjail & make install clean
Enable ezjail
in rc.conf
: ezjail_enable="YES"
Start ezjail
: service ezjail start
.
To setup the base environment: ezjail-admin install -p
.
Copy host's resolv.conf
to jail's template so each newly created jail
is able to resolve domain names:
host> cp /etc/resolv.conf /usr/jails/newjail/etc/
Networking
Conventional way
Each jail must be asigned an IP. Traditionally in ezjail
, this is done
as part of jail creation:
ezjail-admin create dnsjail 'lo1|127.0.1.1,em0|192.168.1.50'
This would assign dnsjail
a private IP 127.0.1.1
on lo1, and an aliased IP
192.168.1.50
. The latter is an alias IP the host OS creates. You can see
it with ifconfig em0
in the host. Also the host is accessible via this IP
in its LAN. For more information about IP aliasing, see virtual host.
Then in the jail, edit hosts
to change 127.0.0.1
to 127.0.1.1
and add
the jail's hostname to each entry. This is essential for it to access
internet.
But this is hard to manage, each network-talking jail needs an IP and you need to configure router for each of these IPs. Rather, it would be good if the jails can do networking through host's IP address. That's what the next section is about.
Networking through host's IP
Inspired by this post. It's done through NAT. You still need a pool of IPs but they don't need to be aliases to host's IP.
In /etc/rc.conf
, add:
cloned_interfaces="lo1"
ipv4_addrs_lo1="192.168.60.1-9/29"
Note the range 192.168.60.1 ~ 192.168.60.9
. I previously used 192.168.0.1-9
and I
lost network connection to my host.
Now restart netif
: host> service netif restart
. And you should see the newly created
IPs.
em0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=4219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC,VLAN_HWTSO>
ether ...
inet 192.168.0.7 netmask 0xffffff00 broadcast 192.168.0.255
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
media: Ethernet autoselect (100baseTX <full-duplex>)
status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
inet 127.0.0.1 netmask 0xff000000
nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
groups: lo
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
inet 192.168.60.1 netmask 0xfffffff8
inet 192.168.60.2 netmask 0xffffffff
inet 192.168.60.3 netmask 0xffffffff
inet 192.168.60.4 netmask 0xffffffff
inet 192.168.60.5 netmask 0xffffffff
inet 192.168.60.6 netmask 0xffffffff
inet 192.168.60.7 netmask 0xffffffff
inet 192.168.60.8 netmask 0xffffffff
inet 192.168.60.9 netmask 0xffffffff
nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
groups: lo
Now we use pf
to map traffics to and from jails.
Enable pf
by adding to rc.conf
: pf_enable="YES"
. Edit /etc/pf.conf
:
# Public IP address
IP_PUB="<host's public IP>"
# Packet normalization
scrub in all
# Allow outbound connections from within the jails
nat on em0 from lo1:network to any -> (em0)
# webserver jail at 192.168.60.2
rdr on em0 proto tcp from any to $IP_PUB port 443 -> 192.168.60.2
rdr on em0 proto tcp from any to $IP_PUB port 80 -> 192.168.60.2
# .. or map jail's host's 80 to jail's 8080:
# rdr on em0 proto tcp from any to $IP_PUB port 80 -> 192.168.60.2 port 8080
# mailserver jail at 192.168.60.3
rdr on em0 proto tcp from any to $IP_PUB port 25 -> 192.168.60.3
rdr on em0 proto tcp from any to $IP_PUB port 587 -> 192.168.60.3
rdr on em0 proto tcp from any to $IP_PUB port 143 -> 192.168.60.3
rdr on em0 proto tcp from any to $IP_PUB port 993 -> 192.168.60.3
Start pf
: host> service pf start
Now creating a jail is simply:
ezjail-admin create <jail_name> <IP>
where IP
is one of those of lo1
's newly created, e.g., 192.168.60.2
.
We can set up another interface lo2
but without configuring NAT for its network, in that case
the jail is restricted to LAN access only:
cloned_interfaces="lo1 lo2"
ipv4_addrs_lo1="192.168.60.1-9/29" # Set up NAT for them
ipv4_addrs_lo2="192.168.70.1-9/29" # Don't set up NAT for them
I observed start of jail with LAN-only access is slower, maybe due to services requiring internet timed out during start.
Jail accessing file system outside of jail
This can be done by nullfs_mount
. Basically by mounting a part of the host file system
under the jail's root:
mkdir /usr/jails/<jail_name>/data
mount -t nullfs -o ro /data /usr/jails/<jail_name>/data
Alternatively, add this to the jail-specific fstab
at: /etc/fstab.<jail_name>
:
/data /usr/jails/<jail_name>/data nullfs ro
However there's a [bug I'm currently investigating][nullfs_issue], where the mount yields inconsistent subfolders.
Working with jails:
- List:
jls [-v]
- Start/stop:
ezjail-admin <start|stop|restart> <jail_name>
- delete:
ezjail-admin delete [-w] <jail_name>
ezjail
's per-jail configuration is in directory/usr/local/etc/ezjail
ezjail
's per-jail root is in/usr/jails/<jail_name>
directory. Here you can modify jail's settings that's created at creation, e.g., the IP.- In jails you can't use
ping
to test network connection, instead, usetelnet google.com 80
. - Root of a jail is at
/usr/jails/<jail_name>
- Jail-specific
fstab
are at/etc/fstab.<jail_name>
Accessing mounted file systems from inside jail
Host file system can be mounted to jail by modifying /etc/fstab.<jail_name>
.
Inside the jail, the mounted file system has the same ACL as in the host. But
the owner/group are shown as IDs. If a user inside jail (e.g., www
) wants to
access the file system, we must first create a user/group inside jail with the
corresponding owner/group ID. And give the target jail user the corresponding
ACL inside the jail. Example:
# /tmp/foo/ has 333:8000
jail> pw groupadd foo_group -g 8000 # create foo_group with ID 8000 inside jail
jail> pw groupmod www -m foo_group # add jail user `www` to foo_group
References
Networking troubleshooting
Routing rable
host> netstat -r
Routing tables
Internet:
Destination Gateway Flags Netif Expire
default 192.168.0.1 UGS em0
hostname-bsd link#2 UH lo0
192.168.0.0/24 link#1 U em0
192.168.0.7 link#1 UHS lo0
192.168.60.1 link#3 UH lo1
192.168.60.2 link#3 UH lo1
192.168.60.3 link#3 UH lo1
192.168.60.4 link#3 UH lo1
192.168.60.5 link#3 UH lo1
192.168.60.6 link#3 UH lo1
192.168.60.7 link#3 UH lo1
192.168.60.8 link#3 UH lo1
192.168.60.9 link#3 UH lo1
Internet6:
Destination Gateway Flags Netif Expire
::/96 hostname-bsd UGRS lo0
hostname-bsd link#2 UH lo0
::ffff:0.0.0.0/96 hostname-bsd UGRS lo0
fe80::/10 hostname-bsd UGRS lo0
fe80::%lo0/64 link#2 U lo0
fe80::1%lo0 link#2 UHS lo0
ff02::/16 hostname-bsd UGRS lo0