Updated: Added how to enable the pam plugin for openvpn

Recently I have been digging deep into openstack and came across a personal need to gain access to private network configured within openstack from my external machine. Rather than giving each machine a floating ip. Below is the simple network topology we will setup.

Note: We want the vpn users to exist on

Embeded FullSize

This guide is going to assume the following.

  • You already have a openstack cloud provider / personal lab.
  • You have a public and private network with corresponding subnets. Note: The subnet can be using dhcp and have a gateway set it won’t interfere.
  • You have already create instances on your private network and a instance on your public network with a public ip associated with it to act as the firewall/vpn provider
  • You are using ubuntu for your firewall/vpn distribution
Step 1

First thing that must be done is installing the required packages.

ubuntu@firewall:~$ sudo apt-get install openvpn easy-rsa
Step 2

After the packages are installed we will now need to generate our certificates. The first certificate we are going to generate is our RootCa. If you already have a root ca generated you can utilize your own.

We create a easy-rsa folder in our openvpn folder and copy over the scripts.

ubuntu@firewall:~$ sudo mkdir /etc/openvpn/easy-rsa
ubuntu@firewall:~$ sudo cp -r /usr/share/easy-rsa/* /etc/openvpn/easy-rsa

Now we are going to modify the file titled “vars” in /etc/openvpn/easy-rsa/vars

ubuntu@firewall:~$ sudo nano /etc/openvpn/easy-rsa/vars

In this file you will want to modify the following variables. Within the file.

KEY_COUNTRY = Country of business code ex."US"
KEY_PROVINCE = Province / State of issuer ex. "Texas"
KEY_CITY = City of issuer ex. "Dallas"
KEY_ORG = Organization the certificate belongs to. ex."EvilCorp"
KEY_EMAIL = Administration email for certificate. ex. "admin@evilcorp.com"
KEY_CN = The common name for the cert ex. "XYZ Root CA"
KEY_NAME = The name of the certificate ex."XYZ ROOT CA"
KEY_OU = Organization Unity ex."Administration"
KEY_ALTNAMES = Alternative Name for the certificate "XYZ Root CAFORREAL"

Now that we have configured the variables we need to generate the certificate. For ease of use we will also drop into a root terminal session. When running the build-ca command you will be prompted for information.

ubuntu@firewall:~$ sudo bash
root@firewall:~# cd /etc/openvpn/easy-rsa
root@firewall:/etc/openvpn/easy-rsa# source vars
root@firewall:/etc/openvpn/easy-rsa# ./clean-all
root@firewall:/etc/openvpn/easy-rsa# ./build-ca

You should now have to files in the keys directory ca.crt and ca.key.

Next we need to generate our vpn server’s certificates. You will be prompted for input.

Note: You can change “MyVpnServerCert” to whatever name you want Note: Make sure when it asks if you want to sign the certificate that you sign it or else there will be problems

root@firewall:/etc/openvpn/easy-rsa# ./build-key-server MyVpnServerCert

Now that we have that configured we need to generate our Diffie-Hellman parameters file.

root@firewall:/etc/openvpn/easy-rsa# ./build-dh

Finally the last thing we need to generate a shared secret file to help prevent against DDOS and other Nasty things.

root@firewall:/etc/openvpn/easy-rsa# openvpn --genkey --secret ta.key

Now we copy these files we have generated to the /etc/openvpn/certs folder.

root@firewall:/etc/openvpn/easy-rsa# mkdir /etc/openvpn/certs
root@firewall:/etc/openvpn/easy-rsa/keys# cd keys
root@firewall:/etc/openvpn/easy-rsa/keys# cp ca.crt /etc/openvpn/certs/
root@firewall:/etc/openvpn/easy-rsa/keys# cp MyVpnServerCert.crt /etc/openvpn/certs/
root@firewall:/etc/openvpn/easy-rsa/keys# cp MyVpnServerCert.key /etc/openvpn/certs/
root@firewall:/etc/openvpn/easy-rsa/keys# cp dh2048.pem /etc/openvpn/certs/
root@firewall:/etc/openvpn/easy-rsa/keys# cp ta.key /etc/openvpn/certs/
root@firewall:/etc/openvpn/easy-rsa/keys# cd ../
Step 3

Now we need to configure the openvpn server itself. First we will copy the example configuration file for openvpn to our openvpn folder.

root@firewall:/etc/openvpn/easy-rsa# cd /etc/openvpn
root@firewall:/etc/openvpn# cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz .
root@firewall:/etc/openvpn# gunzip -d server.conf.gz

A file named “server.conf” should be in /etc/openvpn. There is quite a few changes we must make to this.

root@firewall:/etc/openvpn# nano server.conf

*First we enable the openvpn pam plugin

At the top of the file add the following line

plugin /usr/lib/openvpn/openvpn-plugin-auth-pam.so openvpn

Next we have to set the correct protocol

By default it is set to udp which is fine for most networks. However certain providers have a problem with udp tunneled traffic dropping. Because of this we set it to tcp.

Find the line that states the following.

proto udp

Change it to the following

proto tcp

Next we have to set the correct certificate

Find the following two lines.

ca ca.crt
cert server.crt
key server.key

Change them to the following

ca certs/ca.crt
cert certs/MyVpnServerCert.crt
key certs/MyVpnServerCert.key

Now we need to set the correct Diffie-Hellman parameters.

Find the line that states

dh dh1024.pem

Change it to the following

dh dh2048.pem

Next we need to configure the vpn client address that is issues out.

Locate the following line


Replace it with the following


Next we need to configure our “route” to the network.

Find the following line

;push "route"

Under that line add the following line.

push "route"

Next we enable the duplicate cn

This allows us to issue one client cert that is reused by others. We do this so we only need to hand out one set of client certificates.

Find the following line


Change it to the following


Next just need to enable the shared secret

Find the following line.

;tls-auth ta.key 0

Change it to the following

tls-auth certs/ta.key 0

Finally we just enable logging to help with our sanity

Find the following line

;log openvpn.log

Change it to the following

log openvpn.log

Now that the openvpn server configuration is done we just need to start it.

service openvpn start
Step 5

We need to create the pam service file and user group for our openvpn users.

root@firewall:/etc/openvpn# touch /etc/pam.d/openvpn
root@firewall:/etc/openvpn# nano /etc/pam.d/openvpn

Now we add the following two lines inside our openvpn service file

auth    required        pam_unix.so    shadow    nodelay
account required        pam_unix.so

Close the file then run the following command

root@firewall:/etc/openvpn#groupadd openvpn
Step 6

To finish the server configuration we need to allow for our vpn server to act as a router.

To enable the functionality immediately we need to do the following.

Run the following command to enable ip_forwarding

root@firewall:/etc/openvpn# echo "1" > /proc/sys/net/ipv4/ip_forward

Now the iptables to allow our packets to be forward to the correct destination.

Note: the eth1 interface is important in the POSTROUTING if you pick the wrong interface you will not be able to communicate with the private network

root@firewall:/etc/openvpn# iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
root@firewall:/etc/openvpn# iptables -A FORWARD -s -j ACCEPT
root@firewall:/etc/openvpn# iptables -A FORWARD -j REJECT
root@firewall:/etc/openvpn# iptables -t nat -A POSTROUTING -s -o eth1 -j MASQUERADE

Now we just need to make it permanent.

First to ensure that ip forwarding is always enabled we need to modify the sysctl configuration.

root@firewall:/etc/openvpn# nano /etc/sysctl.conf

Find the following line


Change it to the following


Finally we persist the iptables data.

We achieve this by doing it the lazy way. By modifying our /etc/rc.local file.

root@firewall:/etc/openvpn# nano /etc/rc.local

Find the following line.

exit 0

Before that line add the following

iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -s -j ACCEPT
iptables -A FORWARD -j REJECT
iptables -t nat -A POSTROUTING -s -o eth1 -j MASQUERADE

Save the file and thats it server is configured and will survive a reboot.

Step 7

We will now create the certificate that we will hand our clients.

Note: You can change ClientCert to whatever you want. Note: Make sure to sign the certificate.

ubuntu@firewall:~$ sudo bash
root@firewall:~# cd /etc/openvpn/easy-rsa
root@firewall:/etc/openvpn/easy-rsa# source vars
root@firewall:/etc/openvpn/easy-rsa# ./build-key ClientCert
root@firewall:/etc/openvpn/easy-rsa# exit

Now we copy them to a folder in our home directory

ubuntu@firewall:~$ mkdir ~/ClientConf
ubuntu@firewall:~$ cd /etc/openvpn/easy-rsa/keys
ubuntu@firewall:~$ sudo cp ca.crt ~/ClientConf
ubuntu@firewall:~$ sudo cp ClientCert.crt ~/ClientConf
ubuntu@firewall:~$ sudo cp ClientCert.key ~/ClientConf
ubuntu@firewall:~$ sudo cp ta.key ~/ClientConf

Now we need to copy the sample client configuration file and modify it.

ubuntu@firewall:~$ cd ~/ClientConf
ubuntu@firewall:~$ cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf .
ubuntu@firewall:~$ nano client.conf

First we set the correct protocol

Find the following line

proto udp

Change it to the following

proto tcp

Next we have to set the correct remote address

Find the following

remote my-server-1 1194

Change it to the following


After that we have to set the correct certificates

Find the following lines

ca ca.cert
cert client.crt
key client.key

Change them to the following

ca ca.cert
cert TestClient.crt
key TestClient.key

Next we enable the shared secret

Find the following line

;tls-auth ta.key 1

Change it to the following

tls-auth ta.key 1

Finally we enable the pam module

Add the following line to the bottom of the config


All thats left from here is to create our openvpn user

Note: We do this for each unique user we want to have access to the vpn

Note: We set their shell to /bin/false so they do not have ssh access

Note: You can set TestUser to whatever you want

ubuntu@firewall:~$ sudo bash
root@firewall:~# useradd -g "openvpn" -s /bin/false TestUser
root@firewall:~# passwd TestUser

That’s it if everything works out well the openvpn server will be configured. Permissions will have to be changed on the files in the ~/ClientConf folder.

ubuntu@firewall:~$ sudo chown -R user:user ~/ClientConf
ubuntu@firewall:~$ tar -czf ClientConf.tar.gz ~/ClientConf

Now hand your client the ClientConf.tar.gz and the username/password you create for them.


Network Security and Programming words.