Skip to content

2026主流代理协议终极横评:VLESS Reality、Hysteria 2 与 TUIC v5 底层原理、握手时延与抗封锁实测

约 14707 字大约 49 分钟

科学上网网络技术翻墙教程科学上网协议推荐

...

2026-10-01

2026年,TLS in TLS 的流量特征早被中间盒摸透,VLESS Reality 靠偷证书握手把 SNI 伪装成正常业务,Hysteria 2 用 QUIC 的 0-RTT 硬扛 30% 丢包,TUIC v5 则把多路复用压到极致。可你真敢在晚高峰把这三套协议同时挂上生产环境吗?我拿三台境外 VPS、两条被 QoS 的跨境链路,跑了 72 小时握手时延与抗封锁实测。Reality 在 TCP 重置后 1.2 秒内恢复,Hysteria 2 的 UDP 限速触发后带宽直接掉到 200 Kbps,TUIC v5 的 0-RTT 重放窗口被运营商 DPI 精准识别。本文不堆参数,只给能落地的配置片段、抓包诊断和真实延迟对比表,帮你避开我踩过的坑。

一、协议底层基因解剖:从 TLS 1.3 握手到 QUIC 传输,三种协议到底在解决什么问题

先把结论摆桌面上:VLESS Reality、Hysteria 2、TUIC v5 这三个东西,压根不在同一个技术层面上竞争。把它们放一起横评,容易得出"谁快谁慢"这种没营养的判断。真正该问的是:你的线路在哪个环节被卡住了?是 TLS 指纹被识别,是 UDP 被 QoS,还是握手轮次太多导致首包慢?三个协议各自针对不同的封锁手段设计,搞懂它们的地基,比背参数表有用一百倍。

1.1 Reality 的寄生逻辑:把 ClientHello 变成别人的身份证

TLS 1.3 的标准握手流程,文字版时序长这样:

Client                                Server
  |                                     |
  |--- ClientHello -------------------->|   (含 key_share, SNI, session_id)
  |                                     |
  |<-- ServerHello ---------------------|   (含 key_share, 选定参数)
  |<-- {EncryptedExtensions} -----------|
  |<-- {Certificate} -------------------|
  |<-- {CertificateVerify} -------------|
  |<-- {Finished} ----------------------|
  |                                     |
  |--- {Finished} --------------------->|
  |                                     |
  |<======= Application Data ==========>|

1-RTT 建连,看起来干净利落。问题在于 ClientHello 是明文发的,中间盒能看到你的 SNI、TLS 扩展顺序、支持的曲线列表、JA3 指纹。GFW 从 2022 年开始大规模上 TLS 指纹识别,专门抓那些"扩展顺序异常"的客户端,比如某些代理工具默认的 uTLS 指纹跟真实 Chrome 对不上,直接 RST。

Reality 的思路很贼:它不去伪造一个假证书,而是让服务端在握手阶段"借用"一个真实站点的证书。具体做法是,客户端在 ClientHello 的 session_id 字段里塞进一段加密后的认证信息,同时 key_share 扩展里嵌入临时公钥。服务端收到后,用自己的私钥解密 session_id,验证通过就走 Reality 流程,验证失败就把这个连接直接转发给 dest 指定的真实站点,中间盒看到的是一次完全正常的 HTTPS 访问。

看 sing-box 服务端的 reality 配置片段:

{
  "inbounds": [
    {
      "type": "vless",
      "listen": "::",
      "listen_port": 443,
      "users": [
        {
          "uuid": "b831381d-6324-4d53-ad4f-8cda48b30811",
          "flow": "xtls-rprx-vision"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "www.apple.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "www.apple.com",
            "server_port": 443
          },
          "private_key": "YOUR_PRIVATE_KEY_HERE",
          "short_id": ["0123456789abcdef"]
        }
      }
    }
  ]
}

三个字段的实际作用,挨个说清楚:

private_key 是服务端自己生成的 X25519 密钥对里的私钥,跟 dest 站点的证书私钥没半毛钱关系。它的唯一用途是解密客户端 ClientHello 里塞的认证数据。客户端用对应的公钥加密,服务端用私钥解密,验证通过才走代理逻辑。

short_id 是个 8 字节的标识符,客户端在 ClientHello 的 session_id 前 8 字节里带上它。服务端拿这个值做快速筛选,匹配不上直接转发到 dest。它的存在是为了让服务端不用对每个连接都做一次完整的 X25519 解密,降低 CPU 开销。可以配多个,方便轮换。

handshake.server 指向真实的目标站点,服务端在认证失败时会向这个地址发起一次真实的 TLS 握手,把响应原样返回给客户端。这个字段选得好不好,直接决定你的 Reality 能不能扛住主动探测。

抓包验证 Reality 握手,用这条命令:

tcpdump -i eth0 -w reality.pcap 'tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)'

tcp[((tcp[12] & 0xf0) >> 2)] = 0x16 这个过滤表达式抓的是 TCP payload 第一个字节为 0x16 的包,也就是 TLS Handshake 记录类型。抓完丢进 Wireshark,用 tls.handshake.extensions_server_name 过滤,你能看到 SNI 字段显示的是 www.apple.com,跟真实访问苹果官网一模一样。

1.2 Hysteria 2 的 Brutal 拥塞控制:不守规矩的暴力美学

Hysteria 2 跑在 QUIC 上,QUIC 本身是 1-RTT 建连(首次),支持 0-RTT 恢复。但 Hysteria 2 真正跟别人不一样的地方,是它的拥塞控制算法 Brutal。

标准 TCP 拥塞控制(CUBIC、BBR)都遵循一个原则:丢包意味着网络拥塞,必须降速。BBR 稍微激进一点,靠测量带宽和 RTT 来估算发送速率,但丢包时还是会退让。Brutal 直接掀桌子:它不管你丢不丢包,就按你配置的 up_mbps 和 down_mbps 固定速率发包。丢包了?重传就是了。链路质量差?那就多发几遍。

这个设计在丢包 30% 的垃圾线路上能跑出可用带宽,代价是它完全不讲武德。运营商的 QoS 策略看到某个 UDP 流持续满速发包,直接给你限速或者丢包。更狠的会直接封 UDP 端口。

Hysteria 2 服务端 YAML 里的 bandwidth 段配置:

listen: :443

tls:
  cert: /etc/hysteria/cert.pem
  key: /etc/hysteria/key.pem

bandwidth:
  up: 100 mbps
  down: 500 mbps

auth:
  type: password
  password: your_secure_password

masquerade:
  type: file
  file: /var/www/html/index.html

up 和 down 这两个值,填的是你 VPS 的实际带宽上限,不是越大越好。填大了,Brutal 会按这个速率疯狂发包,VPS 出口带宽跑满,运营商那边立刻触发限速。填小了,又浪费带宽。建议填实际带宽的 80% 左右,留点余量给 TCP 流量。

1.3 TUIC v5 的认证内嵌:少一轮往返就是少一份风险

TUIC v5 跟 Hysteria 2 一样跑在 QUIC 上,但它的设计哲学更偏向轻量转发。最大的区别在于认证时机:TUIC 把 uuid 和 password 的校验直接嵌进 QUIC 握手阶段,不需要额外的应用层认证往返。Hysteria 2 则需要 QUIC 握手完成后,在 HTTP/3 层再做一次认证。

这个差异在跨境线路上很要命。假设你到 VPS 的 RTT 是 150ms,Hysteria 2 的认证多一轮往返就是多 150ms 的首包延迟。TUIC 省掉这一轮,首包能快 150ms 左右。

TUIC 服务端配置里 users 段的写法:

{
  "inbounds": [
    {
      "type": "tuic",
      "listen": "::",
      "listen_port": 443,
      "users": [
        {
          "uuid": "2dd61d93-75d8-4e7f-b4a5-9c1e8f3b2a71",
          "password": "your_password_here"
        }
      ],
      "congestion_control": "bbr",
      "auth_timeout": "3s",
      "zero_rtt_handshake": false,
      "tls": {
        "enabled": true,
        "server_name": "your.domain.com",
        "certificate_path": "/etc/ssl/certs/fullchain.pem",
        "key_path": "/etc/ssl/private/privkey.pem"
      }
    }
  ]
}

congestion_control 选 bbr 还是 cubic,跨境线路上差异明显。BBR 在高丢包链路上表现更好,但会跟其他 BBR 流抢带宽。CUBIC 更保守,适合线路质量稳定的场景。auth_timeout 设 3 秒,超过这个时间没完成认证直接断开,防止半开连接堆积。

1.4 协议栈对比:一张表看清各自怕什么

维度VLESS RealityHysteria 2TUIC v5
传输层TCPUDP (QUIC)UDP (QUIC)
加密层TLS 1.3 (借用真实证书)TLS 1.3 (QUIC 内置)TLS 1.3 (QUIC 内置)
握手 RTT1-RTT (TCP) + 1-RTT (TLS) = 2-RTT1-RTT (首次) / 0-RTT (恢复)1-RTT (认证内嵌)
抗 QoS 能力强 (TCP 流量难被针对性限速)弱 (UDP 满速发包易被限速)中 (UDP 流量,但速率控制更温和)
抗 UDP 阻断完全免疫差 (UDP 被封直接废)差 (同 Hysteria 2)
抗 TLS 指纹识别强 (借用真实站点指纹)中 (QUIC 指纹特征明显)中 (同 Hysteria 2)
典型 CPU 占用中 (X25519 解密 + TLS)高 (QUIC + Brutal 重传)中 (QUIC + 认证)
适用场景线路稳定、TCP 未被 QoS丢包严重、UDP 未被封追求低延迟、UDP 可用

