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

As much more people are getting worried about their online privacy (including me), I started to use a server as a VPN termination (with OpenVPN) when I need to access the Internet via non-secure wired or 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 /24 for each one; take a look at IANA Reserved addresses and do your math);
  • You can use the same tun adapter for both servers at the same time.

Now for the tricky part:

  • Most OpenVPN implementations (depends on your distro) require that you supply a configuration file. In our case, we prepare two config files (one for TCP and one for UDP) under /etc/openvpn
/etc/openvpn # ls *.conf
tcp-server.conf  udp-server.conf
  • systemd must be informed on which configuration it must start whenever openvpn is launched via its service unit. To accomplish that, open /etc/default/openvpn and specify the VPN configurations that must be started:
# Start only these VPNs automatically via init script.
# Allowed values are "all", "none" or space separated list of
# names of the VPNs. If empty, "all" is assumed.
# The VPN name refers to the VPN configutation file name.
# i.e. "home" would be /etc/openvpn/home.conf
#
# If you're running systemd, changing this variable will
# require running "systemctl daemon-reload" followed by
# a restart of the openvpn service (if you removed entries
# you may have to stop those manually)
#
AUTOSTART="tcp-server udp-server"
  • Finally, we need to reload systemd as instructed above:
# 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:

    # netstat -plunt | grep -i openvpn
    tcp 0 0 0.0.0.0:1194 0.0.0.0:* LISTEN 1635/openvpn
    udp 0 0 0.0.0.0:1194 0.0.0.0:* 1644/openvpn

One thought on “OpenVPN with multiple configurations (TCP/UDP) on the same host (with systemd)”

Leave a Reply