Set up TAP networking for QEMU on macOS host

I have been trying to set up internet access for an Ubuntu Server (yes, it has to be an Ubuntu Server, even though I would prefer something lightweight like Alpine) on a macOS host. As far as I understand, I need to use Tap/Tun networking.

What I have done so far:

  • Installed TunTap OSX, so I have a /dev/tap0 device.

  • Set up a bridge1 network device using ifconfig

  • Set the IP of the bridge1 device to 192.168.100.1/24.

  • Assigned IP 192.168.100.0 to tap0.

  • Set up a DHCP server and packet forwarding as per this site

  • Made scripts to addm and deletem tap0 from bridge1 at startup and shutdown of the VM. (I have verified these are working).

Apparent problems

At this point, WireShark shows no traffic through tap0, but all my loopback traffic seems to pass through bridge1.

The Ubuntu Server guest still does not have any internet access. I cannot send any data from the host to the guest or vice versa (I've tried ssh and a netcat listener/client pair).

Running ip link show in the guest shows only 2 devices: lo0 and ens3. When the Ubuntu Server boots, the latter is always DOWN until I run ip link set ens3 up (which doesn't fix anything).

When I used to run this VM on VirtualBox (which seems to be broken on macOS now), networking worked perfectly using a virtual NAT. I converted the .vdi image to .qcow2, so everything in the quest OS is identical to how it was before.

Have I done anything wrong here? If so, what can I fix? And if not, what should my next steps be? I appreciate your consideration.

Data Dumps

bridge1 when the VM is running:

$ ifconfig bridge1

bridge1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=3<RXCSUM,TXCSUM>
    ether fa:ff:c2:96:c0:01 
    inet 192.168.100.1 netmask 0xffffff00 broadcast 192.168.100.255
    Configuration:
        id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
        maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
        root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
        ipfilter disabled flags 0x0
    member: tap0 flags=3<LEARNING,DISCOVER>
            ifmaxaddr 0 port 15 priority 0 path cost 0
    Address cache:
        52:54:0:12:34:56 Vlan1 tap0 992 flags=0<>
    media: autoselect
    status: active

bridge1 when the VM is not running:

$ ifconfig bridge1

bridge1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    options=63<RXCSUM,TXCSUM,TSO4,TSO6>
    ether fa:ff:c2:96:c0:01 
    inet 192.168.100.1 netmask 0xffffff00 broadcast 192.168.100.255
    Configuration:
        id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
        maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
        root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
        ipfilter disabled flags 0x0
    Address cache:
    media: <unknown type>
    status: inactive

tap0 when the VM is not running:

$ ifconfig tap0

ifconfig: interface tap0 does not exist

tap0 when the VM is running:

$ ifconfig tap0

tap0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
    ether 7e:9b:23:d0:c2:97 
    media: autoselect
    status: active
    open (pid 2415)

My QEMU command:

sudo qemu-system-x86_64 \
-m 1024m \
-smp 1 \
-boot d \
-hda Server.qcow2 \
-net nic,model=virtio \
-net tap,id=mynet0,ifname=tap0,script=qemu-ifup.sh,downscript=qemu-ifdown.sh


If you want NAT-networking configured for your VMs automatically, you can just 1) share your Internet connection to the bridge interface in the System Preferences, and 2) add the tapN-interfaces of your VMs to the bridge. Easy!

See more details here - https://gist.github.com/andriytk/bd3def8c30cbd474490280436c779027.