Using (and sharing) a VPN connection on your Mac

Update (2011-05-07): I added a Troubleshooting section at the end of this article, grouping together several common problems (and solutions) people posted in the comments.

First of all, sorry for the lack of posts, I’ve been kinda busy lately. I finally updated my development machine to Snow Leopard (I was on Leopard 10.5.7) and I took the opportunity to sort and organize all my backups, documents and stuff. I’m still not really done with my backup procedures, but at least I’m covered in case of a crash (after the capacitors incident, I decided to take my backups more seriously).

Anyway, one of the things I always wanted (and finally had time) to do was to setup my own OpenVPN server. In case you don’t know, VPN stands for “Virtual Private Network”, and it’s a way to have your own secure network no matter where you are. Whenever you’re at a cafe or an hotel and want to make sure no one can take a peek on what you’re doing (yes, it’s pretty easy to do that) you need a VPN. Having a VPN server can also help you circumvent geoblocking, if that’s what you’re up to.

I decided to write this article to share the experience I had configuring my own VPN, specially when I wanted to share the connection with other devices in my network. If that’s what you want to do, read on and I’ll try to explain what I did and how I did it.

The Server

If you want to have your own VPN, the first thing you need is an OpenVPN server. You have two options: using your own server or using an OpenVPN service provider. The whole process of setting up the server is out of the scope of this article, but if you have a Linux server you can find some great guides on Linode’s Library. By the way, Linode is a great VPS provider (I highly recommend it - this server is located there), so if you want to have your own server there you can use my referral code.

Another option is to use a VPN service provider. There are both free and paid VPN services, and if all you want is to have a VPN without bothering with server setup, this is the easiest way. Here’s a list of some VPN service providers (prices range from $0 to $15 per month, depending on the speed/bandwidth you need).

The Client

Okay, so you have your server, now you need a client to connect to your VPN. I’ll help you setup Tunnelblick on Mac OS X. Since I never used any VPN client on Windows I can’t help you there, but if you’re stuck on Windows I recommend using OpenVPN GUI.

The first time you open Tunnelblick after installing it will ask for your password. It’s ok, it needs your password to secure your keys and configuration files (and that’s very important, since anyone with access to your keys can connect to your VPN server). After that, it will ask if you want to create a sample configuration file. I suppose you already have your config file and keys (that’s part of the server setup) so let’s just ask for it to open the configuration folder, so we can put our files there. If you don’t have a config file from your server, you can let Tunnelblick create one for you. Close the program after that.

Copy your configuration and certificates to the configuration folder. Usually you’ll need to copy 4 files: client.conf, ca.crt, <yourclient>.crt and <yourclient>.key. Rename client.conf to the name you want to use to identify your server (i.e. MyServer.conf), open it in your favorite text editor and check if it already has at least the following lines (leave the rest untouched):

remote <your server address> <your server port>
ca ca.crt
cert <yourclient>.crt
key <yourclient>.key

Save your files and launch Tunnelblick again. It will add a black tunnel icon to your menu bar. That’s where it’ll sit when it’s running, so you can quickly connect to your OpenVPN server whenever you want to. If you click on its icon, you’ll see an option to connect to your server, with the same name you used in your config file. But before you connect, let’s check your current external IP address first: enter this site, look for your IP address and write it down.

Ready to connect? Click on the tunnel icon and select Connect ‘YourServer’. It’ll try to connect to your VPN server (if it asks for your password again there’s nothing wrong, it’s securing the files you changed. It won’t ask every time). The menu icon will animate while it’s connecting, and if it connected successfully the icon will change to an open tunnel. Click on the menu icon again and the first line should read Tunnelblick: 1 connection active. Go back to this site and check your IP again. If it changed then congratulations, you’re already using your VPN connection and all your traffic is going through a secure connection.

If something went wrong and your VPN connection is not working, open Tunnelblick menu again and select Details. It will show you a very detailed log file, so you can check for errors and warnings there. And if you are connected to the VPN server but your IP address didn’t change, the problem is probably in the server: it needs to be configured to forward all VPN traffic and to be the default gateway on the client. All these options are covered in the Linode’s guide I mentioned earlier. Sure, if you’re using a VPN service provider you can also contact their support.

Sharing Your VPN Connection

So now you are connected to your server and your connection is securely being routed thought the VPN (go ahead and try Hulu, I’ll wait. I know you want to). But what if you want to use the same VPN in other devices in your network? Sure you can configure Tunnelblick in more than one Mac, but some devices like an iPhone or a XBOX 360 don’t have OpenVPN clients. What can you do about that?

