Creating an OpenVPN Server on Ubuntu

Dec 1, 2010

I have long used an SSH tunnel (put simply: ssh -D 8000 server + FoxyProxy) to browse the web securely from unencrypted wireless access points and other potentially hostile networks. While this is secure, it isn’t all that convenient and has inherent problems. What I really want is a proper VPN, that will seamlessly encapsulate all traffic from my local machine and pass it through the tunnel to be emitted by the server. OpenVPN is one of those things that has a reputation for being difficult to setup,so I long avoided it. Once I decided to actually make with the go, it turned out to not be terribly difficult, though I did have to do a bit of searching to get exactly what I wanted.

There are a number of good tutorials for setting up OpenVPN, and the following instructions will mostly mirror those. First, install the requisite packages:

caligula:~$ sudo aptitude install openvpn

Then, setup a place to generate the requisite keys:

    caligula:~$ mkdir tmp/vpn && cd vpn
    caligula:~/tmp/vpn$ cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/* .

At this point, many tutorials (the above mentioned ones included) say that you should run ./init-config, which doesn’t exist in recent version OpenVPN. With the scripts for generating keys in place, open up vars and edit the stuff at the bottom, which should be pretty straightforward:

    export KEY_COUNTRY="US"
    export KEY_PROVINCE="NY"
    export KEY_CITY="Rochester"
    export KEY_ORG="Dinomite-Net"
    export KEY_EMAIL="drew@dinomite.net"

The vars file just sets up a bunch of environment variables, so you’ll want to source it and then build the certificate authority:

    caligula:~/tmp/vpn$ source vars
    caligula:~/tmp/vpn$ ./clean-all
    caligula:~/tmp/vpn$ ./build-ca

Building the certificate authority involves a few questions, for most of which the defaults defined from vars are all you need. Next, build the keys for the server and client (I name my computers after Roman emperors):

    caligula:~/tmp/vpn$ ./build-key-server caligula
    caligula:~/tmp/vpn$ ./build-key vespasian
    caligula:~/tmp/vpn$ ./build-dh

With all that done, you can copy the appropriate key files over to the client, in my case vespasian. Since I already had tunnelblick on that machine, I put the files directly where they needed to go:

caligula:~/tmp/vpn$ cd keys
caligula:~/tmp/vpn/keys$ scp vespasian.crt vespasian.key \
    ca.crt vespasian:~/Library/Application Support/Tunnelblick/Configurations/

Two steps left. First, make the client configuration file. For tunnelblick, this goes in the same directory as above, and you can name it whatever you want:

    vespasian:~$ cat Library/Application Support/Tunnelblick/Configurations/client.conf
    client
    dev tun
    proto udp
    remote caligula.dinomite.net 1194
    resolv-retry infinite
    nobind
    persist-key
    persist-tun
    ca ca.crt
    cert vespasian.crt
    key vespasian.key
    comp-lzo
    verb 3

There are plenty of other sites that will explain what all of those options mean, so I won’t go over it here. The important things to change from above are the remote and the names for the cert and key. Now on to the server config and the files that it needs:

    caligula:~/tmp/vpn/keys$ cp dh1024.pem caligula.key caligula.crt /etc/openvpn/
    caligula:~/tmp/vpn/keys$ cat /etc/openvpn/server.conf
    server 10.7.7.0 255.255.255.0
    push "redirect-gateway"

    dev tun0
    proto udp
    keepalive 10 120
    comp-lzo
    dh /etc/openvpn/dh1024.pem
    ca /etc/openvpn/ca.crt
    cert /etc/openvpn/caligula.dinomite.net.crt
    key /etc/openvpn/caligula.dinomite.net.key

    status /var/log/openvpn-status.log
    verb 3

The secret sauce in that config is push "redirect-gateway" which is what tells the client to route all of its traffic through the tunnel to the server. To make this work, the server needs to be set up to do NAT:

    caligula:~/tmp/vpn/keys$ echo "1" > /proc/sys/net/ipv4/ip_forward
    caligula:~/tmp/vpn/keys$ iptables -t nat -A POSTROUTING -s 10.7.7.0/24 -o eth0 -j MASQUERADE

That’s all there is to it! Just restart the server (sudo /etc/init.d/openvpn restart), connect, and all your traffic is now safely encrypted to the server.