Skip to content
Matt Churchyard edited this page Jun 25, 2018 · 10 revisions

Unfortunately, internal NAT configuration has been removed as of v1.2. As a shell script, we relied on configuring external systems such as pf and dnsmasq to provide NAT functions. Some users want to use other tools/firewalls, and many users found NAT broken due to existing pf or dnsmasq configuration they had in place. It has come to the point where it's arguably easier and less error-prone to manually configure NAT than to try and enable it via vm-bhyve.

Below are some basic instructions for setting up a NAT host with pf for use with vm-bhyve guests.

Host configuration

In this example I have chosen to use the 192.168.8.x network for my guests, with 192.168.8.1 as the gateway.

We need to enable gateway functionality, so that the host can relay packets between the public and NAT networks. We also need to turn on the pf service. This is done in /etc/rc.conf

gateway_enable="yes"
pf_enable="yes"

We can now create a NAT rule in /etc/pf.conf to match packets on our private network and perform NAT. Note that in this example, em0 is my public facing interface on the host.

nat on em0 from {192.168.8.0/24} to any -> (em0)

At this point you can restart the host, or start pf and enable forwarding using sysctl manually if preferred.

# sysctl net.inet.ip.forwarding=1
# service pf start

vm-bhyve

We now need to create a switch that we can attach the guests to. This switch should be assigned an IP address from our NAT range that can be used as the gateway in our guests. I've called this public, which is the default switch name used in all vm-bhyve examples, although you may want to use a name that's meaningful in your environment.

# vm switch add -a 192.168.8.1/24 public
# vm switch list
NAME    TYPE      IDENT  ADDRESS         PRIVATE  MTU  VLAN  PORTS
public  standard  -      192.168.8.1/24  no       -    -     -

You should now be ready to configure guests to use this virtual switch and start them.

root@test:~ # cat /etc/rc.conf
...
ifconfig_vtnet0="192.168.8.2/24"
defaultrouter="192.168.8.1"
root@test:~ # ping 192.168.8.1
PING 192.168.8.1 (192.168.8.1): 56 data bytes
64 bytes from 192.168.8.1: icmp_seq=0 ttl=64 time=0.135 ms
^C
--- 192.168.8.1 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.135/0.135/0.135/0.000 ms
root@test:~ # ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: icmp_seq=0 ttl=54 time=12.199 ms
^C
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 12.199/12.199/12.199/0.000 ms
root@test:~ #

DHCP / dnsmasq

Providing DHCP to the guests can be achieved using dnsmasq. This will need to be installed from ports. A simple config such as below should be enough, based on the same situation as above with the virtual switch called public and a 192.168.8.x network range.

port=0
domain-needed
no-resolv
except-interface=lo0
bind-interfaces
local-service
dhcp-authoritative

interface=vm-public
dhcp-range=192.168.8.10,192.168.8.254