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 快速重连 | 文档和教程资源较少 |
| 支持全锥型 NAT | QUIC 依赖 UDP,UDP 受限网络中不可用 |
| 支持 UDP over Datagram 和 UDP over Stream 两种模式 | 社区规模小,遇到问题排障资源有限 |
| BBR 拥塞控制,在高延迟线路上表现好 | — |
与同类协议的对比
| 对比维度 | ShadowQUIC | Hysteria 2 | TUIC v5 | VLESS + Reality |
|---|---|---|---|---|
| 传输层 | QUIC(UDP) | QUIC(UDP) | QUIC(UDP) | TCP |
| SNI 伪装 | 支持(JLS) | 不支持 | 不支持 | 支持(Reality) |
| 需要证书 | 否 | 是 | 是 | 否 |
| 需要域名 | 是(用于 SNI 伪装) | 是 | 是 | 否 |
| 0-RTT | 支持 | 支持 | 支持 | 不适用 |
| 全锥型 NAT | 支持 | 支持 | 有限支持 | 不支持 |
| 拥塞控制 | BBR | Brutal | 标准 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.addr | SNI 伪装目标地址,必须与客户端的 server-name 一致 |
alpn | QUIC 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-name | SNI 伪装域名,必须与服务端 jls-upstream.addr 的域名一致 |
initial-mtu | QUIC 初始 MTU 值,建议 1300 |
zero-rtt | 是否启用 0-RTT |
over-stream | UDP 代理模式: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 / Linux | shadowquic | 支持(官方 CLI) |
| Windows / Linux | Clash-rs | 支持 |
| Windows | v2rayN | 需确认版本 |
| Android | Husi | 支持 |
| Android | NekoBox | 需确认版本 |
| iOS | — | 暂无主流客户端支持 |
| macOS | — | 暂无主流客户端支持 |
ShadowQUIC 目前客户端生态非常有限,主要通过官方 CLI 和 Clash-rs 使用。iOS 和 macOS 平台暂无主流客户端支持。
常见问题
Q:SNI 伪装域名可以随便填吗?
server-name(客户端)和 jls-upstream.addr(服务端)的域名必须一致。建议选择常见的、流量较大的域名(如 cloudflare.com、www.microsoft.com),让伪装流量更自然。端口通常使用 443。
Q:ShadowQUIC 需要证书吗?
不需要。这是 ShadowQUIC 相比 Hysteria 2 / TUIC 的一大优势——SNI 伪装机制不要求服务端持有对应域名的证书。
Q:为什么连接失败?
检查以下几点:
- 客户端
server-name与服务端jls-upstream.addr的域名是否完全一致 - 服务端防火墙是否已开放对应 UDP 端口
- 客户端所在网络是否封锁 UDP
- 服务端是否已重启使配置生效
Q:over-stream 设 true 还是 false?
默认使用 false(UDP over Datagram),延迟更低。如果遇到兼容性问题(如某些 QUIC 库不支持 Datagram),切换为 true。
延伸阅读
- ShadowQUIC 项目:github.com/spongebob888/shadowquic
- JLS 库:github.com/JimmyHuang454/JLS
- Hysteria 2 — 更成熟的 QUIC 系协议
- TUIC — 另一种 QUIC 系协议
- VLESS + Reality — TCP 方向的 SNI 伪装方案