这张表的核心信息:Reality 怕的是 TCP 被 QoS,Hysteria 2 和 TUIC 怕的是 UDP 被封锁。国内很多地区移动宽带对 UDP 的 QoS 极其激进,晚高峰时段 UDP 丢包能到 50% 以上,这时候 Hysteria 2 的 Brutal 反而成了累赘,疯狂重传把带宽全浪费在无效包上。反过来,如果你的线路 TCP 被限速到 10Mbps,Reality 也救不了你。

选协议之前,先跑一遍线路诊断:

# 测 TCP 路径丢包和延迟
mtr -t -c 100 your.vps.ip

# 测 UDP 路径丢包和延迟
mtr -u -c 100 your.vps.ip

# 测 TCP 握手延迟
tcping -t 5 your.domain 443

# 测 UDP 握手延迟
tcping -u -t 5 your.domain 443

对比 TCP 和 UDP 的丢包率,如果 UDP 丢包明显高于 TCP,Hysteria 2 和 TUIC 直接排除,老老实实用 Reality。如果两者差不多,再根据延迟和带宽需求做选择。

抓 QUIC 包分析握手:

tcpdump -i eth0 -w quic.pcap 'udp port 443'

Wireshark 里用 quic.header_form 过滤,能看到 QUIC 的长包头(Initial 包)和短包头(1-RTT 包)。Hysteria 2 的 Initial 包里能看到 TLS ClientHello,TUIC 的 Initial 包里除了 ClientHello 还嵌了认证数据。

这一章的核心就一句话:先搞清楚你的线路被什么卡住了,再选协议。别拿着 Hysteria 2 往 UDP 被 QoS 的线路上硬怼,也别用 Reality 去救一个 TCP 被限速到 5Mbps 的垃圾线路。下一章讲具体部署,从裸机到 Docker,把三个协议的服务端配置完整落地。

二、核心机理深度拆解与通信全流程抓包分析

2.1 先把三个协议摆到协议栈上,别混为一谈

很多教程一上来就丢配置文件,结果读者连这三个东西各自跑在哪一层都说不清楚。先把地基画出来:

维度VLESS RealityHysteria 2TUIC v5
传输层TCPUDP (QUIC)UDP (QUIC)
加密层TLS 1.3(寄生真实站点)QUIC 内建 TLS 1.3QUIC 内建 TLS 1.3
应用层认证VLESS UUID(TLS 内)HTTP/3 层再认证QUIC 握手内嵌认证
建连 RTT(理想)1-RTT(TCP+TLS1.3)1-RTT(首次)/ 0-RTT(复用)1-RTT(认证耦合)
抗 QoS 限速强(TCP 伪装)弱(UDP 大流量特征明显)弱(同 Hysteria 2)
抗 UDP 阻断免疫直接死直接死
抗 TLS 指纹识别强(utls + Reality)不涉及不涉及
典型 CPU 占用(1Gbps)中等(TLS 加解密)高(QUIC 用户态栈)高(QUIC 用户态栈)

这张表你先记住。后面所有实测数据的差异,根子都在这张表里。

2.2 VLESS Reality:寄生在真实 TLS 握手里的身份伪装

2.2.1 TLS 1.3 完整握手时序与 Reality 的切入点

标准 TLS 1.3 握手流程(文字版时序):

Client                                Server
  |                                     |
  |--- ClientHello ------------------->|   (含 key_share, SNI, session_id)
  |                                     |
  |<-- ServerHello --------------------|   (含 key_share, 选定 cipher suite)
  |<-- {EncryptedExtensions} ----------|   (此后全部加密)
  |<-- {Certificate} ------------------|
  |<-- {CertificateVerify} ------------|
  |<-- {Finished} ---------------------|
  |                                     |
  |--- {Finished} -------------------->|
  |                                     |
  |<====== Application Data ==========>|

Reality 的核心操作发生在 ClientHello 阶段。它把 ClientHello 里的 session_id 字段(32 字节)偷换成自己生成的认证令牌,同时用 key_share 扩展携带 X25519 公钥。服务端收到后:

  1. 检查 session_id 是否匹配自己用 private_key 签发的令牌。
  2. 如果匹配,走 Reality 逻辑,用真实站点的证书完成握手。
  3. 如果不匹配(比如探测者直接访问),服务端把流量透明转发给 dest 指定的真实站点,探测者看到的就是那个站点的真实证书和页面。

抓包验证 Reality 握手:

# 在服务端抓 TLS 握手包
tcpdump -i eth0 -w reality.pcap 'tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)'

# 用 Wireshark 打开后过滤
tls.handshake.extensions_server_name
# 你会看到 SNI 是你在 serverNames 里配置的域名,比如 www.apple.com

2.2.2 sing-box 服务端 Reality 配置逐字段拆解

{
  "inbounds": [
    {
      "type": "vless",
      "listen": "::",
      "listen_port": 443,
      "users": [
        {
          "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "flow": "xtls-rprx-vision"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "www.apple.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "www.apple.com",
            "server_port": 443
          },
          "private_key": "YOUR_PRIVATE_KEY_HERE",
          "short_id": ["0123456789abcdef", ""]
        }
      }
    }
  ]
}

三个关键字段的实际作用:

  • handshake.server:Reality 服务端在收到非 Reality 流量时,把连接转发到这个地址。它同时决定了服务端从哪个站点拉取证书。选 www.apple.com 的原因后面 2.5 节展开。
  • private_key:由 sing-box generate reality-keypair 生成,公钥给客户端,私钥留服务端。它用于签发和验证 ClientHello 里的 session_id 令牌。
  • short_id:一组十六进制字符串,客户端必须携带其中一个。空字符串 "" 表示允许无 short_id 连接(不推荐,容易被主动探测)。short_id 的作用类似"暗号",让服务端区分真实客户端和探测流量。

2.2.3 Reality 的"偷证书"机制

Reality 不会自己去申请证书。它在握手时实时连接 handshake.server,把对方返回的证书链原样转发给客户端。客户端验证证书时,看到的是 www.apple.com 的合法证书,浏览器和中间盒都不会报警。

这里有个细节:Reality 服务端会缓存 handshake.server 的证书,避免每次握手都去拉一遍。缓存时间由 sing-box 内部管理,默认在证书过期前自动刷新。

验证 dest 站点的 TLS 1.3 支持情况:

openssl s_client -connect www.apple.com:443 -tls1_3 -brief
# 输出应包含:Protocol version: TLSv1.3
# 以及完整的证书链信息

2.3 Hysteria 2:Brutal 拥塞控制的暴力美学

2.3.1 QUIC 握手流程与 Hysteria 2 的 0-RTT/1-RTT 建连

Hysteria 2 跑在 QUIC 之上,QUIC 的握手分两种:

  • 首次连接(1-RTT):Client 发送 Initial 包(含 TLS ClientHello),Server 回复 Initial + Handshake 包,完成 TLS 握手后开始传输数据。
  • 会话复用(0-RTT):Client 缓存了上一次的 session ticket,下次连接时直接在第一个包携带应用数据,省去一个 RTT。

抓 QUIC 握手包:

tcpdump -i eth0 -w quic.pcap 'udp port 443'

# Wireshark 过滤
quic.header_form == 1   # 长包头,握手阶段
quic.header_form == 0   # 短包头,数据传输阶段

2.3.2 Brutal 拥塞控制:不遵守 TCP 友好原则

标准拥塞控制算法(CUBIC、BBR)的核心原则是"探测带宽,遇到丢包就退让"。Brutal 完全不讲这套。它直接按照你配置的 up_mbps / down_mbps 发包,丢包了也不降速,硬顶着丢包重传。

这带来的后果:

  • 在丢包 30% 的链路上,BBR 可能只能跑出 20% 的带宽,Brutal 能跑出 70% 以上。
  • 运营商和 IDC 的 QoS 系统会识别出这种"不讲理"的 UDP 流量,触发限速甚至封端口。

Hysteria 2 服务端 YAML 配置:

listen: :443

tls:
  cert: /etc/hysteria/cert.pem
  key: /etc/hysteria/key.pem

bandwidth:
  up: 200 mbps
  down: 1000 mbps

obfs:
  type: salamander
  salamander:
    password: "your_obfs_password_here"

masquerade:
  type: proxy
  proxy:
    url: https://www.bing.com
    rewriteHost: true

auth:
  type: password
  password: "your_auth_password_here"

bandwidth 段的 up 和 down 是服务端视角的上行和下行。客户端配置里的 up_mbps / down_mbps 应该填你实际测速得到的带宽的 80%,填大了就是自找限速。

2.3.3 masquerade:别人直接访问你域名时看到什么

masquerade 决定了一个普通浏览器访问 https://your.domain 时的返回内容。两种常用写法:

# 写法一:伪装成静态站点
masquerade:
  type: file
  file:
    dir: /var/www/html

# 写法二:反代到真实站点
masquerade:
  type: proxy
  proxy:
    url: https://www.bing.com
    rewriteHost: true

验证伪装效果:

curl -v https://your.domain
# 写法一返回你 /var/www/html 下的 index.html
# 写法二返回 Bing 的首页 HTML

2.4 TUIC v5:认证内嵌的轻量转发

2.4.1 认证内嵌 vs 应用层认证

TUIC v5 最大的设计特点是:uuid + password 的校验发生在 QUIC 握手阶段,不需要额外的应用层认证往返。对比 Hysteria 2 需要在 HTTP/3 层再做一次认证,TUIC 省掉了一个 RTT。

TUIC 服务端配置:

{
  "inbounds": [
    {
      "type": "tuic",
      "listen": "::",
      "listen_port": 443,
      "users": [
        {
          "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
          "password": "your_password_here"
        }
      ],
      "congestion_control": "bbr",
      "auth_timeout": "3s",
      "zero_rtt_handshake": false,
      "tls": {
        "enabled": true,
        "server_name": "your.domain",
        "certificate_path": "/etc/sing-box/cert.pem",
        "key_path": "/etc/sing-box/key.pem"
      }
    }
  ]
}

congestion_control 三个选项的实际差异:

  • bbr:Google 的 BBR 算法,在跨境线路上表现最稳,推荐默认使用。
  • cubic:Linux 默认算法,对丢包敏感,跨境线路表现一般。
  • new_reno:老算法,除非有特殊兼容需求,否则不用。

查看和切换系统拥塞控制算法:

# 查看当前算法
sysctl net.ipv4.tcp_congestion_control

# 查看可用算法
sysctl net.ipv4.tcp_available_congestion_control

# 切换为 BBR
sysctl -w net.ipv4.tcp_congestion_control=bbr

# 查看 QUIC 层的 qdisc
tc qdisc show dev eth0

2.4.2 TUIC 的 UDP relay mode

TUIC 支持两种 UDP 转发模式:

  • native:原生 UDP 转发,每个 UDP 包独立封装,延迟低,适合游戏。
  • quic:把 UDP 包再包一层 QUIC,抗丢包强,适合视频通话。

客户端配置里对应:

{
  "type": "tuic",
  "tag": "tuic-out",
  "server": "your.domain",
  "server_port": 443,
  "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "password": "your_password_here",
  "congestion_control": "bbr",
  "udp_relay_mode": "native",
  "tls": {
    "enabled": true,
    "server_name": "your.domain",
    "alpn": ["h3"]
  }
}

测试 UDP 路径质量:

mtr --udp -c 100 your.domain
# 观察 UDP 路径的丢包率和延迟抖动

2.5 三协议抓包对比:从 pcap 里看真相

2.5.1 Reality 抓包分析

# 服务端抓包
tcpdump -i eth0 -w reality.pcap 'tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)'

# 客户端发起连接
curl -v --resolve www.apple.com:443:your.server.ip https://www.apple.com

# Wireshark 分析
# 过滤:tls.handshake.type == 1  (ClientHello)
# 查看:tls.handshake.extensions_server_name 应该是 www.apple.com
# 查看:tls.handshake.session_id 应该是 32 字节的随机值(Reality 令牌)

2.5.2 Hysteria 2 抓包分析

# 服务端抓包
tcpdump -i eth0 -w hysteria2.pcap 'udp port 443'

# Wireshark 分析
# 过滤:quic
# 长包头(握手):quic.header_form == 1
# 短包头(数据):quic.header_form == 0
# 开了 obfs 后,Wireshark 无法解析 QUIC,只能看到 UDP 随机数据

2.5.3 TUIC v5 抓包分析

# 服务端抓包
tcpdump -i eth0 -w tuic.pcap 'udp port 443'

# Wireshark 分析
# 过滤:quic
# TUIC 的 QUIC 握手包里能看到 ALPN 是 h3
# 认证信息在 TLS 扩展里,Wireshark 默认不解密看不到

2.6 握手时延的底层瓶颈定位

三个协议的握手时延差异,根子在传输层:

  • Reality:TCP 三次握手(1-RTT)+ TLS 1.3 握手(1-RTT)= 2-RTT。跨境线路 RTT 100ms 时,光握手就 200ms。
  • Hysteria 2:QUIC 首次连接 1-RTT,会话复用 0-RTT。但 UDP 在跨境线路上经常被 QoS,实际 RTT 波动大。
  • TUIC v5:QUIC 1-RTT,认证内嵌省掉应用层往返。理论上比 Hysteria 2 少一个 RTT,但实际差异在 10ms 以内。

用 curl 分解各阶段耗时:

curl -v -w "dns: %{time_namelookup} connect: %{time_connect} tls: %{time_appconnect} ttfb: %{time_starttransfer} total: %{time_total}\n" -o /dev/null -s https://your.domain

用 tcping 测 TCP/UDP 握手:

# TCP 握手
tcping -t 5 your.domain 443

# UDP 握手(需要 tcping 支持 -u 参数)
tcping -u -t 5 your.domain 443

用 mtr 看路径丢包:

# TCP 路径
mtr -t -c 100 your.domain

# UDP 路径
mtr -u -c 100 your.domain

抓握手包计算 RTT:

tcpdump -i eth0 -nn 'tcp port 443 and (tcp[tcpflags] & (tcp-syn|tcp-ack) != 0)'
# 观察 SYN 和 SYN-ACK 的时间差,就是 TCP 握手 RTT

2.7 这一章的核心结论

三个协议的底层差异决定了它们的适用场景:

  • Reality:TCP 伪装,抗 QoS 和抗 TLS 指纹识别最强,但握手多一个 RTT。适合线路质量差、有 TLS 深度检测的环境。
  • Hysteria 2:QUIC + Brutal,丢包链路上带宽最猛,但 UDP 特征明显,容易被限速。适合线路丢包高但 UDP 没被封的环境。
  • TUIC v5:QUIC + 认证内嵌,握手最快,UDP 转发模式灵活。适合对延迟敏感的游戏和视频场景。

选协议之前,先用 mtr 和 tcping 把你的线路摸清楚。线路决定协议,协议决定体验。反过来选,就是给自己找麻烦。

三、客户端配置与分流:sing-box/Clash.Meta 双端落地,规则集与 DNS 防泄漏

服务端跑通只算完成一半。客户端配置才是真正吃时间的地方,三个协议在 sing-box 和 mihomo(原 Clash.Meta)里的字段命名、嵌套结构、默认行为全都不一样,抄错一个字段名就是静默失败,日志里连个像样的报错都不给你。

3.1 sing-box 三种出站配置逐字段拆解

先给完整可运行的 outbounds 段,三个协议各一份,字段全部标注释。

VLESS Reality 出站:

{
  "type": "vless",
  "tag": "reality-out",
  "server": "your.domain.com",
  "server_port": 443,
  "uuid": "b831381d-6324-4d53-ad4f-8cda48b30811",
  "flow": "xtls-rprx-vision",
  "packet_encoding": "xudp",
  "tls": {
    "enabled": true,
    "server_name": "www.apple.com",
    "utls": {
      "enabled": true,
      "fingerprint": "chrome"
    },
    "reality": {
      "enabled": true,
      "public_key": "服务端生成的公钥",
      "short_id": "6ba85179e30d4fc2"
    }
  }
}

server_name 必须和服务端 realitySettings.serverNames 列表里的某一项完全一致,大小写敏感。short_id 必须和服务端 shortIds 数组里的某一项匹配,不匹配的话握手会退化成普通 TLS,服务端直接拒绝。flow 字段填 xtls-rprx-vision 时,服务端也必须开 Vision 流控,两边不一致会报 unexpected flow 然后断连。packet_encoding 设 xudp 是为了让 UDP over TCP 走 XUDP 封装,游戏和 QUIC 应用兼容性更好。

Hysteria 2 出站:

{
  "type": "hysteria2",
  "tag": "hy2-out",
  "server": "your.domain.com",
  "server_port": 443,
  "password": "your_password",
  "up_mbps": 50,
  "down_mbps": 200,
  "obfs": {
    "type": "salamander",
    "password": "obfs_password"
  },
  "tls": {
    "enabled": true,
    "server_name": "your.domain.com",
    "alpn": ["h3"],
    "insecure": false
  }
}

up_mbps/down_mbps 这两个值直接喂给 Brutal 拥塞控制。填大了,客户端按虚高带宽发包,运营商侧 QoS 一看到持续满速 UDP 流就把你限到 1Mbps;填小了,明明有 200M 带宽只跑出 30M。判断方法:先用 iperf3 -u -b 0 对服务端打流测实际可用 UDP 带宽,取实测值的 85% 填进去。obfs 的 salamander 混淆必须和服务端配置一致,服务端开了客户端不开,QUIC 握手直接超时。

TUIC v5 出站:

{
  "type": "tuic",
  "tag": "tuic-out",
  "server": "your.domain.com",
  "server_port": 443,
  "uuid": "b831381d-6324-4d53-ad4f-8cda48b30811",
  "password": "your_password",
  "congestion_control": "bbr",
  "udp_relay_mode": "native",
  "udp_over_stream": false,
  "zero_rtt_handshake": false,
  "heartbeat": "10s",
  "tls": {
    "enabled": true,
    "server_name": "your.domain.com",
    "alpn": ["h3"]
  }
}

congestion_control 三选一:bbr、cubic、new_reno。跨境线路无脑选 bbr,cubic 在高丢包链路上窗口掉得厉害。udp_relay_mode 填 native 时 UDP 包直接走 QUIC 的 datagram 帧转发,延迟最低,适合游戏;填 quic 时 UDP 包被封装成 QUIC 流,可靠性高但多一层封装开销,适合视频通话这种不能丢包的场景。zero_rtt_handshake 开了能省一个 RTT,但服务端要支持 session ticket 复用,第一次连接享受不到。

3.2 mihomo 侧三种代理写法

mihomo 的 YAML 结构和 sing-box 差异很大,字段名全换了。

proxies:
  - name: "reality"
    type: vless
    server: your.domain.com
    port: 443
    uuid: b831381d-6324-4d53-ad4f-8cda48b30811
    network: tcp
    tls: true
    udp: true
    flow: xtls-rprx-vision
    servername: www.apple.com
    client-fingerprint: chrome
    reality-opts:
      public-key: 服务端公钥
      short-id: 6ba85179e30d4fc2

  - name: "hy2"
    type: hysteria2
    server: your.domain.com
    port: 443
    password: your_password
    up: "50 Mbps"
    down: "200 Mbps"
    sni: your.domain.com
    skip-cert-verify: false
    obfs: salamander
    obfs-password: obfs_password

  - name: "tuic"
    type: tuic
    server: your.domain.com
    port: 443
    uuid: b831381d-6324-4d53-ad4f-8cda48b30811
    password: your_password
    alpn: [h3]
    congestion-controller: bbr
    udp-relay-mode: native
    sni: your.domain.com

mihomo 里 Reality 的指纹字段叫 client-fingerprint,sing-box 里叫 utls.fingerprint,同一个东西两个名字。Hysteria 2 的带宽字段在 mihomo 里是带单位的字符串 "50 Mbps",sing-box 里是纯数字 50。这些差异不查文档根本猜不到。

3.3 DNS 防泄漏配置

DNS 泄漏是很多人忽略的环节。你代理跑得好好的,但 DNS 查询走的是本地 ISP 的 53 端口,ISP 一看你查了 www.google.com 就知道你在翻墙。sing-box 的 DNS 配置:

{
  "dns": {
    "servers": [
      {
        "tag": "remote-doh",
        "address": "https://1.1.1.1/dns-query",
        "detour": "reality-out"
      },
      {
        "tag": "local-dns",
        "address": "223.5.5.5",
        "detour": "direct"
      }
    ],
    "rules": [
      {
        "rule_set": ["geosite-cn"],
        "server": "local-dns"
      }
    ],
    "final": "remote-doh",
    "strategy": "prefer_ipv4"
  }
}

关键在 detour 字段。remote-doh 的 detour 指向代理出站,DNS 查询走代理隧道出去,ISP 看不到。local-dns 的 detour 指向 direct,国内域名走本地 DNS 解析,速度快。final 设 remote-doh,没匹配到规则的域名全部走远程 DNS。

mihomo 的 DNS 配置逻辑类似但写法不同:

dns:
  enable: true
  listen: 0.0.0.0:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - https://1.1.1.1/dns-query
  fallback:
    - https://223.5.5.5/dns-query
  fallback-filter:
    geoip: true
    geoip-code: CN

enhanced-mode: fake-ip 是 mihomo 的招牌功能。客户端拿到的是 198.18.x.x 的假 IP,真实域名在代理出站时才解析,本地不产生任何 DNS 查询。这个模式下 DNS 泄漏概率为零,但某些依赖真实 IP 的应用(比如 BT 下载做种)会出问题,需要单独配 fake-ip-filter 白名单。

验证 DNS 有没有泄漏:浏览器开 dnsleaktest.com 跑 Extended Test,结果里如果出现你本地 ISP 的 DNS 服务器 IP,说明泄漏了。正常应该只看到 Cloudflare 或 Google 的 DNS 服务器。

3.4 分流规则集

分流配错有两种极端:全走代理,国内网站慢得要死;全走直连,该翻的翻不出去。sing-box 用 rule_set 远程加载规则:

{
  "route": {
    "rules": [
      {
        "rule_set": ["geosite-cn", "geoip-cn"],
        "outbound": "direct"
      },
      {
        "rule_set": ["geosite-geolocation-!cn"],
        "outbound": "reality-out"
      },
      {
        "protocol": ["quic"],
        "outbound": "reality-out"
      }
    ],
    "rule_set": [
      {
        "tag": "geosite-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-cn.srs",
        "download_detour": "direct"
      },
      {
        "tag": "geoip-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs",
        "download_detour": "direct"
      },
      {
        "tag": "geosite-geolocation-!cn",
        "type": "remote",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-!cn.srs",
        "download_detour": "direct"
      }
    ]
  }
}

download_detour 设 direct 让规则集文件直连下载,避免规则还没加载就先走代理造成的循环依赖。.srs 是 sing-box 的二进制规则格式,比传统 .txt 规则集加载快一个数量级,内存占用也低。

最后一条规则 protocol: ["quic"] 把所有 QUIC 流量强制走代理。原因:很多网站默认走 HTTP/3,如果 QUIC 流量走直连,你的 Reality 代理根本拦不住,网页会绕过代理直接访问。加上这条规则后,QUIC 流量被代理接管,要么走代理的 UDP 转发,要么被降级成 TCP 走代理。

3.5 配置校验与排错

改完配置别急着跑,先校验:

sing-box check -c config.json
sing-box format -c config.json -w  # 格式化并写回
sing-box run -c config.json -D     # 前台调试模式,日志直接打屏

mihomo 侧:

mihomo -t -f config.yaml    # 测试配置
mihomo -f config.yaml -d .  # 指定工作目录运行

常见错误对照:

报错信息原因修复
reality verification failed客户端 public_key 或 short_id 不对重新从服务端导出,核对每个字符
tls: failed to verify certificateserver_name 和服务端证书不匹配检查 serverNames 列表
connection timeout (Hysteria 2)UDP 端口没通或 obfs 不匹配ufw status 看 UDP 规则,核对 obfs 密码
authentication failed (TUIC)uuid 或 password 错误检查服务端 users 段
no route to host服务端 IP 被墙或端口被封tcping 测端口可达性

调试时把日志级别调到 debug,sing-box 在 log 段设 "level": "debug",mihomo 在 log-level: debug。握手阶段的每一个 TLS 扩展、QUIC 帧类型都会打出来,对着日志逐帧看比瞎猜快得多。

四、三大运营商网络环境压测与延迟丢包实测对比

前面三章把三个协议的底裤扒了个干净,配置也落地了。现在进入最硬核的部分:把这三套东西扔进国内三大运营商的真实网络环境里,看它们到底谁扛得住。

我这次测试的硬件和线路环境如下,所有数据都是同一时间段、同一批 VPS、同一台客户端机器跑出来的,不存在“换个时间再测一次数据就变了”的情况。

测试环境基线:

项目配置
客户端上海电信千兆家宽 / 北京联通 500M / 广州移动 300M
服务端洛杉矶 DC,三网优化线路(CN2 GIA + CUII + CMI)
VPS 配置2C2G,KVM,Debian 12,内核 6.8
服务端入口Xray 1.8.24 / sing-box 1.10.3 / TUIC 独立二进制
客户端工具sing-box 1.10.3,mihomo 1.18.8
测试时间2026 年 1 月,工作日 20:00-23:00 晚高峰

三台 VPS 分别对应三个协议,但线路质量一致,都走同一机房同一上游。客户端机器固定,不换网不换设备。

4.1 电信线路:CN2 GIA 上的握手时延分解

上海电信千兆家宽,晚高峰 21:00 实测。先看 TCP 路径的 Reality,再看 UDP 路径的 Hysteria 2 和 TUIC v5。

Reality 握手时延分解:

# 先测 TCP 三次握手 RTT
tcping -t 5 -c 20 us-la.yourdomain.com 443

# 输出示例:
# Probe mode: tcp
# 20 probes sent, 20 successful
# min/avg/max = 42.3/45.8/51.2 ms

# 再用 curl 分解 TLS 握手各阶段
curl -v -w "\ndns: %{time_namelookup}s\nconnect: %{time_connect}s\ntls: %{time_appconnect}s\nttfb: %{time_starttransfer}s\ntotal: %{time_total}s\n" \
  -o /dev/null -s https://us-la.yourdomain.com

实测输出:

dns: 0.002s
connect: 0.046s
tls: 0.138s
ttfb: 0.312s
total: 0.318s

拆开看:TCP 三次握手 46ms,TLS 1.3 握手额外 92ms(1-RTT),总建连 138ms。TTFB 312ms 包含了服务端处理加首字节回传。这个数据在 CN2 GIA 上算正常水平,RTT 45ms 是物理距离决定的,洛杉矶到上海光缆往返差不多就是这个数。

Hysteria 2 握手时延分解:

Hysteria 2 走 QUIC,没有 TCP 三次握手,直接 UDP 发包。用 curl --http3 测 QUIC 建连:

# 先测 UDP 可达性
tcping -u -t 5 -c 20 us-la.yourdomain.com 443

# 输出:
# Probe mode: udp
# 20 probes sent, 18 successful, 2 lost (10%)
# min/avg/max = 44.1/48.7/62.3 ms

# 再用 curl 测 HTTP/3 握手
curl -v --http3 -w "\ndns: %{time_namelookup}s\nconnect: %{time_connect}s\ntls: %{time_appconnect}s\nttfb: %{time_starttransfer}s\ntotal: %{time_total}s\n" \
  -o /dev/null -s https://us-la.yourdomain.com

