Debian & Ubuntu 搭建部署 sing-box 的 Hysteria2 服务

Contents
  1. 1. 背景与原理
    1. 1.1. Hysteria2 与审查现状
    2. 1.2. 拥塞控制选择
    3. 1.3. 本方案不适用的场景
  2. 2. 准备工作
    1. 2.1. 服务器
    2. 2.2. 域名与 DNS
    3. 2.3. 安装所需基本工具
  3. 3. 安装 sing-box
  4. 4. 生成密码
    1. 4.1. 用户认证密码
    2. 4.2. 混淆密码
  5. 5. 防火墙与端口跳跃
    1. 5.1. 系统防火墙
    2. 5.2. 端口跳跃 NAT 规则
  6. 6. 配置 sing-box
    1. 6.1. 创建配置文件
    2. 6.2. BBR 模式
    3. 6.3. 切换为 Brutal 模式
    4. 6.4. 关键字段说明
    5. 6.5. 配置校验
  7. 7. 启动服务
  8. 8. 客户端配置文件
    1. 8.1. BBR 模式客户端
    2. 8.2. Brutal 模式客户端
    3. 8.3. 客户端关键字段说明
  9. 9. 维护与长期可用性
    1. 9.1. 证书续签
    2. 9.2. 定期轮换
    3. 9.3. 更新 sing-box
    4. 9.4. 升级至 sing-box 1.14.0 后的调整
    5. 9.5. 常见排查
  10. 10. References

本文最后更新于 2026 年 4 月 26 日


本文以 Debian 13 为例,介绍如何搭建 sing-box 的 Hysteria2 服务端,并说明对应的客户端配置文件的格式。本文同样完全适用于 Ubuntu 24.04 及以上系统。

本方案有以下特点:

  1. 基于 QUIC(UDP)传输,配合 Brutal 拥塞控制可在高丢包环境下维持较高吞吐
  2. 需要域名,需要 TLS 证书(本文使用 ACME DNS-01 自动签发)
  3. 启用 salamander 混淆以规避按标准 QUIC Initial 提取 SNI 的审查
  4. 配合端口跳跃以缓解运营商单端口 UDP 阻断
  5. 无需 Nginx 或其他 Web 服务器,客户端与 VPS 直连

该方案适用于需要 UDP 吞吐、线路存在拥塞或 QoS 的场景。对于 UDP 环境恶劣、更重视长期隐蔽性的场景,建议考虑 AnyTLS + REALITY 方案 等基于 TCP 的方案。

注:请先参照 Debian & Ubuntu 服务器的初始化配置 一文对服务器进行各种必要的配置。本文以 sammy 用户为例,进行 sing-box 的部署,并默认已按初始化配置文章对服务器进行了配置。


背景与原理

Hysteria2 与审查现状

Hysteria2 基于 QUIC 协议。有些研究显示,自 2024 年 4 月起,已开始针对特定域名实施 QUIC SNI 审查:虽然 QUIC Initial 是加密的,但其密钥可由被动观察者派生,因此审查设备可以解密 Initial 包并提取 SNI。命中规则后,会对对应的源 IP、目的 IP、目的 UDP 端口三元组实施约 180 秒的残留丢包。

这说明标准 QUIC Initial 中的 SNI 已不能视为对被动审查者不可见。需要注意的是,公开研究主要证明的是 对 QUIC Initial/SNI 的解析与阻断机制,并不等于所有未混淆 Hysteria2 流量都会被稳定识别和封锁。

因此,本文默认启用 salamander 混淆。salamander 会使外层 UDP payload 不再呈现标准 QUIC/HTTP3 形态,从而避免被按标准 QUIC Initial 提取 SNI。但这不代表流量不可检测;它仍可能表现为随机 UDP,并受到基于流量统计、持续速率或运营商 UDP 策略的影响。

在运营商层面,中国用户长期存在持续 UDP 连接被限速或单端口阻断的反馈。Hysteria 官方文档也提到,中国用户有时会遇到 ISP 阻断或限速持续 UDP 连接,且此类限制往往只作用于当前端口。因此,本文采用高位端口配合端口跳跃,作为对单端口 UDP 限制的缓解手段。

