Setting up an OpenVPN Server on Ubuntu 14.10

VPN Introduction

I have been doing some work with VPNs lately, having set up a PPTP(Point to Point Tunneling Protocol) VPN for some Android network analysis that I have been doing lately.  It is easy to set up on a server and a mobile device, but PPTP generally isn’t secure unless you are using (P)EAP.  I wanted to try out something that overlaps with something that I’m pretty knowledgeable about, TLS/SSL, with something I have never had to actually set up, an SSL VPN.  Most people who use a VPN to connect into work use an SSL VPN.  Probably either from someone like Cisco or Juniper.  They are pretty easy to set up on the router side of things, and relatively easy for client device to get set up.  Other advantages are that they can be run over port 443, so they won’t be blocked by most firewalls, and that they use the verification properties inherent to TLS/SSL rather than some sort of challenge-response handshake.  Using TLS/SSL allows them to also be flexible about key sizes and cipher suites used and upgrade them as the future requires.

OpenVPN

I went with OpenVPN for setting up an SSL VPN because it is free, and I could install it on hardware I have.  I started with a plain Ubuntu 14.10 server box.  First we need to install a few prerequisites.


$sudo apt-get install bridge-utils openvpn libssl-dev openssl

OpenVPN makes use of a bridge adapter(br0) that sits between the internal clients, once connected, and the external interface(eth0).  We need to modify our network config to add this bridge adapter in.


$sudo nano /etc/network/interfaces

This file should look something like the below file, substituting out the IP information for your machine.  I just moved the info that was in eth0 to br0.


# This file describes the network interfaces available on your
# system and how to activate them. For more information, see
# interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

auto br0
iface br0 inet static
        address 104.236.7.54
        netmask 255.255.192.0
        gateway 104.236.0.1
        network 104.236.0.0
        broadcast 104.236.63.254
        dns-nameservers 8.8.8.8 8.8.4.4

        bridge_ports eth0

        bridge_fd 9
        bridge_hello 2
        bridge_maxage 12
        bridge_stp off

# The primary network interface
auto eth0
#iface eth0 inet static
#        address 104.236.7.54
#        netmask 255.255.192.0
#        gateway 104.236.0.1
#        dns-nameservers 8.8.8.8 8.8.4.4
iface eth0 inet manual
        up ip link set $IFACE up promisc on
        down ip link set $IFACE down promisc off

Next we need to turn on IP forwarding.  We do this in sysctl to make sure that the setting survives a reboot.


$sudo nano /etc/sysctl.conf

Uncomment this line


net.ipv4.ip_forward=1

Reboot the server.


$sudo shutdown -r 0

At this point you may want to do some pinging and whatnot to make sure your networking situation is still intact.

OpenVPN uses a tool called “Easy RSA”. Basically this functions as a very barebones PKI(Public Key Infrastructure) that helps you issue certificates for your server and clients. The reason that OpenVPN needs a PKI is to issue the server certificate and if using client certs, to issue those as well. One of the things that surprised me about OpenVPN is that the certificates are self-signed. I looked into whether or not you can use third-party signed certs for the server side of OpenVPN to make client configuration easier. Because of the way OpenVPN works on the client, you have to at least install a config, and in our case client certificates as well so installing a the public key of the server on the client isn’t really extra work. Anyway, back to it, we install Easy RSA.

apt-get install easy-rsa

We tell it where the CA is going to be located.

make-cadir /etc/openvpn/easy-rsa

We need to set up some options for our self-signed certificated

sudo nano /etc/openvpn/easy-rsa/vars

Modify these to suit your situation.

export KEY_COUNTRY="CA"
export KEY_PROVINCE="SK"
export KEY_CITY="Some Town"
export KEY_ORG="JimCo"
export KEY_EMAIL="spam@spam.com"

Now we are going to set up our CA.

cd /etc/openvpn/easy-rsa/

Load the options into environmental variables

source vars

Make sure we are starting from a clean slate

./clean-all

We generate a Diffie-Hellman parameter for the server end of things so that Perfect Forward Secrecy can be maintained.

./build-dh

This generates the server private key and csr(ca.key and ca.csr).

