Skip to content

macOS guest on Shared network has no internet when host VPN is connected - guest traffic not NATed to VPN interface #40

Open

Description

@blessedagent52

Description

With Mullvad VPN connected on the host, a macOS VM on Shared networking has no internet access. The guest gets an IP (192.168.64.x) and can reach the host (192.168.64.1), but nothing beyond it.

Windows VMs in VMPal work fine with the same VPN connected. Bridged networking also works, but it bypasses the host VPN completely and exposes my real IP, so it's not an acceptable workaround.

Cause (confirmed with tcpdump/pfctl): guest packets are forwarded to the VPN interface (utun10) without NAT, so they enter the tunnel with source 192.168.64.5 and the VPN server drops them. The Internet Sharing pf anchor only contains a NAT rule for the physical interface:

$ sudo pfctl -a com.apple.internet-sharing/shared_v4 -s nat
nat on en0 inet from 192.168.64.0/24 to any -> (en0:0) extfilter ei
no nat on bridge101 inet from 192.168.64.1 to 192.168.64.0/24
$ sudo tcpdump -ni utun10 host 1.1.1.1
IP 192.168.64.5.49153 > 1.1.1.1.443: Flags [S] ...   (repeated, no reply)

IP forwarding is enabled (net.inet.ip.forwarding: 1).

Workaround that confirms it: adding a NAT rule for the VPN interface to the same anchor fixes connectivity immediately:

nat on utun10 inet from 192.168.64.0/24 to any -> (utun10) extfilter ei

Two guest-side tweaks were also needed: MTU 1280 (TLS stalls at 1500 through the WireGuard tunnel) and DNS set to the VPN's resolver 10.64.0.1 (DNS via 192.168.64.1 times out).

But the rule is lost every time the VM restarts (the anchor gets rewritten), and the bridge index changes between runs (bridge100 → bridge101), so it has to be reapplied manually each time. The guest MTU also resets to 1500 after a VM restart.

This is a known limitation of Virtualization.framework NAT with host VPNs (see mullvad/mullvadvpn-app#5213 and utmapp/UTM#3238). Since VMPal already handles Windows VMs correctly, it would be great to get the same for macOS guests, for example:

  1. Offer the networking used for Windows VMs as an option for macOS guests, or
  2. A "Follow host VPN" option that also NATs guest traffic to the current default-route interface (utun*), or
  3. At least document this limitation in the networking docs.

Steps to Reproduce

  1. On the host, connect Mullvad VPN (WireGuard; it takes the default route via utun10).
  2. In VMPal, start a macOS VM with Shared networking.
  3. In the guest, run curl -m 5 -I https://1.1.1.1. It times out.
  4. Switch the VM to Bridged (Wi-Fi). Internet works, but curl https://am.i.mullvad.net/connected shows the guest is not using the VPN (real IP exposed).

Current Behavior

  • Shared: no internet in the macOS guest while the host VPN is connected. No error is shown by VMPal; connections just time out.
  • Bridged: internet works but bypasses the host VPN.
  • Windows VM: works through the host VPN as expected.

Expected Behavior

A macOS guest on Shared networking should reach the internet through the host's active VPN, the same way Windows VMs in VMPal do and the same way host apps do.

Environment

  • App version: VMPal [version 0.67]
  • Mac: [MacBook Pro, M2, 32 GB]
  • macOS version: [macOS 27.0.1]
  • VM's OS: macOS [27.0.1 26A434]
  • Host VPN: Mullvad VPN, WireGuard, "Local network sharing" enabled

Log

Not applicable: no crash or VMPal error, the VM runs normally. The relevant diagnostics (pfctl and tcpdump output) are included above. I'm happy to provide more output or test a build if needed.

Activity

  1. nangtrongvuon commented on Oct 12, 2026

    @nangtrongvuon
    Collaborator

    Hi, thanks for reporting the issue, we'll look into it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions