[HACK] UDP tunneling over TCP for WireGuard

Luca Beltrame lbeltrame at kde.org
Wed Apr 18 13:55:33 CEST 2018


Hello,

at one of the places I use WireGuard, outgoing UDP is *completely* blocked by 
the perimeter firewall. In addition, only a handful of ports are open. (Not 
that this has helped security in any way, but I digress)

This meant that I could not connect to my WireGuard-using OpenWRT router which 
is somewhere else. 

As a happy WireGuard user, I thought about how to handle this. Port was an 
easy solution: 587 is open, so I could just have the router redirect it to the 
actual endpoint port. UDP, not so much.

What came out was a horrid hack involving socat and sacrifices to the Great 
Old Ones, but that it worked enough for me.

tl;dr: Use socat to tunnel local UDP port via TCP to a remote port, then 
redirect UDP there to the actual WireGuard endpoint port.

First of all, I set a systemd unit to have this running continuously:

[Unit]
Description=UDP over TCP forwarder
After=autossh at tsugumi.service

[Service]
ExecStart=/usr/bin/socat -t600 -T600 -d -d UDP4-LISTEN:51821 tcp4:ENDPOINT_IP:
587
User=nobody
Group=nobody
Restart=always
ProtectSystem=full
ProtectHome=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

I set fairly high timeouts because WireGuard is not very chatty and socat 
usually exists when there's no traffic for a while.

Then, I set the relevant bits in wg0.conf:

[Interface]
ListenPort = 51820
PrivateKey =<redacted>
Address = 10.64.0.4/32
MTU=1280

[Peer]
PublicKey = <redacted>
AllowedIPs = 10.64.0.1/32,<internal router LAN IP range>
Endpoint = 127.0.0.1:51821
PersistentKeepalive = 60

As you notice, it goes to localhost then it's pushed via TCP to the remote 
endpoint. At this time, I had to lower the MTU to adjust for overhead (as 
discussed on IRC) that I introduced with this monstrosity. 

On the remote side, I have (running through openWRT's init):

/usr/bin/socat -d -d tcp4-listen:587,reuseaddr,fork UDP4:127.0.0.1:51820

which brings packets back to port 51820, where wg is listening.

And voila', it works:

interface: wg0
  public key: <redacted>
  private key: (hidden)
  listening port: 51820

peer: <redacted>
  endpoint: 127.0.0.1:51821
  allowed ips:  10.64.0.1/32, <LAN>
  latest handshake: 30 seconds ago
  transfer: 300.68 MiB received, 175.78 MiB sent
  persistent keepalive: every 1 minute

Very hacky, but gets the job done. Any suggestions on how to make it better?

-- 
Luca Beltrame - KDE Forums team
KDE Science supporter
GPG key ID: A29D259B
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.zx2c4.com/pipermail/wireguard/attachments/20180418/10e859b2/attachment.asc>


More information about the WireGuard mailing list