Introduction

So the HardenedBSD project, which I cofounded with Oliver Pinter, has been really moving forward at a great pace. Our old development server needed to be replaced and we now have fully automated builds with Jenkins. That’s all besides the point for today’s blog post, which is about the laptop I just bought for HardenedBSD development. I bought a . It has an Intel Core i7 (Haswell) and Intel Wifi, among other awesome hardware features. FreeBSD 11-CURRENT doesn’t support Haswell video acceleration through the i915 KMS driver nor does it support the wifi chip. I’m using the VESA driver for video and I’m using Linux in a bhyve VM for wifi. This blog post will show you how to get wireless working the way I did if Linux natively supports your wifi chip but FreeBSD does not.

The wired ethernet device is supported, so for the installation, I plugged the laptop into a wired connection. Once installation and initial updates are completed, you can disconnect the ethernet cable.

I started with an Ubuntu Server 14.04 LTS ISO. Installation was very straightforward. I followed the to do the initial installation. But instead of using a file, I used a zvol:

zfs create -omountpoint=none rpool/bhyve
zfs create rpool/bhyve/ubuntu-server-amd64-01
zfs create -V 100g -ovolmode=dev \
    rpool/bhyve/ubuntu-server-amd64-01/disk-01

Follow the installation as normal. I selected the SSH server and LAMP server options. Even though LAMP isn’t necessary, it’s a nice thing to have if I ever want to repurpose this VM.

Now that the VM is installed, we’ll get to our dirty work, the reason why this blog post exists.

Setting up the Host

In our particular setup, the host will have a bridge device called bridge0. This bridge device will have an IP of 192.168.6.1/24. We will give the Linux VM an ethernet tap device, tap0, and assign it an IP of 192.168.6.2/24 in the VM.

We’re going to have the host add the bhyve vmm driver, the NULL modem driver, and the tap driver. We also need to tell the host to not try to use the wifi device, but to pass it on to VMs.

To find out what on what PCI device your wifi device lives, run pciconf -lv. You’ll see something like this if it’s an Intel wifi chip:

somethinghere@pci0:2:0:0:        class=0x028000 card=0x82708086 chip=0x08b48086 rev=0x93 hdr=0x00
    vendor     = 'Intel Corporation'
    class      = network

The important part is the pci0:2:0:0. We’ll take that and plug that into /boot/loader.conf. So our loader.conf should have these entries:

vmm_load="YES"
nmdm_load="YES"
if_tap_load="YES"
pptdevs="2/0/0"

Next up is setting up the bridge and the tap devices. Add net.link.tap_up_on_open=1 to /etc/sysctl.conf. This will make it so that you don’t have to manually bring the tap device up before the bhyve VM boots.

In your /etc/rc.conf file, we should add these lines (change according to your situation):

cloned_interfaces="bridge0 tap0"
ifconfig_bridge0="inet 192.168.6.1 netmask 255.255.255.0 addm tap0 up"
defaultrouter="192.168.6.2"

That’s it! The host is now set up. Time to get the guest set up.

Setting up the Linux VM

I decided to go with Ubuntu Server, so these instructions are specific to that. I’m sure other Linux distributions would work just as well. When we boot Linux up, we have to give the bhyve command an extra argument: -s 5,passthru,2/0/0. That tells bhyve to forward the wifi device to the VM via PCI device 5. You’ll notice the 2/0/0 that came from my pciconf output as pci0:2:0:0.

We need to change the /etc/network/interfaces file to give eth0 a static IP and to tell the networking system to use WPA for wireless. You’ll notice a pre-up script for eth0. That will be detailed later.

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 192.168.6.2
        netmask 255.255.255.0
        network 192.168.6.0
        broadcast 192.168.6.255
    pre-up /scripts/nat.zsh

iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant.conf

I had some issues with manually configuring wpa_supplicant. I had to add these lines to /etc/rc.local before the exit line:

ifdown wlan0
ifup wlan0

This will cause Ubuntu to bring up the wireless device at boot time. Of course, if your network is using WPA, then you’ll need to populate /etc/wpa_supplicant.conf with your specific network configuration parameters.

The last detail is the nat.zsh script. That creates the NATing rules. Our Ubuntu VM will share the wifi connection via NAT to our FreeBSD host. It’s a pretty simple script and you’ll want to tailor it to your specific firewalling needs.

#!/usr/bin/env zsh

iptables="/sbin/iptables"

${iptables} -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
${iptables} -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
${iptables} -A FORWARD -i eth0 -o wlan0 -j ACCEPT

Conclusion

This seems like a complete hack–and it definitely is. But once you reboot and start the VM, you should have full networking working. My next task to research is how to boot this VM at bootup time in the host so that I don’t have to manually start it in a new tmux session after logging in.