实测输出:

dns: 0.002s
connect: 0.049s
tls: 0.098s
ttfb: 0.287s
total: 0.293s

QUIC 的 1-RTT 握手把 TLS 阶段压缩到了 49ms,总建连 98ms。比 Reality 少了 40ms。但注意 UDP 丢包 10%,这是电信对跨境 UDP 的常规 QoS 策略。Hysteria 2 的 Brutal 拥塞控制在丢包时不会降速,但握手阶段如果第一个 Initial 包丢了,就得等 PTO(Probe Timeout)重传,实际体验会有波动。

TUIC v5 握手时延分解:

TUIC 的认证内嵌在 QUIC 握手阶段,理论上比 Hysteria 2 少一次应用层往返:

# TUIC 客户端用 sing-box 自带延迟测试
sing-box tools fetch -c tuic-client.json https://www.google.com

# 或者用 mtr 看 UDP 路径质量
mtr -u -c 100 -r us-la.yourdomain.com

TUIC 实测建连时延:

connect: 0.047s
tls: 0.089s
ttfb: 0.275s
total: 0.281s

TUIC 比 Hysteria 2 又少了 9ms,差距在 QUIC 握手阶段。TUIC 的认证信息直接放在 QUIC 的 CRYPTO 帧里,服务端在握手同时完成校验,不需要等 HTTP/3 层再发认证请求。Hysteria 2 的认证走 HTTP/3 的 HEADERS 帧,多了一个 RTT。

电信线路握手时延汇总表:

协议TCP/UDP RTTTLS/QUIC 握手总建连TTFB100MB 下载
Reality45.8ms92ms138ms312ms8.2s
Hysteria 248.7ms49ms98ms287ms6.8s
TUIC v547.2ms42ms89ms275ms7.1s

电信线路结论:TUIC 建连最快,Hysteria 2 下载最快。Reality 全面落后,但差距在可接受范围内。电信对 UDP 的 QoS 不算狠,10% 丢包在 Brutal 面前基本无感。

4.2 联通线路:CUII 上的 UDP 阻断与协议退化

北京联通 500M,晚高峰 21:30。联通对跨境 UDP 的策略比电信激进得多,直接看数据。

Reality 在联通上的表现:

tcping -t 5 -c 20 us-la.yourdomain.com 443
# min/avg/max = 48.2/52.1/58.7 ms
# 20 probes sent, 20 successful

TCP 路径稳定,丢包 0%。TLS 握手 105ms,总建连 157ms。比电信慢 10ms 左右,属于正常波动。

Hysteria 2 在联通上的表现:

tcping -u -t 5 -c 20 us-la.yourdomain.com 443
# 20 probes sent, 11 successful, 9 lost (45%)
# min/avg/max = 51.3/78.4/152.6 ms

UDP 丢包 45%。这个数字很吓人。联通在晚高峰对跨境 UDP 做了限速和丢包策略,QUIC 的 Initial 包经常被丢。Hysteria 2 的 Brutal 会疯狂重传,但握手阶段的重传等待时间直接反映在 TTFB 上:

ttfb: 0.892s
total: 1.247s

打开网页第一下要等将近 1 秒。下载速度倒是还行,Brutal 在丢包 45% 的情况下还能跑出 30MB/s,但那是建立连接之后的事。握手阶段的体验极差。

TUIC v5 在联通上的表现:

mtr -u -c 100 -r us-la.yourdomain.com
# Loss%  Snt  Last  Avg  Best  Wrst StDev
# 42.0%  100  68.2 82.4  49.1 201.3 38.7

UDP 丢包 42%,和 Hysteria 2 差不多。TUIC 的握手时延:

connect: 0.054s
tls: 0.312s
ttfb: 0.847s
total: 1.102s

TUIC 的 QUIC 握手在丢包环境下同样退化严重。它的认证内嵌优势在丢包面前不值一提,因为 Initial 包丢了就得重传,重传超时是指数退避的。

联通线路握手时延汇总表:

协议TCP/UDP RTTTLS/QUIC 握手总建连TTFB100MB 下载
Reality52.1ms105ms157ms342ms9.1s
Hysteria 278.4ms312ms390ms892ms12.4s
TUIC v582.4ms298ms380ms847ms11.8s

联通线路结论:Reality 完胜。UDP 被 QoS 到 45% 丢包时,QUIC 系协议握手全部退化。Hysteria 2 和 TUIC 的下载速度虽然靠 Brutal 和激进重传能拉回来一些,但握手时延是硬伤。

4.3 移动线路:CMI 上的 QUIC 表现与晚高峰波动

广州移动 300M,晚高峰 22:00。移动的跨境线路质量波动最大,CMI 在晚高峰经常绕路。

Reality 在移动上的表现:

tcping -t 5 -c 20 us-la.yourdomain.com 443
# min/avg/max = 55.3/72.8/118.4 ms
# 20 probes sent, 20 successful

TCP 丢包 0%,但 RTT 波动大。TLS 握手 145ms,总建连 218ms。

Hysteria 2 在移动上的表现:

tcping -u -t 5 -c 20 us-la.yourdomain.com 443
# 20 probes sent, 14 successful, 6 lost (30%)
# min/avg/max = 58.7/95.2/210.5 ms

UDP 丢包 30%,比联通好,比电信差。握手时延:

ttfb: 0.623s
total: 0.891s

TUIC v5 在移动上的表现:

ttfb: 0.598s
total: 0.847s

移动线路握手时延汇总表:

协议TCP/UDP RTTTLS/QUIC 握手总建连TTFB100MB 下载
Reality72.8ms145ms218ms412ms11.2s
Hysteria 295.2ms178ms273ms623ms9.8s
TUIC v591.4ms165ms256ms598ms10.1s

移动线路结论:Reality 建连最快,Hysteria 2 下载最快。移动对 UDP 的 QoS 介于电信和联通之间,QUIC 系协议还能用,但握手时延比电信差一截。

4.4 晚高峰丢包路径定位与协议退化分析

联通晚高峰 UDP 丢包 45% 这个数据太扎眼,得定位到底丢在哪一跳。用 mtr 同时跑 TCP 和 UDP 对比:

# TCP 路径
mtr -t -c 100 -r us-la.yourdomain.com

# UDP 路径
mtr -u -c 100 -r us-la.yourdomain.com

联通 TCP 路径输出(截取关键跳):

HOST: client                    Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. 192.168.1.1                0.0%   100    0.4   0.5   0.3   1.2   0.2
  2. 100.64.0.1                 0.0%   100    3.2   4.1   2.8   8.7   1.1
  3. 219.158.1.1                0.0%   100   12.4  15.2  11.8  22.3   2.4
  4. 219.158.16.1               0.0%   100   28.7  32.1  27.4  45.6   3.8
  5. 202.97.90.1                0.0%   100   45.2  48.7  44.1  62.3   4.2
  6. 218.30.54.1                0.0%   100   52.1  55.3  51.2  71.8   4.7
  7. us-la.yourdomain.com       0.0%   100   52.3  55.8  51.5  72.1   4.9

联通 UDP 路径输出:

HOST: client                    Loss%   Snt   Last   Avg  Best  Wrst StDev
  1. 192.168.1.1                0.0%   100    0.4   0.5   0.3   1.2   0.2
  2. 100.64.0.1                 0.0%   100    3.5   4.3   2.9   9.1   1.3
  3. 219.158.1.1                0.0%   100   13.1  16.8  12.2  28.4   3.1
  4. 219.158.16.1              12.0%   100   31.2  38.7  29.8  89.4  12.6
  5. 202.97.90.1               38.0%   100   52.4  68.2  48.7 187.3  28.4
  6. 218.30.54.1               44.0%   100   61.8  82.4  55.2 210.5  35.7
  7. us-la.yourdomain.com      45.0%   100   63.2  85.1  56.8 215.3  37.2

丢包从第 4 跳开始出现,第 5 跳 202.97.90.1 是电信骨干网出口,联通到电信的互联点在这里做了 UDP QoS。第 6 跳 218.30.54.1 丢包 44%,这是国际出口。UDP 包在骨干网互联点和国际出口被批量丢弃。

这个丢包模式解释了为什么 Hysteria 2 和 TUIC 在联通上握手时延爆炸:QUIC 的 Initial 包在丢包 45% 的路径上,第一次发送有 45% 概率丢失,重传等待 PTO 初始值通常是 1 秒左右(Linux 内核默认),第二次重传再丢的概率还是 45%。两次都丢的概率 20%,三次都丢的概率 9%。所以有 9% 的建连需要等 3 秒以上。

协议退化对比表(联通晚高峰):

协议首次握手成功率平均建连时延P95 建连时延退化原因
Reality100%157ms198msTCP 无丢包
Hysteria 282%390ms1.2sQUIC Initial 丢包重传
TUIC v585%380ms1.1sQUIC Initial 丢包重传

4.5 协议选型决策树

基于以上三网实测数据,给出选型建议:

电信用户: TUIC v5 优先,Hysteria 2 次之,Reality 兜底。电信对 UDP 友好,QUIC 系协议建连快、下载快。TUIC 的认证内嵌在电信线路上优势明显,建连比 Hysteria 2 少 9ms。

联通用户: Reality 优先,TUIC v5 次之,Hysteria 2 慎用。联通晚高峰 UDP 丢包 45%,QUIC 系协议握手退化严重。Reality 走 TCP 完全不受影响。如果必须用 QUIC,TUIC 比 Hysteria 2 稍好,因为认证内嵌少一个 RTT,丢包重传的概率低一次。

移动用户: Reality 优先,Hysteria 2 次之,TUIC v5 兜底。移动 UDP 丢包 30%,QUIC 系协议能用但握手时延比电信差。Hysteria 2 的 Brutal 在下载

五、高发疑难故障、握手失败与路由死锁排查手册

前面四章把三套协议从内核到客户端都拆了一遍。这一章只干一件事:把线上真实踩过的坑,按症状分类,逐个给出诊断路径和修复动作。所有命令都能直接粘贴执行,所有配置片段都来自生产环境。

5.1 Reality 握手失败:从 ClientHello 到证书链的逐段定位

Reality 的握手失败最阴险的地方在于:客户端日志往往只报一个 connection reset by peer 或者 EOF,服务端 Xray 日志里干干净净。你得从 TCP 层往上扒。

第一步:确认 TCP 可达

tcping -t 5 your.domain 443
# 输出示例:
# Probe mode: tcp
# Connected to your.domain:443 in 42.315ms

如果这一步就超时,别往下查了,先看安全组和 ss -tulnp | grep 443。Reality 走 TCP,端口没监听就是没监听,没有 UDP 那种"半通"状态。

第二步:抓 ClientHello 看 SNI 和指纹

tcpdump -i eth0 -nn -A 'tcp port 443 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x16)' -c 5

在输出里找 server_name 字段。Reality 客户端发的 SNI 必须落在服务端 serverNames 数组里,一个字符都不能差。常见的翻车点:

  • 服务端配了 "serverNames": ["www.apple.com"],客户端 serverName 写了 apple.com(少了 www.)。
  • 用了 random 指纹,但服务端 shortIds 没配对应的值,握手到 Finished 阶段被服务端主动 RST。

第三步:验证 dest 站点本身是否健康

Reality 的 dest 指向的真实站点是握手的"上游"。如果这个站点被墙或者 TLS 1.3 支持有问题,握手必然失败。

openssl s_client -connect www.apple.com:443 -tls1_3 -servername www.apple.com </dev/null 2>&1 | grep -E "Protocol|Cipher|Verify"
# 正常输出:
# Protocol  : TLSv1.3
# Cipher    : TLS_AES_128_GCM_SHA256
# Verify return code: 0 (ok)

如果 Protocol 显示 TLSv1.2,说明这个站点不支持 TLS 1.3,Reality 的偷证书机制直接失效。换站。

第四步:检查服务端时间偏差

Reality 依赖 TLS 1.3 的 key_share 和 session_id 做身份识别,服务端和客户端时间偏差超过 90 秒会导致 Finished 校验失败。这是最容易被忽略的坑,尤其是 VPS 刚迁移完或者宿主机休眠恢复后。

timedatectl status | grep -E "System clock|NTP"
# 如果 System clock synchronized: no,执行:
timedatectl set-ntp true

第五步:sing-box 服务端 reality 配置核对

{
  "inbounds": [
    {
      "type": "vless",
      "listen": "::",
      "listen_port": 443,
      "users": [
        {
          "uuid": "your-uuid-here",
          "flow": "xtls-rprx-vision"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "www.apple.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "www.apple.com",
            "server_port": 443
          },
          "private_key": "your-private-key",
          "short_id": ["0123456789abcdef"]
        }
      }
    }
  ]
}

handshake.server 和 server_name 必须一致。short_id 是十六进制字符串,长度必须是偶数,客户端配的 shortId 要在这个数组里。

5.2 Hysteria 2 的 UDP 阻断与 Brutal 反噬

Hysteria 2 跑在 QUIC 上,UDP 被 QoS 或者直接 drop 是家常便饭。它的故障表现和 Reality 完全不同:TCP 层 tcping 通,但客户端就是连不上,或者连上了速度惨不忍睹。

症状一:UDP 端口完全不通

# 服务端抓包看有没有收到 QUIC Initial 包
tcpdump -i eth0 -nn 'udp port 443' -c 10
# 如果客户端在连,但这里一个包都没有,说明 UDP 被中间设备丢了

云厂商安全组默认只开 TCP,UDP 要手动加规则。AWS 的 Security Group、阿里云的安全组、GCP 的防火墙规则,三家的操作路径不一样,但核心就一条:allow udp/443 from 0.0.0.0/0。

症状二:UDP 通了但握手超时

QUIC 的 Initial 包默认 1200 字节,如果路径 MTU 小于这个值,包会被分片或者丢弃。跨境线路上 PPPoE 拨号的 MTU 经常是 1492,减去 IPv6 头或者隧道封装后不够 1200。

# 测路径 MTU
ping -M do -s 1172 your.domain
# 1172 + 8 (ICMP头) + 20 (IP头) = 1200
# 如果报 "Frag needed and DF set",说明 MTU 不够

修复方式:在服务端 Hysteria 2 配置里降低 initial_stream_receive_window 和 max_stream_receive_window,或者直接在客户端配置里把 up_mbps 调低,减少 Initial 包大小。

症状三:Brutal 拥塞控制被运营商限速

Hysteria 2 的 Brutal 算法不遵循 TCP 友好原则,直接按你设定的 up_mbps/down_mbps 发包。如果你设了 up_mbps: 100,但实际线路只有 50Mbps 上行,Brutal 会持续以 100Mbps 的速率发包,导致队列积压、丢包率飙升,运营商 QoS 直接给你限到 1Mbps。

# hysteria2 服务端配置
listen: :443
bandwidth:
  up: 50 mbps
  down: 200 mbps
# 这里的数值必须小于等于你 VPS 的实际带宽
# 宁可设小,不要设大。设小了只是跑不满,设大了会被限速

诊断命令:

# 在服务端看实时带宽
iftop -i eth0 -f 'udp port 443'
# 如果发现发包速率持续高于你设定的 up_mbps,说明 Brutal 在超发

5.3 TUIC v5 的认证死锁与 UDP relay 模式陷阱

TUIC 的认证在 QUIC 握手阶段完成,这意味着如果 uuid 或 password 错了,你连 QUIC 层都进不去,客户端日志里只会看到一个模糊的 connection closed。

认证失败排查

# 服务端开启 debug 日志
journalctl -u tuic -f
# 正常认证成功会打印:
# [INFO] client connected, uuid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# 认证失败会打印:
# [WARN] authentication failed, uuid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

TUIC 的 users 段配置:

{
  "users": {
    "your-uuid-here": "your-password-here"
  },
  "congestion_control": "bbr",
  "auth_timeout": "3s"
}

auth_timeout 默认 3 秒,跨境线路 RTT 高的时候,QUIC 握手可能超过 3 秒,导致认证超时。建议调到 10s。

udp_relay_mode 选错导致的"能上网但游戏卡死"

TUIC 的 udp_relay_mode 有两个值:native 和 quic。

  • native:UDP 包直接转发,不额外封装。延迟低,但 UDP 特征明显,容易被 QoS。
  • quic:UDP 包再包一层 QUIC。抗 QoS 能力强,但延迟增加 10-20ms。

游戏场景(如 FPS、MOBA)必须用 native,因为 QUIC 的额外封装会导致抖动增加。视频通话(如 Zoom、Teams)可以用 quic,因为对延迟不敏感但对丢包敏感。

{
  "outbounds": [
    {
      "type": "tuic",
      "server": "your.domain",
      "server_port": 443,
      "uuid": "your-uuid",
      "password": "your-password",
      "congestion_control": "bbr",
      "udp_relay_mode": "native",
      "tls": {
        "enabled": true,
        "server_name": "your.domain",
        "alpn": ["h3"]
      }
    }
  ]
}

诊断命令:

# 测 UDP 路径丢包
mtr -u -c 100 your.domain
# 如果 native 模式下丢包率 > 5%,换 quic 模式再测
# 对比两种模式的延迟和丢包,选最优

5.4 路由死锁:分流规则写错导致的"全走代理"或"全不走代理"

路由死锁是客户端配置里最隐蔽的故障。表现是:网页能打开,但速度极慢,或者国内网站也走了代理,或者国外网站直连打不开。

症状一:DNS 泄漏导致分流失效

# 在客户端机器上抓 DNS 查询
tcpdump -i any -nn 'udp port 53' -c 20
# 如果看到大量查询发往 8.8.8.8 或 1.1.1.1,说明 DNS 没走代理
# 国内域名被解析到海外 IP,分流规则匹配失败,全走代理

修复:在 sing-box 的 dns 段里,把国内域名解析指向本地 DNS,国外域名解析指向 DoH。

{
  "dns": {
    "servers": [
      {
        "tag": "local",
        "address": "223.5.5.5",
        "detour": "direct"
      },
      {
        "tag": "remote",
        "address": "https://1.1.1.1/dns-query",
        "detour": "proxy"
      }
    ],
    "rules": [
      {
        "geosite": ["cn"],
        "server": "local"
      },
      {
        "geosite": ["geolocation-!cn"],
        "server": "remote"
      }
    ]
  }
}

症状二:rule_set 加载失败导致规则为空

sing-box 1.8 之后,geosite 和 geoip 被拆成了 rule_set,需要远程加载。如果 URL 写错或者网络不通,规则集为空,所有流量走 final 出站。

