开启 3 天免费试用
注册即可免费体验全部高级功能。
*仅限新用户;每位用户只能获得一次试用。


sing-box 故障转移依靠 urltest 出站:它探测每个出口,把新连接交给当前最好的健康出口;Mihomo 则提供 fallback 代理组,始终优先使用列表中第一个可用的出口。本文为两台你自己的出口分别配置这两种方式,再说明如何测量切换时间、恢复后的表现,以及已有连接、DNS 和 UDP 会受到什么影响。
关键要点
- 故障转移只让一个出口工作,检查失败时换到另一个;它不会增加带宽。
- sing-box 的
urltest按测得的延迟和容差选择,不按列表顺序。- Mihomo 的
fallback按顺序选第一个可用代理,首选出口恢复后会切回去。- 切换大约需要一个探测间隔加超时时间,应当实测而不是假设。
- HTTP 健康检查通过时,同一出口的 UDP 仍可能已经坏掉。
本文依据文末官方来源整理,未完成完整端到端实测。前提是 Linux 客户端运行 sing-box 1.14.3 或 Mihomo v1.19.32,并有两个你管理或已获授权使用的可用代理出口。先用自建清单规划归属和恢复方式。
故障转移让流量固定走一个出口,只有它连续检查失败时才换出口。负载均衡把连接同时分散到多个出口,链路聚合则把多条线路合起来承载同一个流。链路聚合、负载分担与故障转移的对比解释了为什么只有聚合能提高单个连接的吞吐量。
| 工具与类型 | 如何选择出口 | 首选出口恢复后 |
|---|---|---|
sing-box urltest | 测得延迟最低者,用容差避免来回切换 | 只有恢复的出口快出容差以上才切回 |
sing-box selector | 手动选择,通过 Clash API 控制 | 停在你设定的出口 |
Mihomo fallback | 按列表顺序选第一个可用代理 | 第一个代理重新通过检查后切回 |
Mihomo url-test | 测得延迟最低者,带容差 | 与 sing-box urltest 相同 |
sing-box 的 urltest 出站用一个 URL 测试一组出站,默认每 3m 一次,容差 50 毫秒。[1] 它的 selector 出站只能通过 Clash API 切换。[2] Mihomo 的 fallback 组在当前节点超时后,按 proxies 的顺序选择第一个可用节点。[3] 维护两个出口意味着维护工作翻倍,如果你的目标只是不断线,先权衡自建服务器与托管 VPN。
你需要两个相互独立的出口,这里用两台 Shadowsocks 2022 服务器:203.0.113.10(出口 A)和 198.51.100.20(出口 B),各自使用独立密钥。它们应放在不同机房或不同服务商,否则一次故障会让两者同时失效。分组之前,先确认每个出口单独都能用。
两种工具都会经每个出口请求一个 URL。url 留空时,sing-box 会使用 Google 的 generate_204 地址。[1] 请改用你自己控制的端点,例如 https://check.example.net/generate_204,再加一个返回访问者地址的路径,例如 /ip。从多个出口每分钟探测第三方服务,应遵守该服务的条款;自己的端点还会留下日志,能确认每次探测来自哪个出口。
如果还没有安装 sing-box,sing-box Linux 客户端教程介绍了如何安装固定版本并运行本地监听。把下面内容保存为私有文件 failover.json:
{
"log": {"level": "warn"},
"inbounds": [{"type": "mixed", "tag": "local", "listen": "127.0.0.1", "listen_port": 1084}],
"outbounds": [
{
"type": "urltest",
"tag": "auto-exit",
"outbounds": ["exit-a", "exit-b"],
"url": "https://check.example.net/generate_204",
"interval": "1m",
"tolerance": 300,
"interrupt_exist_connections": true
},
{"type": "shadowsocks", "tag": "exit-a", "server": "203.0.113.10", "server_port": 8388,
"method": "2022-blake3-aes-128-gcm", "password": "REPLACE_KEY_A"},
{"type": "shadowsocks", "tag": "exit-b", "server": "198.51.100.20", "server_port": 8388,
"method": "2022-blake3-aes-128-gcm", "password": "REPLACE_KEY_B"}
],
"route": {"final": "auto-exit"}
}
interval 越短,越早发现故障,代价是探测次数增多。在 sing-box urltest 配置中,较大的 tolerance 能避免在两个延迟相近的健康出口之间来回切换,这对不喜欢地址变化的会话很重要。interrupt_exist_connections 会在所选出站变化时关闭入站连接,内部连接则总会被中断。[1] 如果你宁愿让旧连接自然失败,就保持 false。
用固定版本的可执行文件运行 sing-box check -c failover.json 检查。检查通过只说明语法正确,不代表任一出口可用。
使用 Mihomo 时,在单独目录里保存一个私有的 config.yaml:
mixed-port: 7891
allow-lan: false
bind-address: 127.0.0.1
mode: rule
log-level: warning
external-controller: 127.0.0.1:9090
secret: "REPLACE_LONG_RANDOM_SECRET"
proxies:
- {name: exit-a, type: ss, server: 203.0.113.10, port: 8388, cipher: 2022-blake3-aes-128-gcm, password: "REPLACE_KEY_A", udp: true}
- {name: exit-b, type: ss, server: 198.51.100.20, port: 8388, cipher: 2022-blake3-aes-128-gcm, password: "REPLACE_KEY_B", udp: true}
proxy-groups:
- name: failover
type: fallback
proxies: [exit-a, exit-b]
url: https://check.example.net/generate_204
interval: 60
timeout: 5000
lazy: false
rules:
- MATCH,failover
Mihomo fallback 代理组只检查自己 proxies 字段里的代理;interval 以秒为单位,timeout 以毫秒为单位,lazy 默认为 true,未被选用的组不做测试。[4] 设为 lazy: false 后,组在空闲时也保持测试,流量开始时已经有最新结果。max-failed-times(默认 5)在连续失败后触发一次强制健康检查。[4] 2022 加密方式的名称来自 Mihomo 的 Shadowsocks 参考文档。[5]
保持 allow-lan: false 和 bind-address: 127.0.0.1,其它设备就无法使用这个端口。[6] 控制器可以读取组的状态,请按保护 Mihomo 控制器 API 中的方法加以保护。
每次只在前台运行一种工具,让测试终端使用它的本地端口(sing-box 为 1084,Mihomo 为 7891)。Mihomo 可以通过 API 读取组当前的选择,API 接受 Bearer 密钥:[7]
curl -s -H "Authorization: Bearer $MIHOMO_SECRET" http://127.0.0.1:9090/proxies/failover
返回结果会写明组当前使用的代理。sing-box 则把 /ip 端点返回的地址与每个出口已知的出口地址对比。在设置了同一本地端口的浏览器中,IP 地址检测工具应显示出口 A 或出口 B,而绝不是你自己的网络。
经本地端口运行一个带时间戳的探测循环,然后在维护窗口内停止出口 A 上的代理服务。不要停掉其他人依赖的共享服务器。
while true; do
printf '%s ' "$(date +%T)"
curl -s -m 5 --proxy socks5h://127.0.0.1:1084 https://check.example.net/ip || printf 'FAIL'
echo; sleep 2
done
| 检查方法 | 预期现象 | 不符时的处理 |
|---|---|---|
| 两个出口都正常 | 循环稳定显示同一个出口地址 | 地址在两个出口间来回变:调大 sing-box 容差 |
| 停止出口 A 的代理服务 | 先出现 FAIL,约一个间隔加超时后变成出口 B 的地址 | 组一直不切换:确认经出口 B 能访问探测 URL |
恢复出口 A,Mihomo fallback | 下一次检查成功后切回出口 A | 停在 B:检查列表顺序和 lazy: false |
恢复出口 A,sing-box urltest | 除非 A 快出容差以上,否则停在 B | 频繁切换:容差相对延迟差太小 |
| 两个出口都停止 | 所有请求失败 | 请求仍成功:流量绕过了这个组 |
记录从停止出口 A 到第一次经出口 B 成功的时间。这段间隔才是真实的切换延迟,而不是配置里的间隔值。多重复几次,因为探测计时器与你停止服务的时刻并不同步。
已打开的 TCP 连接留在它最初使用的出口上。出口失效时它们会断开;sing-box 开启 interrupt_exist_connections 时会提前关闭。两种情况下应用都必须重新连接。新连接则使用组在那一刻选中的出口。
健康检查是 HTTP 请求,只经每个出口检验了 TCP。一个出口可能检查通过,但 UDP 转发被封或已损坏,这时基于 UDP 的应用会失败,却不会触发切换。请分别经每个出口测试 UDP 业务;在 Mihomo 中,如果宁可阻断 UDP 也不愿走不可靠路径,可以使用组的 disable-udp 选项。[4]
DNS 行为取决于模式。在 FakeIP 模式下,客户端给应用分配合成地址,真正的解析稍后经所选出口完成;FakeIP 与 redir-host 的对比解释了为什么切换后可能留下看似过期的缓存映射。切换后某个网站一直打不开时,清除应用缓存或重启应用。
保留每个出口单独的配置。回退时停止故障转移客户端,恢复应用原来的代理设置,再经单个出口发一次新请求确认。按你的计划删除测试端点的探测日志,并更换测试期间粘贴进共享终端的任何密钥。
urltest,想要固定的优先顺序就用 Mihomo fallback。文档中的 urltest 出站按测得延迟和容差选择,而不是按列表顺序。需要固定优先顺序时,请使用 Mihomo 的 fallback 组,或者手动切换 selector。
预计最多约一个测试间隔加上探测本身的时间,具体取决于故障发生在哪个时刻。请用带时间戳的循环实测,不要只相信配置里的数值。
通常不能。已有连接会留在失效的出口上或被关闭,应用必须经新出口重新连接,才能继续原来的会话,中间的中断无法完全避免。
因为检查是基于 TCP 的 HTTP 请求。它只证明经该出口的 TCP 转发正常,不能证明 UDP 转发或 QUIC 流量被允许通过。
可以用,但自己的端点能避免依赖别人的服务及其条款,而且它的日志会显示每次探测来自哪个出口,排查时更直接。
取决于你的目标。负载均衡把连接分散到多个出口,但不能加快单个流,还可能让期望固定地址的服务感到困惑,增加排查难度。
fallback 类型始终优先使用列表中第一个可用代理。第一个出口一旦重新通过健康检查,新连接就会回到它上面,已有连接则不受影响。
免责声明: 本文仅供一般信息参考,不构成法律、技术或其他专业建议。我们不保证内容的准确性、完整性或时效性。
来源:
Sources checked 2026 年 10 月 14 日。
延伸阅读:
注册即可免费体验全部高级功能。
*仅限新用户;每位用户只能获得一次试用。