For a project of mine, I'm searching for possibilities to have a UDP-only VPN working over TCP (preferably on port 443 or 80). I have found the following while doing some research:

  • This is possible with socat, however, this is unreliable since UDP connection could keep on pushing traffic, while the TCP buffer will overload.
  • I suspect it might be possible with Secure Socket Funneling (SSF)[1], however I am not sure if this works 100% reliable, and whether it pushes traffic over TCP or they found some way to use TLS over UDP (it seems that way for me).

As for the reason why I want the UDP-only VPN to work over TCP: various corporate firewalls or nation-wide firewalls block UDP traffic on (random) UDP ports. Of course there exist designated UDP ports (say 53 DNS) which are mostly opened, but it is really easy to recognize VPN from the regular traffic on those ports. I know of traffic mimicking, but this implies way to much overhead on the VPN. The protocol used for this project is WireGuard instead of OpenVPN where TCP-fallback is build-in.

As far as I know, no good (reliable) techniques exist to wrap UDP traffic in TCP. Is this true, and if so, are there other techniques which could achieve my goal?

[1] https://securesocketfunneling.github.io/ssf/#home

  • OpenVPN does not have a fallback mechanism. It’s either UDP or TCP, as set up. Unfortunately, I see no other way but to just use OpenVPN. Its versatility in firewalled environments is unmatched. – Daniel B Sep 5 '18 at 12:48
  • @DanielB I actually said it wrong about the fallback. I ment that OpenVPN clients can have the fallback mechanism in place since OpenVPN support both UDP & TCP. However, we are curenntly using OpenVPN for this project, but are looking into options to use WireGuard (UDP-only) instead, while still preserving this option (fallback to TCP when UDP is blocked). – Breus Sep 5 '18 at 12:54
  • Have a look at softether.org maybe. – Patrick Mevzek Sep 5 '18 at 15:07
  • @Patrick Mevzek thanks, however, the point of my question is to get it working for WireGuard in any way. – Breus Sep 5 '18 at 15:30

I can't help you with a direct answer, but you may find good information in the sources below.

Zebedee (open source from 2005)

Zebedee is a simple program to establish an encrypted, compressed “tunnel” for TCP/IP or UDP data transfer between two systems. This allows traffic such as telnet, ftp and X to be protected from snooping as well as potentially gaining performance over low-bandwidth networks from compression.

Some more info may be found here.


This is available as a Linux package (Debian link).

Its source is found on GitHub, where it is described as :

This project tunnels TCP data through a UDP tunnel. The executable can act as the server or client. The server acts as a proxy for the client, listening on a specified UDP port and creating a connection to a TCP server that the client specifies. The client listens on a TCP port, acting as the server that some TCP client connects to. The client recevies any TCP data on that port and sends the data to the udpserver, which sends it to the TCP connection it made with the desired TCP server.

Just to remark that UDP packets passing through a TCP-based VPN tunnel have guaranteed delivery only for the TCP part of their total journey. In the portions of the total path outside the TCP-based VPN tunnel, packet loss may occur.


Maybe a little late but udp2raw-tunnel is a great piece of software for tunneling UDP over TCP. Maybe socat doesn't work because (maybe) it can't split UDP packets correctly on the receiving end after they are concatenated in the TCP tunnel. TCP is a stream after all.

Using udp2raw-tunnel as a UDP-over-TCP tunnel doesn't require root privilege. On the client machine, run:

udp2raw -c -l -r $server_ip:80

and make your VPN client connect to UDP port 3333 on localhost.

Listening on port 80/443 on the server machine may need root privilege:

sudo udp2raw -s -l -r$vpn_server_udp_port

VPN client/server machine is not necessarily the same machine as udp2raw client/server, just set the correct IP and it will work.

Edit: Oops I just found that it's 'fake' TCP, meaning it's using raw IP datagram but makes outside world think it's a TCP connection. So you would achieve no success if you try to tunnel its 'TCP' connection through SSH. But it works great in your scenario nonetheless.

  • Hi man, thanks for the effort of answering! I already finished this project and made a custom wrapper in Go. – Breus Mar 5 '20 at 12:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.