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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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:
1 2 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#!/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.