Skip to content

Instantly share code, notes, and snippets.

@syzdek
Created September 9, 2026 22:56
Show Gist options
  • Select an option

  • Save syzdek/1be1279e9ac77bc9b3f5cac1835e69bc to your computer and use it in GitHub Desktop.

Select an option

Save syzdek/1be1279e9ac77bc9b3f5cac1835e69bc to your computer and use it in GitHub Desktop.
MacOS VPN: Static Route / Split Routing

MacOS VPN Split Routes

MacOS Tahoe does not allow the end user to specify local networks which by-pass the VPN. Routes on MacOS can be manually modified to send default traffic through the local LAN and only send specific routes across the VPN by creating more sepcific routes (i.e. 0.0.0.0/1 and 128.0.0.0/1) to use the local gateway and by creating specific routes for the VPN connection.

In my specific environment, I have the following networks:

  • 192.168.0.0/24 - MacBook/Workstation LAN
  • 192.168.0.1/32 - MacBook/Workstation LAN Gateway
  • 10.0.0.0/8 - Remote VPN Networks
  • en7 - Ethernet Interface on MacBook

The following exmaples use mypubip.com to determine the public IP address used to NAT LAN and VPN connections.

Network Without VPN Connection

The following shows some of the routes on the MacBook prior to starting the IKEv2 VPN:

syzdek@wanderer$  netstat -rn |egrep '^(default|10|0|128|192)'
default            192.168.0.1        UGScg                 en7       
192.168.0/24       link#23            UCS                   en7      !
192.168.0.1/32     link#23            UCS                   en7      !
192.168.0.1        xx:xx:xx:xx:xx:c1  UHLWIir               en7   1190
192.168.0.22       xx:xx:xx:xx:xx:a7  UHLWI                 en7    607
192.168.0.133      xx:xx:xx:xx:xx:85  UHLWI                 en7    512
192.168.0.179      xx:xx:xx:xx:xx:3d  UHLWI                 en7    400
192.168.0.189      xx:xx:xx:xx:xx:3d  UHLWI                 en7    491
192.168.0.203/32   link#23            UCS                   en7      !
192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWbI                en7      !
syzdek@wanderer$ 

The following shows the current public IP address the MacBook is NAT from when accessing the Internet without the VPN:

syzdek@wanderer$ curl -4 mypubip.com
IP Address:   x.x.x.121
Hostname:     <redacted>
User Agent:   curl/8.21.0
syzdek@wanderer$

Network With VPN Connection

The following shows some of the routes on the MacBook after starting the IKEv2 VPN:

syzdek@wanderer$  netstat -rn |egrep '^(default|10|0|128|192)'
default            link#24            UCSg               ipsec0       
default            192.168.0.1        UGScIg                en7       
10.0.0.40          link#24            UHWIig             ipsec0       
10.0.0.41          link#24            UHWIig             ipsec0       
10.0.10.197        10.0.10.197        UH                 ipsec0       
10.0.10.255        link#24            UHWIig             ipsec0       
192.168.0/24       link#23            UCS                   en7      !
192.168.0.1/32     link#23            UCS                   en7      !
192.168.0.1        xx:xx:xx:xx:xx:c1  UHLWIir               en7   1190
192.168.0.22       xx:xx:xx:xx:xx:a7  UHLWI                 en7    607
192.168.0.133      xx:xx:xx:xx:xx:85  UHLWI                 en7    512
192.168.0.179      xx:xx:xx:xx:xx:3d  UHLWI                 en7    400
192.168.0.189      xx:xx:xx:xx:xx:3d  UHLWI                 en7    491
192.168.0.203/32   link#23            UCS                   en7      !
192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWbI                en7      !
syzdek@wanderer$ 

The following shows the public IP address the MacBook is NAT from when accessing the Internet with the VPN:

syzdek@wanderer$ curl -4 mypubip.com
IP Address:   x.x.x.202
Hostname:     <redacted>
User Agent:   curl/8.21.0
syzdek@wanderer$

Manually Modifing Static Routes

In the above example, the following ports and links are used:

  • en7 / link#23 - ethernet port
  • ipsec0 / link#24 - IKEv2 Tunnel

The following commands will effectively override the default route for the VPN tunnel and send only the remote networks through the VPN:

sudo route -nv add -net   0.0.0.0/1 -gateway 192.168.0.1  -ifp en7
sudo route -nv add -net 128.0.0.0/1 -gateway 192.168.0.1  -ifp en7
sudo route -nv add -net  10.0.0.0/8 -link    'link#24'    -ifp ipsec0

The following example shows the output from the above commands:

syzdek@wanderer$ sudo route -nv add -net   0.0.0.0/1 -gateway 192.168.0.1  -ifp en7
u: inet 0.0.0.0; u: inet 192.168.0.1; u: inet 128.0.0.0; u: link 65.6e.37.0.0.e.0.0; RTM_ADD: Add Route: len 148, pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,STATIC>
locks:  inits: 
sockaddrs: <DST,GATEWAY,NETMASK,IFP>
default 192.168.0.1 128.0.0.0 index: 0 65.6e.37.0.0.e.0.0
add net 0.0.0.0
syzdek@wanderer$

