Modern mobile devices are a wonderful, especially when combined with some handy public WiFi hotspot. Unfortunately ne’er-do-wells abound so if you aren’t careful using public hotspots, people can poke around with your data packets and steal fun details like usernames and passwords. What is a mobile internet addict to do?
Simple! Setup up your own VPN. Here’s how to set one up on Amazon EC2, suitable for use with most smartphones and laptops.
Pre-requisites
Similar to my Reviewboard setup guide
this one assumes that you have an AWS EC2 account, and that you are
comfortable with creating instances and ssh‘ing into them.
I’m assuming you are installing this on an Amazon Linux AMI
EC2 instance, but it will probably work with other Linux distributions.
If you’re lucky, all you will need to do is substitute that distribution’s
package manager command in place of yum. For example, apt-get.
The resulting VPN supports PPTP connections which, while not the most secure, are probably the most widely supported. Android, iOS, Linux, Windows 7 and Mac OS X all come with PPTP VPN clients.
What You’ll End Up With
- 1 (one) VPN PPTP daemon (Poptop) running on the server
- n (many) VPN user accounts, as desired
- 1 (one) more secure way to access the internet
Optionally, you will also have a script which allows you to easily add new VPN accounts.
Installing and configuring PPTPD
Install all the stuff for the PPP daemon (PPTP uses this) and some
development tools for compiling Poptop. As usual, you don’t type (and don’t copy)
the $ symbol at the start of the line, I just use that to indicate the command
prompt, but you can include the \ line splitting characters when copying
and pasting:
$ sudo yum --assumeyes install \
ppp \
ppp-devel \
make \
gcc \
gcc-c++ \
openssl-devel \
ntsysv
Fetch and extract Poptop:
$ mkdir ~/pptpd-install
$ cd ~/pptpd-install
$ curl -s http://kent.dl.sourceforge.net/project/poptop/pptpd/pptpd-1.3.4/pptpd-1.3.4.tar.gz | tar -xvz
Configure Poptop to use the /usr directory when it’s installed. I did this
to get around a few issues with paths in the default configuration (alternatively
I could have edited those, but I’m lazy):
$ cd pptpd-1.3.4
$ ./configure --prefix=/usr --exec-prefix=/usr
Next we want to patch the patchlevel.h file so that wtmp logging works. It’s
a bit of a hassle, but I think it’s worth it because you can the use standard
wtmp reading commands such as last venger to see a list of when and where
VPN user venger connected. Handy if you ever suspect someone has been
misusing your account.
This crazy command gets the current pppd version and uses sed to substitute
that version in the plugins/patchlevel.h file:
$ PPPD_VERSION=$(pppd -v 2>&1 | grep -E '^.*version.*$' | gawk '{print $3}'); \
sed -ie 's/\(.*VERSION.*"\)\(.*\)\(".*\)/\1'$PPPD_VERSION'\3/' \
plugins/patchlevel.h
Now make and install Poptop:
$ sudo make install
Add an init script so that we can set it to start automatically later:
$ sudo cp pptpd.init /etc/init.d/pptpd
$ sudo chmod 755 /etc/init.d/pptpd
Copy the basic configuration file for pptpd and specify the local IP address
range to be used for connected clients. NOTE: you cannot have more users
connected simultaneously than the range specified here, which covers 100
IP addresses. The range you give it must be from the
private IP address
block, and must not conflict with other addresses on that machine or the LAN
to which it’s connected or Bad Things may happen.
$ sudo cp samples/pptpd.conf /etc/pptpd.conf
$ echo -e "localip 192.168.69.254\nremoteip 192.168.69.1-101" \
| sudo tee --append /etc/pptpd.conf
Now copy the sample PPP options for PPTP connections and modify it a little to specify a few useful things.
The first echo‘d line sets Google’s public DNS
servers as the DNS servers used to resolve web addresses when you are using the VPN
connection. If you don’t want to use Google’s public DNS
servers, then you could use the public DNS servers provided by OpenDNS
(208.67.222.222 and 208.67.220.220), or find your own alternatives.
The second echo‘d line adjusts the MTU
and MRU. A side effect of the
way VPN wraps data may cause data packets to exceed 1500 octets, causing frequent
disconnects for some. Setting this to 1400 should avoid that. It’s likely
you can get away with using 1492 but that was causing me some issues with my
connection, so 1400 is playing it very safe:
$ sudo cp samples/options.pptpd /etc/ppp/options.pptpd
$ echo -e "\n# Google DNS\nms-dns 8.8.8.8\nms-dns 8.8.4.4\n" \
| sudo tee --append /etc/ppp/options.pptpd
$ echo -e "\n# Make MTU/MRU a little smaller than default\nmru 1400\nmtu 1400" \
| sudo tee --append /etc/ppp/options.pptpd
Configuring NAT and Fixing Your EC2 Firewall
That’s it for the basic PPTP configuration, but now you have to modify your
iptables rules and kernel settings so that your instance knows to forward
data to the correct client when connected via VPN.
First, adjust the iptables rules and save them so it all works after
reboot:
$ sudo iptables -t nat -A POSTROUTING -s 192.168.69.0/24 -j MASQUERADE
$ sudo service iptables save
And now make sure your kernel knows that you want to use NAT.
The sed command here is modifying your sysctl.conf so that your system
remembers to enable NAT on reboot:
$ sudo sysctl net.ipv4.ip_forward=1
$ sudo sed -i -r 's/(net.ipv4.ip_forward)(.*)0$/\1\21/' /etc/sysctl.conf
In order to connect to your EC2 instance from the outside world, you will have to open up the correct port, 1723, in the security group. The easiest way to do this is from the Amazon AWS EC2 web console.
Log in to your AWS account, go to the EC2 tab, select the Security Groups section and then select the security group for the instance you have installed the VPN on:

Now add a custom TCP rule for port 1723 to make it available to everyone. If you
want to limit which IP address ranges can connect to your VPN, use the
appropriate CIDR source
specifier. I want to access it from unknown public IP addresses so I’m
setting it to accept connections from all IP address, 0.0.0.0/0:

Also add a custom UDP rule with the same details. I’m not entirely certain that VPN connections support UDP, but what the hell. NOTE: Don’t forget to click Apply Rule Changes near the bottom of the inbound rule pane before leaving the page. I often miss that.
Starting Everything Up
Now lets make sure all the services we just set up are started, and that they restart when the instance is rebooted:
$ sudo chkconfig iptables on
$ sudo chkconfig pptpd on
$ sudo service iptables restart
$ sudo service pptpd stop # Should fail, but just in case...
$ sudo service pptpd start
Adding Users
All that’s left to do now is to add a VPN user. I prefer to add a VPN user for each device which uses VPN. If the device is ever stolen or lost, having a different user for each allows me to block access for that device by removing the user entry.
To add a user, you must append a user entry to the /etc/ppp/chap-secrets
file with the correct format. The format it expects is defined as:
[username] [vpn_service_name] [password] [allowed_ip_addresses]
You can quickly add a user with the following verbose command. Remember
to change USERNAME to your desired username. The section starting dd in
the echo string generates a random password for the user which will be
shown at the end. I recommend treating this as a once only password – just
copy or email the password to the device and paste the password into your VPN
client setup and tell it to remember the password. If you ever think it’s
compromised, just delete the user or generate a new password. Avoid using
the same password for multiple users. Don’t forget to eat the email you
sent with the password. Eat your vegetables.
echo -e "\nUSERNAME pptpd $(dd if=/dev/urandom count=1 2> /dev/null | sha1sum | cut -c-32) *\n" \
| sudo tee --append /etc/ppp/chap-secrets
To delete a user, simply remove the line with their name from /etc/ppp/chap-secrets
using your favourite text editor running as root. Pro Tip: Real Beings use
vim.
Using that command to add each user is a bit of a faff, so I’ve written a script to make adding users easier. It will also check if a user already exists before adding a new one and just display the password instead. Here’s a sample session where I enter the same user twice:
$ sudo ./nah_vpn_add_user.sh venger
Creating VPN user in '/etc/ppp/chap-secrets'
username: venger
password: 5fac76dfc049ea0f6e7b50c0641cc8c8
VPN service name: pptpd
$ sudo ./nah_vpn_add_user.sh venger
ERROR: User already seems to exist in '/etc/ppp/chap-secrets'
username: venger
password: 5fac76dfc049ea0f6e7b50c0641cc8c8
Here’s the script as a gist on github if you want to use it. As with every
script a stranger gives you, and especially since I’m making you sudo this script,
examine it to make sure I’m not doing anything evil to your system
(I’m not, but I would say that):
You can download it to your machine and make it executable by typing:
$ curl https://raw.github.com/gist/1626638 -o nah_vpn_add_user.sh
$ chmod a+x nah_vpn_add_user.sh
And then add users to your hearts content. Running the script with no parameters
will output some help. The script will only add users – deletion is still
manual as described above (delete the user’s entry in /etc/ppp/chap-secrets).
Setting Up The Device Client
This guide is already far too long, so here are some links to other guides about setting up your client or clients. The main points to remember when following these guides are:
- Protocol: Only use PPTP
- Server Address: The public address or public IP of the EC2 Instance. This can change each time you boot, so you may want to assign an Elastic IP address to the instance or perhaps use Route 53.
- Username: The username used when you created the user above.
- Password: The generated password displayed when you created the user above.
- Encryption Level: Should work as 128 bit or maximum, but you can try auto.
The guides (I don’t endorse any here and haven’t used any of the VPN services who’s guides I’ve linked here, but it’s handy information):
- iPhone guide on bestvpnservice.com
- Android guide on TechRepublic
- PPTP VPN Client Guides on Witopia
- StrongVPN support guides
Checking the Connection
Once you have your client configured, connect to your new VPN and visit:
If all is well you should be able to see the site and it should say that your ISP is Amazon. Well done! You have a shiny new VPN to play with.
Points of Interest
It’s not just when you are using public hotspots that VPNs are useful. It will prevent, for example, your ISP inspecting what services you use or what websites you visit. Before you start merrily torrenting every legal thing in existence though, remember you’re paying for the bandwidth passing through your EC2 server. Also remember that while your ISP can’t see what addresses you visit, Amazon can.
Additionally, your VPN machine’s public IP address will be what the world sees. So if you set up a VPN machine at one of Amazon’s US datacenters then sites you visit will think you are a visitor from America. Or if you set one up in the EU, it will appear as though you come from Ireland.
Also, if anyone’s crazy enough to pass SOPA style regulations in your country, using a VPN in a datacenter outside your country may help, assuming Amazon, Google and OpenDNS aren’t affected directly by the legislation.
Have fun.
