A Virtual Private Network (VPN) is used to extend an existing private network across the internet (public network). VPN enables connected devices all over the world to interact through an encrypted connection as if they were connected directly to the private network. Undoubtedly this opens several obvious advantages.

Example of two VPN connected devices


Therefore, it’s not surprising that almost every company and also many private technically versed households hold their own VPN-Server.


In the last 10 years, I have set up an OpenVPN-Server two times. And both times I encountered some annoying problems that got me hours of researching and googling. That’s why today’s topic is about a simple installation and the basic configuration of OpenVPN-Server as well as tips or solutions for common problems.


OpenVPN-Server Setup

If you have already read some of my blog posts, you know I’m quite a fan of Docker. So it’s not surprising that in the case of OpenVPN I also use one of the huge variety of available images.

Step 1: Choose OpenVPN-Server Docker Image

There exist several quite similar OpenVPN-Server images on DockerHub.
I tested kylemanna/openvpn and evolvedm/openvpn-rpi which is an image specified for Raspberry’s ARM architecture.

Step 2: Generate first (basic) OpenVPN Configuration Files and Certificates

Generate a first basic OpenVPN-Server Configuration applying
docker run -v /HOST/PATH/TO/OPENVPNCONFIG:/etc/openvpn --rm DOCKERIMAGE ovpn_genconfig -u udp://DOMAIN

Note:
Commands that generate certificates will prompt you for password protection.
Replace the following placeholders in the commands listed in this chapter.

  • /HOST/PATH/TO/OPENVPNCONFIG with a path of your choice
  • DOMAIN with your OpenVPN-Server’s Domain or IP-Address
  • DOCKERIMAGE with the chosen Docker image (kylemanna/openvpn, evolvedm/openvpn-rpi or similar)

Finish your OpenVPN configuration using docker run -v /HOST/PATH/TO/OPENVPNCONFIG:/etc/openvpn --rm -it DOCKERIMAGE ovpn_initpki to generate OpenVPN’s certificates.

In order to connect client devices to your VPN, generate OpenVPN-Client certificates for each of your users executing docker run -v /HOST/PATH/TO/OPENVPNCONFIG:/etc/openvpn --rm -it DOCKERIMAGE easyrsa build-client-full USER1and retrieve the client configuration with embedded certificates running docker run -v /HOST/PATH/TO/OPENVPNCONFIG:/etc/openvpn --rm DOCKERIMAGE ovpn_getclient USER1 > /HOST/PATH/TO/OPENVPNCONFIG/vpn-server-USER1.ovpn

And that’s it.
All necessary configuration files are located under the configuration path you specified and your OpenVPN-Server is ready to launch.

OpenVPN configuration files

Step 3: Start OpenVPN-Server Container

docker run -d -v /HOST/PATH/TO/OPENVPNCONFIG:/etc/openvpn --name openvpn --cap-add=NET_ADMIN -p 1194:1194/udp DOCKERIMAGE launches your OpenVPN-Server.


Network Configuration

In preparation for connecting devices to the OpenVPN-Server, make sure that the server port 1194 is publicly reachable.

Hint: Most of the time your server is located inside a NAT I guess, so you need to forward port 1194 inside your router to the OpenVPN-Server.

In case you plan to push (reach) some private subnets to (from) your VPN-Clients, you need to set up a static route inside your router. Otherwise, a response to a VPN-Client’s request will not find any route back to the client.

Static route configuration for 192.168.255.0/24
Request from VPN-Client into a pushed subnet

Connect OpenVPN-Clients

To connect client devices to your VPN install your favorite VPN-Client application. I prefer OpenVPN-Client, which is available for different operating systems.
As a last step import the generated client configuration from Step 2 (vpn-server-USER1.ovpn) into your OpenVPN-Client installation and connect to the VPN.

In order to test your VPN connection, I recommend visiting https://whatismyipaddress.com/.
Compare your public IP-Address in VPN connected and not connected state. Since the first basic generated configuration transports the whole traffic through the VPN, you should recognize a changed public IP-Address.


Adjust OpenVPN-Server and Client Configuration

After a first successful VPN connection test, the configuration can be tailored to your requirements. To do so open, review and adjust the generated OpenVPN-Server (openvpn.conf) and Client (vpn-server-USER1.ovpn) configuration.

Some important configuration commands are described in the working examples below.

# openvpn.conf example

# Configure server mode and supply a VPN subnet for OpenVPN to draw client addresses from.
server 192.168.255.0 255.255.255.0

# Log level
verb 3

