Back to Blog
5 min read

TUIC and Hysteria2 — Why UDP-Based Protocols Change the VPN Equation

TCP-based VPN protocols have fundamental performance limitations. TUIC (QUIC transport) and Hysteria2 (BBR over UDP) solve them differently — here's the technical breakdown of both and when to use each.

TUIC and Hysteria2 — Why UDP-Based Protocols Change the VPN Equation

When I was building Vexonik's multi-protocol support, TCP-based protocols (VLESS, Trojan, VMess) showed consistent performance degradation on high-latency, lossy links — exactly what Chinese users experience on international connections. TUIC and Hysteria2 solve this at the transport layer.

The TCP-Over-TCP Problem

Every standard VPN protocol that tunnels TCP traffic over a TCP connection suffers from a fundamental problem: TCP-over-TCP.

Here's why it matters:

Standard VPN (e.g., VLESS over TLS over TCP):

[Your TCP stream] encapsulated in [VPN TCP connection]

When a packet is lost on the outer TCP connection, the outer TCP layer retransmits it. During the retransmission, the inner TCP stream is stalled waiting. The inner TCP layer doesn't know about the outer loss — it only sees a delay and eventually also triggers its own retransmit.

Result: a single lost packet causes double retransmission, exponential congestion backoff, and throughput collapse on lossy links.

China → International links often have 5-15% packet loss during peak hours. On a 15% loss link, TCP-over-TCP can reduce effective throughput by 60-80%.

The Solution: UDP Transport With Custom Congestion Control

QUIC (the protocol underlying HTTP/3) and raw UDP with custom congestion control both solve this by eliminating inner TCP retransmission. The VPN transport layer has direct control over retransmission decisions.

TUIC — VPN Over QUIC

TUIC (Tiny UDP-based Implicit Connection) uses QUIC as its transport layer. QUIC, developed by Google and now standardized in RFC 9000, provides:

  • Multiplexed streams without head-of-line blocking (unlike TCP)
  • 0-RTT connection establishment — connect and send data in the first packet
  • Connection migration — survive IP address changes (mobile users switching WiFi/4G)
  • TLS 1.3 built in — no separate TLS layer, QUIC encrypts everything by design

TUIC Architecture

Application data
    │
    ▼
TUIC framing (stream assignment, flow control)
    │
    ▼
QUIC transport (multiplexed, loss-tolerant)
    │
    ▼
UDP packets (GFW sees UDP/443 or UDP/custom port)

QUIC over UDP port 443 looks like QUIC traffic (used by ~25% of global web traffic for HTTP/3) — it's extremely difficult to block without breaking legitimate QUIC usage.

Why QUIC Handles Loss Better

QUIC uses stream-level retransmission rather than connection-level. If stream 3 has a lost packet, streams 1, 2, 4, 5... are unaffected. They continue delivering data while stream 3 retransmits.

Additionally, QUIC's BBR congestion algorithm (used in TUIC v5) is designed for high-bandwidth, high-latency links (BDP-heavy links). It probes the available bandwidth continuously rather than reacting only to packet loss.

BBR probe cycle:
- Probe bandwidth: send at 1.25× current rate, measure actual throughput
- Probe RTT: occasionally reduce rate to measure minimum RTT
- Steady state: send at measured bandwidth × BDP / RTT

On a 100ms RTT link with 5% loss, BBR maintains 80-90% of link capacity. TCP Cubic degrades to 40-60%.

TUIC Server Setup (Xray-core)

{
  "inbounds": [{
    "listen": "0.0.0.0",
    "port": 443,
    "protocol": "tuic",
    "settings": {
      "clients": [{
        "id": "YOUR-UUID",
        "password": "YOUR-PASSWORD"
      }],
      "congestion_control": "bbr",
      "zero_rtt_handshake": true,
      "heartbeat": "10s"
    },
    "streamSettings": {
      "network": "quic",
      "security": "tls",
      "tlsSettings": {
        "serverName": "your-domain.com",
        "certificates": [{
          "certificateFile": "/etc/ssl/cert.pem",
          "keyFile": "/etc/ssl/key.pem"
        }],
        "alpn": ["h3"]
      }
    }
  }]
}

The alpn: ["h3"] causes the QUIC connection to present itself as HTTP/3 to DPI — it looks like regular web traffic using the HTTP/3 standard.

Hysteria2 — Aggressive UDP With Fake TCP Disguise

Hysteria2 takes a different approach. It uses raw UDP with a custom protocol, but disguises it as HTTPS using a technique called "masquerade".

The Key Difference From TUIC

TUIC relies on standard QUIC. Hysteria2 uses a modified QUIC implementation with:

  1. Salamander obfuscation: XOR-based packet scrambling that breaks QUIC fingerprinting
  2. Fake HTTP/3 headers: The first packet mimics an HTTP/3 request to fool shallow DPI
  3. Aggressive congestion: Hysteria2's congestion algorithm doesn't back off on loss the way standard algorithms do — it assumes the loss is from censorship throttling, not actual congestion

Hysteria2's Aggressive Bandwidth Approach

This is the most controversial design choice:

Standard congestion control (CUBIC, BBR):
Packet loss → reduce send rate → probe recovery
↳ On 15% loss link: sends at 30-40% of link capacity

Hysteria2:
Packet loss → maintain send rate → fill packet loss with redundancy
↳ On 15% loss link: sends at 80-90% of link capacity
   (but uses ~110-115% of bandwidth due to FEC overhead)

Hysteria2 uses Forward Error Correction (FEC) — it sends redundant packets such that the receiver can reconstruct lost packets without retransmission:

[packet 1][packet 2][packet 3][FEC(1+2+3)]

If packet 2 is lost:
FEC(1+2+3) XOR packet1 XOR packet3 = packet2 (reconstructed)

This trades bandwidth (FEC overhead) for latency (no retransmission round trip). On a high-loss link, the overall throughput is dramatically better despite the overhead.

When This Is Problematic

The aggressive bandwidth approach has a significant downside: it can appear as a DoS attack to network operators. Sending at maximum rate despite loss signals is fundamentally antisocial from a network cooperation perspective.

This is why ISPs sometimes rate-limit or actively block Hysteria2 traffic — not because of content inspection, but because the traffic pattern looks like a misbehaving or malicious client.

Hysteria2 is best used for:

  • Short, high-bandwidth tasks (large file transfers, streaming)
  • Links where you own both ends (you're the ISP)
  • Situations where latency is more important than being a good network citizen

Hysteria2 Configuration

# Server config (Hysteria2's own format)
listen: :443
 
tls:
  cert: /etc/ssl/cert.pem
  key: /etc/ssl/key.pem
 
auth:
  type: password
  password: YOUR-PASSWORD
 
masquerade:
  type: proxy
  proxy:
    url: https://www.bing.com  # Proxy to real site when probed
    rewriteHost: true
 
bandwidth:
  up: 1 gbps
  down: 1 gbps
 
quic:
  initStreamReceiveWindow: 26843545
  maxStreamReceiveWindow: 26843545
  initConnReceiveWindow: 67108864
  maxConnReceiveWindow: 67108864

The masquerade.proxy serves the same purpose as Reality's fallback — unauthenticated connections get proxied to a real website, defeating active probing.

Head-to-Head: TUIC vs Hysteria2

CharacteristicTUICHysteria2
TransportStandard QUICModified QUIC
CongestionBBR (cooperative)Aggressive (FEC)
Packet loss handlingStream-level retransmitFEC reconstruction
DPI resistanceHTTP/3 fingerprintSalamander obfuscation
Best forGeneral useHigh-loss, high-bandwidth
Network impactLow (good citizen)High (aggressive)
StabilityExcellentVariable
Active probing resistanceNeeds masquerade configBuilt-in masquerade

Practical Deployment at Vexonik

At Vexonik we deployed both protocols on the same server instances, letting the client app choose:

Node configuration:
├── Port 443/TCP  → VLESS + Reality (for filtered networks that block UDP)
├── Port 443/UDP  → TUIC (QUIC) (primary UDP protocol)
└── Port 8443/UDP → Hysteria2 (fallback for high-loss links)

The client Flutter app measures the latency and loss to each endpoint on connection and automatically selects the optimal protocol for the current network conditions.

Future<Protocol> selectBestProtocol(List<Node> nodes) async {
  final results = await Future.wait(
    nodes.map((node) => benchmarkNode(node)),
  );
  
  // High loss (>8%) → Hysteria2's FEC helps most
  // Medium loss (2-8%) → TUIC's QUIC stream multiplexing
  // Low loss (<2%) → VLESS+Reality (TCP overhead acceptable, most stable)
  
  return results
      .where((r) => r.reachable)
      .sorted((a, b) => a.effectiveThroughput.compareTo(b.effectiveThroughput))
      .last
      .protocol;
}

This adaptive selection was the single biggest UX improvement — users on mobile networks (high variance loss) saw 3-4× better throughput compared to a fixed protocol selection.

The Current Landscape

As of early 2026, the GFW detection state for these protocols:

  • TUIC (standard QUIC): Occasionally throttled in some regions/ISPs during sensitive periods, generally reliable
  • Hysteria2 with masquerade: Reliable when properly configured; blocked selectively when the aggressive bandwidth pattern is flagged
  • VLESS + Reality + XTLS: Most reliable for TCP use cases; undetected at protocol level but IPs eventually blocked

No single protocol is reliably unblocked 100% of the time in all Chinese ISPs. Multi-protocol support with automatic selection is the only production-grade approach.