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.
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.
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
Commands that generate certificates will prompt you for password protection.
Replace the following placeholders in the commands listed in this chapter.
/HOST/PATH/TO/OPENVPNCONFIGwith a path of your choice
DOMAINwith your OpenVPN-Server’s Domain or IP-Address
DOCKERIMAGEwith 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.
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.
In preparation for connecting devices to the OpenVPN-Server, make sure that the server port 1194 is publicly reachable.
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.
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 126.96.36.199 push dhcp-option DNS 188.8.131.52 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
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
DNS-Server configurations can be pushed to VPN-Clients by adding
dhcp-option DNS IPofDNS into the OpenVPN-Server configuration.
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.
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/udpin 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 ...
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.