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 called em0bridge or 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.

Alias/Shared Interface

  • For classic/standard jails that use an IP that is accessible within your local subnet (alias mode) Bastille will add the IP to the specified interface as an alias.

  • This mode is best used if you have one interface, and don’t want the jail to have its own MAC address. The jail IP will simply be added to the specified interface as an additional IP, and will inherit the rest of the interface.

  • Note that this mode does not function as the two VNET modes above, but still allows the jail to have an IP address inside your local network.

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 setup command and will attempt to use bastille0 (which is created using the setup command) as its interface. If you have not run bastille setup and 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 inherit or ip_hostname, bastille will simply set ip4 to inherit inside 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 set ip4 to ip_hostname inside 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, -B or -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 rdr command.

  • 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 rdr command. Traffic will pass in and out just as in a VNET jail.

  • Setting the IP to inherit will make the jail inherit the entire host network stack.

  • Setting the IP to ip_hostname will 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_jailname and e0b_jailname are the default epair interfaces for every jail. The e0a side is on the host, while the e0b is in the jail. Due to the above mentioned limitations, Bastille will name any epairs whose jail names exceed the maximum length, to e0b_bastilleX and e0b_bastilleX with the X starting at 1 and incrementing by 1 for each new epair. So, mylongjailname will be e0a_bastille2 and e0b_bastille2.

Netgraph and Proxmox VE

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.

Shared Interface on IPV6 network (vultr.com)

Some ISP’s, such as Vultr, give you a single ipv4 address, and a large block of ipv6 addresses. You can then assign a unique ipv6 address to each Bastille Container.

On a virtual machine such as vultr.com the virtual interface may be vtnet0. So we issue the command:

bastille create alcatraz 13.2-RELEASE 2001:19f0:6c01:114c::100 vtnet0

We could also write the ipv6 address as 2001:19f0:6c01:114c:0:100

The tricky part are the ipv6 addresses. IPV6 is a string of 8 4 digit hexadecimal characters. At vultr they said:

Your server was assigned the following six section subnet:

2001:19f0:6c01:114c::/64

The vultr ipv6 subnet calculator is helpful in making sense of that ipv6 address.

We could have also written that IPV6 address as 2001:19f0:6c01:114c:0:0

Where the /64 basicaly means that the first 64 bits of the address (4x4 character hexadecimal) values define the network, and the remaining characters, we can assign as we want to the Bastille Container. In the actual bastille create command given above, it was defined to be 100. But we also have to tell the host operating system that we are now using this address. This is done on freebsd with the following command

ifconfig_vtnet0_alias0="inet6 2001:19f0:6c01:114c::100 prefixlen 64"

At that point your container can talk to the world, and the world can ping your container. Of course when you reboot the machine, that command will be forgotten. To make it permanent, prefix the same command with sysrc

Just remember you cannot ping out from the container. Instead, install and use wget/curl/fetch to test the connectivity.

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|--vnet options 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|--vlan when 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_if variable 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.