syzdek@wanderer$ sudo route -nv add -net 128.0.0.0/1 -gateway 192.168.0.1  -ifp en7
u: inet 128.0.0.0; u: inet 192.168.0.1; u: inet 128.0.0.0; u: link 65.6e.37.0.0.e.0.0; RTM_ADD: Add Route: len 148, pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,STATIC>
locks:  inits: 
sockaddrs: <DST,GATEWAY,NETMASK,IFP>
128.0.0.0 192.168.0.1 128.0.0.0 index: 0 65.6e.37.0.0.e.0.0
add net 128.0.0.0
syzdek@wanderer$

syzdek@wanderer$ sudo route -nv add -net 10.0.0.0/8 -link 'link#24'  -ifp ipsec0
u: inet 10.0.0.0; u: link link:24; u: inet 255.0.0.0; u: link 69.70.73.65.63.30.0.0.e.0.0.0; RTM_ADD: Add Route: len 156, pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,STATIC>
locks:  inits: 
sockaddrs: <DST,GATEWAY,NETMASK,IFP>
10.0.0.0 index: 0 link:24 255.0.0.0 index: 0 69.70.73.65.63.30.0.0.e.0.0.0
add net 10.0.0.0: gateway link#24
syzdek@wanderer$

The following shows some of the routes on the MacBook after manually modifing routes:

syzdek@wanderer$  netstat -rn |egrep '^(default|10|0|128|192)'
0/1                192.168.0.1        UGScg                 en7
default            link#24            UCSg               ipsec0
default            192.168.0.1        UGScIg                en7
10                 link:24            UGSc               ipsec0
10.0.0.40          link#24            UHWIig             ipsec0
10.0.0.41          link#24            UHWIig             ipsec0
10.0.10.197        10.0.10.197        UH                 ipsec0
10.0.10.255        link#24            UHWIig             ipsec0
192.168.0/24       link#23            UCS                   en7      !
192.168.0.1/32     link#23            UCS                   en7      !
192.168.0.1        xx:xx:xx:xx:xx:c1  UHLWIir               en7   1190
192.168.0.22       xx:xx:xx:xx:xx:a7  UHLWI                 en7    607
192.168.0.133      xx:xx:xx:xx:xx:85  UHLWI                 en7    512
192.168.0.179      xx:xx:xx:xx:xx:3d  UHLWI                 en7    400
192.168.0.189      xx:xx:xx:xx:xx:3d  UHLWI                 en7    491
192.168.0.203/32   link#23            UCS                   en7      !
192.168.0.255      ff:ff:ff:ff:ff:ff  UHLWbI                en7      !
128.0/1            192.168.0.1        UGSc                  en7
syzdek@wanderer$ 

The following shows the public IP address the MacBook is NAT from when accessing the Internet with the VPN and modified routes:

syzdek@wanderer$ curl -4 mypubip.com
IP Address:   x.x.x.121
Hostname:     <redacted>
User Agent:   curl/8.21.0
syzdek@wanderer$

Removing Manual Modified Static Routes

To restore the default routing after disconnecting from the VPN, run the following commands:

sudo route -nv delete -net   0.0.0.0/1 -gateway 192.168.0.1  -ifp en7
sudo route -nv delete -net 128.0.0.0/1 -gateway 192.168.0.1  -ifp en7

The following example shows the output from the above commands:

syzdek@wanderer$ sudo route -nv delete -net   0.0.0.0/1 -gateway 192.168.0.1  -ifp en7
u: inet 0.0.0.0; u: inet 192.168.0.1; u: inet 128.0.0.0; u: link 65.6e.37.0.0.e.0.0; RTM_DELETE: Delete Route: len 148, pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,STATIC>
locks:  inits: 
sockaddrs: <DST,GATEWAY,NETMASK,IFP>
default 10.19.84.1 128.0.0.0 index: 0 65.6e.37.0.0.e.0.0
delete net 0.0.0.0
syzdek@wanderer$ 

syzdek@wanderer$ sudo route -nv delete -net 128.0.0.0/1 -gateway 192.168.0.1  -ifp en7
u: inet 128.0.0.0; u: inet 192.168.0.1; u: inet 128.0.0.0; u: link 65.6e.37.0.0.e.0.0; RTM_DELETE: Delete Route: len 148,     pid: 0, seq 1, errno 0, flags:<UP,GATEWAY,STATIC>
locks:  inits: 
sockaddrs: <DST,GATEWAY,NETMASK,IFP>
128.0.0.0 192.168.0.1 128.0.0.0 index: 0 65.6e.37.0.0.e.0.0
delete net 128.0.0.0
syzdek@wanderer$

To restore default routes while connected to the VPN, run the following commands:

sudo route -nv delete -net   0.0.0.0/1 -gateway 192.168.0.1  -ifp en7
sudo route -nv delete -net 128.0.0.0/1 -gateway 192.168.0.1  -ifp en7
sudo route -nv delete -net  10.0.0.0/8 -link    'link#24'    -ifp ipsec0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment