Oct 5, 2025
Networking Rant 1 - Tunnels
My strong opinions about how to build one's personal computer network, not just using one.
Use tunnels, not proxies
Computer network's inherent layered design allows it to carry multiple protocols by default, without specialized treatment. TCP, UDP, ICMP, SCTP, etc. all looks the same by routers from the Network Layer, and IPv4, IPv6 looks the same from the Data Link Layer. It is the very basis of the Internet, and because an amateur network can be no less featureful than the Internet (like dn42 as a whole, or everyone participating in it), it should be just like that.
However, this norm is broken by proxies. HTTP proxy can only handle HTTP(S) traffic, and SOCKS5 proxy, which can only handle TCP and UDP, not even ICMP that allows you to debug the network in the most basic way. And same applies to all of the rest. This doesn't mean there is no place for proxies in networks -- it works fine as a Layer 7 service, just not suited for building a network upon it.
Of course, one can always transform a proxy into tunnel using custom TUN/TAP , but a lot of the implementation by the proxy tool itself is just transparent proxy and still does not handle anything other than TCP and UDP. Even if it does satisfy the above criteria, there are always lighter-weight options available (discussed below).
Avoid tunnels backed by TCP or any reliable protocol
TCP meltdown occurs when one runs TCP inside a TCP stream (TCP-in-TCP). When the network is unreliable (the very nature of the Internet), the two TCP's congestion control conflicts with each other and severely hurts performance.
UDP-in-TCP removes UDP's low-latency, out-of-order benefits brought by its unreliable nature. Since most UDP applications should assume these, it is harmful to their performance.
I appreciate Hysteria for utilising QUIC's Unreliable Datagram Extension to avoid such problem, but it is designed to be a proxy. Tunneling packets inside its proxied UDP packets is certainly doable, then its TCP function becomes bloat and we're back to the Occam's Razor discussed below.
One packet in the tunnel should always correspond to one packet of the tunnel protocol
Packet fragmentation saturates a middlebox device's packets-per-second (PPS) capability ~2x faster than no fragmentation, and adds additional overhead of spliting and reassembling the packets. If you run MTU 1500 inside a tunnel with overhead of 40 bytes, you are splitting the last 40 bytes of the packet into an another packet, incurring these unnessary overhead. It's even worse on a TCP-backed tunnel: the packets just randomly splits, destroying all kinds of performance optimisations, as IP fragments could be efficiently done by hardware offload.
There is one exception: the link's MTU is so small that the tunnel running on top of it cannot have MTU >= 1280 (minimum of which IPv6 supports). And in this undesirable scenario, try to make the tunnel MTU larger so that it split the tunnel protocol packet into multiples of that MTU to squeeze out as much as PPS as possible.
Use the minimum of tunneling protocols and avoid use of obfuscation methods
If your network runs on top of a secure network that you can trust or control, use plain text tunnels like FOU, GRE or Geneve instead of VPN tunnels like WireGuard and OpenVPN. If your ISP or government does not use deep packet inspection (DPI) to crack down VPN tunneling protocols, just use their vanilla version. If simply Mimicking WireGuard's UDP as TCP works, why bother using all of the fancy stuff from Xray?
I actually even avoid using Mimic, and I do hope I could abandon this project one day -- because if there's no need for me to play hide-and-seek, it no longer serves a purpose. Nevertheless, playing hide-and-seek itself -- writing my own project -- is the true fun part.