Sharing a VPN connection with another device on macOS Sierra/El Capitan

13 minute read

There are multiple reasons why you would want to share a VPN connection from your Mac with another device. Maybe you have to install a proprietary VPN client which does not run on your main computer or you just don’t want to run/install it there. Maybe your main computer doesn’t “comply” (i.e. you would need to install additional AV software – who wants that?). Or you simply need it for streaming video to some TV box.

I recently had the problem with a proprietary VPN client which I didn’t want to install on my main machine. I solved it by using another Mac running macOS 10.11 and am going to describe the process here and list the resources that were helpful.

If you are looking for a hardware VPN router or want to share a natively supported VPN connection (L2TP, IPSec) via “Internet Sharing”, you can stop reading here. I won’t cover this topic.

I quickly found the article “Using (and sharing) a VPN connection on your Mac”, which looked like a great solution. It suggested the following little shell script:

#!/bin/sh

natd -interface tun0
ipfw -f flush
ipfw add divert natd ip from any to any via tun0
ipfw add pass all from any to any
sysctl -w net.inet.ip.forwarding=1

Unfortunately, there’s neither ipfw nor natd on El Capitan or Sierra, since they were deprecated with Yosemite. So, the “new” thing to look into was pf (packet filter).

After reading the man page of pfctl and a bit more of googling, I found the solution. To load your own rules and share your VPN connection, you can use pfctl -f and give it a list of nat entries defining the interfaces from and to. This article “Share your VPN with Mac OS X El Capitan” from roelant.net helped a lot.

My working natvpn.sh script now looked like this:

#!/bin/sh

sysctl -w net.inet.ip.forwarding=1
sysctl -w net.inet.ip.fw.enable=1
pfctl -f ./nat-rules -e

You might need a sudo pfctl -d before to disable the packet filter.

…and the nat-rules file:

nat on utun0 from en0:network to any -> (utun0)

You might need to change the interfaces utun0/en0 according to your preferences.

The next step was to go to my main machine and setup a new network service (System Preferences -> Network). After clicking on the “+” button, I chose the adapter (in my case the Display Ethernet) and manual IPv4 configuration and entered my standard local networking details with the exception of the gateway address (might also be called “router address” on your machine). The gateway address is the IP of the mac on which the VPN client (incl. the script from above) was installed.

After the service was created I just needed to change the order of the services to prioritze the newly created service (click on the action menu -> Set Service Order) and then start the script (./natvpn.sh). Et voilà, I could use the VPN connection established by the other Mac on my main machine Mac.

If you don’t like to set the service order every time you use the shared VPN, you might want to set up a new network location for your VPN work (System Preferences -> Network -> Location -> Edit Locations … -> +)

Update: Troubleshooting

If sharing does not work after executing the steps above or stops working from one day to the other (yep, had that problem :-)), you should first check the nat-rules file. It is likely that either one of the interfaces is invalid or you might just have a typo in there. If it all looks OK but still doesn’t work, try to explicitly list the subnet, i.e. nat on utun0 from 192.168.1.0/24 to any -> utun0 and then start again.

After running ./natvpn.sh you may also want to do a sanity check by listing the rules with sudo pfctl -s all. You should see your entry under TRANSLATION RULES.

Another thing to try is to flush all rules before attempting again: pfctl -F all.

Like to comment? Feel free to send me an email or reach out on Twitter.

Did this or another article help you? If you like and can afford it, you can buy me a coffee (3 EUR) ☕️ to support me in writing more posts. In case you would like to contribute more or I helped you directly via email or coding/troubleshooting session, you can opt to give a higher amount through the following links or adjust the quantity: 50 EUR, 100 EUR, 500 EUR. All links redirect to Stripe.