WireGuard + udptunnel

WireGuard is a popular new VPN protocol. A known limitation of WireGuard is that it can only use UDP, which may be blocked on some networks. By combining WireGuard with udptunnel, WireGuard can emulate TCP. Note that udptunnel does not support IPv6.

In this tutorial, WireGuard and udptunnel are implemented on an Ubuntu Linux server and an Ubuntu Linux client. In the examples, the client is assumed to be at IP address 11.11.11.11, and the server is assumed to be at IP address 22.22.22.22. We will use port 1433/tcp for udptunnel and port 51820/udp for WireGuard.

We assume that you SSH into the server as root, but that you use a non-root identity with sudo permissions on the client.

1. Server

1.1. Update Server

Before you do anything else, get your server completely up to date:

apt update && apt upgrade -y

1.2. Configure Firewall

We are going to use port 1433/tcp for udptunnel. Although we use port 51820/udp for WireGuard, this port should generally be kept closed, as that will better camouflage your server.

Here are some sample iptables rules for IPv4. In this example, SSH is confined to a single IP address, which is 11.11.11.11 in the example. This is the IP address of your workstation Replace 11.11.11.11 by the actual IP address of your workstation.

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s 11.11.11.11/32 -j ACCEPT
iptables -A INPUT -p tcp --dport 1433 -j ACCEPT
iptables -P INPUT DROP

udp2tunnel does not support IPv6, so there is no need to open any ports there.

ip6tables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
ip6tables -A INPUT -i lo -j ACCEPT
ip6tables -A INPUT -p icmpv6 -j ACCEPT
ip6tables -P INPUT DROP

To persist these rules across reboots, install the package iptables-persistent:

apt install iptables-persistent -y

1.3. Install WireGuard

Install WireGuard using the script and instructions from https://github.com/angristan/wireguard-install:

apt install curl -y
curl -O https://raw.githubusercontent.com/angristan/wireguard-install/master/wireguard-install.sh
chmod +x wireguard-install.sh
./wireguard-install.sh

You can accept the defaults all the way through the script’s questions, except specify the server’s WireGuard port as 51820.

When prompted for the name of the first client, call it wgtcp. This causes the script to create a client configuration file named wg0-client-wgtcp.conf. The server configuration is placed in /etc/wireguard/wg0.conf.

1.4. Install udptunnel

Install the compiler, etc.:

apt install build-essential pkg-config zip unzip -y

Download the source:

wget https://github.com/rfc1036/udptunnel/archive/refs/heads/master.zip
unzip master.zip

Make and install:

cd udptunnel-master
make
make install

1.5. Run udptunnel

To free up the terminal for any other use you may have, we run udptunnel in its own screen session. If you do not already have screen, install it now:

apt install screen -y

Start a named screen session:

screen -S udptunnel

Run udptunnel in this screen session:

udptunnel --server 0.0.0.0:1433 --verbose 127.0.0.1:51820

Detach from the named screen session by pressing Ctrl+a immediately followed by d on your computer keyboard. (You can resume the named screen session at any time with the command screen -r udptunnel.)

Exit your SSH session:

exit

2. Client

2.1. Update Client

Before you do anything else, get your client completely up to date:

sudo apt update && sudo apt upgrade -y

2.2. Configure Firewall

We are going to use port 1433/tcp for udptunnel. However, all connections will be initiated by the client, so we generally will not need a new firewall rule to open 1433/tcp for input.

2.3. Install udptunnel

Install the compiler, etc.:

sudo apt install build-essential pkg-config zip unzip -y

Download the source:

cd ~/Downloads
wget https://github.com/rfc1036/udptunnel/archive/refs/heads/master.zip
unzip master.zip

Make and install:

cd udptunnel-master
make
sudo make install

2.4. Run udptunnel

To free up the terminal for any other use you may have, we run udptunnel in its own screen session. If you do not already have screen, install it now:

sudo apt install screen -y

Start a named screen session:

screen -S udptunnel

Run udptunnel in this screen session:

sudo udptunnel 127.0.0.1:51820 22.22.22.22:1433

Replace 22.22.22.22 in the above command by the actual IP address of your server.

Detach from the named screen session by pressing Ctrl+a immediately followed by d on your computer keyboard. (You can resume the named screen session at any time with the command screen -r udptunnel.)

2.5. Install WireGuard

Install WireGuard on the client:

sudo apt install wireguard resolvconf -y

2.6. Configure WireGuard

Download the configuration file from the server:

cd ~/Downloads
scp root@22.22.22.22:wg0-client-wgtcp.conf .

Replace 22.22.22.22 in the command above by the actual IP address of your server.

Copy the configuration file into place:

sudo cp wg0-client-wgtcp.conf /etc/wireguard/wg0.conf

Edit the WireGuard configuration file:

sudo vi /etc/wireguard/wg0.conf

udptunnel will take care of forwarding packets to the real server IP address. Therefore change the endpoint of the peer to be localhost, which is where udptunnel is listening. Also remove IPv6 addresses, since udptunnel does not support IPv6.

Here is a sample client configuration file after these changes:

[Interface]
PrivateKey = eFtVksTyhrGjkGbvD8aJEtCbBejoTdpfpZj8eVqkaEU=
Address = 10.66.66.2/32
DNS = 94.140.14.14,94.140.15.15

[Peer]
PublicKey = bPsQarHrizq/3WadVipH0kmpAOPS5VOQHR6RyE3pYlk=
PresharedKey = mCN5BexpDJKTLoCQM8a++DFkpoVWlpyg0HSfB1sY1HY=
Endpoint = 127.0.0.1:51820
AllowedIPs = 0.0.0.0/0

Write the file to disk. Quit the editor.

2.7 Add Static Route

Add a static route from the client to the server, so that it does not try to send WireGuard traffic via udptunnel, then udptunnel via WireGuard, in a continuous and never-ending loop. For example, if your default gateway is 192.168.1.1 and your interface is wlp3s0:

sudo ip route add 22.22.22.22 via 192.168.1.1 dev wlp3s0

Replace 22.22.22.22 in the command above by the actual IP address of your server. Replace 192.168.1.1 and wlp3s0 by your actual default gateway. If you do not know your default gateway, you can determine it by issuing the command ip r.

2.8. Run WireGuard

sudo wg-quick up wg0

You can test your connection by visiting https://whatismyipaddress.com in Firefox.

2.9. Disconnect

Stop WireGuard:

sudo wg-quick down wg0

Stop udptunnel:

screen -r udptunnel

Stop udptunnel with Ctrl+c. Kill the screen session by doing Ctrl+a followed by k, then y to confirm.

Delete the static route:

sudo ip route del 22.22.22.22 via 192.168.1.1 dev wlp3s0

Replace 22.22.22.22 in the command above by the actual IP address of your server. Replace 192.168.1.1 and wlp3s0 by your actual default gateway.

3. Get Help and Report Issues

For WireGuard, the best place to get help is the #wireguard IRC channel on libera.chat.

udptunnel is a very old program and no longer supported.

Updated 2022-02-08