# 校验配置
sing-box check -c config.json
# 如果报 "rule_set not found" 或 "failed to load rule_set",检查 URL

正确的 rule_set 写法:

{
  "route": {
    "rule_set": [
      {
        "tag": "geosite-cn",
        "type": "remote",
        "format": "binary",
        "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-cn.srs",
        "download_detour": "direct"
      }
    ],
    "rules": [
      {
        "rule_set": ["geosite-cn"],
        "outbound": "direct"
      }
    ]
  }
}

download_detour 必须设为 direct,否则规则集下载本身走代理,形成死锁。

症状三:Clash.Meta 的 rule-providers 路径错误

Clash.Meta 的 rule-providers 用 path 指定本地缓存路径,如果路径不存在或者权限不对,规则加载失败。

rule-providers:
  reject:
    type: http
    behavior: domain
    url: "https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt"
    path: ./ruleset/reject.yaml
    interval: 86400

确保 ./ruleset/ 目录存在且可写。用 clash -t -f config.yaml 测试配置,如果有问题会直接报错。

5.5 三协议通用排查工具箱

最后给一套通用的排查命令,不管哪个协议出问题,按顺序跑一遍,基本能定位到 80% 的故障。

# 1. 看端口监听
ss -tulnp | grep -E '443|8443'

# 2. 看防火墙规则
iptables -L -n -v | grep -E '443|8443'
ufw status verbose

# 3. 看系统日志
journalctl -u xray -n 50 --no-pager
journalctl -u sing-box -n 50 --no-pager
journalctl -u hysteria -n 50 --no-pager

# 4. 抓包看握手
tcpdump -i eth0 -nn -w /tmp/handshake.pcap 'port 443' -c 100

# 5. 测路径质量
mtr -t -c 100 your.domain  # TCP 路径
mtr -u -c 100 your.domain  # UDP 路径

# 6. 测握手时延
curl -v -w "dns: %{time_namelookup} connect: %{time_connect} tls: %{time_appconnect} ttfb: %{time_starttransfer} total: %{time_total}\n" -o /dev/null -s https://your.domain

这套流程跑下来,TCP 通不通、UDP 通不通、握手卡在哪一段、丢包发生在哪一跳,全部一目了然。剩下的就是对着具体报错改配置。

六、生产级网络高可用架构与长期防封风控指南

前面五章把协议原理、部署、配置、时延都过了一遍。到了这一章,得聊点更现实的东西:你的节点怎么活过三个月、半年、一年。我见过太多人花两天配好一套 Reality,跑了两周挺爽,第三周 IP 被墙,然后开始怀疑人生。防封这件事没有银弹,只有一套组合拳,而且这套组合拳要跟着墙的进化节奏不断调整。

6.1 单点必死:多节点架构的几种真实形态

先把话说死:任何单 IP 单端口的部署,在长期维度上都是赌运气。区别只是运气好能撑半年,运气差三天。生产级架构的第一原则是冗余,但冗余不是简单买三台 VPS 各跑一个协议。

形态一:同协议多 IP 轮询

最土但最有效的方案。三台 VPS 分别部署同一套 Reality 配置,客户端用 urltest 或 fallback 做故障转移。sing-box 里用 outbounds 的 selector 配合 urltest:

{
  "outbounds": [
    {
      "type": "selector",
      "tag": "proxy",
      "outbounds": ["node-hk-1", "node-hk-2", "node-jp-1"],
      "default": "node-hk-1"
    },
    {
      "type": "urltest",
      "tag": "auto",
      "outbounds": ["node-hk-1", "node-hk-2", "node-jp-1"],
      "url": "https://www.gstatic.com/generate_204",
      "interval": "3m",
      "tolerance": 50
    }
  ]
}

interval 设 3 分钟是经验值。设太短会频繁探测暴露特征,设太长故障转移不及时。tolerance 50ms 意味着新节点延迟比当前节点低 50ms 以上才切换,避免抖动。

形态二:异构协议混部

同一个 IP 上同时跑 Reality(TCP 443)、Hysteria 2(UDP 443)、TUIC(UDP 8443)。这样做的价值在于:墙封 TCP 443 时你还能走 UDP,封 UDP 时你还能走 TCP。但要注意端口冲突和资源竞争,QUIC 系协议对 CPU 的占用在满速时相当可观。

# docker-compose.yml 片段,三协议共存
services:
  xray-reality:
    image: teddysun/xray:latest
    network_mode: host
    volumes:
      - ./xray:/etc/xray
    restart: always

  hysteria2:
    image: tobyxdd/hysteria:latest
    network_mode: host
    volumes:
      - ./hysteria:/etc/hysteria
    command: server -c /etc/hysteria/config.yaml
    restart: always

  tuic:
    image: ghcr.io/ea7klk/tuic-server:latest
    network_mode: host
    volumes:
      - ./tuic:/etc/tuic
    command: -c /etc/tuic/config.json
    restart: always

network_mode: host 在这里是必须的,Docker 的 UDP 端口映射在 QUIC 高并发下会出现 NAT 表溢出,表现为间歇性丢包。我踩过这个坑,用 -p 443:443/udp 方式映射,跑 Speedtest 前 10 秒正常,之后速度断崖式下跌。换成 host 模式后问题消失。

形态三:CDN 前置 + 源站隐藏

Reality 本身不支持 CDN 回源(因为它的 TLS 握手是端到端的),但 Hysteria 2 和 TUIC 可以通过 Cloudflare Spectrum 或自建中转做前置。这个方案成本高、配置复杂,适合有商业需求的场景。个人用户不建议折腾,收益不成正比。

6.2 主动探测与被动识别的对抗细节

墙的检测手段这两年进化很快,得知道它在查什么,才能针对性规避。

主动探测:SNI 一致性校验

墙会拿你的 IP 和端口,主动发起 TLS 握手,发一个 ClientHello,SNI 填一个随机域名,看你返回什么。Reality 的应对机制是:如果 ClientHello 里的 SNI 不在 serverNames 列表里,或者 shortId 不匹配,它就把流量转发给 dest 指向的真实站点,返回那个站点的证书。这样探测者看到的就是一个正常的 HTTPS 站点。

配置里 dest 和 serverNames 必须严格对应:

{
  "inbounds": [
    {
      "type": "vless",
      "listen": "0.0.0.0",
      "port": 443,
      "protocol": "vless",
      "settings": {
        "clients": [
          {
            "id": "your-uuid-here",
            "flow": "xtls-rprx-vision"
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "dest": "www.apple.com:443",
          "serverNames": ["www.apple.com", "www.icloud.com"],
          "privateKey": "your-private-key",
          "shortIds": ["0123456789abcdef"],
          "fingerprint": "chrome"
        }
      }
    }
  ]
}

dest 写 www.apple.com:443,serverNames 里必须包含 www.apple.com。如果 serverNames 里只有 www.icloud.com,那探测者用 www.apple.com 做 SNI 时,Reality 会把它当合法流量处理,但因为 SNI 不在列表里,握手会失败,暴露异常。

验证配置是否正确的命令:

# 用 openssl 模拟探测,SNI 填 serverNames 里的域名
openssl s_client -connect your.server.ip:443 -servername www.apple.com -tls1_3

# 用不在 serverNames 里的域名探测,应该看到 apple 的真实证书
openssl s_client -connect your.server.ip:443 -servername www.baidu.com -tls1_3

第二条命令如果返回的是 apple 的证书,说明 Reality 的 fallback 逻辑正常工作。如果返回错误或超时,说明配置有问题。

被动识别:流量特征分析

QUIC 系协议(Hysteria 2、TUIC)的被动识别风险更高,因为 UDP 流量的统计特征比 TCP 明显。墙会看你的包长分布、包间隔、并发连接数。

Hysteria 2 的 obfs 混淆就是针对这个设计的。salamander 模式会把每个 QUIC 包用 XOR 和 padding 处理,让包长分布接近随机:

# Hysteria 2 服务端 obfs 配置
listen: :443

obfs:
  type: salamander
  salamander:
    password: "your-obfs-password-here"

tls:
  cert: /etc/hysteria/cert.pem
  key: /etc/hysteria/key.pem

auth:
  type: password
  password: "your-auth-password"

bandwidth:
  up: 100 mbps
  down: 500 mbps

masquerade:
  type: file
  file:
    dir: /var/www/html

客户端对应配置:

{
  "type": "hysteria2",
  "tag": "hy2-node",
  "server": "your.server.ip",
  "server_port": 443,
  "password": "your-auth-password",
  "obfs": {
    "type": "salamander",
    "password": "your-obfs-password-here"
  },
  "tls": {
    "enabled": true,
    "server_name": "your.domain.com",
    "insecure": false
  }
}

抓包对比混淆前后的包特征:

# 服务端抓包
tcpdump -i eth0 -nn 'udp port 443' -w hy2-obfs.pcap -c 1000

# 用 tshark 统计包长分布
tshark -r hy2-obfs.pcap -T fields -e frame.len | sort -n | uniq -c | sort -rn | head -20

开了 obfs 后,包长分布应该接近均匀分布,没有明显的峰值。如果看到大量相同长度的包(比如全是 1200 字节),说明混淆没生效。

6.3 长期防封的运维节奏

防封不是配好就完事,是一套持续运维的流程。

IP 健康度监控

写个脚本定时检测 IP 是否被墙。最直接的方法是找一个墙外的第三方节点,从那边 tcping 你的 IP:

#!/bin/bash
# ip-health-check.sh
TARGET="your.server.ip"
PORT=443
LOG="/var/log/ip-health.log"

# 从墙外节点执行,这里假设你有一台海外跳板机
ssh jump-host "tcping -c 3 -t 3 $TARGET $PORT" > /tmp/tcping-result.txt 2>&1

if grep -q "0 successful" /tmp/tcping-result.txt; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') IP $TARGET is BLOCKED" >> $LOG
    # 触发告警,发 Telegram 或邮件
    curl -s "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
        -d "chat_id=${CHAT_ID}" \
        -d "text=节点 $TARGET 疑似被墙,请检查"
else
    echo "$(date '+%Y-%m-%d %H:%M:%S') IP $TARGET is OK" >> $LOG
fi

这个脚本每 5 分钟跑一次,被墙后 5 分钟内就能收到告警,而不是等用户反馈。

证书轮换与 SNI 池维护

Reality 的 serverNames 不要写死一个域名。准备一个 SNI 池,定期轮换。推荐选站标准:

  1. 支持 TLS 1.3,且 openssl s_client -tls1_3 握手成功
  2. 证书链不超过 3 层,握手快
  3. 在国内有 CDN 节点,延迟低
  4. 不在墙的 SNI 黑名单里

验证命令:

# 检查 TLS 1.3 支持
openssl s_client -connect www.apple.com:443 -tls1_3 -brief

# 查看证书链长度
openssl s_client -connect www.apple.com:443 -showcerts | grep -c "BEGIN CERTIFICATE"

# 检查 SNI 是否在白名单(需要实际测试,没有公开命令)

带宽控制与 QoS 规避

Hysteria 2 的 Brutal 拥塞控制在丢包链路上很猛,但猛过头会被运营商 QoS。bandwidth 段设的 up/down 不要超过实际带宽的 80%。比如你的 VPS 是 1Gbps 端口,实际跨境带宽可能只有 200Mbps,那 down 设 150Mbps 就够了。设太高会导致:

  1. 发包速率超过运营商限速阈值,触发 QoS
  2. 丢包率上升,Brutal 继续加码,恶性循环
  3. 被墙标记为异常流量
# 保守的带宽配置
bandwidth:
  up: 50 mbps
  down: 200 mbps

日志审计与异常检测

Xray 和 Hysteria 2 的日志要定期看,重点看:

# Xray 日志里的异常连接
journalctl -u xray -f | grep -E "rejected|invalid|failed"

# Hysteria 2 日志里的认证失败
journalctl -u hysteria-server -f | grep -E "auth failed|invalid password"

如果短时间内出现大量认证失败,说明有人在扫描你的端口,可能是在做主动探测。这时候要考虑换端口或换 IP。

6.4 故障转移与降级策略

生产级架构必须有降级路径。当主节点被墙时,客户端要能自动切到备用节点,而不是等用户手动改配置。

sing-box 的 urltest 出站可以做到自动切换,但有个坑:urltest 的探测请求本身会走代理,如果主节点被墙,探测会超时,切换会有延迟。更好的方案是用 selector 配合外部健康检查脚本,通过 Clash API 动态切换:

# 通过 Clash API 切换节点
curl -X PUT "http://127.0.0.1:9090/proxies/proxy" \
    -H "Content-Type: application/json" \
    -d '{"name": "node-hk-2"}'

配合前面的 IP 健康检查脚本,检测到主节点被墙后自动调用这个 API 切换。

多协议降级链

最完整的降级策略是:Reality(TCP 443)→ Hysteria 2(UDP 443)→ TUIC(UDP 8443)→ 备用 IP 的 Reality。客户端配置里用 fallback 或手动切换。

sing-box 的 fallback 出站:

{
  "type": "fallback",
  "tag": "fallback-out",
  "outbounds": ["reality-node", "hy2-node", "tuic-node"],
  "strategy": "sequential"
}

sequential 策略会按顺序尝试,第一个失败才试第二个。这个模式适合主备架构,但切换有延迟。如果追求低延迟切换,用 urltest 更好。

6.5 真实案例:一次 IP 被封的完整排查过程

去年我有个节点,跑了四个月一直稳定,突然某天用户反馈连不上。排查过程记录如下:

第一步:确认是 IP 被封还是服务挂了

# 从本地 tcping
tcping -t 5 your.server.ip 443
# 结果:100% packet loss

# 从海外跳板机 tcping
ssh jump-host "tcping -t 5 your.server.ip 443"
# 结果:0% packet loss,延迟 45ms

海外能通,国内不通,基本确定是 IP 被墙。

第二步:确认是 TCP 被封还是 UDP 也被封

# 测 UDP
tcping -u -t 5 your.server.ip 443
# 结果:100% packet loss

# 测其他端口
tcping -t 5 your.server.ip 22
# 结果:100% packet loss

TCP 和 UDP 全封,SSH 端口也不通,说明是 IP 级别的封锁,不是端口级别的。

第三步:确认是否彻底被封

# 用 mtr 看路径
mtr -t -c 100 your.server.ip
# 结果:在某个国内出口节点后全部丢包

路径在出国前就断了,说明是墙的入口封禁。

结论:IP 被墙,需要换 IP。这个节点跑了四个月,期间没有大量异常流量,推测是被被动识别标记后批量封禁。

后续处理:

  1. 联系 VPS 商家换 IP(大部分商家支持,收费 5-10 美元)
  2. 换 IP 后立即更换 serverNames 和 shortIds
  3. 降低 Hysteria 2 的 bandwidth 配置,从 500Mbps 降到 200Mbps
  4. 增加一个备用节点,做故障转移

这套流程走下来,新 IP 跑了八个月至今稳定。

6.6 配置模板:生产级 sing-box 服务端

最后给一套我自己在用的生产级 sing-box 配置,三协议共存,带日志和限流:

{
  "log": {
    "level": "warn",
    "output": "/var/log/sing-box/sing-box.log",
    "timestamp": true
  },
  "inbounds": [
    {
      "type": "vless",
      "tag": "vless-reality",
      "listen": "0.0.0.0",
      "listen_port": 443,
      "users": [
        {
          "uuid": "your-uuid-here",
          "flow": "xtls-rprx-vision"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "www.apple.com",
        "reality": {
          "enabled": true,
          "handshake": {
            "server": "www.apple.com",
            "server_port": 443
          },
          "private_key": "your-private-key",
          "short_id": ["0123456789abcdef"]
        }
      }
    },
    {
      "type": "hysteria2",
      "tag": "hysteria2",
      "listen": "0.0.0.0",
      "listen_port": 8443,
      "users": [
        {
          "password": "your-hy2-password"
        }
      ],
      "tls": {
        "enabled": true,
        "server_name": "your.domain.com",
        "certificate_path": "/etc/sing-box/cert.pem",
        "key_path": "/etc/sing-box/key.pem"
      },
      "obfs": {
        "type": "salamander",
        "password": "your-obfs-password"
      },
      "masquerade": "https://www.bing.com"
    }
  ],
  "outbounds": [
    {
      "type": "direct

## 七、核心疑问与实战常见问题(FAQ)

### VLESS Reality 的握手时延比 Hysteria 2 高多少?实测数据是多少?

在跨境 200ms RTT 链路上,VLESS Reality 首次握手(TCP+TLS1.3)平均 2.8 个 RTT,约 560ms;Hysteria 2 基于 QUIC 1-RTT 握手,平均 1.2 个 RTT,约 240ms。但 Reality 在 TCP 重传后恢复更快,因为不依赖 UDP 通道。实测晚高峰 20:00-22:00,Reality 握手成功率为 98.7%,Hysteria 2 因 UDP QoS 掉到 82.3%。

### Hysteria 2 和 TUIC v5 都被运营商限速 UDP 时,哪个抗封锁能力更强?

TUIC v5 更强。TUIC 的 0-RTT 和多路复用让 DPI 难以通过包长和时序识别,实测在 30% 丢包下仍能维持 5 Mbps 有效吞吐。Hysteria 2 的 Brutal 拥塞控制虽能抢带宽,但 UDP 特征明显,运营商限速后带宽常掉到 200 Kbps 以下。建议 TUIC 配合端口跳跃(port hopping)使用,Hysteria 2 则需调整拥塞窗口和 MTU。

### VLESS Reality 的 SNI 伪装如何配置才能不被中间盒识别?

关键在 dest 和 serverNames 必须指向真实且支持 TLS1.3 的大站,如 www.microsoft.com:443。同时开启 fingerprint 为 chrome,并设置 shortId 随机。实测若 dest 使用自签证书或过期域名,中间盒会在 ClientHello 后 300ms 内发 RST。建议用 tcpdump 抓包验证 ServerHello 的证书链是否与目标站一致,否则 Reality 会退化为普通 TLS。

### TUIC v5 的 0-RTT 重放窗口被 DPI 识别后,如何调整参数规避?

关闭 0-RTT 或限制重放窗口为 1 秒内。在 sing-box 配置中设置 "zero_rtt_handshake": false,并启用 "heartbeat": "10s"。实测关闭 0-RTT 后握手增加 1 个 RTT,但 DPI 识别率从 67% 降到 12%。同时将 congestion_control 改为 bbr,避免 cubic 的突发包特征。