Skip to content

Instantly share code, notes, and snippets.

@insdavm
Last active April 29, 2024 20:09
Show Gist options
  • Star 65 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save insdavm/90cbeffe76ba4a51251d83af604adf94 to your computer and use it in GitHub Desktop.
Save insdavm/90cbeffe76ba4a51251d83af604adf94 to your computer and use it in GitHub Desktop.
WireGuard over TCP with udptunnel

WireGuard over TCP with udptunnel

udptunnel is a small program which can tunnel UDP packets bi-directionally over a TCP connection. Its primary purpose (and original motivation) is to allow multi-media conferences to traverse a firewall which allows only outgoing TCP connections.

Server

# udptunnel -s 443 127.0.0.1/51820

Client

# udptunnel -c [SERVER PUBLIC IP]/443 127.0.0.1 50001
  • Remember to open TCP port 443 on the server's firewall
  • In the WireGuard client config file, replace the server's public IP (endpoint) with 127.0.0.1:50001
@bcnx
Copy link

bcnx commented Nov 10, 2021

Would I be able to use this tool when my Wireguard server is on the inside of a restricted network and my Wireguard client is on the outside of the network (meaning on the internet)? I'm looking for a way to make a Wireguard install available on the internet while I cannot alter the firewall for the internal network. Cheers!

@testingnic
Copy link

@patrickzzz I have the same problem I can not solve it, in what way did you do it? I need help, can you tell me more details?

@raisaputra
Copy link

any solutions for "Address already in use" in server side?

@testingnic
Copy link

