Clash API节点自动切换进阶配置与工程实践
在日常使用中,我们经常会遇到只有 PC 端开启了代理,但手机、电视盒或其他移动设备也需要科学上网的情况。通过 Clash Verge Rev 的「允许局域网连接(Allow LAN)」功能,你可以轻松地将电脑的代理网络共享给同一 Wi-Fi 下的所有设备。本文将手把手带你完成从软件开关到 Windows 防火墙策略的完整配置流程。
Clash API 与 external-controller 的工作原理
Clash API 节点自动切换的核心,不是让客户端自己“猜”哪个节点更快,而是由脚本通过 external-controller 访问 Clash 内核提供的管理接口,读取当前代理状态、查询策略组成员,再根据健康检查结果发出切换指令。Clash Verge、Clash Verge Rev、Clash for Windows、ClashX 以及 Mihomo 客户端的界面虽然不同,但只要底层内核启用了 External Controller,基本都可以用同一套思路管理。
External Controller 通常监听在本机的 HTTP 接口,例如 127.0.0.1:9090。它与普通代理端口完全不同:mixed-port、http-port 和 socks-port 用来承载用户流量,而 external-controller 用来接受管理请求。脚本不能把代理端口当作 API 端口访问,否则得到的通常是连接失败、HTTP 代理响应或无法解析的内容。
API 的典型工作链路可以拆成四步。第一步,读取配置中的控制器地址和密钥;第二步,调用接口获取代理组以及当前选中的节点;第三步,针对候选节点发起延迟测试或真实连接测试;第四步,使用 PUT 请求把策略组切换到健康节点。这个流程既适合临时故障转移,也适合部署在服务器、家庭网关或定时任务中长期运行。
需要先确认的配置项
- external-controller:API 监听地址,例如
127.0.0.1:9090。 - secret:API 鉴权密钥。启用后,请求必须携带
Authorization: Bearer 密钥。 - 策略组名称:例如
PROXY、🚀 节点选择或自定义的故障转移组。 - 候选节点:策略组中实际可切换的节点名称,必须与 API 返回值完全一致。
不同内核的接口能力可能略有区别。原版 Clash、Clash Premium、Clash.Meta 和 Mihomo 在测速参数、TUN 支持、代理类型以及策略组字段上并不完全相同,因此生产脚本不要只依赖客户端界面显示名称。最稳妥的做法是先通过 API 读取实际 JSON,再根据返回字段编写逻辑,并在升级内核后重新验证。
查询代理状态与切换策略组
Clash API 常用接口并不复杂,但理解每个接口的用途很重要。查询所有代理可以使用 GET /proxies,返回内容中包含代理节点、策略组、当前选中项以及延迟信息。查询单个策略组时,可以访问 GET /proxies/{name};如果名称中包含空格、表情符号或中文,必须进行 URL 编码。
GET /version:确认控制器是否可访问,并查看内核版本。GET /proxies:获取所有代理和策略组,是自动化脚本最常用的入口。GET /proxies/{group}:读取指定策略组的候选节点及当前节点。GET /proxies/{proxy}/delay?url=...&timeout=5000:测试某个节点访问目标 URL 的延迟。PUT /proxies/{group}:向策略组发送新的节点名称,完成节点切换。GET /traffic与GET /connections:查看流量和连接信息,适合调试而不是频繁轮询。
最小化的查询请求可以这样验证。执行命令时,把地址、端口和密钥替换为自己的实际值:
curl -s \
-H "Authorization: Bearer YOUR_SECRET" \
http://127.0.0.1:9090/proxies
如果返回 JSON,说明 API 已经正常工作。接下来可以筛选策略组。假设策略组名称是 PROXY,切换到名为 节点-日本-01 的节点时,请求方法必须是 PUT,请求体是 JSON,而不是普通表单数据:
curl -X PUT \
-H "Authorization: Bearer YOUR_SECRET" \
-H "Content-Type: application/json" \
-d '{"name":"节点-日本-01"}' \
http://127.0.0.1:9090/proxies/PROXY
实际使用时,策略组名称和节点名称经常包含中文、空格或特殊符号。建议脚本使用 HTTP 客户端的 URL 编码功能,不要手动拼接路径。还要注意,PUT /proxies/{group} 只能切换支持手动选择的策略组。像 url-test、fallback 这类自动策略组,内核可能会自行选择节点,脚本更多时候应负责修改组配置、检查状态或触发测试,而不是与内核的自动决策互相覆盖。
调试建议
先调用 /version 和 /proxies,再执行切换请求。每一步都保存 HTTP 状态码和响应正文。401 通常表示密钥错误,404 多半是路径或策略组名称不正确,400 常见于节点不属于该策略组、请求体格式错误或策略组不支持手动选择。
YAML 配置与 API 安全加固
自动切换能否稳定运行,首先取决于配置文件。一个适合本机脚本控制的基础示例如下:
mixed-port: 7890
allow-lan: false
external-controller: 127.0.0.1:9090
secret: "change-this-to-a-long-random-secret"
proxy-groups:
- name: PROXY
type: select
proxies:
- 节点-日本-01
- 节点-日本-02
- DIRECT
external-controller 最好绑定到 127.0.0.1,这样只有本机进程能够访问管理接口。不要为了让手机或其他电脑调用 API,就直接写成 0.0.0.0:9090。一旦端口暴露在局域网甚至公网,任何能够连接该端口的人都可能读取节点信息、切换策略组,甚至通过其他管理接口影响客户端运行。
如果确实需要远程管理,建议使用 SSH 隧道、内网 VPN 或防火墙白名单,而不是直接开放端口。远程访问时至少应同时满足三项条件:使用足够长且随机的 secret,限制允许访问的源地址,避免在日志、代码仓库和截图中泄露完整密钥。对于运行在服务器上的 Mihomo,还应把 API 监听地址与代理监听地址分开,避免把管理权限和普通代理权限混在一起。
不要关闭鉴权
删除 secret 或使用空密钥,只适合完全隔离的临时实验环境。自动化脚本应从环境变量或权限受限的配置文件读取密钥,而不是直接硬编码在公开脚本中。若怀疑密钥泄露,应立即修改 YAML、重启内核,并检查历史日志中是否出现异常的策略切换请求。
订阅更新也可能覆盖手动编辑的配置。若机场订阅每次更新都会生成新的 YAML,建议使用客户端支持的配置覆写、Mixin 或独立的本地配置层,把 external-controller、secret 和策略组定义放在稳定的覆写文件中。修改后要重新检查最终生效配置,而不是只看原始订阅文件。对 Mihomo 用户,还应确认覆写语法与当前内核版本一致,避免因为字段名称变化导致配置加载失败。
动手实现:健康检查与自动故障转移
一个可用的自动切换脚本不能只比较一次延迟。网络抖动、目标网站限速、DNS 缓存和节点冷启动都会让单次结果失真。更可靠的策略是设置多个检查目标,连续失败达到阈值后才切换,并在切换后留出冷却时间,避免节点在两个候选项之间来回震荡。
- 通过
/proxies/{group}读取策略组当前状态,确认组存在且候选列表不为空。 - 从候选节点中排除
DIRECT、已禁用节点和脚本明确列入黑名单的节点。 - 使用一个或多个稳定的 HTTPS 地址进行测速,设置合理的超时时间,例如 3 到 8 秒。
- 记录连续失败次数,只有达到阈值后才执行切换;单次超时不要立即改变生产流量。
- 按照延迟、成功率和最近切换时间计算候选节点,优先选择近期稳定而不是单次最快的节点。
- 发送 PUT 请求切换策略组,随后再次查询策略组确认当前节点确实已经改变。
- 记录切换原因、旧节点、新节点、测试结果和时间,便于日后定位机场线路或本地网络问题。
下面是一段用于说明请求流程的 Python 示例。它没有绑定某个特定客户端界面,适合在 Linux、macOS 或 Windows 的 Python 环境中改造:
import os
import time
import requests
API = "http://127.0.0.1:9090"
GROUP = "PROXY"
TOKEN = os.environ["CLASH_SECRET"]
HEADERS = {"Authorization": f"Bearer {TOKEN}"}
TARGET = "https://www.gstatic.com/generate_204"
def get_group():
return requests.get(
f"{API}/proxies/{GROUP}",
headers=HEADERS,
timeout=5
).json()
def check(proxy):
params = {"url": TARGET, "timeout": 5000}
response = requests.get(
f"{API}/proxies/{proxy}/delay",
headers=HEADERS,
params=params,
timeout=7
)
return response.ok and response.json().get("delay", 99999)
def switch_to(proxy):
return requests.put(
f"{API}/proxies/{GROUP}",
headers={**HEADERS, "Content-Type": "application/json"},
json={"name": proxy},
timeout=5
)
group = get_group()
current = group.get("now")
candidates = [p for p in group.get("all", []) if p != "DIRECT"]
results = {p: check(p) for p in candidates}
healthy = [p for p, delay in results.items() if delay and delay < 3000]
if healthy:
best = min(healthy, key=results.get)
if best != current:
switch_to(best).raise_for_status()
time.sleep(2)
print(f"switched: {current} -> {best}")
生产环境中不要照搬“延迟最低就切换”的简单规则。首先,测速 URL 应与真实业务相关:视频、代码仓库、办公 SaaS 和普通网页的网络特征不同,单一目标不能代表所有流量。其次,连续失败阈值可以设置为 2 或 3 次,恢复阈值可以设置为连续成功 2 次。再次,切换后应设置 5 到 15 分钟冷却期,避免某个目标短暂抖动时反复切换。
建议的生产参数
- 检查周期:桌面端可设为 60 秒,家庭网关可根据 CPU 和节点数量设为 2 至 5 分钟。
- 单次超时:通常设置为 3 至 8 秒,过短容易把正常抖动判断为故障。
- 失败阈值:连续 2 至 3 次失败后切换,避免一次丢包造成误判。
- 冷却时间:切换后暂缓再次切换,给新节点完成连接建立和 DNS 缓存预热。
- 回切策略:不要只因为原节点恢复一次就回切,应要求它连续稳定,并且质量明显优于当前节点。
如果策略组本身是 fallback 或 url-test,可以优先利用内核提供的自动健康检查能力,减少外部脚本的职责。外部脚本更适合处理跨组联动、异常通知、黑名单维护和业务级探测。例如,一个节点的网页延迟很低,但无法连接企业 API,此时脚本可以把它加入临时黑名单,并通知管理员检查线路,而不是让内核单纯根据 TCP 延迟做决定。
监控、日志与常见故障排查
自动化的难点通常不在发出切换请求,而在于判断“切换是否真的解决了问题”。建议至少记录以下字段:检测时间、策略组、当前节点、候选节点、测试目标、HTTP 状态、延迟、失败原因、切换结果以及冷却状态。日志中不要打印完整订阅 URL、API 密钥或带有认证参数的地址。
可以先用命令行确认三层状态。第一层是端口层,用 curl http://127.0.0.1:9090/version 检查控制器是否监听;第二层是鉴权层,加入 Bearer 请求头确认返回不是 401;第三层是业务层,通过代理端口访问实际网站,判断节点切换后流量是否真的按照预期转发。只验证 API 返回成功并不够,因为策略组改变了不代表已有连接会立即迁移,部分长连接仍会继续使用旧出口。
- API 连接拒绝:检查 Clash 是否运行、端口是否被修改,以及控制器是否绑定到了其他地址。
- 返回 401:检查密钥是否包含多余空格、引号或换行,确认请求头格式为
Bearer token。 - 策略组找不到:不要凭界面猜名称,先读取
/proxies返回的键名,并进行 URL 编码。 - 切换成功但网页仍失败:检查 DNS、规则匹配、已有连接、TUN 路由以及目标站点本身是否可用。
- 节点频繁来回切换:提高失败阈值,增加冷却时间,使用成功率和历史数据,而不是只比较瞬时延迟。
定时任务也要考虑进程并发。如果上一次检查尚未完成,下一次任务又启动,两个脚本可能同时切换同一个策略组。可以使用文件锁、系统服务的单实例机制或 Redis 分布式锁避免竞态。对于 Linux,可将脚本作为 systemd service 配合 timer 运行;Windows 则可以使用任务计划程序,并设置“如果任务已在运行,则不要启动新实例”。
常见问题
Clash Verge 和 Mihomo 的 API 地址一样吗?
不一定。它们可能使用不同的默认端口,也可能在客户端设置中被用户修改。不要假定一定是 127.0.0.1:9090,应以当前配置文件或客户端的外部控制器设置为准。只要接口路径和返回字段兼容,脚本通常可以复用。
可以不设置 secret 吗?
不建议。即使 API 只监听本机,也可能被本机其他用户、恶意软件或错误的端口转发访问。实验时可以短暂省略,但正式使用应启用随机密钥,并限制配置文件和环境变量的读取权限。
切换节点后,已有连接会自动换线路吗?
不一定。新建连接通常会使用新的策略组节点,但已经建立的 TCP、WebSocket 或长连接可能继续维持原来的出口。若业务必须立即迁移,需要在客户端或 API 中谨慎处理连接关闭,同时评估对下载、视频播放和在线会议的影响。
为什么测速结果很好,实际访问仍然不稳定?
延迟测试只能说明某个节点访问某个目标的首包表现,不能代表视频、上传、长连接或所有地区线路。应结合多个测试目标、实际业务探测、失败率和一段时间内的历史数据综合判断。
让自动化配置建立在稳定的客户端之上
一些仅提供基础代理开关的工具,往往缺少清晰的策略组结构、稳定的管理接口或可追踪的日志;当节点故障时,用户只能手动打开界面逐个尝试,脚本也难以判断切换是否成功。不同平台的配置格式和 API 行为如果差异过大,还会增加维护成本。
Clash 更适合需要工程化管理的场景:它通过 YAML 明确描述代理、策略组和规则,external-controller 提供标准化管理入口,日志与连接面板便于验证结果,Clash Verge、Mihomo 等客户端也能为桌面和服务器环境提供相对一致的操作体验。若你希望在掌握节点自动切换的同时保留可视化配置、规则分流与多平台支持,可以从稳定版本开始配置。
前往下载 Clash,选择适合你设备的客户端并开始实践。