./pkitool --initca

This creates the self-signed certificate(ca.crt).

./pkitool --server server

At first I thought this step was generating a static key to do something that I had read about but never seen implemented, TLS-PSK, but the fact that we generated a Diffie Hellman perameter a few steps ago made me skeptical of that. But according to the OpenVPN documentation the tls-auth directive, requires you to authenticate with a static key before you even attempt any computationally expensive public key encryption.

cd keys
openvpn --genkey --secret ta.key

Now we copy out server’s certificate, and private key, our Diffie Hellman parameter and static key to the OpenVPN configuration directory, /etc/openvpn. I believe this is where our config file looks for them.

sudo cp server.crt server.key ca.crt dh2048.pem ta.key ../../

Next we create a startup script for OpenVPN.

nano /etc/openvpn/up.sh

#!/bin/sh
BR=$1
DEV=$2
MTU=$3
/sbin/ifconfig $DEV mtu $MTU promisc up
/sbin/brctl addif $BR $DEV

And a shutdown script as well.

nano /etc/openvpn/down.sh
#!/bin/sh
BR=$1
DEV=$2
/sbin/brctl delif $BR $DEV
/sbin/ifconfig $DEV down

Make them executable.

sudo chmod +x /etc/openvpn/up.sh /etc/openvpn/down.sh

We need to write our server config. Make sure you set any options, like port or IP/hostname. You may want to run over 443 to avoid firewalls. You also set the network information for clients that are connecting within this file.

sudo nano /etc/openvpn/server.conf
mode server
tls-server

local 104.236.7.54 ## ip/hostname of server
port 1194 ## default openvpn port
proto udp

#bridging directive
dev tap0 ## If you need multiple tap devices, add them here
up "/etc/openvpn/up.sh br0 tap0 1500"
down "/etc/openvpn/down.sh br0 tap0"

persist-key
persist-tun

#certificates and encryption
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh dh2048.pem
tls-auth ta.key 0 # This file is secret

cipher BF-CBC        # Blowfish (default)
comp-lzo

#DHCP Information
ifconfig-pool-persist ipp.txt
server-bridge 192.168.1.10 255.255.255.0 192.168.1.100 192.168.1.110
push "dhcp-option DNS 8.8.8.8"
push "dhcp-option DOMAIN secstuff.org"
max-clients 10 ## set this to the max number of clients that should be connected at a time

#log and security
user nobody
group nogroup
keepalive 10 120
status openvpn-status.log
verb 3

A guide I read recommended creating this file, but may not be necessary.

touch /usr/share/openssl-blacklist/blacklist.RSA-4096

Restart the OpenVPN service.

sudo /etc/init.d/openvpn restart

Now we need to generate a certificate and key that we will copy down to the client. Feel free to use the actual name of your client instead of client-cert. It is recommended that you create a unique client certificate for each client connecting in.


cd /etc/openvpn/easy-rsa/
source vars
./pkitool client-cert

You will need to copy these files down to the client. The signing certificate, so that the client trusts your VPN, the client certificate and private key so that the VPN can trust your client, and the static key for pre-authentication.

/etc/openvpn/easy-rsa/keys/ca.crt
/etc/openvpn/easy-rsa/keys/client-cert.key
/etc/openvpn/easy-rsa/keys/ta.key
/etc/openvpn/easy-rsa/keys/client-cert.crt

Put those files in the configuration folder on the client. For example on Windows it is “C:\Program Files\OpenVPN\Config\”. Next create a config file with the following contents in the same folder. On Windows name it “client.ovpn”, and on other platforms call it “client.conf”

### Client configuration file for OpenVPN

# Specify that this is a client
client

# Bridge device setting
dev tap

# Host name and port for the server (default port is 1194)
# note: replace with the correct values your server set up
remote secstuff.org 1194

# Client does not need to bind to a specific local port
nobind

# Keep trying to resolve the host name of OpenVPN server.
## The windows GUI seems to dislike the following rule.
##You may need to comment it out.
resolv-retry infinite

# Preserve state across restarts
persist-key
persist-tun

# SSL/TLS parameters - files created previously
ca ca.crt
cert client-cert.crt
key client-cert.key

