Setting up a VPN-server on Amazon EC2

Amazon has recently announced the new Micro Instances in their Elastic Cloud service. A so called Micro Instance is a virtual machine with 620 MB main memory and CPU power in the area of an 1 GHz Opteron processor. The advantage of the Micro Instance is its low cost of only $0.02 per hour of operation (be advised, there are some additional costs for traffic and storage).

The EC2 Micro Instance is an ideal way to operate your own VPN-server, when you need it only a couple of hours per month. Let’s assume, that you want to use it for about 50 hours per month with around 10 GB of traffic, this means $1.00 for computation time + $1.50 for 15 GB of storage + $1.50 for 10 GB outgoing traffic. So for $4 this is quite a good offer. Granted, you can find commercial VPN providers for $5 per month, but it is more fun to do it yourself. In this article I will describe, how to setup an EC2 instance as a VPN-server.

I choose to setup a PPTP server. PPTP is not the most secure type of VPN, but it has the big advantage, that it is the most compatible. Nearly every OS is able to open a PPTP connection without additional software and this includes mobile devices like iPhones/iPads.

First, you need to choose a base image to boot in the Micro Instance. I have selected an 32-bit Ubuntu 10.04 server image. The AMI-ID of this image is ami-6c06f305. Start this image in a Micro Instance and log in with your SSH-key. For more details on these steps, refer to the AWS documentation.

Once you are logged in, you can install the pptp-daemon:

sudo aptitude install pptpd

Configuring the pptp-daemon is a breeze. First you to define an IP address range which will be used for connected clients. This can be any IP range, but keep in mind, if you want to avoid routing problems, choose a private IP range. Uncomment and modify 2 lines at the end of /etc/pptpd.conf:

localip 192.168.240.1
remoteip 192.168.240.2-9

With the above settings, the pptpd server will get the address 192.168.240.1 and there are 8 possible client addresses 192.168.240.2 to 192.168.240.9.

It is also a good idea to specify the address of at least one DNS server. You can use the DNS server of amazon (172.16.0.23) or the Google Public DNS. I choose the latter. Open the file /etc/ppp/pptpd-options and make sure it contains the following settings:

ms-dns 8.8.8.8
ms-dns 8.8.4.4

The last step for configuring the pptpd-daemon is to add a user account for the service:

echo "USERNAME pptpd PASSWORD *" | sudo tee -a /etc/ppp/chap-secrets

Replace USERNAME and PASSWORD with whatever credentials you like. It is possible to add as many users as you like.

Now restart the pptp-daemon:

sudo /etc/init.d/pptpd restart

It is already possible to open a PPTP-connection to the server, although no traffic will be forwarded to the Internet. We still need to enable packet forwarding and network address translation on the server.

To enable packet forwarding, uncomment the following line in /etc/sysctl.conf:

net.ipv4.ip_forward=1

Now reload this config:

sudo sysctl -p

The last step is to enable network address translation:

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

This setting is reset on every reboot, so make sure that you add the following line above exit 0 in the file /etc/rc.local:

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

Now the VPN server is fully functional. The only small problem is, that the server will get a new IP address every time you reboot it. I would recommend using a dynamic dns-provider to assign this machine a unique domain name. I am using DynDNS.

The ddclient is a great little tool to update the current IP address on a number of different dynamic DNS services. Installation is done as usual:

sudo aptitude install ddclient

Once installed, the configuration is done in the file /etc/ddclient.conf. It will already contain some usefull settings, because the installer will require you to enter some information about the DNS service you are using. In the end the configuration should look something like this:

protocol=dyndns2
use=web, web=checkip.dyndns.com/, web-skip='IP Address'
server=members.dyndns.org
login=LOGINNAME
password='PASSWORD'
DOMAINNAME.dyndns.org

Replace LOGINNAME, PASSWORD and DOMAINNAME.dyndns.org with your own settings. The most important line is the one starting with use=. This defines that the registered IP-address is detected by DynDNS itself. This is neccessary, because the virtual machine is running with a private IP address.

That’s it! Now you have your own VPN-server up and running. Just start the instance in the AWS Management Console whenever you need it.

Update:

Here is a screenshot of the security groups setup I am using:

Update 2:

Please take a look at my follow up posting on how to connect to the VPN from an iOS or Android device.

  • Rizky

    yep.. found it! thx! but i have the same problem like i’ve mentioned in your iOS/Android post. i can’t seem to connect if i’m on (my office) wifi.

    the only thing i didn’t do as your post instructed is installing the ddclient. i bind the server instance with an elastic IP from the AWS console.

    to be honest, i’m not really sure what i’m doing. i just knew that AWS has a one year free offer, so i decided to try it out :P
    first, i created a server instance, came here for instructions, create an elastic IP address for the instance, and that’s it! did i forget anything?

    fyi, i have no problem connecting to other VPN provider such as Hotspot Shield and OpenVPN’s Private Tunnel.

  • lee

    thanks for the tut, worked for me!

    would definitely recommend only opening ports on firewall that you need. also, created my own subdomain to point to the public dns which hopefully shouldn’t change (although if it does the AWS console will relocate it). now I vpn to vpn.myorg.com (or equivalent). :)

  • Mark

    For whatever reason, this use to work ok – however now on multiple separate instances, it sucsessfully connects, however i get no tcp traffic incoming to the pptp client – I can see outgoing traffic but no incoming traffic. It used to work fine, now it doesnt work – nothing has changed – has amazon put an end to this?

  • Pingback: Quick Markup » 亚马逊云服务平台介绍(6) – EC2 构建VPN服务器

  • jens

    You can always get public ip with

    wget -q -O – http://169.254.169.254/latest/meta-data/public-ipv4

    Just put it in a script within your instance and voila …

  • Alexis J

    Thanks for this !

    I’d recommend only opening port 1723 on the security group. It works with just that port open.

    Regards
    AJ

  • Aaron

    Using OpenVPN, my MacMini is assigned a static internal IP address of 10.8.0.2. While connected to EC2, I can enter 10.8.0.2 into my browser and see the default MacMini server page (If I enter this when not connected via VPN to EC2 I get nothing, because my server’s static IP off the VPN is different). When I enter 10.8.0.1 I see “It Works!” (also confirming I am connected to the VPN). What I can’t do is reach my local (home) server by redirecting the external address. When I enter the external EC2.IP.address or EC2.IP.address:80 I also see “It Works” (this is normal behavior for the IP on the public internet).

    I would like for some way to see the MacMini server page via the EC2.IP.address — that is, to use EC2 to enable access to my home files from a remote location. I used to be able to do this without OpenVPN and EC2 using port forwarding and DynDNS. I moved to Russia, however, and now my server is now stuck behind an ISP-imposed NAT. I figured that since I can VPN through EC2 to reach the public internet, there should be a way to move backward from the public internet to my home computer as long as it, too, is connected to OpenVPN with a static IP.

    Do you think this is possible? if so, how?

  • http://oscartong.tumblr.com Oscar Tong

    Do we have to restart the pptpd everytime when new user and password are added?

  • Peter

    No, the file with the user logins is read with every new connection.

  • Colin

    While this works great for regular browsing, I am having problems using https sites (like the facebook login screen etc.) with this setup. Is there something I am missing to allow secure connections for Credit Card processing etc?

  • Tony

    Peter, thanks for useful tutoirial! But I have same problem as Colin’s. All works great except https protocol (timeouts). How do you work through it?

  • Peter

    Sorry, I have no idea, I did only access http-Sites through the VPN-connection.

  • ec

    Excellent guide. Just a minor problem. I my experience the

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

    does not persist after instance termination, despite having it at rc.local

    I have to login with ssh and rerun it with sudo. Then everything works
    Any thoughts how to make it persist or run after new instance creation?

    Regards,
    EC

  • Tushar

    This is a very helpful article. Having moved to India recently I have been struggling to get Netflix to work reliably. I have managed to setup pptp on a 32 bit Ubuntu micro instance but for some strange reason the speeds I get are super slow. On a 10mbps line I get upload and download speeds of less than 0.5 Mbps on the. Pptp VPN. I tried strong VPN and get over 2mbps . Both Ips are on the east coast so I know latency is approx the same. I am using speedtest.net to check the speeds

    Would you have any advice for me? Thanks

  • Peter

    Sorry, no idea. You might retry the speed test with a bigger instance.

  • Tyler G.

    I know you wrote this a long time ago, but was curious if you could take a look at my question.

    In the section where you set the remote and local ips, I’m confused.

    localip 192.168.240.1
    remoteip 192.168.240.2-9

    Is localip supposed to be set the public ip of my ubuntu instance? If not, when I point my android to the public ip of my instance, how does it know to route to pptp?

  • Peter

    No, both localip and remoteip should be in their own subnet. This subnet should not collide with your local lan ip range. When your mobile device is connected to the VPN all traffic is routed through the VPN server. Routing is done on the server itself.