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:
-
macOS to forward traffic
-
macOS to NAT traffic into the Docker virtual machine
-
Docker VM to forward traffic into the VPN tunnel (click here for instructions on installing the VPN Docker container on macOS)
Requirements
-
macOS (Intel or Apple Silicon)
-
Docker Desktop for macOS (uses HyperKit / Apple Virtualization Framework)
-
NordVPN service account (click here to watch the video on how to generate service account credentials)
-
Admin (sudo) access on macOS
-
Router that either:
-
Allows changing the DHCP gateway OR
-
You are OK setting the gateway manually on each device
-
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=1Load:
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:
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.1Now that device routes through the Mac.
Step 10 – Test
On the device:
-
Visit https://whatismyip.com
-
Should show NordVPN location.
If not:
-
pfctl -sr -
pfctl -sn -
iptables -t nat -L -
netstat -rnon macOS