# Since we specified the tls-auth for server, we need it for the client
# note: 0 = server, 1 = client
tls-auth ta.key 1

# Specify same cipher as server
cipher BF-CBC

# Use compression
comp-lzo

# Log verbosity (to help if there are problems)
verb 3

And you should be done! OpenVPN requires a bit more hands-on than other VPNs for client setup, but hey it is free. I also took a look at OpenVPN Access Server which gives you a very similar experience to Juniper or Cisco SSL VPNS, but near as I can tell it is a commercial offering that requires a license for more than 2 concurrent connections. Looks promising though.

Photo Credit.

6 thoughts on “Setting up an OpenVPN Server on Ubuntu 14.10

  1. Hi,
    first, thanks for the great guide.
    I followed your steps and was able to connect with my Windows OpenVPN client.
    But I think i made a error somewhere along the way since my IP-Adress doesn’t change.
    My SSH connections don’t break up either if they are active while i connect via the OpenVPN too.

    Following is the Connection log i get when connecting. (only change i made in the config is changing Port)

    Tue Dec 09 19:31:32 2014 OpenVPN 2.3.6 x86_64-w64-mingw32 [SSL (OpenSSL)] [LZO] [PKCS11] [IPv6] built on Dec 1 2014
    Tue Dec 09 19:31:32 2014 library versions: OpenSSL 1.0.1j 15 Oct 2014, LZO 2.08
    Tue Dec 09 19:31:32 2014 MANAGEMENT: TCP Socket listening on [AF_INET]127.0.0.1:25340
    Tue Dec 09 19:31:32 2014 Need hold release from management interface, waiting…
    Tue Dec 09 19:31:33 2014 MANAGEMENT: Client connected from [AF_INET]127.0.0.1:25340
    Tue Dec 09 19:31:33 2014 MANAGEMENT: CMD ‘state on’
    Tue Dec 09 19:31:33 2014 MANAGEMENT: CMD ‘log all on’
    Tue Dec 09 19:31:33 2014 MANAGEMENT: CMD ‘hold off’
    Tue Dec 09 19:31:33 2014 MANAGEMENT: CMD ‘hold release’
    Tue Dec 09 19:31:33 2014 WARNING: No server certificate verification method has been enabled. See http://openvpn.net/howto.html#mitm for more info.
    Tue Dec 09 19:31:33 2014 Control Channel Authentication: using ‘ta.key’ as a OpenVPN static key file
    Tue Dec 09 19:31:33 2014 Outgoing Control Channel Authentication: Using 160 bit message hash ‘SHA1’ for HMAC authentication
    Tue Dec 09 19:31:33 2014 Incoming Control Channel Authentication: Using 160 bit message hash ‘SHA1’ for HMAC authentication
    Tue Dec 09 19:31:33 2014 Socket Buffers: R=[65536->65536] S=[65536->65536]
    Tue Dec 09 19:31:33 2014 UDPv4 link local: [undef]
    Tue Dec 09 19:31:33 2014 UDPv4 link remote: [AF_INET][ServerIP]:1199
    Tue Dec 09 19:31:33 2014 MANAGEMENT: >STATE:1418149893,WAIT,,,
    Tue Dec 09 19:31:33 2014 MANAGEMENT: >STATE:1418149893,AUTH,,,
    Tue Dec 09 19:31:33 2014 TLS: Initial packet from [AF_INET][ServerIP]:1199, sid=221fe21b 5cccfc19
    Tue Dec 09 19:31:33 2014 VERIFY OK: depth=1, C=FR, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=MyOrganizationalUnit, CN=Fort-Funston CA, name=EasyRSA, emailAddress=me@myhost.mydomain
    Tue Dec 09 19:31:33 2014 VERIFY OK: depth=0, C=FR, ST=CA, L=SanFrancisco, O=Fort-Funston, OU=MyOrganizationalUnit, CN=server, name=EasyRSA, emailAddress=me@myhost.mydomain
    Tue Dec 09 19:31:34 2014 Data Channel Encrypt: Cipher ‘BF-CBC’ initialized with 128 bit key
    Tue Dec 09 19:31:34 2014 Data Channel Encrypt: Using 160 bit message hash ‘SHA1’ for HMAC authentication
    Tue Dec 09 19:31:34 2014 Data Channel Decrypt: Cipher ‘BF-CBC’ initialized with 128 bit key
    Tue Dec 09 19:31:34 2014 Data Channel Decrypt: Using 160 bit message hash ‘SHA1’ for HMAC authentication
    Tue Dec 09 19:31:34 2014 Control Channel: TLSv1, cipher TLSv1/SSLv3 DHE-RSA-AES256-SHA, 2048 bit RSA
    Tue Dec 09 19:31:34 2014 [server] Peer Connection Initiated with [AF_INET][ServerIP]:1199
    Tue Dec 09 19:31:35 2014 MANAGEMENT: >STATE:1418149895,GET_CONFIG,,,
    Tue Dec 09 19:31:36 2014 SENT CONTROL [server]: ‘PUSH_REQUEST’ (status=1)
    Tue Dec 09 19:31:36 2014 PUSH: Received control message: ‘PUSH_REPLY,dhcp-option DNS 8.8.8.8,dhcp-option DOMAIN [ServerIP],route-gateway 192.168.1.10,ping 10,ping-restart 120,ifconfig 192.168.1.100 255.255.255.0’
    Tue Dec 09 19:31:36 2014 OPTIONS IMPORT: timers and/or timeouts modified
    Tue Dec 09 19:31:36 2014 OPTIONS IMPORT: –ifconfig/up options modified
    Tue Dec 09 19:31:36 2014 OPTIONS IMPORT: route-related options modified
    Tue Dec 09 19:31:36 2014 OPTIONS IMPORT: –ip-win32 and/or –dhcp-option options modified
    Tue Dec 09 19:31:36 2014 do_ifconfig, tt->ipv6=0, tt->did_ifconfig_ipv6_setup=0
    Tue Dec 09 19:31:36 2014 MANAGEMENT: >STATE:1418149896,ASSIGN_IP,,192.168.1.100,
    Tue Dec 09 19:31:36 2014 open_tun, tt->ipv6=0
    Tue Dec 09 19:31:36 2014 TAP-WIN32 device [LAN-Verbindung] opened: \\.\Global\{327E6EAE-F305-4618-8F91-0C1B981E67A9}.tap
    Tue Dec 09 19:31:36 2014 TAP-Windows Driver Version 9.9
    Tue Dec 09 19:31:36 2014 Notified TAP-Windows driver to set a DHCP IP/netmask of 192.168.1.100/255.255.255.0 on interface {327E6EAE-F305-4618-8F91-0C1B981E67A9} [DHCP-serv: 192.168.1.0, lease-time: 31536000]
    Tue Dec 09 19:31:36 2014 Successful ARP Flush on interface [8] {327E6EAE-F305-4618-8F91-0C1B981E67A9}
    Tue Dec 09 19:31:41 2014 TEST ROUTES: 0/0 succeeded len=0 ret=1 a=0 u/d=up
    Tue Dec 09 19:31:41 2014 Initialization Sequence Completed
    Tue Dec 09 19:31:41 2014 MANAGEMENT: >STATE:1418149901,CONNECTED,SUCCESS,192.168.1.100,[ServerIP]

    I replace my Server IP with [ServerIP].

    Do you have any idea why it is not working right?

    Thanks!

    1. “WARNING: No server certificate verification method has been enabled” I’d be interested to see why that is. The way I configured things I believe that verification should work.

  2. Hi Jim,

    Why does your bridge have a publicly routable IP address? Is it supposed to? Is there an unstated assumption here that your VPN server needs to also be your router?

    1. That also confused me. The bridge IP adress is set as 104.236.7.54 at /etc/network/interfaces, but then the OpenVPN server.conf sets it to 192.168.1.10? Or does that only affect the tap0 interface within the br0? Most of the time those two addresses are set the same. Why are they different in this example?

  3. Hi
    I have deploy the website the on my ubuntu server.Now I want my client connect to it.How I will do this please help me.

    I dont have Static ip.

    Thanks
    Arsalan

Leave a Reply