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 *