启用 salamander 后,服务器对不知道 obfs 密码的普通探测者不再表现为有效 HTTP/3 服务,因此 masquerade 不应被视为主要伪装手段。两者不是配置项互斥,但在 salamander 模式下,masquerade 的实际作用有限。

拥塞控制选择

Hysteria2 内置两种拥塞控制模式:

BBR:主流拥塞控制算法之一,不需要用户手动声明带宽,行为通常比 Brutal 更接近常规 QUIC/TCP 拥塞响应。FOCI 2025 的实验表明 Brutal 的自定义拥塞控制更容易产生可分类的统计特征;但这并不代表 BBR 完全不可被区分,只能说相对 Brutal 指纹风险更低。配置简单,适合作为首次部署的默认选择。

Brutal:用户声明目标带宽,丢包时不降速而是补偿发送。适用于骨干网拥塞(高 RTT、高丢包)场景,前提是准确声明带宽。声明值高于实际会导致大量无效重传。Brutal 只在实际传输数据时按目标速率发包,空闲时不产生额外流量。需注意 FOCI 2025 论文已在实验室环境中证明 Brutal 的恒速率行为可与标准拥塞控制统计区分,存在指纹风险。

选择建议:首次部署、免费实例、小流量配额、弱性能节点或更重视隐蔽性的场景用 BBR;优化线路或需要吞吐的普通线路,且能准确声明带宽时,可切换为保守 Brutal。

本方案不适用的场景

  1. 运营商实施 UDP 白名单策略(仅放行可识别协议的 UDP、阻断其余所有 UDP)
  2. VPS IP 已被标记为全端口 UDP 封锁
  3. 公司、校园、酒店等 UDP 受限网络环境(应改用 TCP 方案)

准备工作

服务器

  1. 可用的公网 IP 服务器
  2. 根据防火墙位置放行 UDP 入站:本机防火墙放行 sing-box 监听端口;云平台安全组 / 网络安全组放行端口跳跃范围

域名与 DNS

  1. 将域名的 NS 记录指向 Cloudflare(若尚未托管)
  2. 在 Cloudflare 控制台为域名添加 A 记录,指向 VPS 的公网 IP。若 VPS 有 IPv6 地址,并且你也准备配置 IPv6 端口跳跃与云防火墙 IPv6 入站规则,可额外添加 AAAA 记录;否则建议暂时只添加 A 记录,避免客户端优先连接 IPv6 后因端口跳跃未配置而失败
  3. DNS 记录必须设为 DNS only(灰色云朵)。Hysteria2 客户端必须直连 VPS IP;Cloudflare 橙云代理只代理特定 HTTP/HTTPS 端口到 Cloudflare 边缘,不会将任意 UDP Hysteria2 流量转发到源站
  4. 在 Cloudflare 控制台创建 API Token,权限为 Zone → DNS → Edit,作用域限定至当前域名。

ACME DNS-01 验证过程中,sing-box 会通过该 API Token 自动创建和清理 _acme-challenge TXT 记录,无需手动操作。证书到期前也会自动续签。

安装所需基本工具

1
sudo apt update && sudo apt install curl vim wget ca-certificates -y

安装 sing-box

sing-box 官方提供了 APT 仓库,推荐优先使用此方式,便于后续升级。

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo mkdir -p /etc/apt/keyrings &&
sudo curl -fsSL https://sing-box.app/gpg.key -o /etc/apt/keyrings/sagernet.asc &&
sudo chmod a+r /etc/apt/keyrings/sagernet.asc &&
echo '
Types: deb
URIs: https://deb.sagernet.org/
Suites: *
Components: *
Enabled: yes
Signed-By: /etc/apt/keyrings/sagernet.asc
' | sudo tee /etc/apt/sources.list.d/sagernet.sources &&
sudo apt-get update &&
sudo apt-get install sing-box

验证版本:

1
sing-box version

APT 包已自带 systemd 单元,服务读取 /etc/sing-box/config.json。此时尚未编写配置文件,暂不启动服务。


生成密码

用户认证密码

1
openssl rand -base64 16

用于服务端 users[].password 与客户端 password 字段。

混淆密码

1
openssl rand -base64 32

用于服务端与客户端的 obfs.password 字段。混淆密码与用户认证密码是两个独立的凭据,不应使用相同的值。


防火墙与端口跳跃

