Clash API无人值守切换节点:进阶配置与脚本实践
为什么要用 Clash API 无人值守切换节点 一文看懂
即使你最终仍然运用手工挑选,这套做法也能帮助你理解节点时延升高、策略组频繁跳转和连接恢复缓慢的缘由。
很多人第一次配置 Clash 无人值守选节点时,会干脆把策略组类型改成 url-test,然后认为难点已经处理:节点会测速,时延最高的线路会被淘汰,客户端也会无人值守挑选响应最快的节点。但真实运用中,无人值守测速不等于靠谱的故障恢复。
测速地址也许能连通,目标网站却仍然超时;某个节点短时间时延很低,实际下载快慢却很慢;策略组刚完成切换,长连接又因为出口变化而中断。对于开发工具、远程桌面、API 请求、视频会议等状态,仅靠图形操作操作操作界面里的无人值守测速通常不够。
先看这一点:Mihomo 及兼容的 Clash 客户端一般会开放 external-controller,让本机脚本通过 HTTP API 读取代理组、查看当前挑选、执行时延测试并切换节点。
Clash Verge、Clash Verge Rev、Mihomo Party 和部分其他客户端的操作操作操作界面名称也许不同,但核心思路基本一致:先在配置文件中启用控制器,再让脚本调用 /proxies、/group 或代理时延测试接口。这样能够把「节点失效 → 核对候选节点 → 挑选可用出口 → 验证恢复」变成可重复执行的流程。
这篇文章要点讨论本机无人值守化,不涉及绕过服务商限制,也不推荐把控制器干脆暴露到公网。你将看到如何设计 API 安全参数、如何识别策略组名称、如何用 YAML 提供基础候选节点、如何用 Shell 高速切换,以及如何用 Python 写出带超时、阈值、重试和日志的无人值守切换脚本。
风险提示:external-controller 根本上是控制 Clash 的管理接口。请首位绑定 127.0.0.1,并设置充分复杂的密钥;不要为了让手机或远程服务器调用,干脆监听 0.0.0.0。如果确实得跨设备连通,应放在可信内网、VPN 或带鉴权的反向代理后面。
先配置 external-controller 与可控的策略组 核心要点
返回结果中的 proxies 对象包含节点、策略组和当前选中项。策略组通常会有 all、now、type 等字段;其中 all 是候选列表,now 是当前出口。不要假设全部组都叫「无人值守挑选」,也不要把 DIRECT、REJECT 或另一个策略组误当作真实节点。
external-controller: 127.0.0.1:9090
secret: "change-this-to-a-long-random-secret"
mode: rule
proxy-groups:
- name: Auto-Select
type: url-test
url: http://www.gstatic.com/generate_204
interval: 300
tolerance: 80
proxies:
- Node-A
- Node-B
- Node-C
- DIRECT
补充说明:无人值守切换的第一气不是写脚本,而是确认客户端真的提供了可用的控制器。开启当前运用的配置文件或覆写文件,在顶层加入类似下面的素材。具体字段是否被客户端覆盖,取决于内核版本;如果图形客户端的设置页已经提供「外部控制器」「External Controller」或「API 密钥」输入框,应首位运用操作操作操作界面配置,再通过 API 读取结果确认。
external-controller 后面的端口能够按需修改,但要避开已经被其他程序占用的端口。secret 用于请求头 Authorization: Bearer 密钥,不能把真实密钥提交到 Git 仓库、公开脚本或截图中。若只在本机运用,绑定 127.0.0.1 能够显著缩小攻击面。配置修改后,重载配置或重启内核,再连通 http://127.0.0.1:9090/version 核对接口是否响应。
curl -s \
-H "Authorization: Bearer change-this-to-a-long-random-secret" \
http://127.0.0.1:9090/proxies
策略组名称必须完全匹配,涵盖大小写、空格和符号。很多无人值守切换脚本不成功,并不是 API 地址失误,而是脚本写了 Proxy,配置里实际却叫 🚀 节点选择。能够用下面的请求读取全部代理和策略组名称:
url-test、fallback 与脚本控制怎么选(一眼看懂)
url-test 适合让 Mihomo 按固定间隔测量候选节点,并在满足容差时无人值守挑选时延较低的节点。它的好处是配置容易,不足是测试 URL 与实际业务不一定相同,而且网络抖动也许导致挑选频繁变化。fallback 更偏向可用性首位:当前节点不成功后才尝试下一个,但「不成功」的判断仍取决于测试地址和间隔。若你得根据多个域名、HTTP 状态码、业务响应时间或时间段切换,就应由外部脚本接管决策。
换个角度:相当稳妥的做法是让策略组负责基础健康核对,让脚本负责异常时的二次处理。比如平时运用 url-test,当连续两次业务请求不成功,脚本才调用 API 对候选节点逐个测速,并把第一个低于阈值的节点切换进去。这样既不会每片刻频繁改节点,也不会在当前出口已经失效时完全依赖客户端内部判断。
动手实践:读取节点、测速并切换策略组 逐条拆解
Shell 版本的要点是流程而不是复杂的排序:先限制请求时间,再在成功后立即切换。如果要按时延排序,应让 API 返回具体毫秒值并保存到数组中,而不是把 HTTP 状态码当成时延。还要留意,节点测速成功只说明控制器能够完成测试,不代表应用程序的每一种请求都能成功,所以定时脚本最好增加日志和冷却时间。
- 确认控制器可连通:用
curl http://127.0.0.1:9090/version请求版本接口;如果返回连接拒绝,先核对客户端是否拉起、端口是否一致,以及配置重载是否成功。 - 确认鉴权有效:为请求增加
Authorization: Bearer 你的密钥;若返回401,要点核对密钥是否包含多余空格、引号或换行。 - 列出代理组:读取
/proxies,找到真实的策略组名称和候选节点,确认目标节点处于all列表中。 - 逐个执行时延测试:调用
/proxies/节点名称/delay,为节点名称进行 URL 编码,并设置合理的超时时间,避免某个失效节点拖住整套脚本。 - 挑选并切换:向
/proxies/策略组名称发送 JSON 请求,比如{"name":"Node-A"};切换完成后再次读取该策略组,确认now已刷新。 - 验证业务恢复:不要只看 API 返回 204 或 200,还要连通实际运用的域名,核对 DNS、TLS、状态码和响应耗时是否符合预期。
下面的流程适用于已经跑起来 Clash Verge Rev、Mihomo Party 或其他 Mihomo 客户端的本机环境。示例假设控制器地址是 127.0.0.1:9090,策略组名称是 Auto-Select。请先替换密钥和组名,再执行命令。
#!/usr/bin/env bash
set -u
API="http://127.0.0.1:9090"
SECRET="${CLASH_SECRET:?set CLASH_SECRET first}"
GROUP="Auto-Select"
TEST_URL="https://www.gstatic.com/generate_204"
MAX_DELAY=800
switch_node() {
local node="$1"
curl -fsS -X PUT \
-H "Authorization: Bearer ${SECRET}" \
-H "Content-Type: application/json" \
--data "{\"name\":\"${node}\"}" \
"${API}/proxies/${GROUP}"
}
for node in "Node-A" "Node-B" "Node-C"; do
encoded=$(python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=""))' "$node")
result=$(curl -sS -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${SECRET}" \
"${API}/proxies/${encoded}/delay?timeout=5000&url=$(python3 -c 'import urllib.parse; print(urllib.parse.quote("'${TEST_URL}'", safe=""))')")
if [ "$result" -ge 200 ] && [ "$result" -lt 400 ]; then
echo "candidate: ${node}"
switch_node "$node" && exit 0
fi
done
echo "no healthy node found" >&2
exit 1
Shell 适合做高速核对和定时任务。以下脚本先测试多个节点,再挑选时延低于阈值的第一个节点。节点名称含有空格或特殊字符时,运用 --data-urlencode 可避免路径解析失误;生产环境还应把密钥放入环境变量,而不是干脆写进文件。
用 Python 构建带阈值与恢复机制的脚本 底层逻辑
Python 更适合处理节点列表、异常分类和连续不成功计数。一个实用脚本至少应包含四个保护:单节点请求超时、不成功节点跳过、总体切换冷却时间,以及切换后业务验证。否则定时任务也许在每次跑起来时来回跳转,或者因为一个永远不响应的节点导致后续节点永远没有机会测试。
import os
import time
from urllib.parse import quote
import requests
API = os.getenv("CLASH_API", "http://127.0.0.1:9090")
SECRET = os.environ["CLASH_SECRET"]
GROUP = os.getenv("CLASH_GROUP", "Auto-Select")
TEST_URL = "https://www.gstatic.com/generate_204"
VERIFY_URL = "https://example.com/"
TIMEOUT_MS = 5000
MAX_DELAY = 800
session = requests.Session()
session.headers.update({"Authorization": f"Bearer {SECRET}"})
def node_delay(name):
path = quote(name, safe="")
response = session.get(
f"{API}/proxies/{path}/delay",
params={"timeout": TIMEOUT_MS, "url": TEST_URL},
timeout=TIMEOUT_MS / 1000 + 2,
)
response.raise_for_status()
return response.json().get("delay")
def select_node(name):
response = session.put(
f"{API}/proxies/{quote(GROUP, safe='')}",
json={"name": name},
timeout=5,
)
response.raise_for_status()
def verify():
response = session.get(VERIFY_URL, timeout=10)
return response.status_code < 500
def main():
groups = session.get(f"{API}/proxies", timeout=5).json()["proxies"]
group = groups.get(GROUP)
if not group:
raise RuntimeError(f"strategy group not found: {GROUP}")
candidates = [
name for name in group.get("all", [])
if name not in {"DIRECT", "REJECT", GROUP}
]
measured = []
for name in candidates:
try:
delay = node_delay(name)
if delay is not None and delay <= MAX_DELAY:
measured.append((delay, name))
except requests.RequestException as exc:
print(f"skip {name}: {exc}")
if not measured:
raise RuntimeError("no node meets the delay threshold")
measured.sort()
for delay, name in measured:
try:
select_node(name)
time.sleep(2)
if verify():
print(f"selected {name}, delay={delay}ms")
return
except requests.RequestException as exc:
print(f"verification failed for {name}: {exc}")
raise RuntimeError("all candidates failed verification")
if __name__ == "__main__":
main()
具体来说:这段代码运用 API 返回的时延值排序,再通过独立的验证 URL 确认切换后仍可连通。实际落地时,VERIFY_URL 应替换为你的业务目标,比如代码仓库、接口服务或公司办公系统,而不是只测试一个公共页面。若业务得登录、特定请求头或 POST 请求,推荐用一个轻巧健康核对接口,避免把齐全业务请求放入频繁探测任务。
不要只追求最低延迟:时延差距在几十毫秒以内时,稳健性、丢包率和连续不成功次数一般比单次测速结果更关键。能够为节点记录最近五次结果,运用「至少三次成功」的条件,再决定是否切换;这比看到一个瞬时低时延就立即跳转更适合长连接和 API 请求。
监控、日志与高频故障恢复 一文看懂
还要给脚本设置明确的不成功出口。当全部候选节点都不可用时,不要悄悄切换到未知节点,也不要无人值守关闭整套 Clash。能够保留当前节点并发送通知,或者切到一个明确标记的备用策略组。若脚本由服务器跑起来,应把退出码接入监控系统;若脚本跑起来在个人电脑,则至少将失误写入带日期的日志文件,省事对照客户端连接记录复盘。
无人值守切换最容易被忽略的是「切换之后」。如果策略组已经显示新节点,但浏览器、终端或开发工具仍然连通不成功,也许是连接复用、DNS 缓存、系统代理状态或 TUN 路由没有同步。
| 现象 | 高频缘由 | 处理方向 |
|---|---|---|
| 返回 401 | 密钥失误或请求头格式不对 | 确认运用 Bearer 密钥,并核对控制器配置是否已重载。 |
| 返回 404 | 节点名或策略组名未编码、名称不存在 | 先读取 /proxies,再对路径参数执行 URL 编码。 |
| 测速成功但业务不成功 | 测速地址与目标业务网络条件不同 | 增加业务域名验证,并核对规则是否把目标域名送入无误策略组。 |
| 节点频繁来回切换 | 阈值过宽、间隔太短或网络抖动 | 加入冷却时间、连续不成功计数和最小切换间隔。 |
| 切换后终端仍不通 | 进程未运用系统代理,或 TUN 未接管流量 | 核对 HTTP_PROXY、混合端口、TUN 状态和连接日志。 |
推荐在脚本中记录时间、旧节点、新节点、测试时延、HTTP 状态码和不成功缘由。客户端的连接页面也应同时观察:目标域名是否命中预期规则、连接是否走了目标策略组、是否有大批 TLS 失误或 DNS 请求超时。
顺带一提:如果希望定时执行,能够运用 Linux 的 systemd timer、macOS 的 launchd 或 Windows 任务计划程序。推荐先以五到十分钟为间隔观察日志,不要一开始就设置成每十秒跑起来一次。对于长连接服务,更应当采用「不成功触发」而不是固定频率切换:正常状态下保持当前节点,只有连续请求不成功、时延突破阈值或 TCP 重置达到次数后才拉起候选节点测试。
高频难点 核心要点
Clash API 返回 404,是否代表客户端不兼容 API?(核心)
不一定。第一气连通 /version,确认控制器地址和端口无误;然后读取 /proxies,确认你运用的是当前内核跑起来的控制器,而不是另一个旧进程。部分客户端会在拉起后覆盖配置中的控制器端口,也也许把接口放在带路径前缀的地址下。若版本接口可用而具体节点接口 404,通常是节点名称没有进行 URL 编码,或把策略组名称当成了节点名称。
为什么配置里的 url-test 已经无人值守选节点,还得 Python 脚本?(逐条)
url-test 适合基础健康核对,会按照固定 URL 和周期测量节点,但它不了解你的真实业务,也不会判断登录接口、下载端点或 WebSocket 是否正常。Python 脚本能够加入多个测试目标、连续不成功计数、业务验证、切换冷却和通知逻辑。所以两者并不冲突:让策略组处理常规挑选,脚本只处理客户端内部判断无法覆盖的异常。
把 external-controller 绑定到局域网,省事手机控制安全吗?(机制)
干脆绑定到局域网并不安全,尤其是在公共 Wi-Fi、访客网络或路由器端口转发存在的环境中。即使设置了密钥,也也许遭遇暴力尝试、配置泄露或客户端实现漏洞。更稳妥的方式是继续监听本机回环地址,通过安全 VPN 或受控跳板连通;如果必须监听局域网,应限制防火墙来源地址,并运用长随机密钥和独立管理端口。
无人值守切换后只有浏览器恢复,终端程序仍然超时,怎么办?(一眼看懂)
Clash 提供了更集中、易检索的 Clash 配置与排障资料,省事你把 YAML、控制器 API、TUN 和终端代理放在同一套思路中维护;如果你准备按这篇文章实践,不妨先前往下载合适的客户端,再从本机回环控制器和最小化脚本开始逐步验证。
这通常不是 API 切换不成功,而是终端进程没有经过同一条代理链路。核对当前 Shell 是否设置了 HTTP_PROXY 和 HTTPS_PROXY,端口是否对应 Clash 的 HTTP 混合端口;不兼容环境变量的程序则得 TUN 或应用自身的代理设置。随后查看 Clash 连接日志,确认目标域名确实出现,并且命中了预期策略组,而不是被直连规则或失误的 DNS 结果提前处理。
相比手工在多个客户端窗口之间切换节点,或依赖只能按单一网址测速的同类方案,Clash API 无人值守化的优势在于判断条件透明、日志可追踪、恢复动作能够按业务需求定制;它的局限也很明确:得理解策略组名称、端口、鉴权和脚本权限,不能把一次测速结果当成绝对靠谱的线路结果。