no one says anything about that =( i need help anyway @jpnbreakfast

@raisaputra
Copy link

raisaputra commented Jan 26, 2022

no one says anything about that =( i need help anyway @jpnbreakfast

i found alternative for doing this, like using websocket or udp2raw, but too bad my openwrt router only can use udptunnel cause of small ROM size

@testingnic
Copy link

@jpnbreakfast how to use it? ☹️ explain me

@diyaa59
Copy link

diyaa59 commented Feb 25, 2022

read the manual page :)
man udptunnel

@testingnic
Copy link

@at1047 did you solve the problem?

@excelsi
Copy link

excelsi commented Jun 4, 2022

Can you add support for IPV6?
Thanks!

@milankowww
Copy link

milankowww commented Jan 15, 2023

If you face the "Address already in use" problem: the tunnel is incorrectly implemented. It requires more substantial patches to actually work. It uses different sockets for send and receive, resulting in different source port numbers even when you overcome the original problem. Instead, use this utility with the same name: https://github.com/rfc1036/udptunnel which works with Wireguard unmodified.

@arkq
Copy link

arkq commented Nov 17, 2023

I've been facing the same issues with "Address already in use". Other projects did not work for me as well.... So, I've created https://github.com/arkq/wg-tcp-tunnel which handles everything properly. Also, one does not need root privilege to run it. I'm using it on RPi4 (behind NAT using ngrok) and not-rooted Android phone (via Termux). On Android the wg-tcp-tunnel is compiled in Termux as well, since it only depends on Boost and STL. The README explains how to use it.

@fearocanity
Copy link

I've been facing the same issues with "Address already in use". Other projects did not work for me as well.... So, I've created https://github.com/arkq/wg-tcp-tunnel which handles everything properly. Also, one does not need root privilege to run it. I'm using it on RPi4 (behind NAT using ngrok) and not-rooted Android phone (via Termux). On Android the wg-tcp-tunnel is compiled in Termux as well, since it only depends on Boost and STL. The README explains how to use it.

Cool

@andrew-aladjev
Copy link

If you face the "Address already in use" problem: the tunnel is incorrectly implemented. It requires more substantial patches to actually work. It uses different sockets for send and receive, resulting in different source port numbers even when you overcome the original problem. Instead, use this utility with the same name: https://github.com/rfc1036/udptunnel which works with Wireguard unmodified.

No, original udptunnel has a bunch of issues about "address is already in use". It doesn't work as expected and it should be investigated.

@andrew-aladjev
Copy link

I've found what happens:

for (ai = res; ai; ai = ai->ai_next) {
        if ((fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) < 0)
            continue;           /* ignore */
        opt = 1;
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
            err_sys("setsockopt(SOL_SOCKET, SO_REUSEADDR)");
        if (bind(fd, (struct sockaddr *) ai->ai_addr, ai->ai_addrlen) < 0)
            err_sys("Cannot bind to %s", s);

It tries to bind to target TCP port using AF_INET (ipv4) and to target TCP port using AF_INET6 (ipv6). First attemt succeded and second one failed. I will try to investigate how to fix it.

@testingnic
Copy link

I've been facing the same issues with "Address already in use". Other projects did not work for me as well.... So, I've created https://github.com/arkq/wg-tcp-tunnel which handles everything properly. Also, one does not need root privilege to run it. I'm using it on RPi4 (behind NAT using ngrok) and not-rooted Android phone (via Termux). On Android the wg-tcp-tunnel is compiled in Termux as well, since it only depends on Boost and STL. The README explains how to use it.

Bro can this be used with ovpn?

@andrew-aladjev
Copy link

andrew-aladjev commented Apr 21, 2024

Ok, I've figured it out. udptunnel is trying to bind on 0.0.0.0 and after that it is trying to bind on :: using the same port. Second bind will fail if /proc/sys/net/ipv6/bindv6only is 0. You can disable this flag using sysctl net.ipv6.bindv6only = 1, but don't do it, because you will ruin other applications that may depend on bindv6only = 0, they may expect that binding on 0.0.0.0 implies binding on ::.

I am going to provide pull request to udptunnel that will fix it.

@testingnic
Copy link

Ok, I've figured it out. udptunnel is trying to bind on 0.0.0.0 and after that it is trying to bind on :: using the same port. Second bind will fail if /proc/sys/net/ipv6/bindv6only is 0. You can disable this flag using sysctl net.ipv6.bindv6only = 1, but don't do it, because you will ruin other applications that may depend on bindv6only = 0, they may expect that binding on 0.0.0.0 implies binding on ::.

I am going to provide pull request to udptunnel that will fix it.

I HOPE YOU PROVIDE A GUIDE ON THIS

@patrickzzz
Copy link

Sounds good.. would be nice to find a solution.
https://manpages.ubuntu.com/manpages/focal/man1/udptunnel.1.html shows that IPv6 is not supported, maybe due to this or even bigger problems..

@andrew-aladjev
Copy link

I've added issue and pull request.

@testingnic My patch is trivial, and it fixes a well-known problem with ipv6. You can email the maintainer of your distro (Ubuntu, OpenWrt, etc) and it will add this patch for sure. I will also send emails to Ubuntu and OpenWRT distro so they may release a patched version of udptunnel soon.

For now you can't do anything except net.ipv6.bindv6only = 1, but please don't do it.

@andrew-aladjev
Copy link

I've investigated openwrt udptunnel and found that its version is really ancient, maybe udptunnel from 1999, it supports only IPv4 (it is specified in sin_family).

@patrickzzz, Ubuntu uses the same ancient version as OpenWRT.
@testingnic We need to wait until package maintainers start using the recent udptunnel from github. For now, we can only build it manually and install it locally.

Gentoo has tamiko overlay with same ancient version of udptunnel.

So everything is pretty bad for regular user, you need to build recent udptunnel from github manually and install it locally.

@testingnic
Copy link

but how do I download the latest update if it hasn't been updated in 9 years ahaha

@testingnic
Copy link

https://twitter.com/rfc1036

twitter creator

@andrew-aladjev
Copy link

andrew-aladjev commented Apr 22, 2024

@testingnic, please just download it from github, apply important important patches and build it.

git clone https://github.com/rfc1036/udptunnel.git
cd udptunnel

curl https://patch-diff.githubusercontent.com/raw/rfc1036/udptunnel/pull/5.patch -o /tmp/5.patch
git apply /tmp/5.patch

curl https://patch-diff.githubusercontent.com/raw/rfc1036/udptunnel/pull/14.patch -o /tmp/14.patch
git apply /tmp/14.patch

make

sudo ./udptunnel -s 443 127.0.0.1/51820

@andrew-aladjev
Copy link

andrew-aladjev commented Apr 22, 2024

@testingnic, I've made the udptunnel-1.2.0 release in my own fork with deb and rpm packages, because we can wait for @rfc1036 almost forever. You can now just download and install it.

@andrew-aladjev
Copy link

andrew-aladjev commented Apr 22, 2024

I've added here my gist with configs. I've tested it on several machines and it works perfect. Please try it.

PS From my experience TCP tunnel is a bit faster than UDP in several countries, because of QOS.

@patrickzzz
Copy link

well done so far.. although i don't like to use unmaintained software-packages for this purposes.. ;-(

@andrew-aladjev
Copy link

@patrickzzz I am also using wstunnel. It is maintainable and easy. Of course he can't bypass GFC, but it can provide good experience in any country except China.

udptunnel is required for low memory devices like old routers with openwrt. I don't really see any requirement for further udptunnel updates and maintenance.

@testingnic
Copy link

Tranks bro 💖

@andrew-aladjev
Copy link

I've made additional work on wireguard routing. You may be interested in it. Question is here, gist with route scripts and configs here.

@testingnic
Copy link

I've made additional work on wireguard routing. You may be interested in it. Question is here, gist with route scripts and configs here.

udp puncher could be added

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment