I’ve run into plenty of authorized engagements and lab setups where a firewall only allows outbound TCP, but I needed to get UDP traffic — DNS queries, VoIP test traffic, or a custom UDP-based service — from one side of a network boundary to the other. UDPTunnel is a small, purpose-built utility that solves exactly that problem: it encapsulates UDP packets inside a TCP stream so they can cross a TCP-only path and get reassembled back into UDP on the other side.
What UDPTunnel Is and How It Works
UDPTunnel runs as a pair of processes — one acting as a client-side listener, one as a server-side relay — connected to each other over a plain TCP connection. The mechanics are simple:
- On the client side, UDPTunnel listens for UDP packets on a local port
- Each UDP packet it receives gets wrapped and forwarded over an established TCP connection to the remote UDPTunnel instance
- The remote instance unwraps the payload and re-sends it as a genuine UDP packet to the real destination service
- Return traffic follows the same path in reverse
Because the actual transport between the two endpoints is TCP, this lets UDP-dependent traffic pass through environments where only TCP is permitted (certain corporate proxies, restrictive firewalls, or SSH port-forwarding setups that only carry TCP).
Installing UDPTunnel
On Debian/Ubuntu:
sudo apt update
sudo apt install -y udptunnel
Verify:
udptunnel -h
Building from source if it’s unavailable in your distro:
git clone https://github.com/rfinnie/udptunnel.git
cd udptunnel
make
sudo make install
Basic Syntax
udptunnel -s <listen_port> <remote_host> <remote_port> # server/relay side
udptunnel -c <local_udp_port> <tunnel_host> <tunnel_port> # client side
Exact flags vary slightly by build/version, so I always check udptunnel -h on the specific system first; conceptually you’re always defining a local UDP listening point and a remote TCP endpoint to relay through.
Real Example (Authorized Lab Environment)
Setting up a relay on a lab jump host that forwards to an internal DNS server:
# On the relay/server host (has access to the internal DNS server on UDP 53)
udptunnel -s 5353 10.0.0.53 53
On the client side, tunneling local UDP traffic through the TCP-restricted path to that relay:
# On the client host (behind the TCP-only firewall)
udptunnel -c 5300 relayhost.lab.local 5353
Testing the tunnel with a DNS query aimed at the local tunnel port:
dig @127.0.0.1 -p 5300 example.internal
If everything is wired up correctly, the DNS response comes back through the TCP tunnel exactly as if the client had direct UDP access to the internal DNS server.
Real-World Use Cases
Authorized penetration testing pivoting — getting UDP-based reconnaissance or exploitation traffic (like certain UDP service probes) through a segment that only permits outbound TCP from a compromised host, as part of a documented internal network test.
Lab and training environment setup — building constrained network exercises where students or trainees need to demonstrate understanding of protocol tunneling techniques.
Legacy VoIP/UDP application testing across restrictive links — validating whether a UDP-dependent service can still function when routed through a TCP-only intermediate hop, for network engineering test scenarios.
Integration with Other Tools
- SSH port forwarding — UDPTunnel is often layered on top of or alongside SSH tunnels, since SSH’s native forwarding is TCP-only; UDPTunnel bridges the gap for UDP-dependent traffic riding on top of an SSH-secured TCP channel.
- stunnel — for engagements requiring encrypted transport of the tunnel itself, I wrap the UDPTunnel TCP connection inside an stunnel-secured channel (see the separate stunnel article) rather than relying on UDPTunnel’s own transport, which by itself doesn’t provide encryption.
- Nmap/service enumeration tools — used after establishing a tunnel to confirm the relayed UDP service is actually reachable and responding correctly through the new path.
Performance and Troubleshooting
- UDPTunnel adds latency compared to native UDP, since every packet now involves TCP’s connection-oriented overhead and reliability guarantees; this is usually fine for DNS-style request/response traffic but can be noticeable for latency-sensitive applications like real-time voice.
- If packets seem to vanish, double-check that both the local UDP listener and the remote destination UDP service ports are correctly matched — a common misconfiguration is swapping the client-side and server-side port arguments.
- Firewalls that do deep packet inspection may still flag or block a TCP stream carrying obviously tunneled UDP payloads; for engagements where firewall evasion itself is in scope, document this limitation explicitly.
Best Practices
- Only deploy UDPTunnel within environments and against systems you’re explicitly authorized to test.
- Since UDPTunnel doesn’t encrypt traffic on its own, pair it with a proper encrypted transport (SSH or stunnel) whenever the tunneled traffic is sensitive.
- Clearly document tunnel endpoints, ports, and purpose in your engagement notes so the setup can be torn down completely at the end of testing.
FAQ
Does UDPTunnel encrypt traffic? No — it only re-encapsulates UDP into TCP; you need to layer it with something like stunnel or an SSH tunnel if encryption is required.
Can it tunnel any UDP-based protocol? In principle, yes, since it works at the packet-relay level rather than understanding the specific application protocol — though very latency-sensitive protocols may perform poorly over the added TCP overhead.
Is UDPTunnel still commonly used today? It’s a lightweight, special-purpose utility; for full VPN-style tunneling most engagements now reach for more general tools, but UDPTunnel remains useful for quick, minimal UDP-over-TCP relay needs.
Summary
UDPTunnel solves a narrow but real problem: getting UDP traffic across a TCP-only path. In authorized testing and lab scenarios, I use it specifically when I need a lightweight way to relay a UDP-dependent service through a restrictive network boundary without standing up a full VPN.
References
- GitHub repository: https://github.com/rfinnie/udptunnel
- Man page:
man udptunnel
