SagerNet / SagerNet/sing-box

AnyTLS inbound + Hysteria2 outbound: severe and erratic throughput degradation (83-808 Mbps swing), not CPU-bound

Open
#4,381 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

need more information
Dominant language
Go
Stars
38.1k
Forks
4.6k
Avg merge
19d 15h
Merged PRs (30d)
1

Description

Environment

  • sing-box version: 1.13.16 (official .deb, tags: with_quic, with_utls, with_acme, ...)
  • OS: Debian 13 (trixie), kernel 6.12.43+deb13-amd64
  • Hardware: KVM VPS, 1 vCPU / 1 GB RAM
  • sysctl tuning: BBR + fq, tcp_wmem max 16 MB, tcp_mtu_probing=1, tcp_slow_start_after_idle=0

Configuration (minimal repro)

Server A (US West, 1 vCPU):

{
  "inbounds": [
    {
      "type": "anytls",
      "tag": "anytls-2",
      "listen": "::",
      "listen_port": 8444,
      "users": [{ "name": "u", "password": "***" }],
      "tls": { "enabled": true, "acme": { "domain": ["example.com"], "email": "a@b.c", "provider": "letsencrypt", "disable_tls_alpn_challenge": true } }
    }
  ],
  "outbounds": [
    {
      "type": "hysteria2",
      "tag": "hy2-landing",
      "server": "landing.example.com",
      "server_port": 34639,
      "password": "***",
      "tls": { "enabled": true, "server_name": "landing.example.com" }
    },
    { "type": "direct", "tag": "direct" }
  ],
  "route": {
    "rules": [{ "inbound": "anytls-2", "action": "route", "outbound": "hy2-landing" }],
    "final": "direct"
  }
}

Server B (landing, US West, same metro area as A) runs a hysteria2 server.

Problem

Throughput through the chain client -> AnyTLS inbound -> Hysteria2 outbound -> landing swings wildly between ~83 Mbps and ~808 Mbps across consecutive iperf3 runs minutes apart, while neither CPU nor the network link is saturated.

Controlled experiments (all single-stream iperf3, 10 s each, measured end-to-end through the full chain back to an iperf3 server):

Test Result Notes
Raw UDP iperf3 A -> B (200M / 700M target) 0% / 0.34% loss, jitter 0.006-0.01 ms UDP path between the two hosts is essentially perfect (same metro)
Raw TCP iperf3 A -> B 872 / 783 Mbps stable TCP path also fine
AnyTLS inbound -> direct outbound 2.12 Gbps, sing-box ~44% CPU AnyTLS layer alone is fast
Hysteria2 only (sing-box client with hy2 outbound, no AnyTLS inbound in path) 820 Mbps stable, CPU idle ~5% hy2 outbound alone is fast and stable
AnyTLS inbound -> Hysteria2 outbound (the chain) 83 / 129 / 291 / 749 / 808 Mbps across runs; during the slow runs CPU idle stays 45-50% erratic, and NOT CPU-bound

Expected behavior

Chain throughput should be close to the slowest single layer (~800 Mbps) and stable across runs, as it is when the same inbound is paired with a direct outbound, or when the same hy2 outbound is fed from a local client.

Actual behavior

Throughput collapses unpredictably (down to ~10% of capacity) with plenty of CPU headroom. Suspected interaction between AnyTLS's padding-generated bursty traffic and the QUIC (BBR/Brutal) pacing in the hysteria2 outbound - the padded stream arrives in bursts, which may break the pacing/QPacing assumptions of the QUIC stack.

Note: replacing the hy2 outbound with a TCP-based chained outbound (VLESS+REALITY to the same landing) yields a stable ~800 Mbps through the identical AnyTLS inbound, so the issue is specific to the AnyTLS -> Hysteria2 combination.

Logs

Nothing relevant at warn level (no errors); happy to re-run with debug/trace logging and pprof if you tell me what you need.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the minimal AnyTLS inbound to Hysteria2 outbound chain with consecutive single-stream iperf3 runs, then compare it with the direct and Hysteria2-only controls described in the issue. Use the requested debug or trace logging and pprof if needed; done means explaining the throughput swings and obtaining stable performance close to the individual components.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
networking, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.