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.
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.
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:
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 firstname.lastname@example.org 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!