Let’s say that you’ve come across a web site that refuses to serve up its content to people located outside of a certain geographical region. For instance, “Japan” (or UK for BBC streams, etc).
There are two basic ways to go about this: pointing your web browser at an HTTP/HTTPS proxy service that’s located in Japan, or opening a VPN connection to a server in Japan. I chose the second method, in part because it isn’t limited to web traffic (allowing you to do things like bypass your ISP’s outgoing SMTP blocking), and in part because I already knew how.
Step 1: sign up for Amazon EC2 service, select the Tokyo region, and launch a t1.micro instance with the standard 32-bit Amazon Linux, opening UDP port 1194 in the security group. Yes, I realize there’s a whole lot to learn in this step, but the documentation is quite good. When you reach the point where you’ve successfully ssh’d into your new machine and are staring at a root shell, we can continue. And hey, if you’ve always wanted your very own fully-functional Linux server in the cloud, there you go.
Step 2: install the openvpn package, run chkconfig openvpn on, cd to /usr/share/openvpn/easy-rsa/2.0, and follow the “Typical usage for initial PKI setup” instructions at the very end of the README (you need to generate one server and at least one client key), with one addition:
openvpn -‐genkey -‐secret keys/ta.key
Step 3: copy the following files from the keys directory to /etc/openvpn: ca.crt, dh1024.pem, myserver.crt, myserver.key, ta.key. Nail down the file permissions.
Step 4: Create /etc/openvpn/openvpn.conf, containing (note the NAT subnet must be the same in this step and the next one):
ca ca.crt dh dh1024.pem cert myserver.crt key myserver.key tls-auth ta.key 0 server 192.168.100.0 255.255.255.0 push "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 126.96.36.199" port 1194 proto udp dev tun keepalive 10 120 user nobody group nobody persist-key persist-tun verb 3 log openvpn.log ifconfig-pool-persist ipp.txt status openvpn-status.log
Step 5: Replace the contents of /etc/sysconfig/iptables with the following (note that this allows ICMP, SSH, and OpenVPN; if you decide to use this machine for other services, you’ll need to open them in iptables and in the security group):
*nat :PREROUTING ACCEPT [0:0] :OUTPUT ACCEPT [3:268] :POSTROUTING ACCEPT [3:268] -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE COMMIT *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT ACCEPT [93:11892] -A INPUT -p icmp -m icmp -‐icmp-type 8 -j ACCEPT -A INPUT -p icmp -m icmp -‐icmp-type 18 -j DROP -A INPUT -p icmp -m icmp -‐icmp-type 17 -j DROP -A INPUT -p icmp -m icmp -‐icmp-type 10 -j DROP -A INPUT -p icmp -m icmp -‐icmp-type 9 -j DROP -A INPUT -p icmp -m icmp -‐icmp-type 5 -j DROP -A INPUT -i tun0 -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -i eth0 -m state -‐state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -m state -‐state RELATED,ESTABLISHED -j ACCEPT -A INPUT -i eth0 -p icmp -m icmp -‐icmp-type 8 -m limit -‐limit 1/sec -j ACCEPT -A INPUT -p tcp -m tcp -‐dport 22 -j ACCEPT -A INPUT -p udp -m udp -‐dport 1194 -j ACCEPT -A INPUT -i eth0 -p tcp -m tcp -j DROP -A INPUT -i eth0 -p udp -m udp -j DROP -A FORWARD -i tun0 -j ACCEPT -A FORWARD -m state -‐state RELATED,ESTABLISHED -j ACCEPT -A OUTPUT -o tun0 -j ACCEPT -A OUTPUT -o lo -j ACCEPT -A OUTPUT -p icmp -m state -‐state NEW -j ACCEPT COMMIT
Step 6: turn on packet forwarding so the NAT works, by editing /etc/sysctl.conf:
net.ipv4.ip_forward = 1
Step 7: Sign up for a free account with DynDNS, install the perl-IO-Socket-SSL package, download a copy of ddclient, unpack it,, and follow the 7-step install instructions in the README, putting the following into /etc/ddclient/ddclient.conf (substituting appropriate values for the placeholders):
daemon=600 syslog=yes mail-failure=EMAIL pid=/var/run/ddclient.pid use=web, web=169.254.169.254/latest/meta-data/public-ipv4 login=USER password=PASSWD protocol=dyndns2 server=members.dyndns.org HOST.dyndns.org
Step 8: reboot your EC2 server; when it comes back up, login to it by its new DynDNS name. If you’re ssh’ing from Linux or a Mac, the following lines in ~/.ssh/config will make your life a little easier:
Host HOST.dyndns.org User ec2-user IdentityFile /myhomedir/.ssh/amazon-key-file.pem UserKnownHostsFile=/dev/null StrictHostKeyChecking=no
Step 9: copy the following files from your easy-rsa keys directory down to your client machine, putting them wherever your client tells you: ca.crt, dh1024.pem, client1.crt, client1.key, ta.key.
TunnelBlick: ~/Library/Application Support/TunnelBlick/Configurations
OpenVPN GUI: \Program Files\OpenVPN\config
Step 10: create a client config file in the same directory, named openvpn.conf (for Windows, openvpn.ovpn), containing the following, substituting your DynDNS hostname:
client dev tun proto udp remote HOST.dyndns.org 1194 resolv-retry infinite persist-key persist-tun ca ca.crt cert client1.crt key client1.key tls-auth ta.key 1 ns-cert-type server verb 3
Step 11: fire up your OpenVPN client and surf to some page that will report your current IP address, like DSLReports.com. If everything worked, you can not only reach the outside world, but your IP address will match the current value of your dynamic DNS host name.
Step 12: shut down your EC2 server when you’re not using it. A t1.micro is cheap to run 24x7, but it’s even cheaper 2x4.
Note that with a minor config change, you can set up a split-tunnel VPN with local subnet access, allowing you to do things like securely access another machine that’s connected to the same VPN, wherever it happens to be, without having to open incoming firewall holes, even if they’re both hidden behind NAT routers. Just replace the two “push” lines in the server openvpn.conf with: