Networking
Bastille is very flexible with its networking options. Below are the supported networking modes, how they work, and some tips on where you might want to use each one.
Bastille also supports VLANs to some extent. See the VLAN section below.
Jail Network Modes
Bastille tries to be flexible in the different network modes it supports. Below is a breakdown of each network mode, what each one does, as well as some suggestions as to where you might want to use each one.
VNET
For VNET jails (
-V) Bastille will create a bridge interface and attach your jail to it. It will be calledem0bridgeor whatever your interface is called. This will be used for the host/jail epairs. Bastille will create/destroy these epairs as the jail is started/stopped.This mode works best if you want your jail to be in your local network, acting as a physical device with its own MAC address and IP.
Bridged VNET
For bridged VNET jails (
-B) you must manually create a bridge interface to attach your jail to. Bastille will then create and attach the host/jail epairs to this interface when the jail starts, and remove themwhen it stops.This mode is identical to VNET above, with one exception. The interface it is attached to is a manually created bridge, as opposed to a regular interface that is used with VNET above.
NAT/Loopback Interface
For classic/standard jails that use an IP not reachable in your local subnet, Bastille will add the IP to the specified interface as an alias, and additionally, add it to the pf firewall table (if available) to allow the jail outbound access. If you do not specify an interface, Bastille will assume you have run the
bastille setupcommand and will attempt to usebastille0(which is created using the setup command) as its interface. If you have not runbastille setupand do not specify an interface, Bastille will error.This mode works best if you want your jail to be in its own private network. Bastille will dynamically add each jail IP to the firewall table to ensure network connectivity.
This mode is similar to the Alias/Shared Interface mode, except that it is not limited to IP addresses within your local network.
Inherit
For classic/standard jails that are set to
inheritorip_hostname, bastille will simply setip4toinheritinside the jail config. The jail will then function according the jail(8) documentation.This mode makes the jail inherit the entire network stack of the host.
IP Hostname
For classic/standard jails that are set to
ip_hostname, bastille will simply setip4toip_hostnameinside the jail config. The jail will then function according the jail(8) documentation.This is an advanced parameter. See the official FreeBSD jail(8) documentation for details.
You cannot use -V|--vnet with any interface that is already a member of
another bridge. For example, if you create a bridge, and assign vtnet0 as a
member, you will not be able to use vtnet0 with -V|--vnet.
IP Address Options
IPv4 Network
Bastille includes a number of IP options for IPv4 networking.
bastille create alcatraz 13.2-RELEASE 192.168.1.50/24 vtnet0
The IP address specified above can be any of the following options.
An IP in your local subnet should be chosen if you create your jail using
-V,-Bor-P(VNET jail).Note: It is mandatory to add the subnet mask (/24 or whaterver your subnet is) to the IP for any types of VNET jail. See below…
DHCP, SYNCDHCP, or 0.0.0.0 will configure your jail to use DHCP to obtain an address from your router. This should only be used with VNET jails.
Any IP address inside the RFC1918 range if you are not using a VNET jail. Bastille will automatically add this IP to the firewall table to allow outbound access. It you want traffic to be forwarded into the jail, you can use the
bastille rdrcommand.Any IP in your local subnet without any VNET options will add the IP as an alias to the selected interface, which will simply end up sharing the interface. If the IP is in your local subnet, you will not need the
bastille rdrcommand. Traffic will pass in and out just as in a VNET jail.Setting the IP to
inheritwill make the jail inherit the entire host network stack.Setting the IP to
ip_hostnamewill add all the IPs that the hostname resolves to. This is an advanced option and should only be used if you know what you are doing.
Standard (non-VNET) jails support specifying an IP without the subnet (/24 or whatever yours is), but for VNET jails it is mandatory. If none is supplied, it will default to /24. This is because FreeBSD does not support adding an IP to an interface without a subnet.
IPv6 Network
Bastille also supports IPv6. Instead of an IPv4 address, you can specify an IPv6 address when creating a jail to use IPv6.
bastille create alcatraz 13.2-RELEASE 2001:19f0:6c01:114c:0:100/64 vtnet0
The IP address specified above can be any of the following options.
A valid IPv6 address including the subnet. If not subnet is given, it will defalut to /64.
SLAAC will configure your jail to use router advertisement to obtain an address from your router. This should only be used with VNET jails.
Dual Stack Network
It is also possible to use both IPv4 and IPv6 by quoting an IPv4 and IPv6 addresses together as seen in the following examples.
bastille create alcatraz 14.3-RELEASE "192.168.1.50/24 2001:19f0:6c01:114c:0:100/64" vtnet0
bastille create alcatraz 14.3-RELEASE "DHCP SLAAC" vtnet0
Note: For the inherit and ip_hostname options, you can also specify
-D|--dual to use both IPv4 and IPv6 inside the jail. Otherwise, for dual
stack networking, simply supply both IPv4 and IPv6 addresses as seen above.
Networking Limitations
VNET Jail Interface Names
FreeBSD has certain limitations when it comes to interface names. One of these is that interface names cannot be longer than 15 characters. Because of this, Bastille uses a generic name for any epairs created whose corresponding jail name exceeds the maximum length. See below…
e0a_jailnameande0b_jailnameare the default epair interfaces for every jail. Thee0aside is on the host, while thee0bis in the jail. Due to the above mentioned limitations, Bastille will name any epairs whose jail names exceed the maximum length, toe0b_bastilleXande0b_bastilleXwith theXstarting at1and incrementing by 1 for each new epair. So,mylongjailnamewill bee0a_bastille2ande0b_bastille2.
Netgraph and Proxmox VE
When running a FreeBSD VM on Proxmox VE, you might encounter crashes when using Netraph. This bug is being tracked at https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=238326
One workaround is to add the following line to the
jail.conffile of the affected jail(s).
exec.prestop += "jng shutdown JAILNAME";
Network Scenarios
SOHO (Small Office/Home Office)
This scenario works best when you have just one computer, or a home or small office network that is separated from the rest of the internet by a router. So you are free to use private IP addresses.
In this environment, we can create the container, give it a unique private ip address within our local subnet, and attach its ip address to our primary interface.
bastille create alcatraz 13.2-RELEASE 192.168.1.50 em0
You may have to change em0
When the alcatraz container is started it will add 192.168.1.50 as an IP
alias to the em0 interface. It will then simply be another member of the
hosts network. Other networked systems (firewall permitting) should be able to
reach services at that address.
This method is the simplest. All you need to know is the name of your network interface and a free IP on your local network.
We can also run bastille setup shared to configure our primary interface as
a default interface for Bastille to use. Once we have run the command and chosen
our interface, it will not be necessary to specify an interface in our create
command.
bastille create alcatraz 13.2-RELEASE 192.168.1.50
This will automatically use the interface we selected during the setup command.
Note that we cannot use the shared option together with the loopback
option. Configuring one using the bastille setup command will disable the other.
VNET (Virtual Network)
(Added in 0.6.x) VNET is supported on FreeBSD 12+ only.
Virtual Network (VNET) creates a private network interface for a container. This includes a unique hardware address. This is required for VPN, DHCP, and similar containers.
To create a VNET based container use the -V|--vnet option, an IP/netmask and
external interface.
bastille create -V azkaban 13.2-RELEASE 192.168.1.50/24 em0
Bastille will automagically create the bridge interface and connect /
disconnect containers as they are started and stopped. A new interface will be
created on the host matching the pattern interface0bridge. In the example
here, em0bridge.
The em0 interface will be attached to the bridge along with the unique
container interfaces as they are started and stopped. These interface names
match the pattern eXb_bastilleX. Internally to the containers these
interfaces are presented as vnet0.
If you do not specify a subnet mask, you might have issues with jail to jail networking, especially VLAN to VLAN. We recommend always adding a subnet to VNET jail IPs when creating them to avoid these issues.
VNET also requires a custom devfs ruleset. Create the file as needed on the host system:
## /etc/devfs.rules (NOT .conf)
[bastille_vnet=13]
add include $devfsrules_hide_all
add include $devfsrules_unhide_basic
add include $devfsrules_unhide_login
add include $devfsrules_jail
add include $devfsrules_jail_vnet
add path 'bpf*' unhide
Lastly, you may want to consider these three sysctl values:
net.link.bridge.pfil_bridge=0
net.link.bridge.pfil_onlyip=0
net.link.bridge.pfil_member=0
Below is the definition of what these three parameters are used for and mean:
- net.link.bridge.pfil_onlyip Controls the handling of non-IP packets
which are not passed to pfil(9). Set to 1 to only allow IP packets to pass (subject to firewall rules), set to 0 to uncondi- tionally pass all non-IP Ethernet frames.
- net.link.bridge.pfil_member Set to 1 to enable filtering on the incom-
ing and outgoing member interfaces, set to 0 to disable it.
- net.link.bridge.pfil_bridge Set to 1 to enable filtering on the bridge
interface, set to 0 to disable it.
Bridged VNET (Virtual Network)
To create a VNET based container and attach it to an external, already existing
bridge, use the -B option, an IP/netmask and external bridge.
bastille create -B azkaban 13.2-RELEASE 192.168.1.50/24 bridge0
Bastille will automagically create the needed interface(s), attach it to the specified bridge and connect/disconnect containers as they are started and stopped. The bridge needs to be created/enabled before creating and starting the jail.
Below are the steps to creating a bridge for this purpose.
The first thing you have to do is to create a bridge interface on your system. This is done with the ifconfig command and will create a bridged interface named bridge0:
ifconfig bridge create
Then you need to add your system’s network interface to the bridge and bring it up (substitute your interface for em0).
ifconfig bridge0 addm em0 up
Optionally you can rename the interface if you wish to make it obvious that it is for bastille:
ifconfig bridge0 name bastille0bridge
To create a bridged container you use the -B option, an IP or DHCP, and the
bridge interface.
bastille create -B folsom 14.2-RELEASE DHCP bastille0bridge
All the epairs and networking other than the manually created bridge will be
created for you automagically. Now if you want this to persist after a reboot
then you need to add some lines to your /etc/rc.conf file. Add the
following lines, again, obviously change em0 to whatever your network interface
on your system is.
cloned_interfaces="bridge0"
ifconfig_bridge0_name="bastille0bridge"
ifconfig_bastille0bridge="addm vtnet0 up"
VLAN Configuration
Jail VLAN Tagging
Bastille supports VLANs to some extent when creating jails. When creating a jail,
use the --vlan ID options to specify a VLAN ID for your jail. This will set
the proper variables inside the jails rc.conf to add the jail to the specified
VLAN. The jail will then take care of tagging the traffic. Do not use -v|--vlan
if you have already configured the host interface to tag the traffic. See limitations
below.
When using this method, the interface being assigned must be a trunk interface. This means that it passes all traffic, leaving any VLAN tags as they are.
Host VLAN Tagging
Another method is to configure a host interface to tag the traffic. This way, the jail doesn’t have to worry about it.
You can only use -B|--bridge with host VLAN interfaces, due to the limitation
mentioned below. With this method we create the bridge interfaces in rc.conf
and configure them to tag the traffic by VLAD ID.
Below is an rc.conf snippet that was provided by a user who has such a
configuration.
# rename ethernet interfaces (optional)
ifconfig_igb1_name="eth1"
ifconfig_eth1_descr="vm/jail ethernet interface"
# setup vlans
vlans_eth1="10 20 30"
# setup bridges
cloned_interfaces="bridge10 bridge20 bridge30"
ifconfig_bridge10_name="eth1.10bridge"
ifconfig_bridge20_name="eth1.20bridge"
ifconfig_bridge30_name="eth1.30bridge"
ifconfig_eth1_10bridge="addm eth1.10 up"
ifconfig_eth1_20bridge="addm eth1.20 up"
ifconfig_eth1_30bridge="addm eth1.30 up"
# bring interfaces up
ifconfig_eth1="up"
ifconfig_eth1_10="up"
ifconfig_eth1_20="up"
ifconfig_eth1_30="up"
Notice that the interfaces are bridge interfaces, and can be used with -B|--bridge
without issue.
VLAN Limitations
You cannot use the
-V|--vnetoptions with interfaces that have dots (.) in the name, which is the standard way of naming a VLAN interface. This is due to the limitations of the JIB script that Bastille uses to manage VNET jails.Do not attempt to configure both the host and the jail to tag VLAN traffic. If you use the host method, do not use
-v|--vlanwhen creating the jail. Doing so will prevent the jail from having network access.
Tip: Don’t forget to set you gateway and nameserver is applicable
using -g|--gateway and -n|--nameserver.
Regarding Routes
Bastille will attempt to auto-detect the default route from the host system and
assign it to the VNET container. This auto-detection may not always be accurate
for your needs for the particular container. In this case you’ll need to add a
default route manually or define the preferred default route in the
bastille.conf.
bastille sysrc TARGET defaultrouter=aa.bb.cc.dd
bastille service TARGET routing restart
To define a default route / gateway for all VNET containers define the value in
bastille.conf:
bastille_network_gateway=aa.bb.cc.dd
This config change will apply the defined gateway to any new containers. Existing containers will need to be manually updated.
Public Network
In this section we describe how to network containers in a public network such as a cloud hosting provider who only provides you with a single ip address. (AWS, Digital Ocean, etc) (The exception is vultr.com, which does provide you with lots of IPV6 addresses and does a great job supporting FreeBSD!)
So if you only have a single IP address and if you want to create multiple containers and assign them all unique IP addresses, you’ll need to create a new network.
Netgraph
Bastille supports netgraph as an VNET management tool, thanks to the jng script. To enable netgraph, run bastille setup netgraph. This will load and persist the required kernel modules. Once netgraph is configured, any VNET jails you create will be managed with netgraph.
Note that you should only enable netgraph on a new system. Bastille is set up to use either netgraph or if_bridge as the VNET management, and uses if_bridge as the default, as it always has. The netgraph option is new, and should only be used with new systems.
This value is set with the bastille_network_vnet_type option inside the config file.
loopback (bastille0)
What we recommend is creating a cloned loopback interface (bastille0) and
assigning all the containers private (rfc1918) addresses on that interface. The
setup I develop on and use Bastille day-to-day uses the 10.0.0.0/8 address
range. I have the ability to use whatever address I want within that range
because I’ve created my own private network. The host system then acts as the
firewall, permitting and denying traffic as needed.
I find this setup the most flexible across all types of networks. It can be used in public and private networks just the same and it allows me to keep containers off the network until I allow access.
Having said all that here are instructions I used to configure the network with a private loopback interface and system firewall. The system firewall NATs traffic out of containers and can selectively redirect traffic into containers based on connection ports (ie; 80, 443, etc.)
To set up the loopback address automatically, we can simply run bastille setup.
This will configure the storage, pf firewall, and loopback addresses for us.
To set these up individually, we can run bastille setup storage,
bastille setup firewall, and bastille setup loopback respectively.
Alternatively, you can do it all manually, as shown below.
First, create the loopback interface:
ishmael ~ # sysrc cloned_interfaces+=lo1
ishmael ~ # sysrc ifconfig_lo1_name="bastille0"
ishmael ~ # service netif cloneup
Second, enable the firewall:
ishmael ~ # sysrc pf_enable="YES"
Create the firewall rules:
/etc/pf.conf
ext_if="vtnet0"
set block-policy return
scrub in on $ext_if all fragment reassemble
set skip on lo
table <jails> persist
nat on $ext_if from <jails> to any -> ($ext_if:0)
rdr-anchor "rdr/*"
block in all
pass out quick keep state
antispoof for $ext_if inet
pass in proto tcp from any to any port ssh flags S/SA modulate state
Make sure to change the
ext_ifvariable to match your host system
interface.
- Make sure to include the last line (port ssh) or you’ll end up locked out.
Note: if you have an existing firewall, the key lines for in/out traffic to containers are:
nat on $ext_if from <jails> to any -> ($ext_if:0)
The nat routes traffic from the loopback interface to the external
interface for outbound access.
rdr-anchor "rdr/*"
The rdr-anchor "rdr/*" enables dynamic rdr rules to be setup using the
bastille rdr command at runtime - eg.
bastille rdr TARGET tcp 2001 22 # Redirects tcp port 2001 on host to 22 on jail
bastille rdr TARGET udp 2053 53 # Same for udp
bastille rdr TARGET list # List dynamic rdr rules
bastille rdr TARGET clear # Clear dynamic rdr rules
Note that if you are redirecting ports where the host is also listening (eg. ssh) you should make sure that the host service is not listening on the cloned interface - eg. for ssh set sshd_flags in rc.conf
sshd_flags="-o ListenAddress=<host-address>"
Finally, start up the firewall:
ishmael ~ # service pf restart
At this point you’ll likely be disconnected from the host. Reconnect the ssh session and continue.
This step only needs to be done once in order to prepare the host.
Note that we cannot use the loopback option together with the shared
option. Configuring one using the bastille setup command will disable the other.
local_unbound
If you are running “local_unbound” on your server, you will probably have issues with DNS resolution.
To resolve this, add the following configuration to local_unbound:
server:
interface: 0.0.0.0
access-control: 192.168.0.0/16 allow
access-control: 10.17.90.0/24 allow
Also, change the nameserver to the servers IP instead of 127.0.0.1 inside /etc/rc.conf
Adjust the above “access-control” strings to fit your network.