系统防火墙

本文示例将 sing-box 实际监听端口设为 29999。该端口只作为 VPS 本机 NAT REDIRECT 后的内部目标端口,客户端不会直接连接它;外部可见的是 30000–50000 的端口跳跃范围。因此监听端口选择 29999 或其他未占用 UDP 端口,在审查和伪装层面没有区别,只需避免与现有服务冲突。

由于 iptables REDIRECT 发生在 nat 表的 PREROUTING 链,包进入 INPUT 链(UFW 在此处检查)时目标端口已被改写为 29999,因此本机 UFW 只需放行监听端口:

1
sudo ufw allow 29999/udp

若 VPS 位于云平台(如 Oracle Cloud),云防火墙(安全列表 / 网络安全组)工作在 VPS 外部、iptables 之前,必须放行整个端口跳跃范围,否则包到不了 VPS。

仅需放行 UDP。Hysteria2 全程基于 QUIC/UDP,不涉及 TCP。

端口跳跃 NAT 规则

sing-box 上的 Hysteria2 服务端只能监听单个端口。端口跳跃可通过 NAT REDIRECT 实现。

若系统使用 UFW 管理防火墙,建议将 NAT 规则写入 UFW 的 before.rules,避免引入 netfilter-persistent 与 UFW 产生规则冲突。

首先确认公网网卡名称:

1
ip route get 1.1.1.1

常见网卡名为 eth0(Vultr、搬瓦工等)或 ens3(Oracle Cloud)。以下示例以 eth0、端口跳跃范围 30000–50000、监听端口 29999 为例,按实际替换。

编辑 /etc/ufw/before.rules,在文件末尾追加以下内容(不要插入到已有的 *filter 段中):

1
sudo vim /etc/ufw/before.rules
/etc/ufw/before.rules
1
2
3
4
5
# hysteria2 port hopping
*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -i eth0 -p udp --dport 30000:50000 -j REDIRECT --to-ports 29999
COMMIT

若 VPS 有 IPv6 地址且需要 IPv6 端口跳跃,先确认内核支持 IPv6 nat 表:

1
sudo ip6tables -t nat -L

若命令正常输出(即使为空),说明支持。编辑 /etc/ufw/before6.rules,在文件末尾追加:

1
sudo vim /etc/ufw/before6.rules
/etc/ufw/before6.rules
1
2
3
4
5
# hysteria2 port hopping
*nat
:PREROUTING ACCEPT [0:0]
-A PREROUTING -i eth0 -p udp --dport 30000:50000 -j REDIRECT --to-ports 29999
COMMIT

若命令报错(如 Table does not exist),不要将 *nat 段写入 before6.rulesip6tables-restore 遇到不支持的表会导致 before6.rules 加载失败,使 IPv6 防火墙规则未按预期生效。此时只配置 IPv4 端口跳跃即可。

重载 UFW 使规则生效:

1
sudo ufw reload

NAT 规则随 UFW 一起持久化,重启后自动加载。可通过以下命令验证规则已生效:

1
sudo iptables -t nat -L PREROUTING -n

配置 sing-box

创建配置文件

1
2
sudo mkdir -p /etc/sing-box
sudo vim /etc/sing-box/config.json

以下先给出 BBR 模式的完整配置,再说明如何切换为 Brutal。

BBR 模式

不需要声明带宽,配置简单,指纹风险相对较低。适用于免费实例、小流量配额、弱性能节点或首次部署验证连通性。

注意替换其中的密码、域名、邮箱和 Cloudflare API Token。

/etc/sing-box/config.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
"log": {
"level": "warn",
"timestamp": true
},
"dns": {
"servers": [
{
"type": "https",
"tag": "local",
"server": "1.1.1.1"
}
],
"strategy": "prefer_ipv4"
},
"inbounds": [
{
"type": "hysteria2",
"tag": "hy2-in",
"listen": "::",
"listen_port": 29999,
"ignore_client_bandwidth": true,
"obfs": {
"type": "salamander",
"password": "你生成的混淆密码"
},
"users": [
{
"name": "sammy",
"password": "你生成的用户认证密码"
}
],
"tls": {
"enabled": true,
"server_name": "你的域名",
"alpn": ["h3"],
"acme": {
"domain": "你的域名",
"email": "你的邮箱",
"dns01_challenge": {
"provider": "cloudflare",
"api_token": "你的 Cloudflare API Token"
}
}
}
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct",
"domain_resolver": "local"
}
],
"route": {
"rules": [
{
"action": "sniff"
},
{
"ip_is_private": true,
"action": "reject"
},
{
"protocol": "bittorrent",
"action": "reject"
}
],
"final": "direct"
}
}

切换为 Brutal 模式

若线路存在明显拥塞(晚高峰 BBR 吞吐过低),可切换为 Brutal。将 ignore_client_bandwidth 替换为 up_mbpsdown_mbps

1
2
"up_mbps": 500,
"down_mbps": 50,

up_mbps 是服务端发送上限(对应客户端下载),down_mbps 是服务端接收上限(对应客户端上传)。建议填写实际链路带宽的 30–70%,不要高于实际可达速度。两组参数互斥,不可同时使用。

切换后客户端也需要相应增加带宽声明,参见后文客户端配置。

关键字段说明

具体参见 Hysteria2 Inbound

inbounds[].listen_port:本机监听端口。客户端不直接连接此端口,而是连接端口跳跃范围内的端口,由 NAT REDIRECT 转发至此。

inbounds[].ignore_client_bandwidth:设为 true 时令客户端使用 BBR 拥塞控制。与 up_mbps/down_mbps 互斥。

inbounds[].up_mbpsdown_mbps:服务端带宽声明,单位 Mbps。设置后客户端将使用 Brutal 拥塞控制。

inbounds[].obfs:salamander 混淆配置。启用后外层 UDP payload 不再呈现标准 QUIC 形态。

inbounds[].tls:TLS 配置。acme 配置 Let’s Encrypt 自动证书签发与续签,通过 DNS-01 验证,不依赖 80 端口。

outbounds[]:本方案作为纯代理服务端,只需一个 direct 出站。

route.rules[] 中的规则:ip_is_private 拒绝内网访问,protocol: bittorrent 拒绝 BT 流量。

配置校验

1
sudo sing-box check -c /etc/sing-box/config.json

若无输出则表示通过校验。


启动服务

1
2
3
sudo systemctl enable --now sing-box
sudo systemctl status sing-box
sudo journalctl -u sing-box --output cat -e

首次启动时 sing-box 会通过 ACME 签发证书,需要数秒至数十秒。若日志出现证书相关错误,检查 Cloudflare API Token 权限及域名 DNS 配置。


客户端配置文件

BBR 模式客户端

BBR 模式不需要设置 up_mbpsdown_mbps

注意替换其中的用户认证密码、混淆密码和域名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
{
"log": {
"level": "warn",
"timestamp": true
},
"dns": {
"servers": [
{
"type": "https",
"tag": "remote",
"server": "1.1.1.1",
"detour": "proxy"
},
{
"type": "udp",
"tag": "local",
"server": "223.5.5.5"
}
],
"rules": [
{
"rule_set": "geosite-cn",
"server": "local"
}
],
"final": "remote",
"strategy": "prefer_ipv4"
},
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"address": [
"172.19.0.1/30",
"fdfe:dcba:9876::1/126"
],
"auto_route": true,
"strict_route": true
}
],
"outbounds": [
{
"type": "hysteria2",
"tag": "proxy",
"server": "你的域名",
"server_ports": ["30000:50000"],
"hop_interval": "30s",
"obfs": {
"type": "salamander",
"password": "你生成的混淆密码"
},
"password": "你生成的用户认证密码",
"tls": {
"enabled": true,
"server_name": "你的域名"
}
},
{
"type": "direct",
"tag": "direct"
}
],
"route": {
"default_domain_resolver": "local",
"rules": [
{
"action": "sniff"
},
{
"protocol": "dns",
"action": "hijack-dns"
},
{
"ip_is_private": true,
"outbound": "direct"
},
{
"rule_set": "geosite-cn",
"outbound": "direct"
},
{
"rule_set": "geoip-cn",
"outbound": "direct"
}
],
"rule_set": [
{
"type": "remote",
"tag": "geosite-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-cn.srs",
"download_detour": "proxy"
},
{
"type": "remote",
"tag": "geoip-cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs",
"download_detour": "proxy"
}
],
"final": "proxy",
"auto_detect_interface": true
},
"experimental": {
"cache_file": {
"enabled": true
}
}
}

