Skip to content

Tunnel is TCP-only: add a UDP/QUIC (HTTP/3) transport to end TCP-over-TCP head-of-line blocking #185

Description

@davvd

Our tunnel carries IP packets inside a single TLS-over-TCP connection on :443, and there is no UDP path anywhere in the stack. The node opens one TCP listener (node/cmd/server/main.go, tunnel.New(subnet, subnet6, 1420)), and both clients hand-roll TLS 1.3 over a raw TCP socket (ios/APNExtension/TLSWire.swift, SwiftNIO ClientBootstrap; android/src/main/java/tech/apn/vpn/TLSWire.kt, SocketChannel). Every inner flow shares one reliable ordered byte stream.

This is the classic TCP-over-TCP problem: because inner TCP rides an outer reliable stream, a single lost or dropped outer segment stalls all inner flows until it is retransmitted (head-of-line blocking). WireGuard is UDP-based precisely to avoid this (general VPN design principle). The MSS clamp in node/internal/tunnel/tunnel.go and the 1280 client MTU only limit fragmentation; they do not address meltdown. Worse, theories.md (PROOF #2) shows Russia's TSPU implements its freeze as a surgical retransmit black-hole — it drops one segment and every retransmission of it, wedging a permanent head-of-line hole while the socket still looks alive — which our single-TCP design is maximally exposed to. theories.md itself lists "leave the TCP-TLS bucket (QUIC / non-TLS)" as an escape lever.

Add an optional QUIC / HTTP-3 masquerade transport alongside the existing TLS-over-TCP one: QUIC on :443/UDP is legitimate modern HTTPS (keeps the cover story), gives independent streams (no cross-flow head-of-line blocking), and its connection migration lets a session survive an IP/port change without re-handshaking (which also cuts our roaming/reconnect cost). Concrete first step: a node-side QUIC listener behind an env flag (e.g. APN_QUIC), advertised to clients through the existing Peer/Property SNI+port fields in pong.proto, with TLS-over-TCP kept as the fallback for UDP-blocked networks. This is an enhancement, not a defect; filing per a WireGuard comparison review.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions