OpenVPN with multiple configurations (TCP/UDP) on the same host (with systemd)

As much more people is getting worried about their online privacy (including me), I started to use my home server as a VPN termination (with OpenVPN) when I am not at home and I need to access Internet via non-secure wired/wireless networks (e.g., hotel wireless network, airport Wi-Fi, etc.).

Some overzealous network admins, though, try to lock down the network usage to users, for understandable reasons: fair usage, fear of abuse, and so on. To name some of such limitations:

  • non-encrypted traffic sniffing (who trusts HTTP nowadays for sensitive data? Surprisingly, there is still someone who deploys HTTP for that!);
  • traffic shaping (especially downstream);
  • destination ports limited to 80/tcp and 443/tcp;
  • dns locking and consequently leaking (yes, I’m paranoid).

To overcome this limitations, I decided to use multiple configurations for OpenVPN, I wanted some flexibility on my side, offering multiple configurations of a VPN termination: one for TCP and one for UDP. I want to share some implementation notes that might save some time for whoever wants the same setup:

  • TCP subnets must be separated from UDP subnets (I use a /16 for each one; take a look at IANA Reserved addresses and plan accordingly);
  • You can use the same tun adapter for both servers at the same time.

Now for the tricky part:

  • Yes, most OpenVPN implementations (depends on your distro) require that you supply an /etc/openvpn/server.conf file. In our case, we do not want that. Just remove it and prepare two config files under /etc/openvpn

/etc/openvpn # ls *.conf
tcp-server.conf udp-server.conf

  • Now we need to tell systemd scripts that we do not have a server (default) OpenVPN configuration, but we actually have two configurations; so systemd should plan accordingly its scripts. Everything is already built-in into openvpn and its systemd integration, so we just generate the newest scripts with a simple instruction:

/etc/openvpn # /lib/systemd/system-generators/openvpn-generator <filename>

In our case:

/etc/openvpn # /lib/systemd/system-generators/openvpn-generator tcp-server
/etc/openvpn # /lib/systemd/system-generators/openvpn-generator udp-server

  • Finally, we need to reload systemd for the newly created scripts:

/etc/openvpn # sudo systemctl daemon-reload

  • Now, if you restart OpenVPN with systemctl restart openvpn and you check your logs, you should see that both your VPN are started:

11:38:33 vpn02.lin.michelebologna.net systemd[1]: Starting OpenVPN connection to tcp-server...
11:38:33 vpn02.lin.michelebologna.net systemd[1]: Starting OpenVPN connection to udp-server...
11:38:33 vpn02.lin.michelebologna.net systemd[1]: Started OpenVPN connection to tcp-server.
11:38:33 vpn02.lin.michelebologna.net systemd[1]: Started OpenVPN connection to udp-server.

and you can also check that OpenVPN is listening with netstat:

/etc/openvpn # netstat -polenta | grep -i openvpn
tcp 0 0 0.0.0.0:x 0.0.0.0:* LISTEN 0 470780879 5375/openvpn off (0.00/0/0)
/etc/openvpn # netstat -polenua | grep -i openvpn
udp 0 0 0.0.0.0:x 0.0.0.0:* 0 470780930 5396/openvpn off (0.00/0/0)

Leave a Reply