I've searched around and the only thing I've found is that "yes, OpenVPN supports connections over TCP", but I haven't found any way to coerce the openvpn server to listen the same port for both protocols at the same time. I've found some very old guides about creating tap interfaces, or recommending to have another instance of the server with the same configuration running at the same time. The former looks too complicated for something simple, and the later seems obsolete.

2 Answers 2


The same openvpn process can't listen on UDP and TCP sockets at the same time.

You have two good options:

  1. use two tap interfaces for openvpn. Have two openvpn server processes, one for each tap interface; one should listen on UDP, the other on TCP. Bridge these two tap interfaces on the server.

  2. use two tun interfaces. These can't be bridged, so if you want to share the IP space between TCP and UDP clients, you'll need to use a learn-address script like the one at http://thomas.gouverneur.name/2014/02/openvpn-listen-on-tcp-and-udp-with-tun/ (however, this specific script is vulnerable to a /tmp symlink attack, so remove the logging to /tmp if you use it).

The third option is to just run two openvpn instances and assign separate client IP space to both (for example, one /25 from the same /24 subnet each). This avoids bridging and the need for a learn-address script.

EDIT: since I needed such a learn-address script myself, I wrote one. I place it in the public domain.

# This script allows an openvpn server with several openvpn instances that
# use tun interfaces to share client IP space by adjusting the routing table
# to create entries towards specific clients as needed

cn="$3" # not used, but it's there; you could e.g. log it

case "$action" in
                echo "sudo ip ro add $addr/32 dev $dev" >&2
                sudo ip ro change $addr/32 dev $dev || sudo ip ro add $addr/32 dev $dev # if a route already existed, add will fail but change should work, and vice versa
# even if a client connects to one OpenVPN instance first, then reconnects to the other before the first connection times out, the "add" case above sets up the correct route; it may thus not be necessary to delete routes, ever
#               echo "sudo ip ro del $addr/32 dev $dev" >&2
#               sudo ip ro del $addr/32 dev $dev
#               exit 0 # ignore errors
                echo "sudo ip ro change $addr/32 dev $dev" >&2
                sudo ip ro change $addr/32 dev $dev \
                   || exec sudo ip ro add $addr/32 dev $dev # 'change' can fail with ENOENT, in which case we must 'add'

This script logs to stderr, which should end up in the openvpn log.

  • 1
    To get this working, you also need to add "script-security 2" to each file where you put learn-address "/etc/openvpn/learn-address.sh" : forums.openvpn.net/viewtopic.php?t=12613 . For IPv6 compliance, add : echo "$2" | grep ":" >/dev/null && length=128 || legth=32 ; and replace all 32 with $length. Now I got IPv4+IPv6 / UDP+TCP. Commented May 20 at 21:46

If you want your OpenVPN server to listen on a TCP port instead of a UDP port, use proto tcp instead of proto udp (If you want OpenVPN to listen on both a UDP and TCP port, you must run two separate OpenVPN instances).

Do you mean this page is obsolete?

I think you can run two OpenVPN servers (one for TCP, one for UDP,) bridge each of them with a TUN, and then connect the TUNs.

  • 2
    tun interfaces don't have a MAC layer and thus can't be members of a bridge. If you want bridging, you need to use tap interfaces. Commented Jun 4, 2019 at 6:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .