OpenVPN is a tool to create a Virtual Private Network over a public network connection. With a VPN you create a secure tunnel over the
internet which is fully secured. Device on both sides of the tunnel can talk as if they were connected to the same network. Breaking in on
the secure tunnel is impossible.
With a VPN you can work where ever you are, on a company network or a public wifi hotspot, as if you were at home. Accessing all your local
servers and data.
OpenVPN is opensource and available on many devices including Linux, Windows, IOS and Android. This HOW-TO describes how to setup a OpenVPN server on Ubuntu Linux Server 12.04 and connect with a Windows 7 client.
First we need to install the OpenVPN software. OpenVPN is available in the Ubuntu repository.
apt-get install openvpn
OpenVPN will be installed and all required software and libraries will be installed with it.
OpenVPN uses SSL certificates to sign and encrypt the connection. It requires a server and client certificate. The easiest way is creating a CA. This CA will be used to sign all server and client certificates. OpenVPN comes with a tool called easy-rsa that will do most of the certificate stuff for us. Lets start by activating easy-rsa.
sudo mkdir /etc/openvpn/easy-rsa/
sudo cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0/* /etc/openvpn/easy-rsa/
sudo chown -R $USER /etc/openvpn/easy-rsa/
The certificate defaults are kept in a file called vars. Edit this file and change the following settings to setup a CA.
export KEY_ORG="Example Company"
Now we can create the CA by executing the following commands.
./pkitool --server server
openvpn --genkey --secret ta.key
sudo cp server.crt server.key ca.crt dh1024.pem ta.key /etc/openvpn/
An error could be show saying the openssl.conf must use verion 2.0 or something. This is a known bug in Ubuntu. The work around for this is creating a link and follow the procudure again.
sudo ln -s openssl-1.0.0.cnf openssl.cnf
The ta.key file is a extra security. The ta.key is used to create an additional HMAC signature. The server first checks this HMAC signature, any package that doesn't have the right signature is dropped immediately. Coursing the server to be more protected for DoS attacks and port scans.
Now we have a keypair created for the server (named server). The CN in the certificate does not have to be the hostname of the server like in a HTTPS server certificate.
Every client should have an own certificate. Again the name of the client certificate is free, as long as it is signed by the CA. Although using the hostname or username of the client is the easiest way to keep track of you clients. Remember that anyone with a private key signed by the OpenVPN CA can create a tunnel!
Now we can copy the required certificates for the client to the client. The client will require the following files:
- /etc/openvpn/easy-rsa/keys/clienthostname.key - Keep this file secret on the client.
Make sure to remove any leftovers of copying these files to the clients. These files are your keys to you private network!
Now it is time to configure the OpenVPN server. First we will configure the easy connection. This is a dedicated connection between the client and the server. Later we will include the server's network and use the internet connection of the servers network.
OpenVPN comes with a couple of sample configuration files. We start off by using one of the sample configuration files.
sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
sudo gzip -d /etc/openvpn/server.conf.gz
In this howto we will use the following network addresses
|10.0.0.0 / 255.255.255.0
|Internal side router on private network
|External side router
|OpenVPN DHCP network
|10.8.0.0 / 255.255.255.0
Now we can edit the /etc/openvpn/server.conf file and make the following changes
server 10.8.0.0 255.255.255.0
push route 10.8.0.0 255.255.255.0
tls-auth ta.key 0
We setup a server on 10.0.0.2 using udp port 1194 (which is the OpenVPN default). The server parameter defines the network used by the VPN connection, the server gives all clients an ipaddress in this 10.8.0.0 range. The ifconfig-pool-persist parameter tells OpenVPN to remember all the DHCP addresses given to the clients so they key the same address the next time the logon. Next we push the new route to the client so it can find the server on the 10.8.0.0 network. The last user and group options tell linux to run the OpenVPN server using this user and group. Just some extra security.
Now we can start the OpenVPN server.
Check your logfile on any errors, a netstat -lpun will show OpenVPN running on port 1194 if everything wend ok.
We will use a Windows 7 client to connect to the VPN server. The client must be connected to another network as the server (10.0.0.0). The Windows software can be downloaded from the OpenVPN website. The software contains a sample configuration file. Change the configuration C:\Program Files\OpenVPN\config\client.ovpn as followed:
remote 18.104.22.168 1194
tls-auth ta.key 1
First we define that we use the tun device on remote address 22.214.171.124 using udp port 1194. The ns-cert-type parameter is an additional security that tell the client to check the server uses a certificate with the indicated name (server in our case). The certificate files need to be copied to the config folder.
We can now start the client using the following command (run as administrator!).
If the connection is successfull the client should have a second network interface with a new ip-address in the 10.8.0.0 range. We should now
be able to ping the server on 10.8.0.1.
The default firewall settings of Windows and Ubuntu should be ok to connect, but when facing connection problems a good look at the both firewall settings would be advisable.
Access private network
We can connect to the OpenVPN server, but we want to be able to connect to all the other systems in our private network as well.
For this we need some additional setting in the server configuration and push some additional routes to the client. Make the following changes to the server.conf file and restart the OpenVPN server.
push "route 10.0.0.0 255.255.255.0"
This add's the route to the private network to the clients. Also the option client-to-client enables clients on the OpenVPN network (10.8.0.0) to see and connect to each other, as if they were connected on the private network.
The clients can now connect through the OpenVPN server to all systems on the network. But the systems on the network don't know the route to
the VPN network. There are 2 options to tell the systems were to find the VPN network address. The first option is to add a route on every individual
system on the private network. This is a lot of work and can easily be forgotten when a new device is added to the private network.
The second option is to add a route to the VPN network in the router (ADSL Internet router). Most modern routers come with the option to manually add a route to another subnet. Setup a route to network 10.8.0.0 using gateway 10.0.0.2 (our OpenVPN server).
Now we should be able to ping from the client any server on the private network. If we can only ping our OpenVPN server as 10.0.0.2 and not the other server, the route is misconfigured on not yet activated.
Address Internet over VPN
There could be 2 reasons to use the VPN's internet connection. The first is to disable any other traffic than the VPN traffic to make sure we do not create a backdoor to our private LAN. The second reason is that the clients Internet connection could be blocked by firewalls to block us to use specific services or sites.
Again we need to make some changes to the server.conf file on the OpenVPN server, and restart the server.
push "route 0.0.0.0 0.0.0.0"
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 10.0.0.1"
First we add a new route to route all network address via the VPN server. Next we tell the client to overrule the default gateway and use the OpenVPN server as default gateway. The last option tells the client to use our private networks router as DNS server. This could be any DNS server used on the private network.
The client will now try to connect through the OpenVPN server to the internet. But we must also setup our OpenVPN server to forward all requests from the VPN network to the private network router. For this we need to enable ip forwarding and add some firewall rules on the OpenVPN linux server.
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
iptables -A INPUT -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -j ACCEPT
iptables -A FORWARD -i tun+ -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i eth0 -o tun+ -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
The change to the sysctl.conf file will enable ip forwarding. The first rule reject all traffic. The second rule accepts all related and established connections. The 3rd rule accepts connections from the VPN network. So only connection from the VPN network will be allowed. The last rule is the forward rule to masquerade all traffic from the VPN network (10.8.0.0) as it comes from the local network (10.0.0.0). Now we should be able to connect from the VPN client to the internet using the private network internet connection.
Hide OpenVPN behind Apache
OpenVPN comes with a very nice option to share the used port with another service. We can use this option to hide OpenVPN behind an Apache HTTPS website. This can be very usefull when our client's network uses a very restricted firewall. Another advantage is that a portscan will not reveal an OpenVPN port as it reuses the HTTPS port 443.
To enable this option we need to make some adjustment to both the server and the client configuration files. Lets start with the server config.
port-share 10.0.0.3 443
In my case the Apache webserver is located on another server in the private network (10.0.0.3) so we can simply forward any HTTPS traffic to this existing server. The only thing we now need to do is change the portforwarding rule on the router to route HTTPS traffic to 10.0.0.2 (our OpenVPN server) instead of our Apache server (10.0.0.3). If the Apache server is located on the same server as the OpenVPN server, we need to change the HTTPS port number of the Apache server to eg. 8081. The OpenVPN configuration needs to forward the port-share to 127.0.0.1 8081.
Next we need to change the client config.
remote 126.96.36.199 443
We should be able to make a VPN connection from the client again. Also check if the HTTPS site still works.
Our VPN connection can easily be setup by double clicking the shortcut on the client. So if our client gets stolen, someone could easily connect to our local network. An easy option to protect us from misusing the clients VPN connection is by adding a username and password to the VPN connection. This is easily done by adding an extra configuration parameter to both the server and the client.
plugin /usr/lib/openvpn/openvpn-auth-pam.so login
This will tell OpenVPN to check any client against the Linux pam login module. Now we need a valid Linux user to connect to the VPN server.
This option tells the client to ask for a username and password prior to connect to the VPN server.
Updated on sept. 18 2014, iptables configuration after Ubuntu 14 package update