# Key configuration
key /etc/openvpn/pki/private/DOMAIN.key
ca /etc/openvpn/pki/ca.crt
cert /etc/openvpn/pki/issued/DOMAIN.crt
dh /etc/openvpn/pki/dh.pem
tls-auth /etc/openvpn/pki/ta.key

# Key-direction needs to be 0 for server and 1 for client.
key-direction 0

# The keepalive directive causes ping-like messages to be sent back and forth over the link so that each side knows when the other side has gone down.
# Ping every 10 seconds, assume down if no ping received during 60 seconds.
keepalive 10 60

# Persist the tun device and the authentication keys across restarts.
persist-key
persist-tun

# UDP server.
proto udp

# Which TCP/UDP port should OpenVPN listen on? (Docker internally always 1194.)
port 1194

# Creates a routed IP tunnel.
dev tun0

# Reduce the OpenVPN daemon's privileges after initialization
user nobody
group nogroup

# Pushes DNS Server which should be used from clients
push dhcp-option DNS 8.8.8.8
push dhcp-option DNS 8.8.4.4

status /tmp/openvpn-status.log
# vpn-server-USER1.ovpn example

# Configure client mode
client

# The hostname/IP and port of the server.
remote DOMAIN 1194 udp

# Most clients don't need to bind to a specific local port number.
nobind

# Use the same setting as you are using on the server.
dev tun

# Verify server certificate.
remote-cert-tls server

# Key configuration
<key>
  # removed!
</key>
<cert>
  # removed!
</cert>
<ca>
  # removed!
</ca>
<tls-auth>
  # removed!
</tls-auth>

# Key-direction needs to be 0 for server and 1 for client.
key-direction 1

# redirect all traffic through the VPN.
redirect-gateway def1

Common Configuration Changes

This chapter describes some very common configuration adjustments. For further information and configuration commands please visit the OpenVPN website.

Traffic through VPN

The default configuration you generated in Step 2 routes the whole network traffic through the VPN by default. This is configured using redirect-gateway def1 in the client configuration file.

traceroute google.com
1  18ms  19ms  20ms  192.168.255.1 (OpenVPN-Server)
2  18ms  18ms  19ms  172.17.0.1 (Docker-Host)
3  21ms  18ms  19ms  192.168.1.0 (Router)
4  31ms  23ms  23ms  google.com


It is very common to route only traffic for specific destinations through the VPN. For that purpose, just remove the redirect-gateway definition inside the client configuration and push routes that should use the VPN.

traceroute google.com
1  18ms  19ms  20ms  192.168.2.1 (Router)
2  31ms  23ms  23ms  google.com

Push routes

In case of private networks need to be available inside the VPN, or traffic for specific destinations should be transported through VPN, just push a route that configures your clients to use the VPN tunnel. push route 192.168.1.0 255.255.255.0

traceroute 192.168.1.101
1  19ms  18ms  20ms  192.168.255.1
2  19ms  18ms  19ms  172.17.0.1
3  19ms  30ms  17ms  192.168.1.101

Push DNS-Server

DNS-Server configurations can be pushed to VPN-Clients by adding dhcp-option DNS IPofDNS into the OpenVPN-Server configuration.


Troubleshooting

Of course, setting up a VPN-Server the first time without that much background information is not that easy, and so it is quite normal to face some problems. And that’s why I decided to mention some hints and commands for basic troubleshooting next to reading OpenVPN-Server and Client logs.

Network Configuration

In case of any connection issues, I recommend double-checking your network configuration as a first starting point.

  • Make sure your VPN-Server is publicly reachable using the specified port -p 1194:1194/udp in Step 3.

Hint: Enable port forwarding inside your router when the VPN-Server is located in a private network.
Netcat can be used as one option to check whether the VPN-Server is publicly reachable. (nc -uv PUBLIC-IP 1194)

  • Especially in case of unavailable pushed subnets, check your static route configuration.

Check Network Routing Table of VPN-Clients

When clients are connected successfully to the VPN but does not route traffic through the tunnel, utilize the route command to check the client’s routing table.

Hint: For each pushed route (destination) there should be an entry with an IP-Address of the VPN-Subnet as Gateway.

Kernel IP routing table
Destination    Gateway          Genmask          ...
192.168.1.0    192.168.255.5    255.255.255.0    ...

Traceroute

As an attentive reader, you may have noticed that the traceroute command is very useful to sheld light into the magic of routing.


In case you have further recommendations, hints, solutions in the field of troubleshooting, or VPN in general, do not hesitate to leave a comment.

Categories: DevOpsInfrastructure