Installing, Configuring Open VPN on Ubuntu Server with Certificate and Password Authorization

Quickly and Easily Construct Secure Networks

Michael Chletsos
OpenVPN is great for creating secure networks across logical or physical distances. With OpenVPN, you can OpenSSL library to encrypt a two physically disparate networks to run as a single homogeneous network over a single UDP or TCP port. Another nice feature of OpenVPN is that it runs on Linux, Windows 2000, Windows XP, Windows Vista, OpenBSD, FreeBSD, NetBSD, Mac OS X, and Solaris operating systems. There is a gui frontend to control OpenVPN on Windows, Mac OS X, Linux, and KDE. If you need access to the office from a remote location or laptop or a site to site VPN, OpenVPN allows for an easy to use secure connection to be established easily.

Initial Installation:

To install OpenVPN on your Ubuntu system type the following at a command prompt:

sudo apt-get install openvpn openvpn-blacklist bridge-utils openssl

make a directory to store keys:

sudo mkdir -p /etc/openvpn/keys

Copy the openvpn file structure to ensure future upgrades will not overwrite your configuration changes:

sudo cp -r /usr/share/doc/openvpn/* /usr/src/openvpn/

cd /usr/src/openvpn/examples/easy-rsa/2.0/

Generate Server and Client Certificates:

Here we will generate the keys and certificate that will allow for the encryption of your data.

Generate Certificate Authority (CA) Certificate and Key first by editing the vars file (sudo vi /usr/src/openvpn/examples/easy-rsa/2.0/vars) and change these values:

export KEY_COUNTRY="US"

export KEY_PROVINCE="NM"

export KEY_CITY="MyCity"

export KEY_ORG="MyCompany"

export KEY_EMAIL="sysadmin@mycompany.com"

If you want to have more security, or are really paranoid, you can change the key size from 1024 to 2048 by changing this value:

export KEY_SIZE=2048

This will slowdown the TLS negotiation and the Diffie-Hellman parameters generation process, that you will perform later.

Now we must initialize the Public Key Infrastructure (PKI):

first source the vars file (the next command is period space period forward-slash vars:

. ./vars

clean up the directory:

./clean-all

build the PKI:

./build-ca

Country Name (2 letter code) [US]:
State or Province Name (full name) [NM]:
Locality Name (eg, city) [MyCity]:
Organization Name (eg, company) [MyCompany]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [MyCompany CA]:
Email Address [sysadmin@mycompany.com]:

Next we generate the server key without a challenge password:

./build-key-server server

Country Name (2 letter code) [US]:
State or Province Name (full name) [NM]:
Locality Name (eg, city) [MyCity]:
Organization Name (eg, company) [MyCompany]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [server]:
Email Address [sysadmin@mycompany.com]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/src/openvpn/examples/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'NM'
localityName          :PRINTABLE:'MyCity'
organizationName      :PRINTABLE:'MyCompany'
commonName            :PRINTABLE:'server'
emailAddress          :IA5STRING:'sysadmin@mycompany.com'
Certificate is to be certified until Nov  9 14:44:59 2018 GMT (3650 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y

(Alternatively to build with a challenge password use ./build-key-pass maybe used instead of ./build-key-server. There is also ./build-key-pkcs12 which will produce a PKCS #13 format. And ./build-key which will not designate the certificate as a server-only cert, not recommended.)

Now Create a client certificate for each client:

./build-key client1 #Here you put the username of the client and repeat for each client

Country Name (2 letter code) [US]:
State or Province Name (full name) [NM]:
Locality Name (eg, city) [MyCity]:
Organization Name (eg, company) [MyCompany]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) [username]:
Email Address [username@mycompany.com]:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /usr/src/openvpn/examples/easy-rsa/2.0/openssl.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
countryName           :PRINTABLE:'US'
stateOrProvinceName   :PRINTABLE:'NM'
localityName          :PRINTABLE:'MyCity'
organizationName      :PRINTABLE:'MyCompany'
commonName            :PRINTABLE:'username'
emailAddress          :IA5STRING:'username@mycompany.com'
Certificate is to be certified until Nov  9 14:46:45 2018 GMT (3650 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y

Generate Diffie-Hellman (A protocol that allows two users to exchange a secret key over an insecure medium without any prior secret keys) parameters:
./build-dh

Generating DH parameters, 1024 bit long safe prime, generator 2
This is going to take a long time
.................+...........................................
...................+.............+.................+.........
......................................

Now that we have done this, we have generated our certs in keys in the keys subdirectory. Here is a listing of what keys and files we have and who needs it and what the purpose is:

File Location Purpose Secret

ca.crt server and all clients Root CA certificate Public

ca.key key signing machine Root CA key PRIVATE

dh1024.pem server only Diffie Hellman parameters Public

server.crt server only Server Certificate Public

server.key server only Server Key PRIVATE

client1.crt client1 only Client1 Certificate Public

client1.key client1 only Client1 Key PRIVATE

Copy the server keys into their appropriate locations:

sudo scp /usr/src/openvpn/examples/easy-rsa/2.0/keys/ca.crt /usr/src/openvpn/examples/easy-rsa/2.0/keys/ca.key /usr/src/openvpn/examples/easy-rsa/2.0/keys/dh1024.pem /usr/src/openvpn/examples/easy-rsa/2.0/keys/server.crt /etc/openvpn/keys

Distribute the client keys to the appropriate clients either with scp or possibly via a cd. I would use a secure method since you are transferring the Secret keys.

ca.crt client1.crt and client1.key should be copied to the client machine.

(Alternatively you could have the client generate its own private key locally and send in a Certificate Signing Request (CSR) to the key signing machine, and then provide the client back with a signed certificate. This way no key files need be transferred around and this method should be used if using insecure transfers of the file..)

Configuring OpenVPN Server:

The first decision when configuring an OpenVPN server is whether to Bridge or Route the traffic through the VPN tunnel. Generally speaking routing is a more efficient and is easier to set up than bridging, but bridging allows for the creation of a wide area virtual network. Bridges must use OS specific tools in order to "bridge" a physical ethernet adapter and a virtual TAP device. Once connected to the VPN server, the client is assigned an IP address that is part of the server's subnet, which allows it to interact with this subnet as if it were local. Routed VPN's, however, have the clients use their own subnet and sets up a rout on the client and server in order to connect the two subnets. We will be setting up a bridged VPN since we want complete access for our roadwarriors. The key advantages to using bridging is that no routing statements need be configured on the client or the server and broadcasts will traverse the VPN allowing for complete access to the server (office) LAN. Routing the VPN, while it may be slightly more efficient and thereby more scalable, one must setup routes for each subnet to link the server and client networks together and if trying to use services that rely on broadcasts, you must setup up specialized software like a WINS server.

To get a basic config for OpenVPN do the following:

cd /etc/openvpn/

gunzip /usr/src/openvpn/examples/sample-config-files/server.conf.gz

cp /usr/src/openvpn/examples/sample-config-files/server.conf /etc/openvpn/

vi /etc/openvpn/server.conf

Configuring OpenVPN can be a rather confusing task, following is a basic configuration built off of the above config with some comments to help you understand the directives:

# Which local IP address should OpenVPN

# listen on? (optional)

local 192.168.0.121

# Which TCP/UDP port should OpenVPN listen on? 
# If you want to run multiple OpenVPN instances 
# on the same machine, use a different port 
# number for each one.  You will need to 
# open up this port on your firewall. 
port 1194 

# TCP or UDP server? 
;proto tcp 
proto udp 

dev tap0 #when using a bridge you must use a tap device, we will set it up later.
;dev tun #a tun device is more efficient and should be used with a routing setup.

ca keys/ca.crt #location of the ca.crt we created earlier
cert keys/server.crt #location of the server.crt we created earlier
key keys/server.key  #location of the server.key This file should be kept secret

# Diffie hellman parameters. 
# Generate your own with: 
#   openssl dhparam -out dh1024.pem 1024 
# Substitute 2048 for 1024 if you are using 
# 2048 bit keys. 
dh keys/dh1024.pem 

;server 10.8.0.0 255.255.255.0 #this directive is for use with routing setups.

Server-bridge 192.168.0.121 255.255.255.0 192.168.0.225 192.168.0.230 #This directive is effectively your dhcp for your clients.  Ensure that you use an ip space that is not currently in use or potential use.  Here we are allocating .225 - .230 for our clients.  And we are using the 192.168.0.121 interface.

;push "route 192.168.0.0 255.255.255.0" #pushing our office lan route to client

;push "route 10.0.0.0 255.255.255.0" #here we are pushing another office lan to the client.


push "dhcp-option DNS 192.168.0.2" #pushing our office dns servers to client
push "dhcp-option WINS 192.168.0.3" #pushing our office wins servers to client

# Uncomment this directive to allow different 
# clients to be able to "see" each other. 
# By default, clients will only see the server. 
# To force clients to only see the server, you 
# will also need to appropriately firewall the 
# server's TUN/TAP interface. 
client-to-client 

;duplicate-cn #this directive would allow clients to have more than one connection

;keepalive 10 120 # same as ping 10 ping-restart 120 push "ping 10" push "ping-restart 120"
ping 10 # ping client every 10 secs
;ping restart 3600 # force a key renegotation if ping fails for 3600 secs
push "ping 10" # push ping 10 directive to client
ping-exit 3600 # force disconnect with client if no ping for 3600
push "ping-exit 3600" #push the ping-exit 3600 directive to client

#lets add some pam auth (optional - can authenticate against radius or ldap with pam - must do optional step at end of howto)
plugin /usr/lib/openvpn/openvpn-auth-pam.so system-auth

# Select a cryptographic cipher. 
# This config item must be copied to 
# the client config file as well. 
;cipher BF-CBC        # Blowfish (default) 
cipher AES-128-CBC   # AES 
;cipher DES-EDE3-CBC  # Triple-DES 

# Enable compression on the VPN link. 
# If you enable it here, you must also 
# enable it in the client config file. 
comp-lzo 

# Output a short status file showing 
# current connections, truncated 
# and rewritten every minute. 
status openvpn-status.log 

# The persist options will try to avoid 
# accessing certain resources on restart 
# that may no longer be accessible because 
# of the privilege downgrade. 
persist-key 
persist-tun 

# By default, log messages will go to the syslog (or 
# on Windows, if running as a service, they will go to 
# the "\Program Files\OpenVPN\log" directory). 
# Use log or log-append to override this default. 
# "log" will truncate the log file on OpenVPN startup, 
# while "log-append" will append to it.  Use one 
# or the other (but not both). 
;log         openvpn.log 
log-append  /var/log/openvpn.log

# Set the appropriate level of log 
# file verbosity. 
# 
# 0 is silent, except for fatal errors 
# 4 is reasonable for general usage 
# 5 and 6 can help to debug connection problems 
# 9 is extremely verbose 
verb 3 

#do not cache auth (necessary if you use a one-time passcode like RSA authentication to prevent stale passwords.)
push "auth-nocache"

#stopping renegotiation (necessary if using a one-time passcode)
reneg-sec 0

There are so many more directives you can use in the OpenVPN config, but this will get you a basic setup that is robust and gives you a pretty good understanding of what OpenVPN can do.

Setup TAP device:

Since we are using a TAP device, we need to set it up with a script so that it can restart at boot time.

vi /etc/init.d/openvpn-bridge

#!/bin/bash
#################################
# Set up Ethernet bridge on Linux
# Requires: bridge-utils
#################################

# Define Bridge Interface
br="br0"

# Define list of TAP interfaces to be bridged,
# for example tap="tap0 tap1 tap2".
tap="tap0"

# Define physical ethernet interface to be bridged
# with TAP interface(s) above.
eth="eth1"
eth_ip="192.168.0.121"
eth_netmask="255.255.255.0"
eth_broadcast="192.168.0.255"
eth_gw="192.168.0.254"
start_bridge(){

for t in $tap; do
openvpn --mktun --dev $t
done

brctl addbr $br
brctl addif $br $eth

for t in $tap; do
brctl addif $br $t
done

for t in $tap; do
ifconfig $t 0.0.0.0 promisc up
done

ifconfig $eth 0.0.0.0 promisc up
ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast
route add default gw $eth_gw $br
}

stop_bridge(){

ifconfig $br down
brctl delbr $br
for t in $tap; do
openvpn --rmtun --dev $t
done

ifconfig $eth $eth_ip netmask $eth_netmask broadcast $eth_broadcast up   
route add default gw $eth_gw $eth
}
case "$1" in 
start) 
echo -n "Starting Bridge" 
start_bridge
;; 
stop)
echo -n "Stopping Bridge"
stop_bridge
;; 
restart)
stop_bridge
sleep 2
start_bridge
;; 
*)
echo "Usage: $0 {start|stop|restart}" >&2
exit 1
;; 
esac 

Fix Permissions:

chmod 755 /etc/init.d/openvpn-bridge

Set to startup/shutdown automatically:

update-rc.d openvpn-bridge stop 81 1 6 . start 15 2 3 4 5 .

test interface:

/etc/init.d/openvpn-bridge start

Getting PAM-auth to work with radius (Optional):

Using PAM-authentication is an easy way to integrate OpenVPN with products such as RSA radius authentication or Secure Computing SafeWord.

apt-get install libpam-radius-auth

Edit Config file:
vi /etc/pam_radius_auth.conf

#127.0.0.1      secret             1
other-server    other-secret       3
Setting up an OpenVPN server on Ubuntu is not hard, but can be very confusing. Please ensure that you know what you are doing before you just blindly follow this setup. It does use a TAP device which allows complete transparency of disparage networks. This could be a security hole if you do not understand what you are doing. All in all, OpenVPN is a great product and will allow you to easily and cheaply setup a VPN tunnel.

To comment, please sign in to your Yahoo! account, or sign up for a new account.