TCP-over-TCP VPNs are generally avoided due to inherent performance problems caused by competing congestion control layers. Yet DSVPN challenges this long-held wisdom by coupling inner and outer TCP congestion controllers, making TCP tunneling over restricted networks feasible and practical. This is a rare example where a clever kernel-level tweak enables a VPN to run smoothly over networks that only allow TCP port 80 or 443.
What dsvpn is and how it works
DSVPN is a minimalist VPN implemented in about 25 KB of C code. It’s designed to run on a wide range of Unix-like platforms: Linux, macOS, OpenBSD, FreeBSD, NetBSD, and DragonFly BSD. The VPN operates exclusively over TCP, which allows it to work even on restrictive networks where only TCP/80 and TCP/443 are open — a common scenario in corporate or public Wi-Fi environments.
The design philosophy behind DSVPN is simplicity and minimalism. It uses a single shared secret key for cryptographic authentication and encryption, avoiding the complexity of certificate management or multi-party key exchanges. There are no configuration files or complicated setup steps required. You don’t have to fiddle with firewall rules or routing tables after installation. This zero-configuration approach makes it incredibly straightforward to deploy.
Cryptographic operations rely on the Charm library, a formally verified cryptography library that ensures a high standard of security guarantees without external dependencies. The entire binary is self-contained and compact, with a memory footprint that remains constant during execution — DSVPN avoids heap allocations entirely. This design not only minimizes resource usage but also reduces attack surface.
Under the hood, DSVPN runs a TCP tunnel that encapsulates a TCP connection inside another TCP connection. While this setup breaks conventional networking advice, DSVPN implements a smart trick to make it work.
How congestion control coupling makes TCP-over-TCP viable
TCP-over-TCP tunnels typically suffer from poor performance due to the nested congestion control layers fighting each other. Each TCP layer independently manages retransmission, flow control, and congestion avoidance, which often results in amplified latency, throughput collapse, and packet loss.
DSVPN’s key innovation is coupling the inner and outer TCP congestion controllers by tweaking the TCP_NOTSENT_LOWAT socket option. This parameter controls the minimum amount of unsent data in the TCP send buffer before the socket blocks or signals backpressure.
By lowering TCP_NOTSENT_LOWAT, DSVPN reduces the amount of data queued in the inner TCP connection, which aligns its sending behavior more closely with the outer TCP layer’s congestion state. Additionally, DSVPN proactively drops packets when it detects congestion on the outer layer, preventing the inner layer from blindly retransmitting packets that would only exacerbate the problem.
This coupling mechanism effectively synchronizes the two congestion control loops, preventing the destructive interference that usually plagues TCP-over-TCP tunnels. The result is a VPN tunnel that behaves more predictably and efficiently on networks where UDP is blocked or restricted.
Beyond congestion control, DSVPN also blocks IPv6 on the client side to prevent potential leaks, an important privacy consideration. The codebase maintains a small, constant memory footprint without dynamic memory allocation, which reduces complexity and potential runtime errors.
Installation and building dsvpn
Getting DSVPN up and running is straightforward thanks to its zero-dependency design and simple build process.
The primary build method is using make:
make
For Raspberry Pi 3 and 4 devices, DSVPN supports NEON optimizations to improve performance. You can enable them by setting an environment variable before building:
env OPTFLAGS=-mfpu=neon make
If you prefer the Zig compiler, DSVPN can also be compiled using Zig’s build system with a release profile:
zig build -Drelease
On macOS, you can install DSVPN easily with Homebrew:
```sh
brew install dsvpn
This range of options covers common platforms and hardware, making it accessible whether you’re running on a desktop, server, or ARM-based embedded device like a Raspberry Pi.
Verdict: who should consider dsvpn
DSVPN offers a pragmatic solution for scenarios where traditional VPNs fail due to network restrictions or complexity. Its ability to tunnel TCP over TCP with practical performance, thanks to congestion control coupling, is worth understanding for network engineers and developers dealing with restrictive firewalls.
The zero-configuration, single shared-key setup makes it easy to deploy quickly without a deep understanding of networking or VPN internals. The formally verified Charm library integration adds confidence in its cryptographic security.
However, the tradeoff is that DSVPN uses a single shared secret key instead of a more flexible certificate or PKI system, which might not suit larger or more complex deployments. Also, while the congestion control trick improves TCP-over-TCP performance significantly, it still won’t match the raw throughput and latency characteristics of UDP-based VPNs under optimal network conditions.
In production environments where UDP is blocked or unreliable, or where simplicity and minimal dependencies are priorities, DSVPN is a solid tool to have in your toolbox. Its compact codebase and cross-platform support make it a neat example of minimalist, pragmatic VPN design that challenges conventional wisdom with a clever kernel-level tweak.
→ GitHub Repo: jedisct1/dsvpn ⭐ 5,653 · C