Why you might need OpenVPN
At work, we often need our company LAN (local area network) to be accessible from outside our premises. The reason is to either give access to contractors (who need to setup or maintain our software systems) or to provide our employees with the ability to do remote work.
Making a LAN accessible from the Internet can cause security issues. So, I had to select and implement a method to grant outside access that was as safe as possible.
Commercial remote desktop applications like TeamViewer and AnyDesk are a secure and easy-to-setup solution in certain scenarios. However, they are not free for business use. Furthermore, they only allow the remote user to connect to a specific computer in the company LAN and control it by mirroring its screen. While in some cases this approach works well, I wanted the added flexibility of connecting directly to all our company network resources (e.g. NAS, CNC machines, applications such as CAD & CAM, ERP, MES, etc.), as if I was physically at our premises and without having to pass through the desktop of a specific computer.
Having used a VPN (virtual private network) at the organization where I worked previously, I knew it was a better solution to my problem. A VPN provides a secure and private way for authorized individuals, such as vendors or employees, to access your company’s network from anywhere in the world. It creates a virtual tunnel over the Internet and encrypts the traffic, allowing accredited users to securely access files, applications, and other resources on your company’s network, as if they were physically present in the office. Another advantage is that it logs all connections, recording who has connected and when.
After doing some research on various VPN providers, I decided to implement OpenVPN Community Edition as our virtual private nework platform. OpenVPN is the most widely adopted open source VPN platform, thanks to it’s security, efficency and proven history. With OpenVPN, I can provide secure, tailored access to both contractors and our own employees, relying on a time-tested and completely free protocol. The fact that the code is open source gives me the added peace of mind that it has been reviewed by third parties and doesn’t hide any suspicious functionality. Please note, this guide is not about the paid versions of OpenVPN, denoted as Cloud Connexa (cloud based) and Access Server (self-hosted).
Although implementing OpenVPN solved my business problem, it took me a while to figure out how to setup both server and client sides of this platform. The official guide is comprehensive, but it can be overwhelming, because it lacks some practical configuration examples. There is plenty of forum threads on the Internet about common issues with OpenVPN configuration, as well as some useful step-by-step videos on how to set it up. However, none of these resources, taken individually, was sufficient to ensure a smooth and easy implementation of OpenVPN Community Edition on Windows OS.
The following tutorial is my attempt at providing you with a comprehensive, step-by-step guide on how to setup and configure OpenVPN Community Edition on Windows computers. I also included explanations about the different options provided by this platform and some troubleshooting scenarios I incurred during my early stages of VPN utilization.
Fundamental OpenVPN options explained
Configuring OpenVPN requires choosing between different options. Since information about these options is quite scattered across the Internet, I have provided a brief summary for each of them, along with an explanation of why I chose one over the other.
Static key vs Public key infrastructure (PKI)
Static key and Public key infrastructure (PKI) are both methods for securing VPN connections. However, they differ in how they manage encryption keys and authentication.
Static key, also known as a pre-shared key, is a simple method for setting up a secure VPN connection. It uses a single, static key that is shared between the server and clients. A static key is relatively easy to setup. However, it’s limited scalability and security features make it suitable only for point-to-point VPNs or proof-of-concept testing.
In a PKI (public key infrastructure), each client and server has its own unique key pair. This system allows for user authentication and the revocation of keys if a client device is compromised or needs to be removed from the network.
PKI is the most secure and scalable choice for securing VPN connections. Therefore, this is the system we will use in this tutorial.
TAP vs TUN vs DCO device
A TAP device is a virtual network interface that simulates an Ethernet network adapter, i.e. it works at the Ethernet protocol level. This is called Layer 2 network connectivity in the OSI model. It is like having a virtual Ethernet network connecting the two devices. This interface is enabled by including the command dev tap
in the OpenVPN config file (see below), where dev refers to the virtual network device.
A TUN device is a newer, faster virtual network interface, ideal for point-to-point connections. TUN works at the IPv4 or IPv6 level, i.e. it is a virtual point-to-point IP link. This is called Layer 3 network connectivity in the OSI model. It is like having a long Ethernet cable connecting the two devices. In Windows, this interface is enabled by including the following commands in the OpenVPN config file: dev tun
windows-driver wintun
The two interfaces discussed above cannot be mixed on different sides of the connection (client and server). You must select one or the other consistently:
- if you need to bridge two Ethernet segments in two different locations, you should use TAP. Using this interface, remote devices will appear on the same subnet as the local devices.
- If you want the client devices to be on a different subnet than the server, you should select TUN. With this interface, traffic will be routed between networks. This interface is also more efficient than TAP, because it has less traffic overhead, therefore it is more scalable.
Starting from version 2.6, the OpenVPN team has released the Data Channel Offload driver, denoted as ovpn-dco for Linux and as ovpn-dco-win for Windows. This driver optimizes network traffic by offloading some of the encryption, decryption and routing tasks from the OpenVPN userspace to a new kernel module. This approach helps improve the efficiency and performance of the VPN connection in two ways:
- by reducing the context switches between user space and kernel space to the minimum and
- by taking advantage of the kernel concurrency model for packet processing. This means that the encryption is now multi-threaded, i.e. this task is split into smaller units and assigned to different CPUs.
The Data Channel Offload driver allows for faster data transmission while maintaining security. The ovpn-dco-win is the default driver starting from OpenVPN 2.6 and the minimum supported OS version is Windows 10 20H1. To use DCO, just include the command dev tun
in the OpenVPN config file.
Important: ovpn-dco-win only supports client/p2p mode, but server mode is not available. This feature was not implemented because there is not much demand for OpenVPN servers running on Windows, as opposed to Linux. In this tutorial, we will use Data Channel Offload for our clients, while TAP will be automatically enabled by the OpenVPN server.
Routing vs bridging
Routing and bridging are two different methods for handling network traffic. We briefly covered these approaches in the previous section, when discussing TAP and TUN devices.
Routing is the more common and default method in OpenVPN. In a routed setup, OpenVPN functions as a router, directing traffic between distinct subnets. Clients are usually assigned IP addresses from a subnet separate from that of the OpenVPN server.
Bridging essentially extends the server’s LAN by bridging the virtual and physical network interfaces. In a bridged setup, clients share the same subnet as the server, and their devices receive IP addresses from the server’s local subnet.
Routing is often recommended for most scenarios, as it provides better isolation and security between the VPN clients and the server’s local network. The official OpenVPN guide recommends using routing rather than bridging, because the former method is simpler to configure and it allows tailoring the access rights for each client. Routing can work on both TAP or TUN devices, however TUN tends to be more efficient. In this guide, we will configure a routed VPN.
Bridging is used when you need all clients to be on the same LAN segment and appear as if they are part of the local network. Bridging requires the use of TAP. As mentioned earlier, ensure that you select the same interface on both ends of the connection.
Minimizing the probability of IP address conflicts
Establishing a VPN typically involves connecting private subnetworks located in various places. The Internet Assigned Numbers Authority (IANA) has designated the subsequent three ranges within the IP address spectrum for private networks, as specified in RFC 1918:
- 10.0.0.0 to 10.255.255.255 (10/8 prefix)
- 172.16.0.0 to 172.31.255.255 (172.16/12 prefix)
- 192.168.0.0 to 192.168.255.255 (192.168/16 prefix)
While addresses from the above ranges can be used for VPNs, it is crucial to choose IP ranges that decrease the likelihood of conflicts between subnets. During the setup of our VPN at work, I realized that the 192.168.0.0/24 subnet used by our company LAN was highly popular, because it is the default configuration in most routers.
To minimize the risk of IP conflicts, I chose a subnet in the middle of the 10.0.0.0/8 range and I applied it to our company LAN. For the purposes of this tutorial, we will use the following subnet: 10.66.0.0/24. The “/24” is the CIDR notation for a subnet with 256 IP addresses, corresponding to a 255.255.255.0 subnet mask.
This procedure also provided me with an opportunity to review all static IP addresses in our network, create an Excel spreadsheet listing all of them, and (where possible) convert some to dynamic allocations. To list all the IP addresses in our LAN, I use Angry IP Scanner, a free and open source network scanner.
Essential devices in a OpenVPN setup
To setup OpenVPN, we’ll need to configure a minimum of three devices (see Figure 1):
- An OpenVPN server, responsible for managing all incoming VPN connections. This machine can take various forms, such as a desktop PC or a dedicated server. Additionally, certain routers come equipped with pre-installed OpenVPN software, enabling them to function as OpenVPN servers as well. In this tutorial, we will assume that a Windows-based computer (either desktop or server) will act as the OpenVPN server.
- One or more OpenVPN clients, securely connected to the OpenVPN server over the Internet through an encrypted connection. In this tutorial, we will configure a Windows-based desktop client.
- The company router, where some configurations must be modified, as described in the following sections.
Setting up the OpenVPN server
Prior to installing OpenVPN on the machine designated to host the server, it is advisable to set up a static IP address on this machine. Ensure to record this address, as it will be required for subsequent steps. Then, download the latest version of OpenVPN Community Edition (free). The Windows 64-bit MSI installer is typically the version you’ll need.
- Run the setup as administrator.
- Click on Customize and enable all features, including EasyRSA 3 (see Figure 2).
- Finish the installation by clicking on the Close button.
Creating the PKI
In Windows Explorer, go to C:\Program Files\OpenVPN and copy the folder named easy-rsa. Then, go to your user folder (C:\Users\<user-name>) and paste the easy-rsa
folder here. This step is not required, but it’s highly recommended for two reasons:
- to avoid receiving a security warning when running Easy RSA, indicating that PKI files stored in C:\Program Files\OpenVPN are not password protected. By storing them in the user folder, we are protecting them with the Windows user password.
- to prevent the OpenVPN setup from overwriting the PKI files upon future updates.
Run the Command Prompt in admin mode (for example, by pressing CTRL + ALT + SHIFT + Left click on its icon).
Launch the Easy RSA utility by executing the following commands:
cd C:\users\<user-name>\easy-rsa
.
Make sure to replace <user-name> with your Windows account name.easyrsa-start.bat
Now we are going to build the PKI by executing the following commands:
./easyrsa clean-all
to delete previous certificates and keys, if present. This command will automatically execute also./easyrsa init-pki
, that initializes the PKI directory.
- [Optional step] Open the
vars.example
file in Notepad and save it asvars
in the same folder. Then, edit the following fields. This is just a cosmetic change that will be visible later, when creating the Certificate Authority (CA):set KEY_COUNTRY=US
set KEY_PROVINCE=CA
set KEY_CITY=SanFrancisco
set KEY_ORG=OpenVPN
set KEY_EMAIL=mail@host.domain
In the Command Prompt, execute the following commands:
./easyrsa build-ca nopass
This will generate the Certificate Authority. Thenopass
option can be used to disable password locking the CA../easyrsa build-server-full Server-01 nopass
You can choose any server name in place ofServer-01
. This step will generate the server certificate and key. These are typically left unencrypted by using thenopass
option, because servers usually start up without any password input. Since this approach generates an unencrypted key, it’s important to protect its access and file permissions carefully../easyrsa gen-dh
This will generate the Diffie–Hellman parameters, which are required for the encryption.
Using your favourite text editor, open the file server.ovpn
which is located in the C:\Program Files\OpenVPN\sample-config
folder.
Save a copy of this file in the C:\Program Files\OpenVPN\config-auto
folder. This is the folder where the OpenVPN service will automatically look for its configuration file(s) upon startup. You can either leave the default filename or choose a different one.
Now we need to edit a few settings in this configuration file:
- Make sure that
dev tun
is enabled, i.e. there is not a#
at the start of the line. - Edit the paths and filenames of the PKI files we have just created. Please note that, in Windows, paths need to be enclosed in double quotation marks (
"
) and the double backslash (\\
) must be used to separate folders. The paths should be as follows:ca "C:\\users\\<username>\\easy-rsa\\pki\\ca.crt"
cert "C:\\users\\<username>\\easy-rsa\\pki\\issued\\Server-01.crt"
key "C:\\users\\<username>\\easy-rsa\\pki\\private\\Server-01.key" # Note: this file should be kept secret!
dh "C:\\users\\<username>\\easy-rsa\\pki\\dh.pem"
- Indicate the subnet from which the OpenVPN client IPs will be drawn. You can leave the default
10.8.0.0
subnet with255.255.255.0
as subnet mask. - Disable the cryptographic cipher because, from v2.4, client and server will automatically negotiate AES-256-GCM in TLS mode:
# cipher AES-256-CBC
. - Save the modified configuration file.
Choosing a Dynamic Domain Name System (DDNS) hostname
Dynamic Domain Name System (DDNS) is a service that automatically updates the DNS records for a domain name to reflect the current IP address of a device. It is useful in scenarios where your Internet Service Provider (ISP) assigns you a dynamic IP address that may change periodically. If you want to remotely access devices at your home or office (such as a surveillance camera, server, or router), DDNS provides a consistent domain name even if your IP address changes. If your internet provider assigns a static public address to your network (typically as a paid service), then you do not need to use DDNS.
There are several online providers that offer free DDNS, as well as premium plans with additional features. After exploring a few options including:
- noip.com
- FreeDNS on afraid.org
- dynu.com
- YDNS.io
I settled for noip.com: it offers a free DDNS hostname and has a very intuitive user interface. The only catch is that you must confirm your hostname once every 30 days; otherwise, it will be deleted. You will receive an automated email reminder a few days before expiry. The renewal process is quick and painless, and their DDNS service is reliable, so I’m quite happy with it.
To setup a free DDNS with noip.com, you need to create a new account and choose your domain name. Please note that you can actually only choose the subdomain, as the second-level and top-level domains can only be selected among a list of options. Make a note of your domain name, as it will be needed in the following steps.
Configuring DDNS on your router
The following step is required to send the up-to-date public IP address of your router to the DDNS provider of your choice. In turn, the DDNS provider will update the hostname you selected with the public IP address of your network.
Below I will assume that your router supports DDNS. If your router doesn’t have this feature, most DDNS services will provide you with a so called dynamic update client, i.e. an application that can be installed on a computer in your LAN to perform the same task.
Here is the procedure for a FritzBox router. These steps should be similar for routers from other brands:
- Click on the Internet tab.
- Click on the Permit access item.
- Click on the DynDNS tab.
- Enable the option Use DynDNS.
- Enter the update URL for your DDNS provider. This URL can be found either in your provider or your router documentation. It is a string containing the URL to your DDNS provider and some placeholders for your domain name, username, password and IP address.
- Enter the domain name you created.
- Enter the username and password for your DDNS account.
- Click Apply to save the settings.
Now your router will transmit its current IP address to the DDNS provider every time it connects to the Internet. This way, your router can always be accessed via the unique DDNS hostname you selected.
Configuring port forwarding on your router
Port forwarding is a network configuration technique that allows incoming traffic from the Internet to be directed to specific devices within a private network. It involves mapping a specific external port to a local port on a device inside the network. When a client attempts to connect to the OpenVPN server using a specific port, the router forwards those incoming connections to the OpenVPN server on the corresponding local port. This enables the client to establish a secure connection with the server for remote access.
In our configuration, traffic directed to port 1194 must be routed to the OpenVPN server machine. At work, we have a FritzBox router; however, the following steps should be similar on routers of different brands:
- After logging into your router user interface, select the Internet tab and click on Permit Access.
- Select the Port sharing tab.
- Click Add Device for Sharing and either select the OpenVPN server hostname from the drop-down menu or scroll down at the end of the list and enter its static IP address manually.
- Click on New sharing.
- Select Port sharing and Other application.
- Enter a name for the rule, select the UDP protocol and enter the port number (1194 in this example). Since we need to enable only a single port, enter the same number as both the start and the end of the port range.
- Click on Enable sharing and on OK.
- Click on Apply to save the port forwarding rule you have just created.
Configuring Windows Firewall for OpenVPN
By default, Windows Firewall blocks all incoming connections while allowing all outgoing connections. Therefore, in this tutorial, we will only make modifications to the firewall settings on the server machine and not on the client machine.
Specifically, we must establish an inbound rule on the server firewall to allow OpenVPN traffic through port 1194. While you can choose any name for the rule and any port number ranging from 0 to 65000, it is recommended to avoid the well-known ports (0-1023, also known as system ports) and the ephemeral ports (49000 – 65000). Well-known ports are assigned by IANA for widely recognized services, such as HTTP (port 80) and FTP (ports 20, 21), facilitating consistent communication on the Internet. Ephemeral ports are temporary ports dynamically assigned by the operating system for outbound connections initiated by client applications.
To inspect the ports in use by your computer, open the Windows Resource Monitor (resmon.exe
). Then, navigate to the Network tab, expand the Listening ports tab and arrange the ports in ascending order. Here you can identify an available port by locating a gap within the list of occupied ports.
To create the inbound rule for OpenVPN:
- type
wf.msc
in the Windows Search box and click on the result. This will open the Windows Defender Firewall with Advanced Security app. - Right-click on Inbound rules and select New Rule.
- In Rule type select Program and click on Next.
- In Program click on Browse and navigate to
C:\Program Files\OpenVPN\bin\openvpn.exe
. Click Open and then click Next. - Select Allow the connection and then click Next.
- Select all three profiles, Domain, Private and Public, then click Next.
- Choose a name for the rule, for example
OpenVPN
, then click Finish. - To restrict the OpenVPN inbound connections only to a specific protocol and port, double click on the rule you have just created and go to the Protocols and Ports tab. Next, select UDP as Protocol type and set the Local port to 1194 (or whatever port number you have chosen earlier for OpenVPN). Then click on OK.
Configuring the OpenVPN client(s)
On the OpenVPN server machine, we need to stop and re-start the OpenVPN service, to make all previous changes effective. In the Command Prompt, execute the following commands:
net stop openvpnservice
net start openvpnservice
.
The next step is to configure the PKI files for the client(s). In the Command Prompt, launch the Easy RSA utility as explained above. Then, run the following command:
./easyrsa build-client-full Client-01 nopass
You can replaceClient-01
with a name of your choice. It is recommended to omit thenopass
option, because unencrypted keys can pose a risk if obtained by unauthorized individuals. Encrypted keys, while safer, necessitate the user to input a password when connecting through OpenVPN. Note that when creating a password, no characters will be visible on the screen as you type. You’ll need to re-enter the same password to ensure accuracy and avoid typos during the password creation process.
Now we can set up OpenVPN on the client machine, executing the same installer we used for the server. This time you can proceed with the default setup process, eliminating the need to click on the Customize button.
Once finished, copy the following files from the server machine and paste them in the user folder of the client machine, by using a safe channel (I used a USB drive):
C:\users\<username>\easy-rsa\pki\ca.crt
C:\users\<username>\easy-rsa\pki\issued\client.crt
C:\users\<username>\easy-rsa\pki\private\client.key
The next step is to customize the client configuration file (client.ovpn
), using the same settings already selected for the server:
- Open the sample file located in
C:\Program Files\OpenVPN\sample-config\client.ovpn
, using your favourite text editor. - Save the config file in this folder:
C:\Program Files\OpenVPN\config
. You can either leave the default filename or choose a different one that makes it easier to identify the client machine or user. Note that, as of OpenVPN version 2.5.0, the config-auto folder is for the service wrapper to auto-start configurations from, whereas the config directory is for configurations for the GUI component. The OpenVPN service is started automatically by the server machine on startup and is expected to run continuously. In contrast, the GUI component is manually launched by the user on the client machine when connecting to the remote network via OpenVPN. - Enter the DDNS hostname and include the port number:
remote <DDNS-hostname> 1194
If your Internet provider assigns you a static public address, you can enter it instead of the DDNS hostname. - You’ll notice that some options are missing in the client config file, compared to the server config file. This is normal, as these options are pushed by the server to the clients.
- Save the modified file.
Testing your OpenVPN connection
Now it’s time to test the OpenVPN connection that we have just configured:
- Right-click on the OpenVPN GUI icon in the task bar (it looks like a white computer screen with a padlock) and click on Connect (see picture below). If you cannot see the icon, type
openvpn gui
in the Windows Search bar and launch the corresponding app.
- You’ll see a log indicating the connection establishment and, if the process is successful, the network interface of your client will be assigned an IP address within the 10.8.0.0/24 range (assuming you didn’t modify the default IP address pool in the server configuration file). In addition, the OpenVPN GUI icon in the task bar will turn from a white to a green computer screen with a padlock.
- From the Command Prompt, run
ipconfig/all
to see the result of the above configuration process. You will notice that the OpenVPN network interface will not feature a gateway IP address. This is normal, as there can be only one gateway and this is reported in your physical network connection (i.e., your Ethernet or Wi-fi interface).
At this point, your OpenVPN tunnel should allow the client to reach only the server. To check your connection, the most obious method would be to ping the server from the client. However, it took me a few hours to realize that Windows Firewall blocks incoming pings by default on public connections. Since most documentation about OpenVPN is related to Linux machines, this concept is not made clear across the guides and forums I found online. Therefore, since I was unable to ping my OpenVPN server, I was under the impression that my setup was not working.
Luckily, there is another way to check whether your OpenVPN connection is configured correctly: you can connect to the server using Microsoft Remote Desktop, a technology that allows users to control another computer in the LAN, as if they were physically present at this remote machine. Please note that you must identify the OpenVPN server by its IP address, not its computer name, because we haven’t yet configured a DNS server to translate names into IP addresses. Furthermore, for Remote Desktop to work, it must be enabled on the remote machine, otherwise the connection will be rejected. This feature can be enabled in Windows by going to Settings > Remote Desktop > On
. If you can connect from the client to the server using Remote Desktop, it means OpenVPN is doing its job.
If you don’t need to use ping for other reasons, you can ignore the fact that Windows Firewall is blocking it on public connections, and skip to the next step. In contrast, if you do need to use ping, you will have to either move the OpenVPN network connection from the public profile to the private profile or enable the inbound rule denoted as File and Printer Sharing (Echo request - ICMPv4-In)
in Windows Firewall of your server. However, this rule must also be modified to allow pings from all IP addresses, not just those from the Local Subnet. For safety, it is advisable to make a copy of this rule and edit it, rather than modifiying the orginal.
Expanding the scope of the VPN to include the server subnet
Now that we have established an OpenVPN tunnel to reach our server from our client, we can expand our configuration to enable the client(s) to reach the rest of the server-side subnet.
i) Pushing routes to the clients
First, we must advertise the 10.66.0.0/24 server subnet to the OpenVPN clients as being accessible through the VPN. To this end, we add the following line to the server configuration file (server.ovpn
):push "route 10.66.0.0 255.255.255.0"
where 10.66.0.0 is the network prefix of our remote network and 255.255.255.0 is the netmask, providing a subnet size of 256 IP addresses.
The above line gives the client access to the entire server-side subnet. However, if you want to restrict access to only a single IP in the subnet, you can modify the line above as follows:push "route 10.66.0.123 255.255.255.255"
In this case, a specific IP and a subnet mask with size 1 were entered. You can enter as many lines as the individual IP addresses that you want your clients to access.
Important: to make the above changes effective, you need to stop and restart the OpenVPN service with the usual commands from an elevated Command Prompt:
net stop openvpnservice
net start openvpnservice
.
ii) Configuring a static IPv4 route
Definition: a static route is a manually configured rule that can be used to directly connect networks that are not directly connected to each other.
In this tutorial, it’s important to note that the OpenVPN server doesn’t function as the gateway for the server-side subnet; instead, the server-side router plays that role. For this reason, a static IPv4 route must be configured in the router to route the client subnet (10.8.0.0/24) to the OpenVPN server.
In my FritzBox router, this setting is found in:
Home network > Network > Network Settings > Additional Settings > Static route table > IPv4 Routes > New IPv4 Route.
The required configuration parameters are listed below:
Destination network: 10.8.0.0
Mask: 255.255.255.0
Gateway device: <the IP of your OpenVPN server, e.g., 10.66.0.100>
iii) Enabling IP forwarding in the OpenVPN server
When an OpenVPN server receives data from a client, it needs to forward that data to the appropriate destination, whether it’s another client on the VPN network or a resource on the external network. IP forwarding allows the server to act as a router, directing traffic between the connected clients and the rest of the network.
To enable this feature in Windows, we must edit the following Registry key on the OpenVPN server:
HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
IPEnableRouter = 1
and then restart the server to make the change effective.
iv) Specifying the DNS server for OpenVPN
At this point, you should be able to reach all clients in the server subnet by using their IP addresses. However, connecting to them via their hostnames is not possible because the OpenVPN client doesn’t know the address of the DNS server in the server-side subnet.
To reach all devices by hostname instead of using their IP addresses, we must specify the DNS server address by adding the following line to the OpenVPN server config file:
push "dhcp-option DNS <your-DNS-server>"
In this tutorial, we’ll consider the router as the DNS server for the server-side subnet, with an IP address of 10.66.0.1.
To test this change, run the following command in the Command Prompt of the client, after the machine has connected to the OpenVPN server:
ipconfig /all
and check whether the currently active OpenVPN network interface (which should be the OpenVPN Data Channel Offload) displays the DNS server that you have just entered.
Furthermore, you can use the nslookup
command-line tool to query the DNS server to obtain the hostname mappings of the server subnet. For example, if you run:nslookup <hostname>
it will query the DNS server to find and display the IP address associated with that hostname. If this command works, it means the DNS server has been specified correctly in your OpenVPN configuration.
Note: some routers, like my FritzBox, append a suffix to each connected device name (e.g., ComputerXYZ.fritz.box
). When typing the hostname of a remote device in your OpenVPN client, ensure you include this suffix too.
To check if routing is working, you can use the method described in the previous section.
Enhancing OpenVPN security
In OpenVPN, tls-auth
refers to Transport Layer Security (TLS) Authentication. It is a security feature used to add an additional layer of authentication to the OpenVPN connection. The purpose of tls-auth
is to verify the authenticity of the remote server and to ensure that the packets have not been tampered with. Enabling TLS Auth is a recommended security practice for OpenVPN implementations, to further enhance the integrity and resilience of the VPN connection.
To enable tls-auth, we must generate a shared-secret key that is used alongside the standard RSA certificate/key. From the server Command Prompt, run:
"C:\Program Files\OpenVPN\bin\openvpn.exe" --genkey secret "C:\users\<username>\easy-rsa\pki\private\ta.key"
Note: on the Internet, you might find examples using the --secret
option, but it is deprecated. --genkey secret
is currently the recommended option.
After generating ta.key
, copy it securely to the client. In this tutorial, we use the same path for both server and client.
To enable TLS Auth in OpenVPN, we must add the tls-auth directive in both the server and client configurations. In the server configuration file, add the following line:
tls-auth "C:\\users\\<username>\\easy-rsa\\pki\\private\\ta.key" 0
In the client configuration file, add:
tls-auth "C:\\users\\<username>\\easy-rsa\\pki\\private\\ta.key" 1
Summary of the generated files and their use
Files written in red (i.e., the .key
files) must be kept secret (see Table 1).
Filename | Needed by | Secret? |
ca.crt | Server + all clients | No |
ca.key | Key signing machine only | Yes |
dh.pem | Server only | No |
server.crt | Server only | No |
server.key | Server only | Yes |
client1.crt | Client1 only | No |
client1.key | Client1 only | Yes |
ta.key | Server + all clients | Yes |
server.ovpn | Server only | No |
client.ovpn | All clients | No |
.key
files must be kept secret.Revoking an OpenVPN certificate
One of the advantages of the PKI infrastructure is that you can easily revoke access for a specific client. This might be needed, for example, if the private key is compromised, the password of an encrypted key is forgotten, or if you want to terminate a VPN user’s access.
These are the required steps, to be performed on the OpenVPN server machine:
- Launch the Command Prompt as administrator.
- Change directory to the easy-rsa folder:
cd c:\program files\openvpn\easy-rsa
- Run the command:
easyrsa-start.bat
. - The following command will revoke the certificate and create the Certificate revocation list (
crl.pem
):./easyrsa revoke-full <client-name>
Please note that thecrl.pem
file is not secret.
If you see the following error at the end of the output of therevoke-full
command:error 23 at 0 depth lookup:certificate revoked
it is normal, as the certificate verification of the revoked certificate failed. - Enable the verification of the
crl.pem
in the server config file, by adding the following line:crl-verify "C:\\users\\<username>\\easy-rsa\\pki\\crl.pem"
From now on, all connecting clients will undergo verification of their certificates against the CRL and any positive match will lead to the termination of the connection. - To ensure the CRL check is working, you can check the OpenVPN log, which is located in the following folder:
C:\Program Files\OpenVPN\log\
Here you should find the following message in correspondence of the connection attempt made by the client with the revoked certificate:VERIFY ERROR: depth=0, error=certificate revoked: CN=<client name>, serial=<serial number>
Frequently, certificates require revocation when users encrypt their private keys with a password and subsequently forget that password. Revoking the original certificate enables the generation of a new certificate/key pair while retaining the user’s original common name.
Troubleshooting OpenVPN connections
General tips
- When copying and pasting paths in Windows, such as from a website to a text editor, I’ve observed that occasionally the incorrect quotation mark symbol is pasted into the destination file, such as the OpenVPN config file. If you encounter issues with your OpenVPN configuration, ensure to manually delete and re-type the quotation marks directly in your text editor, rather than relying on the ASCII character obtained from the copy-paste process.
- If you cannot connect to other computers via the OpenVPN tunnel after the connection has been established, try the following steps:
- Disconnect the client from the OpenVPN tunnel.
- From an elevated Command Prompt on the server, stop the OpenVPN service:
net stop openvpnservice
- Restart the OpenVPN service:
net start openvpnservice
- Reconnect the client to OpenVPN.
- Wait a few seconds for the connection to establish. Sometimes this simple troubleshooting can resolve some connection issues.
“Route gateway is not reachable”
At one point, a client was unable to establish a connection to the OpenVPN tunnel. Despite apparent success in the log, connecting to the server via Remote Desktop wasn’t possible. The OpenVPN log displayed the following warning message:
Warning: route gateway is not reachable on any active network adapters: 10.8.0.2
So, in the OpenVPN server, I entered the ncpa.cpl
command in the Windows Search bar to open the Network Connections window. Here, I examined the OpenVPN TAP connection and noted it had an IP address starting with 169. This is an Automatic Private IP Addressing (APIPA), typically assigned during IP conflicts. An attempt to resolve the issue by disabling and re-enabling the TAP interface proved unsuccessful. When I tried to assign a static IP address to the network interface, I reiceved a pop-up message stating that such address was already in use by another network interface and couldn’t be saved.
Considering the pop-up message, I suspected there was a conflict between different network interfaces. Consequently, I disabled all unused OpenVPN network interfaces on the server (OpenVPN Data Channel Offload and OpenVPN Wintun). This change promptly resolved the issue, i.e. the TAP interface acquired the correct IP address (10.8.0.1) and the client was able to connect to the server via Remote Desktop.
“TLS error: TLS key negotiation failed to occur within 60 seconds” and “TLS error: TLS handshake failed”
After several months of successfully using OpenVPN at work, one day I was suddenly unable to connect remotely as a client, despite not having changed any configurations. The error messages I received on the client machine were the following:
TLS error: TLS key negotiation failed to occur within 60 seconds
.
TLS error: TLS handshake failed
.
After some research online and several attempts at disabling individual lines in my configuration files, I realised that the culprit was this line of the server configuration file:
crl-verify "C:\users\Administrator\easy-rsa\pki\crl.pem"
which is the Certificate revocation list (CRL) verification.
Once the line was disabled with a “;” and both the openvpnservice
and the OpenVPN GUI on the server were stopped and restarted, the connection worked again.
The issue was caused by the fact that EASYRSA_CRL_DAYS has a default expiration of 180 days, so the certificate had expired.
Therefore, if there are no revoked certificates in your network, it is best not to use a CRL at all. Otherwise, you can specify your own CRL expiration period in the following configuration file:
C:\Program Files\OpenVPN\easy-rsa\vars
by adding the following line at the bottom:
set_var EASYRSA_CRL_DAYS 5000
This line doesn’t exist by default and you can set the days to any value you want. Then, regenerate the CRL with a new nextUpdate
value. If you don’t want your CRLs to expire put that value far enough into the future.
Using EasyRSA a new CRL can be generated with ./easyrsa gen-crl
.