As privacy concerns grow, I’ve been running a self-hosted OpenVPN server to protect my traffic on untrusted networks: hotel Wi-Fi, airport connections, and the like. Some networks, however, are aggressively filtered:
- Traffic to non-standard ports is blocked
- Only
80/tcpand443/tcpare allowed outbound - DNS is locked to the local resolver, which can cause DNS leaks
To work around this, I set up two OpenVPN configurations on the same host: one over TCP (to survive port-restricted networks) and one over UDP (preferred for performance when there are no restrictions). Here are the implementation notes.
Subnet separation Link to heading
TCP and UDP VPN clients must be on separate subnets. OpenVPN needs distinct IP ranges to route traffic correctly when both servers are running simultaneously. I use a /24 for each. Refer to IANA reserved address ranges when choosing your subnets.
Both servers can share the same tun adapter.
Configuration files Link to heading
Place one .conf file per OpenVPN instance under /etc/openvpn:
/etc/openvpn # ls *.conf
tcp-server.conf udp-server.conf
Each file defines its own proto, port, server subnet, and any instance-specific settings.
Telling systemd which configurations to start Link to heading
Open /etc/default/openvpn and set AUTOSTART to list the names of the configurations to start automatically (the name corresponds to the .conf filename without the extension):
# 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.
AUTOSTART="tcp-server udp-server"
Reload systemd after making changes:
systemctl daemon-reload
Verify both servers are running Link to heading
Restart OpenVPN and check the logs:
systemd[1]: Starting OpenVPN connection to tcp-server...
systemd[1]: Starting OpenVPN connection to udp-server...
systemd[1]: Started OpenVPN connection to tcp-server.
systemd[1]: Started OpenVPN connection to udp-server.
Confirm both are listening with netstat or ss:
# 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
With this setup, clients can connect over UDP for the best performance, and fall back to TCP automatically when UDP is blocked.