OpenVPN: Listen on TCP and UDP with TUN

Today I’ll describe how to get OpenVPN to listen both to UDP and TCP port, using both tun device and the same network for clients. Meaning the same client can connect on either TCP or UDP and get the same IP Address assigned.

To achieve this, we’re gonna need:

  • OpenVPN
  • Sudo

I’m running this on a Debian Wheezy installation, but any Linux distribution can do the trick.

Let’s create the first OpenVPN instance, to listen on UDP/1194, creation of certificate is not covered by this HOWTO, as plenty of resources can already be found online.

port 1194
proto udp
dev tun0
ca /etc/openvpn/MYVPN/keys/ca.crt
cert /etc/openvpn/MYVPN/keys/server.crt
key /etc/openvpn/MYVPN/keys/server.key

dh /etc/openvpn/MYVPN/keys/dh1024.pem

tls-server
server 10.1.2.0 255.255.255.0
ifconfig-pool-persist /etc/openvpn/MYVPN/ipp.txt
client-config-dir /etc/openvpn/MYVPN/ccd
ccd-exclusive

keepalive 10 60
tls-auth /etc/openvpn/MYVPN/keys/ta.key 0
cipher AES-256-CBC   # AES

max-clients 20
user vpn
group vpn

persist-key
persist-tun
ping-timer-rem
status /etc/openvpn/MYVPN/status.log
status-version 2

verb 4
mute 20

script-security 2
learn-address /etc/openvpn/MYVPN/learn-address.sh

Note that, the only difference with a standard VPN configuration, is the following line:


learn-address /etc/openvpn/MYVPN/learn-address.sh

This configuration line will make the script ‘learn-address.sh’ be ran whenever a client’s address is learned or unlearned. This will allow us to modify the kernel’s routing table upon client connection/disconnection and specify which tunnel interface we should use for that particular client.

Let’s now configure the TCP VPN:

port 1194
proto tcp
dev tun1
ca /etc/openvpn/MYVPN/keys/ca.crt
cert /etc/openvpn/MYVPN/keys/server.crt
key /etc/openvpn/MYVPN/keys/server.key

dh /etc/openvpn/MYVPN/keys/dh1024.pem

tls-server
server 10.1.2.0 255.255.255.0
ifconfig-pool-persist /etc/openvpn/MYVPN/ipp-tcp.txt
client-config-dir /etc/openvpn/MYVPN/ccd
ccd-exclusive

keepalive 10 60
tls-auth /etc/openvpn/MYVPN/keys/ta.key 0
cipher AES-256-CBC   # AES

max-clients 20
user vpn
group vpn

persist-key
persist-tun
ping-timer-rem
status /etc/openvpn/MYVPN/status-tcp.log
status-version 2

verb 4
mute 20

script-security 2
learn-address /etc/openvpn/MYVPN/learn-address.sh

Note that we only changed the name of log files, IPP, the tun device name and of course, the protocol.

Now, let’s configure a client’s CCD file like the following:

ifconfig-push 10.1.2.6 10.1.2.5
iroute 10.1.2.6

Allow vpn user to run /sbin/ip through sudo, to be able to make routing table changes within the learn-address.sh script; Let’s create a ‘/etc/sudoers.d/openvpn’ file with the following content:


vpn ALL=(ALL:ALL) NOPASSWD: /sbin/ip

And last but not least, let’s put together the learn-address.sh script which will make all the magic:

#!/bin/bash
#!/bin/bash
##
# learn-address script which allow
# OpenVPN to run on both TCP and UDP
# with the same range of address on both
# protocol.
#
# tgouverneur -- 2014
##

if [ $# -lt 2 ]; then
  exit 0;
fi
action=$1;
addr=$2;

case ${action} in
        add|update)
                echo "[-] ${addr} logged in to ${dev}" >> /etc/openvpn/MYVPN/vpn.log
                /usr/bin/sudo /sbin/ip ro del ${addr}/32
                /usr/bin/sudo /sbin/ip ro add ${addr}/32 dev ${dev};
        ;;
        delete)
                # Found out we'd better do nothing when delete is called.
#               echo "[-] Deleting addr ${addr} -> ${dev}" >> /etc/openvpn/MYVPN/vpn.log
#               /usr/bin/sudo /sbin/ip ro del ${addr}/32
        ;;
        *)
        ;;
esac

exit 0;

As some comments have mentioned, you also need to run these:


# adduser --system --group vpn
# chmod +x learn-address.sh

Now, you can try and make your client connect to the UDP instance, disconnect and connect again to the TCP one. You can tail -f the /tmp/learn.log file in which you can see routing changes if everything is working:


[-] Adding addr 10.1.2.6 -> tun0
[-] Deleting addr 10.1.2.6 ->
[-] Adding addr 10.1.2.6 -> tun1
[-] Deleting addr 10.1.2.6 ->

This was useful to you? Have questions? Thoughts? Don’t hesitate to leave a comment if so.

This entry was posted in GNU/Linux, Networking and tagged , , , . Bookmark the permalink.

17 Responses to OpenVPN: Listen on TCP and UDP with TUN

Leave a Reply

Your email address will not be published. Required fields are marked *