OpenVPN on CoreOS/EC2
Fri, Apr 3, 2015Many public wifi networks are unencrypted to allow password-less access, which makes it easy for someone to sniff your wifi traffic or mount a man-in-the-middle attack. Encrypting the connection via a VPN helps protect your data when it’s intercepted.
Solution Summary
Let’s build a vpn “tunnel” through the internet between my client (ie, laptop/phone) and another secure machine (ie, the server). We’ll collectively call these machines the tunnel endpoints.
All data entering the tunnel is encrypted as it enters an endpoint, and that data is decrypted only as it leaves the tunnel via the other endpoint. All hops along the tunnel and all observers watching the tunnel’s traffic will not be able to decrypt the data.
The Server Endpoint
To protect your wifi traffic, the server needs to be on the internet side of the wifi AP. In other words, the wifi network should be between the two endpoints, so that traffic traversing the wifi network will be encrypted in our VPN tunnel. When connected to the VPN, all internet-bound traffic from the client will pass through this endpoint, so it must be secure, highly available, and provided with sufficient bandwidth. Example diagram below:
client <–encrypted tunnel–> server <–unencrypted internet–> arstechnica.com
AWS micro instances provide cheap real estate (a reserved instance costs $3-4 a month) and decent network bandwidth to ensure the VPN won’t impose a noticeable connection bottleneck for basic web activity. Even youtube and rdio work just fine.
I initially configured an OpenVPN server running on Ubuntu, but have recently switched to an easy-to-deploy docker container running on a CoreOS AMI. Core’s containerized environment and automated patching are good characteristics for an endpoint that must remain secure despite being exposed to the open internet.
Software Ingredients
- OpenVPN - Runs on the server (inside docker). OpenVPN manages the connection, encrypting data going into the tunnel and decrypting data coming out of the tunnel.
- iptables - Runs on the server (inside docker). Provides a bridge between the private VPN network and the public internet.
- TunnelBlick - Runs on the client. It’s an OpenVPN-compliant endpoint for OS X. For iOS, I use the OpenVPN Connect app. There are Windows options too.
Keys, Certificates, and CAs
The easy way to get OpenVPN running is to use symmetric crypto, which requires all endpoints to share the same secret key. This makes key loss catastrophic, however - a compromised phone could compromise the other clients. Fortunately, the docker container provides asymmetric crypto via public key encryption, which is more complex to configure but provides a unique private key to the server and to each client.
Because a client never knows the server’s secret key, a compromised client key only compromises that client. As an added perk, access can be revoked on a per-client basis if needed.
As an overview, here are typical components for a two-client setup under a public key setup (see openvpn docs):
- PKI Certificates - Used to verify client and server identities, these are the public keys. Public keys can be freely distributed because there’s no way to determine the matching private key.
- Certificate Authority cert (stored on each client and server)
- Server cert (stored on each client and server)
- Client A cert (stored on client A and server)
- Client B cert (stored on client B and server)
- Private Key - Known only to the matching endpoint (and no one else!). This key is used to decrypt data that has been encrypted with the matching public key. Never share this with other nodes.
- Server key (stored on server only)
- Client A key (stored on Client A only)
- Client B key (stored on Client B only)
Since the Certificate Authority issues the server and client certificates, it is the ultimate source of trust here. In our small example, this doesn’t mean much, but in a larger VPN provider, this means you only need to trust one entity (the CA) to know that you’re connecting to the right endpoint, since you can verify that the endpoint’s cert was issued by that CA. This is a deep subject in security, but suffice it to say that CA trust chains are a topic of interest to security experts.
Implementation
###Step 1: Deploy OpenVPN Server Software
There are OpenVPN configuration guides elsewhere online. I have previously used Ubuntu 12.04 Server Guide, but fortunately docker makes this a non-issue.
Encapsulating the server in a container makes sense for security and portability reasons; the server doesn’t need access to the rest of the host machine, and a portable container means I can destroy my server instance and boot up another one with ease.
@kylemanna has published a fork of @jpetazzo’s OpenVPN docker container configured for PKI. It is simple to deploy on the server machine. These instructions should be implemented on the server machine. If you’re using a CoreOS host like I am, I’ve published a unit file and instructions at github.com/mypetyak/unit-openvpn.
###Step 2: Retrieve Server Keys and Certs Fortunately, too, the container comes with instructions to extract a single *.ovpn text file with complete client configuration, server certificate, client certificate, and client private key.
This *.ovpn file contains all information needed to establish a trusted connection with the VPN server, so it should be guarded. A secure way to easily transfer this file to the client is to pull it via scp
. Assuming you’re running OpenVPN on an AWS EC2 instance:
On the (OS X) client machine:
scp -i <your_ec2_ssh_credentials.pem> username@server_ip:/<path_to_ovpn_file> client.ovpn
###Step 3: Install Client OpenVPN-compliant client software is available for many platforms. On OS X, I use Tunnelblick.
The *.ovpn file format produced by the server is readily imported into most clients. With Tunnelblick, just double click the ovpn file. With OpenVPN Connect on iOS, follow these instructions
Notes
- VPNs are used for many other things, like sharing resources on the server’s local network with authenticated clients through a firewall. This is why the
redirect-gateway def1
statement is needed in the configuration. By default, OpenVPN will not force the client to route all traffic through the tunnel, just the packets to/from destinations local to the server. - Other (simpler) options that bypass local wifi snoopers include: tethering via USB to your mobile phone network, connecting to a wired network, and connecting to a wifi AP with encryption. A VPN can still be useful in cases where you don’t trust your local network to be free of malware.
- Efforts like Let’s Encrypt are working on making it easy and free for web hosts to deploy end-to-end TLS, but TLS will never be deployed on 100% of the internet since it is host-specific. A VPN tunnel, on the other hand, can guarantee encryption of all web traffic between a machine and the VPN endpoint, protecting all traffic passing through the wifi AP.
- Beware of DNS leaks, in which your computer may bypass the VPN connection for DNS lookups.
- A downside of using the VPN as a redirection gateway is that all traffic must route through the VPN server, regardless of whether that is the most efficient path between the source and destination. For example, if I’m in Berlin accessing a website hosted in Munich via a VPN server in Virginia, all traffic must make a round trip to the US rather than go directly between the two German cities. This can add latency and throttle transmission speeds.
- Outbound traffic is only encrypted up until it reaches the server endpoint. Beyond the server, it is no longer protected by the VPN tunnel. Same goes for inbound traffic - it’s only protected once it reaches the server. An attacker with access to the traffic on the unencrypted side of the server can still mount a man-in-the-middle attack. Thankfully, such an attack requires direct access to internet backbone lines, which makes it much more difficult than coffee shop snooping.
- Not only does the VPN tunnel traverse the wifi network, but the ISP as well (unless the server is hosted by the ISP). This means your internet service provider cannot see your data either.
- The VPN only encrypts the packet payload; it leaves the header data unencrypted. This is by necessity - each router along the way to your endpoint must be able to access the header data so that your packet gets routed to the right destination at the right data rate. A side effect of this is important: someone monitoring your encrypted traffic can still determine where the VPN endpoints are. The rest of the path beyond the endpoint is obscured. Below is a (redacted) tcpdump capture of a packet sent over an encrypted tunnel, something an attacker could obtain with ease. Note that it indicates my traffic is headed to a server at Amazon, though my traffic’s final destination is encrypted within the packet contents:
21:53:37.091286 IP 10.1.242.230.54450 > ec2-XXX-XXX-XXX-XXX.compute-1.amazonaws.com.openvpn: UDP, length 93
0x0000: 4500 0079 ab0c 0000 4011 a9c5 0a01 f2e6 E..y....@.......
0x0010: 36a4 f216 d4b2 04aa 0065 a2c2 31c8 1454 6........e..1..T
0x0020: d362 e0d9 cf27 f5b6 3d04 e2c7 a168 eef5 .b...'..=....h..
0x0030: df9a fad3 246b 9c58 5c08 23fb 5b3d 0b3a ....$k.X\.#.[=.:
0x0040: 3ce1 05eb 7bc5 2f6a db5b e252 21d8 f2ca <...{./j.[.R!...
0x0050: 8975 9b84 8f7c 2352 60fa a757 790a ad27 .u...|#R`..Wy..'
0x0060: 94f2 7797 e6ad 90e9 c11a 7300 cb86 a978 ..w.......s....x
0x0070: 0a26 a222 a15d 1dd5 0d .&.".]...