FreeBSD jails fixed address
In illumos, zones (which are based on FreeBSD jails) are configured through ZONECFG(1M). On which you could specify an option called allowed-address, this option gives a zone a fixed IP address that users cannot change.
In FreeBSD, there is no such JAIL(2) property, but we could create nested jails with which could accomplish the same. To do this, we need to create a parent jail that will use VNET(9), and the children will just inherit its ip4/ip6 configuration. For creating interfaces on jails I'm using the jng script which uses NETGRAPH(3) to generate the interfaces inside the jail which are not visible to the host, that feature does not pollute the host which multiple interfaces.
Creating the parent and child jails
First copy the jng script from /usr/share/examples/jails/jng to /usr/local/sbin Then create the jails and use vnet for networking. You will need to load the ng_ether kernel module for this to work.
# kldload ng_ether
Now for example create the following I used the following /etc/jail.conf
demojail { vnet=new; vnet.interface = "ng0_eth0"; path=/jails/outer; persist; exec.system_user = "root"; exec.jail_user = "root"; exec.prestart += "jng bridge eth0 vtnet0"; exec.start += "/sbin/ifconfig ng0_eth0 192.168.1.233 netmask 255.255.255.0 up"; exec.start += "/sbin/ifconfig lo0 127.0.0.1 up"; exec.start += "/sbin/route add default 192.168.1.1"; exec.poststop += "jng shutdown demojail"; allow.raw_sockets; allow.set_hostname; devfs_ruleset="11"; mount.devfs; } demojail.j0 { host.hostname = "demojail"; # hostname path = "/jails/demojail"; # root directory ip4 = inherit; ip6 = inherit; allow.raw_sockets; devfs_ruleset="0"; exec.start += "/bin/sh /etc/rc"; exec.stop = "/bin/sh /etc/rc.shutdown"; persist; }
/etc/devfs.rules
[devfsrules_jail=11] add include $devfsrules_hide_all add include $devfsrules_unhide_basic add include $devfsrules_unhide_login add path 'bpf*' unhide
the children.max option on jail.conf allows this jail to have at most 1 child jail. Then to enable the jail to be started at startup, type:
# sysrc jail_enable=YES
Now simply start the jails
# service jail start
then enter the jail, first get the jail id using jls, in my case the child jail id is 48.
neirac@fbsd-dev:~ $ sudo jexec 48 sh # ifconfig -a lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384 options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6> inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 inet 127.0.0.1 netmask 0xff000000 groups: lo nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> ng0_eth0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=28<VLAN_MTU,JUMBO_MTU> ether 0a:a0:8d:81:9f:d3 hwaddr 58:9c:fc:10:ff:bb inet 192.168.1.233 netmask 0xffffff00 broadcast 192.168.1.255 media: Ethernet autoselect (1000baseT <full-duplex>) status: active nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL> #
Trying to change the ip address of the jail errors out with
# ifconfig ng0_eth0 192.168.1.234 netmask 255.255.255.0 ifconfig: ioctl (SIOCDIFADDR): permission denied