Hardening OpenVPN on Windows
Default settings often work well in most cases. But knowing how to optimize the tool as well as its environment brings a stronger control over its operation, especially against corner cases which could backfire when least expected.
This article is specifically based on my setup of OpenVPN. That said, it’s for OpenVPN on Windows; tun-mode (i.e. Routing).
Hardening OpenVPN Server
- Non-default port:
This may help against quick blocking of OpenVPN usage.
- UDP protocol:
Better protection against DoS attack and port scanning .
- Large RSA Key size, i.e.
More time to generate, but better safe than sorry. Bonus point: future-proof against Quantum Computing .
- Large Symmetric Key:
This key is used to encrypt the Data Channel, and here we indicate the desired Cipher to be used. Advanced Encryption Standard with 256 bit key length. Nothing can be better! 
- TLS minimum supported version:
As recommended in , it helps defend against Downgrade Attack .
- Stronger Hashing algorithm for message authentication:
According to , SHA-256 is advised. In addition, at present, no collision found for SHA-256 yet .
- Disable logging:
When OpenVPN Server is running stably, it’s better to disable Logging, so no trace, particularly the Client’s Public IP address, is stored on disk.
- Prevent DNS query leak:
DNS queries are carried out in Client side. With this setting pushed from Server to Client, no DNS queries are leaked outside of the VPN.
Plus, let’s ask Client to redirect its traffic through the OpenVPN interface.
push "redirect-gateway def1"
- Disable IPv6:
In my case, Client’s OS supports both IPv4 and IPv6. In addition, public IP addresses assigned by ISP are also available for both. However, Server’s OS only supports IPv4. When testing with  after the VPN was established, I found a serious issue: the public IPv4 in Client side is the public IPv4 of Server, which was expected; but the public IPv6 in Client side is its real IPv6, meaning it is leaked. There might be some settings to overcome this situation; but I do not know. I workarounded by simply disabling IPv6 on Client’s OS.
- Hide TLS Handshake and reduce DoS Attacks:
The key file is used to not only authenticate, but also encrypt the TLS Control Channel, which helps hide the initialization of TLS handshake as well as preventing TLS DoS Attacks. (Meta)Data is encrypted twice, once by tls-crypt and once by the TLS session. See .
Hardening OpenVPN Client
The Client shares some settings with the Servers’. They must be the same so that Server and Client can work well together in establishing the VPN.
Another big setup in Client side is to enforce that there is no accidential traffic leaking out of the established VPN between Server and Client. Totally relying on correctly configuring OpenVPN all the time might be challenging. Therefore, we need “fail-safe” mode; in case things don’t turn out expectedly (Our expectation: all the Client’s traffic must go through the VPN toward Server, and contact the Internet up there), we just simply lose Internet connection, and no network package is leaked whatsovever.
To enforce such requirement, I leverage Windows built-in Firewall.
Update on 27.01.2020: To be more clear, this configuration assumes that the normal Internet network connection, which you use to connect to Internet without VPN, is of Public profile (see below: Ethernet, picture “Connection Types”). In contrast, the network connection under VPN is of Private profile (see below: ClientVPN, picture “Connection Types”). The OpenVPN process should access Internet directly via the normal connection, while any other processes, e.g. uTorrent, must be put through VPN connection.
Firstly, Inbound/Outbound connections are forbidden unless allowed.
Secondly, only allow specific programs, e.g. uTorrent, to access Internet through Private profile. Note: Of course, the OpenVPN Client (bin\openvpn.exe) must be allowed to access Internet directly.
Lastly, in Client side, the OpenVPN’s Tap-Interface must be made private:
Thanks to , find out the OpenVPN’s Tap-interface index (
route print -4), e.g.
15. Then add a static route (
route -p add 0.0.0.0 mask 0.0.0.0 192.168.100.1 metric 50 if 15). The
192.168.100.1 is the IP address of the OpenVPN Server within the VPN. After that, when connecting to the remote OpenVPN Server, Windows will ask us to classify the Network as either Private or Public. Certainly, we choose Private. The key point here is that this configuration survives the reboot of the Client’s PC as well as disconnecting/reconnecting to OpenVPN Server.
From now on, in Client side, making a VPN toward the OpenVPN Server is as easy as clicking the Connect menu.
After the VPN is established, how can one make sure that configuration is done correctly? Let’s test that with ,  and  in a browser. Notice that it must return results as if the browser ran on the Server.
We have learned techniques to harden the use of OpenVPN in both Server and Client sides. On Linux, we might go even further, e.g. run OpenVPN in least privileged mode; however, it is outside the scope of this article because we’re using Windows! Protecting traffic by encrypting it through a VPN is great, but the presence of OpenVPN usage, to Network Administrators, is detectable. See . Another technique, called Obfsproxy, can help obfuscate the OpenVPN traffic. But this might in turn raise suspicion…
Last but not least, I can’t stress enough the false assumption of utilizing powerful tools as well-illustrated here.