跳到主要内容

ShadowQUIC

ShadowQUIC 是一种基于 QUIC 的代理协议,核心特点是通过 SNI 伪装(由 JLS 库提供)将 QUIC 握手伪装成对任意域名的 TLS 连接,从而规避基于 SNI 的检测和封锁。它于 2025 年 4 月发布,目前处于早期阶段,以工程实现为主导。

基本信息

项目信息
发布2025.04
传输层QUIC(UDP)
主要实现spongebob888/shadowquic
SNI 伪装基于 JLS
生态成熟度早期 / 规模较小

核心特性

SNI 伪装(JLS)

ShadowQUIC 的核心创新在于使用 JLS(Just Like SNI)库进行 SNI 伪装。与传统的 TLS 伪装不同,JLS 将 QUIC 握手伪装成对任意指定域名的 TLS 连接:

客户端 --[QUIC 握手,SNI=cloudflare.com]--> 服务端
|
| 外部观测者看到的是到 cloudflare.com 的正常 TLS 握手
| 实际上建立的是 QUIC 代理连接
v
服务端验证 SNI 后建立代理通道

这一机制的特点:

  • 抗劫持:即使中间设备劫持了 SNI,由于 JLS 的验证机制,不会泄露代理信息
  • 抗主动探测:服务端对不符合 JLS 协议的连接表现为普通 TLS 服务器
  • 无需证书:SNI 伪装不要求服务端持有对应域名的证书,降低了部署门槛

0-RTT 连接

ShadowQUIC 支持 QUIC 的 0-RTT 特性,在已建立过连接的情况下可以实现零往返时间的快速重连:

首次连接:
客户端 --[完整握手 + SNI 伪装]--> 服务端(1-RTT)

后续连接:
客户端 --[0-RTT 恢复]--> 服务端(0-RTT,几乎无延迟)

全锥型 NAT

ShadowQUIC 支持全锥型 NAT(Full Cone),适合需要 NAT 穿透的场景。UDP 代理支持两种模式:

  • UDP over Datagram(默认):使用 QUIC Datagram 原生传输,延迟更低
  • UDP over Stream:使用 QUIC Stream 传输,兼容性更好

通过配置 over-stream 字段切换。

BBR 拥塞控制

ShadowQUIC 使用 BBR 作为默认拥塞控制算法,在高延迟线路上表现优于传统 CUBIC。

多用户支持

服务端支持配置多个用户,每个用户通过 username + password 认证。

工作原理

连接建立流程

客户端
|
| 1. 发起 QUIC 握手,SNI 伪装为指定域名(如 cloudflare.com)
| 2. JLS 层完成 SNI 验证与握手伪装
| 3. 在 QUIC 连接上发送代理请求(username + password 认证)
v
服务端
|
| 4. JLS 验证 SNI 合法性
| 5. 验证用户凭据
| 6. 解析代理目标地址
| 7. 建立到目标的连接
v
目标服务器

多路复用

QUIC 连接(单一 UDP 连接,SNI 伪装)
├── Stream 1 → TCP 请求 A(Google)
├── Stream 2 → TCP 请求 B(GitHub)
├── Datagram → UDP 请求 C(DNS)
└── Stream 3 → TCP 请求 D(YouTube)

优缺点

优点缺点
SNI 伪装,可伪装为任意域名,规避基于 SNI 的检测协议尚处早期,生态不成熟
无需服务端持有证书,部署门槛低客户端支持有限
支持 0-RTT 快速重连文档和教程资源较少
支持全锥型 NATQUIC 依赖 UDP,UDP 受限网络中不可用
支持 UDP over Datagram 和 UDP over Stream 两种模式社区规模小,遇到问题排障资源有限
BBR 拥塞控制,在高延迟线路上表现好

与同类协议的对比

对比维度ShadowQUICHysteria 2TUIC v5VLESS + Reality
传输层QUIC(UDP)QUIC(UDP)QUIC(UDP)TCP
SNI 伪装支持(JLS)不支持不支持支持(Reality)
需要证书
需要域名是(用于 SNI 伪装)
0-RTT支持支持支持不适用
全锥型 NAT支持支持有限支持不支持
拥塞控制BBRBrutal标准 QUIC标准 TCP
高丢包性能较强极强较强一般
客户端支持极少广较广广
生态成熟度早期成熟成熟成熟

总结: ShadowQUIC 的 SNI 伪装能力是其独特优势,无需证书即可部署。但生态成熟度远不如 Hysteria 2、TUIC 或 VLESS + Reality,目前更适合技术探索。

适用场景

推荐使用 ShadowQUIC 的场景:

  • 对 SNI 伪装有明确需求,且不愿或无法申请证书
  • 技术探索与小规模试验
  • 作为已有方案的补充,测试其抗封锁能力
  • 需要全锥型 NAT 的场景

不推荐作为主力方案的场景:

  • 生产环境或需要稳定性的场景
  • 需要广泛客户端支持的用户
  • 不愿投入时间自行排障的用户

服务端部署

前置条件

  • 一台公网 VPS,已开放 UDP 端口
  • 用于 SNI 伪装的域名(可以不是你自己的域名,如 cloudflare.com

一键安装(Linux)

curl -L https://raw.githubusercontent.com/spongebob888/shadowquic/main/scripts/linux_install.sh | bash

安装脚本会自动完成以下操作:

  • shadowquic 安装到 /usr/local/bin/
  • 生成随机凭据和配置文件到 /etc/shadowquic/server.yaml
  • 配置并启动 systemd 服务

手动安装

从 GitHub Releases 下载对应平台的二进制文件,然后手动创建配置文件。

服务端配置(/etc/shadowquic/server.yaml)

inbound:
type: shadowquic
bind-addr: "0.0.0.0:1443"
users:
- username: "your_username"
password: "your_password"
jls-upstream:
addr: "cloudflare.com:443" # SNI 伪装目标域名,需与客户端一致
alpn: ["h3"]
congestion-control: bbr
zero-rtt: true
gso: true # 启用 Generic Segmentation Offload
outbound:
type: direct
dns-strategy: prefer-ipv4 # 可选:prefer-ipv6, ipv4-only, ipv6-only
log-level: "info"

配置字段说明:

字段说明
bind-addr服务端监听地址和端口
users用户列表,支持多用户
jls-upstream.addrSNI 伪装目标地址,必须与客户端的 server-name 一致
alpnQUIC ALPN 标识
congestion-control拥塞控制算法
zero-rtt是否启用 0-RTT
gso是否启用 Generic Segmentation Offload,提升性能
dns-strategy出站 DNS 解析策略

启动服务

# 使用一键安装脚本配置的服务
systemctl start shadowquic.service
systemctl status shadowquic.service

# 查看日志
journalctl -u shadowquic.service -f

Docker 部署

ShadowQUIC 提供了 Docker 镜像:

# docker-compose.yml
services:
shadowquic:
image: ghcr.io/spongebob888/shadowquic:latest
volumes:
- ./server.yaml:/etc/shadowquic/server.yaml
ports:
- "1443:1443/udp"
restart: unless-stopped

开放防火墙规则

ufw allow 1443/udp

客户端配置参考

ShadowQUIC 官方客户端

shadowquic -c client.yaml

客户端配置(client.yaml):

inbound:
type: socks
bind-addr: "127.0.0.1:1089"
outbound:
type: shadowquic
addr: "your-server-ip:1443"
username: "your_username"
password: "your_password"
server-name: "cloudflare.com" # 必须与服务端 jls-upstream 一致
alpn: ["h3"]
initial-mtu: 1300
congestion-control: bbr
zero-rtt: true
gso: true
over-stream: false # true: UDP over Stream, false: UDP over Datagram
log-level: "info"

配置字段说明:

字段说明
bind-addr本地 SOCKS5 代理监听地址
addr服务端地址和端口
server-nameSNI 伪装域名,必须与服务端 jls-upstream.addr 的域名一致
initial-mtuQUIC 初始 MTU 值,建议 1300
zero-rtt是否启用 0-RTT
over-streamUDP 代理模式:false 为 Datagram,true 为 Stream

Clash-rs 客户端

ShadowQUIC 已被 Clash-rs 支持:

proxies:
- name: "shadowquic-node"
type: shadowquic
server: your-server-ip
port: 1443
username: your_username
password: your_password
server-name: cloudflare.com

客户端支持

平台客户端支持状态
Windows / Linuxshadowquic支持(官方 CLI)
Windows / LinuxClash-rs支持
Windowsv2rayN需确认版本
AndroidHusi支持
AndroidNekoBox需确认版本
iOS暂无主流客户端支持
macOS暂无主流客户端支持
客户端支持有限

ShadowQUIC 目前客户端生态非常有限,主要通过官方 CLI 和 Clash-rs 使用。iOS 和 macOS 平台暂无主流客户端支持。

常见问题

Q:SNI 伪装域名可以随便填吗?

server-name(客户端)和 jls-upstream.addr(服务端)的域名必须一致。建议选择常见的、流量较大的域名(如 cloudflare.comwww.microsoft.com),让伪装流量更自然。端口通常使用 443。

Q:ShadowQUIC 需要证书吗?

不需要。这是 ShadowQUIC 相比 Hysteria 2 / TUIC 的一大优势——SNI 伪装机制不要求服务端持有对应域名的证书。

Q:为什么连接失败?

检查以下几点:

  1. 客户端 server-name 与服务端 jls-upstream.addr 的域名是否完全一致
  2. 服务端防火墙是否已开放对应 UDP 端口
  3. 客户端所在网络是否封锁 UDP
  4. 服务端是否已重启使配置生效

Q:over-stream 设 true 还是 false?

默认使用 false(UDP over Datagram),延迟更低。如果遇到兼容性问题(如某些 QUIC 库不支持 Datagram),切换为 true

延伸阅读