Brutal 模式客户端

若服务端已切换为 Brutal,客户端需要增加带宽声明。up_mbpsdown_mbps 应填写本地宽带的实际带宽。以 1000M 下行 / 50M 上行为例,up_mbps 填 40,down_mbps 填 500(保守值)。Brutal 取服务端与客户端声明值中的较小值作为目标速率。

在 BBR 配置的 outbound 基础上增加两个字段即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"type": "hysteria2",
"tag": "proxy",
"server": "你的域名",
"server_ports": ["30000:50000"],
"hop_interval": "30s",
"up_mbps": 40,
"down_mbps": 500,
"obfs": {
"type": "salamander",
"password": "你生成的混淆密码"
},
"password": "你生成的用户认证密码",
"tls": {
"enabled": true,
"server_name": "你的域名"
}
}

客户端关键字段说明

outbounds[].server_ports:端口跳跃范围,与服务端 NAT REDIRECT 规则对应。自 sing-box 1.11.0 起支持。

outbounds[].hop_interval:端口跳跃间隔。sing-box 1.13.11 仅支持固定间隔。若未来升级至 1.14.0 或以上,可加入 hop_interval_max,使实际跳跃间隔在两者之间随机选择。

outbounds[].up_mbpsdown_mbps:客户端带宽声明。仅在服务端使用 Brutal 时需要设置。up_mbps 填本地上行带宽,down_mbps 填本地下行带宽,建议使用保守值。

outbounds[].obfs:混淆配置,password 必须与服务端完全一致。


维护与长期可用性

证书续签

ACME 签发的 Let’s Encrypt 证书有效期 90 天,sing-box 运行期间自动续签,无需手动干预。

定期轮换

建议按以下周期轮换凭据:用户认证密码每 1–2 年,混淆密码每 1–2 年。

更新 sing-box

1
2
sudo apt update && sudo apt upgrade sing-box -y
sudo systemctl restart sing-box

升级前查看 sing-box Change LogMigration,确认无破坏性变更。升级后执行 sudo sing-box check -c /etc/sing-box/config.json 验证配置兼容性。

升级至 sing-box 1.14.0 后的调整

本文配置以 sing-box 1.13.11 为准。1.14.0 起部分配置项发生变更,升级后建议进行以下调整:

  1. 服务端 BBR 模式可加入 bbr_profile 字段(可选 conservativestandardaggressive),控制 BBR 的激进度
  2. 客户端可加入 hop_interval_max 字段,与 hop_interval 配合实现随机跳跃间隔,降低端口切换的规律性
  3. tls.acme 迁移为 certificate_providersdownload_detour 迁移为 http_client,路由规则中的 outbound 字段迁移为 action: "route" 格式。具体写法参见官方 Migration 文档

常见排查

  1. 完全无法连接:确认云平台安全组已放行 UDP 端口跳跃范围;确认本机 UFW 已放行 UDP 监听端口;确认 NAT 规则已生效(sudo iptables -t nat -L PREROUTING -n);确认域名 DNS 记录为 DNS only;确认客户端的 server_portspasswordobfs.password 与服务端一致
  2. 连接后数分钟断流:运营商单端口 UDP 阻断,确认端口跳跃已正确配置
  3. 所有节点同时不可用:可能是 IP 级 UDP 标记或运营商全局 UDP QoS,考虑切换至基于 TCP 的方案(如 AnyTLS + REALITY)
  4. 证书签发失败:检查 Cloudflare API Token 权限(需 Zone → DNS → Edit,签发异常时可额外添加 Zone → Zone → Read)及域名是否确实托管在 Cloudflare
  5. 怀疑本地 DNS 解析异常:可临时将客户端 server 改为 VPS 公网 IP,但 tls.server_name 仍保留为证书域名

References

sing-box

sing-box Hysteria2 Inbound

sing-box Hysteria2 Outbound

Hysteria 2 Official Documentation

Hysteria 2 Port Hopping

GFW Report: USENIX Security 2025 — QUIC Censorship

FOCI 2025: Is Custom Congestion Control a Bad Idea for Circumvention Tools?

Mastodon