NAT network

A NAT network can be used to send requests from a private VM network (for example, a Host-Only network) to an external network.

NAT network 1:
VM instance with a NAT network configuration.

Under TwinCAT/BSD the forwarding of IP packets between network interfaces must be activated for this:

doas sysctl net.inet.ip.forwarding=1

To save this setting persistently net.inet.ip.forwarding=1 can be added to the file /etc/sysctl.conf. In addition, the translation of private network addresses to an external network requires appropriate network address translation (NAT) rules in pf(8).

The following sample uses the vmnet0 configuration from chapter Host-Only network for the private network between virtual machine and TwinCAT/BSD host.

ifconfig vmnet0
vmnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        ether 58:9c:fc:10:56:5b
        inet 192.168.1.1 netmask 0xffffff00 broadcast 192.168.1.255
        groups: vmnet
        media: Ethernet autoselect
        status: no carrier
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

The IPC is connected to an external network via the physical network interface igb0:

ifconfig igb0
igb0: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4a004a9<RXCSUM,VLAN_MTU,JUMBO_MTU,VLAN_HWCSUM,LRO,RXCSUM_IPV6,NOMAP>
        ether 00:01:05:62:3b:b0
        inet 172.17.98.154 netmask 0xffffff00 broadcast 172.17.98.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>

For the translation of private addresses to the external network, the following pf rule can first be saved in a text file (samplevm.nat.conf) and then loaded via pfctl(8):

nat on igb0 from vmnet0:network to any -> (igb0)
doas pfctl -a "bhf-nat/samplevm-nat" -f samplevm.nat.conf

Additionally, incoming network traffic should be allowed into the private network:

pass from vmnet0:network to any keep state

The rule set can in turn be saved in a text file and loaded via pfctl(8):

doas pfctl -a "bhf/bhyve/samplevm " -f samplevm.filters.conf

Once both rule sets have been loaded, the virtual machine can be started with vmnet0 as the backend for the virtio-net-based network controller:

doas bhyve \
-c sockets=1,cores=1,threads=1 \
-m 2G \
-l bootrom,/usr/local/share/uefi-firmware/BHYVE_BHF_UEFI.fd,fwcfg=qemu \
-s 0,hostbridge \
-s 20,virtio-net,vmnet0 \
-s 31,lpc \
-A -H -P \
samplevm

Within the guest operating system, communication into the external network can be checked with ping requests:

ping beckhoff.com
PING beckhoff.com (18.195.44.45) from 192.168.1.2 : 56(84) bytes of data.
64 bytes from ec2-18-195-44-45.eu-central-1.compute.amazonaws.com (18.195.44.45): icmp_seq=1 ttl=245 time=7.44 ms
64 bytes from ec2-18-195-44-45.eu-central-1.compute.amazonaws.com (18.195.44.45): icmp_seq=2 ttl=245 time=7.27 ms
64 bytes from ec2-18-195-44-45.eu-central-1.compute.amazonaws.com (18.195.44.45): icmp_seq=3 ttl=245 time=7.36 ms
^C

It should be noted that the virtual network interface in the guest operating system is assigned a network address in the range of the vmnet0 network (192.168.1.0/24 see above). In addition, the vmnet0 address (192.168.1.1) must be entered as the default gateway and name server addresses must be stored in order to resolve public domain names such as beckhoff.com.