Raspberry Pi as an OpenVPN Gateway/Router

Over the last week, I got myself a VPS on DigitalOcean and have been playing around with it. Something I’ve wanted to do for a while is to set up a VPN tunnel for myself, and I finally did it.

I decided to write a blog post on my setup. I have a Raspberry Pi set up as a router on my Wi-Fi network, and it sends all traffic over the VPN. I’m not going to get into the reasoning for why I’m using something versus something else for fear of getting into rants in what’s going to be a long post anyway.

The Server

I got myself a “droplet” on DigitalOcean with 512MB of RAM and a 20GB SSD and Ubuntu 14.10 x64. I uploaded my pubkey on creation of the droplet, so it automatically set up ssh to work with it. If you choose not to, it will email you the default root password. I recommend disabling root login and setting up pubkey authentication immediately.

The first thing I did was create a new user account for myself and grant it sudo access. Then I enabled ssh on an additional port (just in case) and disabled password authentication. Finally, I took a “snapshot” of the basic setup as a backup.

Installing OpenVPN

I followed the instructions here to set up the OpenVPN server. Make sure you get the right deb file for your OS – the one in the post is for Ubuntu 12.x. OpenVPN offers an auto-login config profile – I grabbed this from the web UI so my Raspberry Pi could connect without me having to type in a password every time.
That’s it! Now for the client side.

The Wi-Fi Router

My Wi-Fi router is setup in IP sharing mode. This means that traffic from all the devices in my room will appear to my dorm’s router as coming from the same IP, and I have a local network on the 192.168.1.0/24 subnet.

The Raspberry Pi as an OpenVPN Client

The distro I’m running is Raspbian “wheezy” from Septeber 2013. I’m using this because the image was already available on the campus FTP server. Setting up OpenVPN is easy:

$sudo apt-get install openvpn

After that, I copied over the auto-login config file:

$scp /path/to/client.ovpn pi@<pi's ip address>:/tmp/client.ovpn
$ssh pi@<pi's ip address>
$sudo mv /tmp/client.ovpn /etc/openvpn/client.conf

Now to start the client and test if it’s working:

$sudo service openvpn restart
$curl ifconfig.me

The output should be the VPS’s public IP – that means everything is working. If it’s not, keep curl’ing a few times – it might take a few seconds to take effect.

Finally, I added the following line in the OpenVPN config file to bypass the VPN for intranet IPs:

route 10.0.0.0 255.0.0.0 192.168.1.1

That will bypass the VPN for any connections to the 10.0.0.0/8 subnet (192.168.1.1 is my Wi-Fi router’s local IP).

The Raspberry Pi as a Router

I wanted the Raspberry Pi to serve as a gateway and DHCP server for my Wi-Fi network. To achieve this, first it needed a static IP. I edited /etc/network/interfaces for this:

auto eth0
iface eth0 inet static
address 192.168.1.11
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1 # Wi-Fi router IP

Then, I needed to allow NAT:

$sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

To make this rule persist (from https://wiki.debian.org/iptables):

$iptables-save > /etc/iptables.up.rules

To restore the rules after a reboot, create this file:

$nano /etc/network/if-pre-up.d/iptables

Add these lines to it:

 #!/bin/sh
 /sbin/iptables-restore < /etc/iptables.up.rules

The file needs to be executable so change the permissions:

$chmod +x /etc/network/if-pre-up.d/iptables

Now, I was able to connect any client to the Wi-Fi network and browse through the VPN using the Pi (192.168.1.11) as the gateway!

The Raspberry Pi as a DHCP Server

Finally, I wanted devices to automatically use the Raspberry Pi as the gateway without any “advanced” manual configuration. To do this, I installed dnsmasq:

$sudo apt-get install dnsmasq

And edited the config file (/etc/dnsmasq.conf) to set the DHCP ip-range:

interface=eth0
dhcp-range=192.168.1.2,192.168.1.254,255.255.255.0,12h #start,end,mask,lease time

Now all I had to do was disable my Wi-Fi router’s DHCP server and voilà. Now any device connected to my Wi-Fi would automatically go through the Pi and hence the VPN connection.

Making DC++ Work in Active Mode

DC++ is widely used for file sharing on campus. Behind a firewall or router (like in my setup), I could only use DC in passive mode – which limits my search results greatly. To make active mode work, I set up my Raspberry Pi as a virtual DMZ station on my Wi-Fi router. This makes the router redirect all inbound packets to the Raspberry Pi. After that, it was a matter of setting up port forwarding.

First, I added this line to /etc/dnsmasq.conf to give my Macbook a hostname (nhnt11-mbp) and static IP with an infinite lease time:

dhcp-host=<macbook's mac="" address="">,nhnt11-mbp,192.168.1.12,infinite

Then, I made my Raspberry Pi forward port 1412 (TCP and UDP) to my Macbook:

$sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1412 -j DNAT --to-destination 192.168.1.12:1412
$sudo iptables -t nat -A PREROUTING -i eth0 -p udp --dport 1412 -j DNAT --to-destination 192.168.1.12:1412
$sudo iptables-save > /etc/iptables.up.rules

And that was it! My room is now fully VPN’d.

Automator App to Connect Pi to VPN

As a bonus, I decided to make a small Automator app to run a shell script to reconnect the Raspberry Pi to the VPN and display a notification when the connection was good to go. The content of the shell script is as follows, you can figure out Automator yourself 😉

#!/bin/bash
ssh pi@192.168.1.11 sudo service openvpn restart
IP=`curl ifconfig.me`
while [ "$IP" != "<VPS's public IP>" ]; do
    sleep 1
    IP=`curl ifconfig.me`
done
echo "Connected!"

That’s it! Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *