GUIDES
Lane Cove Tunnel: A Linux VPN Implementation From Scratch
Lane Cove Tunnel is a learning-focused VPN implementation in C that builds a layer 3 overlay network over UDP. It covers the same conceptual ground as WireGuard — X25519 key exchange, AES-256-GCM encryption, identity hiding, replay protection — but written from scratch to make the internals visible and understandable.
Not for production use. The cryptography has not been audited or hardened.
Source: github.com/jecklgamis/lanecove-tunnel
How It Works
Every node runs the same peer binary. Two topologies are supported.
Hub-and-spoke — peers behind NAT connect outbound to a relay with a public IP, which forwards traffic between them. The relay is inbound-only; it never initiates connections.
peer-1 (10.9.0.2) ──┐
├── UDP 5040 ── relay (10.9.0.1, public IP)
peer-2 (10.9.0.3) ──┘
Direct peer-to-peer — if at least one peer has a public IP, they skip the relay entirely. The public peer omits -E; the other peer points -E at it. If both have public IPs, both set -E and race to initiate, converging on a shared session.
peer-1 (10.9.0.1, public IP) ──── UDP 5040 ──── peer-2 (10.9.0.2)
A TUN interface (lanecove0) gives the OS a real layer 3 interface, so standard tools like ping, curl, and ip route work against overlay addresses without any special configuration.
Tech Stack
The peer binary is C with no runtime dependencies beyond OpenSSL 3.x (X25519, AES-256-GCM, HMAC-SHA256). It uses Linux TUN (/dev/net/tun) for packet injection and epoll for non-blocking I/O. Docker is used for multi-node local testing — required on macOS since the TUN interface is Linux-only. Each peer container also includes an Envoy proxy and an nginx server for load testing across the tunnel.
Security Model
Each session starts with an X25519 handshake. Both sides generate ephemeral key pairs; static public keys are AES-256-GCM encrypted inside the handshake so passive observers can’t identify peers. An optional PSK adds HMAC-SHA256 authentication. A 5-second cooldown per address and public key limits handshake flooding.
The session key mixes three DH outputs — ephemeral-ephemeral for forward secrecy, plus static-ephemeral and ephemeral-static for mutual authentication:
SHA-256(DH(eph_c, eph_s) || DH(static_c, eph_s) || DH(eph_c, static_s) || public keys...)
Data packets are AES-256-GCM with a 12-byte IV derived from a per-direction 64-bit counter. A 2048-bit sliding window per direction drops replayed or reordered packets. Sessions rekey every 5 minutes.
Envoy Proxy
Each peer container optionally runs an Envoy proxy (enabled by setting ENVOY_UPSTREAM_HOST). It exposes two listeners for proxying traffic across the tunnel to a service on a remote peer: a TCP pass-through on port 15040 and an HTTP proxy with connection pooling on port 15050. The HTTP proxy is preferred for HTTP traffic — it amortizes the tunnel’s ~200ms round-trip across ~130–170 requests per upstream connection rather than paying it on every request.
Performance
Load tested using gatling-scala-example over peer-1’s Envoy HTTP proxy to peer-2’s nginx, with the relay on a DigitalOcean 1 vCPU/512 MB droplet and both peers on Mac M4 hardware.
| Load | Requests | OK | p50 | p95 | p99 |
|---|---|---|---|---|---|
| 10 rps | 4,800 | 100% | 204ms | 222ms | 249ms |
| 40 rps | 9,600 | 100% | 203ms | 209ms | 228ms |
| 100 rps | 24,000 | 100% | 202ms | 207ms | 216ms |
| 250 rps | 60,000 | 82% | — | — | — |
The ~200ms floor reflects the two-hop overlay (peer → relay → peer). Latency actually tightens at higher concurrency as the connection pool fills up. At 250 rps the single-threaded relay saturates on a 1 vCPU droplet, shedding ~18% of requests as 503/504 errors. The ceiling for this hardware is somewhere between 100 and 250 rps.
Limitations
- Linux only — does not compile on macOS; use Docker
- IPv4 only — IPv6 and non-IP traffic are dropped
- Single-threaded — not designed for high throughput
- Hub-and-spoke only — no NAT hole-punching; peers route through the relay, not directly (unless one has a public IP)
- Not production-ready — unaudited, no hardening