How to Route All Network Traffic Through a VPN Using Docker on macOS

When installing a VPN directly on your router isn’t possible (which is very common with ISP-provided or locked-down models, instructions here for doing it though), macOS can be used as an intermediate gateway to route all network traffic through a VPN running inside a Docker container. In this setup, the Mac accepts traffic from other devices on the network, forwards it into Docker’s virtual machine, and the VPN container tunnels it out to the internet. This effectively gives you “router-level” VPN behavior without touching the router itself. However, because macOS and Docker both add virtualization layers, it’s more fragile than a true router solution and can be impacted by sleep mode, firewall rules, and OS updates—so it’s best viewed as a functional workaround rather than a permanent infrastructure replacement.

If you’re running Windows there are different instructions for installing a VPN in Docker on Windows + instructions for routing traffic.

MacOS Architecture Reality

So we need:


Requirements

Click if you need a NordVPN service account


Important Note

On macOS, Docker does not run natively on the host network stack — it runs inside a Linux virtual machine. This means traffic must pass through three layers:

Device → macOS → Docker VM → VPN tunnel → Internet

Because of this architecture, macOS is acting as an intermediate gateway, not a true router. This works, but it is more fragile than a dedicated router or Linux gateway and can be affected by sleep mode, firewall rules, and OS updates.

Real-World macOS Gotchas (Very Important)

These are not edge cases — these are guaranteed pain points:

1. Sleep Kills Everything

If the Mac sleeps:

Your whole network loses internet.

You must disable sleep.


2. macOS Updates Can Reset pf

After updates:

pf rules can be wiped or reordered.

You must reapply.


3. Docker Updates Can Change Interfaces

bridge100 can become vmenet0, etc.

Your routing rule breaks.


4. Some Devices Refuse Non-Router Gateways

Smart TVs, consoles, IoT devices may:

  • Refuse to talk

  • Partially work

  • Break multicast

Click if you need a NordVPN service account

Step 1 – Enable IP Forwarding on macOS

sudo sysctl -w net.inet.ip.forwarding=1

To persist:

sudo nano /etc/sysctl.conf

Add:

net.inet.ip.forwarding=1

Load:

sudo sysctl -p

This tells macOS:

“You are allowed to route packets between interfaces.”

Without this, nothing works.


Step 2 – Run NordVPN in Docker

Example:

docker run -d \
--name nordvpn \
--cap-add=NET_ADMIN \
--device /dev/net/tun \
nordvpn/nordvpn

Then:

docker exec -it nordvpn bash
nordvpn login
nordvpn connect

Verify:

ip a

You must see tun0.
If not, stop here — the rest is meaningless.


Step 3 – Identify Docker VM Interface on macOS

Run:

ifconfig

You will usually see one of:

  • bridge100

  • vmenet0

  • vmenet1

This is the interface macOS uses to talk to the Docker VM.

We’ll call it:

DOCKER_IF = bridge100 (example)

Also identify your LAN interface:

en0 = Wi-Fi
en1 = Ethernet

Step 4 – Enable NAT on macOS (pf firewall)

Edit pf config:

sudo nano /etc/pf.conf

Add at the top or in NAT section:

nat on en0 from 192.168.1.0/24 to any -> (en0)

This says:

“Any LAN traffic leaving en0 gets NAT’d”

Then load:

sudo pfctl -f /etc/pf.conf
sudo pfctl -e

Check:

sudo pfctl -s nat

You should see your rule.


Step 5 – Route LAN Traffic Into Docker VM

Now we tell macOS:

“Traffic coming from LAN → send it into Docker VM”

Add this to /etc/pf.conf:

pass in on en0 route-to (bridge100) from 192.168.1.0/24 to any keep state

(Replace bridge100 with your actual Docker interface.)

Reload:

sudo pfctl -f /etc/pf.conf

At this point:
macOS is forwarding + NAT’ing + routing into Docker VM.


Step 6 – Enter Docker VM

On macOS:

docker run -it --privileged --pid=host alpine sh

Or:

screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty

(This drops you into the Linux VM itself.)

Alternatively, easier:

docker exec -it nordvpn bash

and then inspect networking from there.


Step 7 – Enable Forwarding Inside Docker VM

Inside the VM:

sysctl -w net.ipv4.ip_forward=1

Step 8 – NAT Docker VM Traffic Into VPN Tunnel

Inside the VM:

iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE

Allow forwarding:

iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT

Now the chain is complete:

Device → macOS → Docker VM → tun0 → VPN → Internet

Step 9 – Make macOS the Gateway for Other Devices

This is the same router reality problem as Windows.

Best case (rare):

Router LAN DHCP settings:

Gateway = <macOS IP>

Common case:

Manually set on each device:

IP: 192.168.1.120
Subnet: 255.255.255.0
Gateway: 192.168.1.50 ← macOS machine
DNS: 1.1.1.1

Now that device routes through the Mac.


Step 10 – Test

On the device:

If not:

  • pfctl -sr

  • pfctl -sn

  • iptables -t nat -L

  • netstat -rn on macOS