The solution I found is simple: you can share the VPN connection in your Mac and then use your Mac as a gateway for your other devices. The problem is that the OSX’s native Internet Sharing doesn’t seem to play nice with OpenVPN. I really tried to use it in every way possible, but it didn’t work. So I spent some time researching how Internet Sharing works under the hood and I found a solution that is not so simple, but once configured works perfectly.

Open your favorite text editor and create a new file. Paste the following lines on it:

#!/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

Save it with a name like natvpn.sh. Right click the file in Finder, select Get Info and under Permissions mark Execute. Close the Get Info window.

Now what the hell was that all about? Let me break it down to you. We’re using some native commands to allow your Mac to act like a gateway and forward all the packets to the VPN connection. This is very similar to what OSX’s Internet Sharing does for you. The name tun0 is the default interface name Tunnelblick will use for your VPN connection, and you can confirm that by opening Terminal and typing ifconfig while connected to your VPN.

Open Terminal. If you’re not connected to your VPN, connect now. Go to the directory you saved your file (if you saved it in your home folder, you’re already there) and type:

sudo ./natvpn.sh

You’ll need to replace natvpn.sh with the name you saved your file. It’ll ask for your password, type it and you’ll see something similar to this:

Flushed all rules.
00100 divert 8668 ip from any to any via tun0
00200 allow ip from any to any
net.inet.ip.forwarding: 0 -> 1

It worked: your Mac is already a gateway! Now all you have to do is go to the device you want to use with the VPN connection and, under its network settings, change the default gateway to your Mac’s IP address. In most devices, to change the default gateway you’ll also need to configure it to use Static IP (my iPhone needed, for example). Just copy the same IP address, subnet mask and DNS server it’s currently using and change only the gateway to your Mac’s IP address. Oh, and if you don’t know your Mac’s IP address go to Preferences, open Network and select your network connection. In the right panel it’ll show your IP address under Status.

Test your device by going to the same site again and it should show you the server’s IP address. Congratulations, enjoy your new secure VPN connection!

Conclusion

As you can see, setting up a VPN connection is pretty simple. Sharing it might be a little more complicated, but now that it’s configured all you have to do is open Terminal and type sudo ./natvpn.sh while connected to the VPN everytime you want to share it. It’s not automatic, but it works pretty well. And of course, if all you want is to use the VPN on your Mac, then you only have to connect using Tunnelblick and you’re done.

This guide assumes you have at least a little experience using the terminal. If you don’t, you may find yourself a little lost in some parts, especially if you want to share your VPN connection. If that’s the case, feel free to leave a comment below and I promise I’ll try to help you!

Troubleshooting

The method I described above doesn’t work together with OSX Internet Sharing. So check if you have it enabled (under Preferences, go to Sharing) and disable it.

If you can’t find the option in Finder to make the script executable, you can also do it in Terminal. Just type chmod +x natvpn.sh.

Be sure to save the script in TextEdit (or your preferred editor) as a plain text file, not as rich text. You can check this by typing cat natvpn.sh in Terminal. If you see garbage instead of the script, the file was saved as rich text.

If you get the error “Address already in use” from natd when running the script, it’s because you already have natd running, and only one instance can be active. Check if you didn’t leave OSX Internet Sharing enabled (you have to disable it) or try to run the following code in the Terminal to see what app is running it:

ps aux | grep natd

When configuring your client device (the one which will be using your Mac’s connection) set the DNS servers to external addresses. You can use, for example, Google DNS (IPs 8.8.8.8 and 8.8.4.4) (thanks Damian).

If you’re using a PPTP VPN interface (OSX VPN Client) instead of OpenVPN you need to do a few additional steps. First, add a line IPFORWARDING=-YES- in the file /etc/hostconfig, then change the natd -interface tun0 line in the script with (thanks Zantiss):

natd -same_ports -use_sockets -unregistered_only -dynamic -interface ppp0 -clamp_mss

There are some reports of speed issues when using a PPTP VPN, but I don’t have access to a PPTP VPN so I can’t confirm it.

If your VPN server doesn’t register itself as your default gateway, you can override this in your client configuration file. Just add the line redirect-gateway def1 to the file (thanks Jon).

If you want to turn VPN sharing off, create another script called natvpnoff.sh (or something similar) and put the following lines inside it (thanks Yohann):

#!/bin/sh
killall natd
ipfw -f flush
sysctl -w net.inet.ip.forwarding=0

After saving, run the script with sudo natvpnoff.sh. You could also reboot your machine to disable VPN sharing, since none of the changes in the script is permanent.