使用教程 精选 Clash 入门 VPN 区别 新手指南

Clash API自动切换节点:外部控制器进阶配置指南

2026年9月15日 更新于 2026年9月15日 约 12 分钟阅读

前言:让节点切换从手动变成自动

在日常使用 Clash 或 Mihomo 时,节点质量会随着时间、线路拥塞和出口服务状态不断变化。早上延迟只有 80ms 的节点,到了晚上可能已经丢包严重;某个地区的服务器也可能临时维护,导致网页加载缓慢、视频缓冲或连接直接中断。单纯依靠客户端界面手动切换,既耗时,也很难在故障发生时及时处理。

外部控制器(External Controller)提供了一种更灵活的管理方式。Clash 内核会在本机监听一个 HTTP API,外部脚本、监控程序或自定义面板可以通过 API 查询代理组、测试节点延迟、切换当前代理,并根据检测结果执行故障转移。本文以 Mihomo 兼容的 Clash 配置为例,构建一个实用的自动化方案:先安全开启 API,再读取代理组和节点状态,最后使用 Shell 与 Python 完成延迟检测、自动选优和定时切换。

适用场景

适合已经能够正常运行 Clash Verge、Clash Verge Rev、Clash for Windows 或 Mihomo,并希望进行脚本化管理的用户。本文示例默认 API 运行在本机,不建议直接暴露到公网。

1开启外部控制器并做好认证

外部控制器的核心配置通常位于 YAML 文件的顶层。最关键的两个字段是 external-controllersecret。前者决定 API 的监听地址和端口,后者用于 Bearer Token 认证。推荐只监听 127.0.0.1,这样只有当前电脑上的程序可以访问 API,局域网中的其他设备无法直接控制你的 Clash。

external-controller: 127.0.0.1:9090 secret: "change-this-to-a-long-random-token"

修改配置后,需要在客户端中重新载入配置或重启内核。不同 GUI 的菜单名称可能略有区别,但一般可以在“设置”“内核设置”“配置文件”或“覆写”区域找到外部控制器选项。如果客户端已经自动生成了 external-controller,请不要同时配置两个监听端口,否则脚本可能连到了错误的实例。

先验证认证和连通性

API 请求需要把密钥放在 Authorization 请求头中,格式为 Bearer 密钥。可以先请求版本接口,确认端口、密钥和内核都正常:

curl -s \ -H "Authorization: Bearer change-this-to-a-long-random-token" \ http://127.0.0.1:9090/version

如果返回包含 versionmeta 或类似字段的 JSON,说明连接成功。若出现 401 Unauthorized,通常是密钥不一致、Bearer 拼写错误,或者客户端保存的配置并不是当前正在运行的配置。若出现连接被拒绝,则应检查内核是否启动、端口是否被其他程序占用,以及是否误写成了 127.0.0.1:9090/ 这类带路径的地址。

不要暴露管理接口

外部控制器不仅可以查看节点,还可以切换代理、修改运行状态,部分内核还提供配置和连接管理接口。除非你非常清楚防火墙、TLS 和访问控制的配置,否则不要监听在 0.0.0.0,也不要把带有密钥的 API 地址发布到网页或公共代码仓库。

2代理组接口:读取状态、测试延迟与切换节点

自动切换并不是直接对所有节点进行随机选择,而是围绕一个代理组完成。常见的代理组类型包括手动选择组、url-test 自动测速组、故障转移组和负载均衡组。外部脚本最容易控制的是手动选择组:脚本读取该组的成员,逐一测试延迟,然后向组接口发送新的当前代理名称。

读取代理组与当前节点

请求 /proxies 可以获得当前内核识别到的所有代理和代理组。为了只查看指定的策略组,可以使用 URL 编码后的组名访问,例如组名为 Proxy

curl -s \ -H "Authorization: Bearer change-this-to-a-long-random-token" \ http://127.0.0.1:9090/proxies/Proxy

返回结果中的 now 表示当前选中的节点,all 通常表示该策略组可选择的成员。不同内核版本返回字段可能略有差异,因此脚本不要假定每个成员都是物理节点;一个代理组也可能嵌套在另一个代理组中。建议先过滤出名称位于目标节点集合中的项目,再执行延迟测试。

调用延迟测试接口

延迟测试接口一般采用以下形式,其中 NAME 是节点名称,url 是测试地址,timeout 是超时时间:

curl -G -s \ -H "Authorization: Bearer change-this-to-a-long-random-token" \ --data-urlencode "url=https://www.gstatic.com/generate_204" \ --data-urlencode "timeout=5000" \ "http://127.0.0.1:9090/proxies/日本节点/delay"

成功时通常会返回类似 {"delay":123} 的 JSON。需要注意,延迟值只反映一次 HTTP 测试,并不等于真实下载速度、视频稳定性或所有网站的访问质量。测试地址应选择响应稳定、体积很小的目标;如果目标本身被网络环境拦截,所有节点都会得到超时结果,脚本就会错误地认为线路全部失效。

切换策略组当前节点

完成选择后,使用 PUT 请求向代理组接口提交 JSON。下面的示例把 Proxy 组切换到名为 日本节点 的成员:

curl -s -X PUT \ -H "Authorization: Bearer change-this-to-a-long-random-token" \ -H "Content-Type: application/json" \ -d '{"name":"日本节点"}' \ http://127.0.0.1:9090/proxies/Proxy

节点名称必须与 API 返回的名称完全一致,包括空格、地区标记和特殊符号。切换后可以再次请求 /proxies/Proxy,确认 now 已经改变。部分客户端会在界面上短暂显示切换状态,这是正常现象;如果组类型本身由自动策略接管,手动切换可能很快又被内核的自动逻辑覆盖。

3动手实践:用 Python 构建健康检查与自动切换

下面的脚本实现一个保守的自动切换流程:读取指定代理组,遍历组成员并测试延迟,忽略测试失败的节点,选择低于阈值且延迟最小的节点;只有当新节点与当前节点不同,并且新节点确实通过测试时,才执行切换。这样可以避免每次运行脚本都重复切换,减少连接被频繁重置的问题。

Python 自动选择示例

将下列内容保存为 clash_switch.py。请根据自己的策略组名称修改 GROUP,并通过环境变量提供密钥:

import os import sys import time import requests BASE = os.getenv("CLASH_API", "http://127.0.0.1:9090") TOKEN = os.getenv("CLASH_SECRET") GROUP = os.getenv("CLASH_GROUP", "Proxy") TEST_URL = os.getenv("CLASH_TEST_URL", "https://www.gstatic.com/generate_204") TIMEOUT_MS = 5000 MAX_DELAY = 800 if not TOKEN: raise SystemExit("请先设置 CLASH_SECRET 环境变量") HEADERS = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } def get_group(): response = requests.get( f"{BASE}/proxies/{requests.utils.quote(GROUP, safe='')}", headers=HEADERS, timeout=5, ) response.raise_for_status() return response.json() def test_delay(name): url = f"{BASE}/proxies/{requests.utils.quote(name, safe='')}/delay" params = {"url": TEST_URL, "timeout": TIMEOUT_MS} try: response = requests.get(url, headers=HEADERS, params=params, timeout=8) response.raise_for_status() delay = response.json().get("delay") return int(delay) if delay is not None else None except (requests.RequestException, ValueError, TypeError): return None data = get_group() current = data.get("now") candidates = data.get("all", []) results = [] for name in candidates: # 组嵌套时可按需排除组名,避免把另一个策略组当作节点测试 if name == GROUP: continue delay = test_delay(name) if delay is not None and delay <= MAX_DELAY: results.append((delay, name)) time.sleep(0.1) if not results: raise SystemExit("没有找到满足条件的可用节点") delay, best = min(results) print(f"当前: {current}; 最优: {best}; 延迟: {delay} ms") if best != current: response = requests.put( f"{BASE}/proxies/{requests.utils.quote(GROUP, safe='')}", headers=HEADERS, json={"name": best}, timeout=5, ) response.raise_for_status() print(f"已切换到: {best}") else: print("当前节点仍然满足条件,无需切换")

首次运行前安装依赖并设置环境变量:

python -m pip install requests export CLASH_SECRET='change-this-to-a-long-random-token' export CLASH_GROUP='Proxy' python clash_switch.py

这个示例没有把“最快”作为唯一标准。实际环境中,延迟低于 800ms 并不代表线路一定稳定,因此还可以增加连续失败次数、最小切换间隔、节点地区白名单和冷却时间。例如最近五分钟已经切换过一次,就暂时不再切换;连续两次测试都失败后,才把当前节点标记为故障。对于视频、会议或下载任务,稳定性通常比瞬时延迟更重要。

Shell 故障转移方案

如果你只需要在当前节点不可用时切换到备用节点,可以使用更轻量的 Shell 脚本。它先测试当前节点的延迟;当请求失败或超过阈值时,再切换到预先指定的备用节点:

#!/usr/bin/env bash set -u API="http://127.0.0.1:9090" TOKEN="${CLASH_SECRET:?请设置 CLASH_SECRET}" GROUP="Proxy" CURRENT="日本节点" BACKUP="新加坡节点" URL="https://www.gstatic.com/generate_204" delay=$(curl -G -sS --max-time 8 \ -H "Authorization: Bearer $TOKEN" \ --data-urlencode "url=$URL" \ --data-urlencode "timeout=5000" \ "$API/proxies/$(python -c "import urllib.parse; print(urllib.parse.quote('''$CURRENT'''))")/delay" \ | python -c "import json,sys; print(json.load(sys.stdin).get('delay',''))" 2>/dev/null || true) if [[ -z "$delay" || "$delay" -gt 800 ]]; then curl -sS -X PUT \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d "{\"name\":\"$BACKUP\"}" \ "$API/proxies/$(python -c "import urllib.parse; print(urllib.parse.quote('''$GROUP'''))")" echo "当前节点异常,已切换到 $BACKUP" else echo "当前节点正常,延迟 ${delay}ms" fi

Shell 方案依赖 curl、Python 的 URL 编码功能和 JSON 解析,适合 Linux、macOS 或安装了相关工具的 Windows 环境。若节点名称来自不可信输入,不要直接拼接到 Shell 命令中;生产环境应使用 Python 的请求库,或者对名称进行严格转义,避免特殊字符导致命令执行异常。

4定时执行、故障转移与参数调优

自动化脚本真正投入使用时,最重要的不是“多久测一次”,而是避免过度测试和频繁切换。每次延迟测试都会产生连接请求,节点数量较多时可能增加本机和远端服务的负担。通常可以将健康检查间隔设置为 5 至 15 分钟;对于会议、直播等对稳定性敏感的场景,可以在任务开始前主动运行一次,而不是全天高频轮询。

使用定时任务运行

Linux 或 macOS 可以通过 cron 每十分钟执行一次:

*/10 * * * * CLASH_SECRET='change-this-to-a-long-random-token' /usr/bin/python3 /home/user/clash_switch.py >> /tmp/clash-switch.log 2>&1

密钥直接写在 crontab 中虽然方便,但会出现在进程管理和配置备份中。更安全的做法是把环境变量写入权限为仅当前用户可读的文件,脚本启动时读取该文件;同时限制日志内容,不要打印完整的 Authorization 请求头。Windows 用户可以使用“任务计划程序”,设置为登录后运行,并让任务以固定间隔启动。

推荐的筛选规则

  • 延迟阈值:先设置 500 至 800ms,观察真实使用效果后再调整。阈值过低会让脚本频繁判定无可用节点。
  • 失败重试:单次超时不应立即切换,建议连续两次或三次失败后再执行故障转移。
  • 切换冷却:切换后至少等待数分钟,避免多个脚本同时运行造成来回跳转。
  • 节点白名单:只测试自己信任的地区或线路,排除“剩余流量”“过期”“维护中”等名称。
  • 测速地址:准备两个或三个稳定的测试 URL,必要时轮换使用,避免单一目标故障造成误判。

推荐运行逻辑

先检测当前节点,再检测候选节点;只有候选节点明显更好,或当前节点连续失败,才执行切换。切换后记录时间、节点名称、延迟和失败原因,出现问题时才能快速回滚。

常见问题解答

请求 API 时返回 401,应该怎么处理?

首先确认请求头格式是 Authorization: Bearer 你的密钥,Bearer 与密钥之间必须有空格。然后检查脚本连接的端口是否与正在运行的 Clash 内核一致。部分客户端会在切换配置后覆盖外部控制器设置,建议重新打开当前配置确认 external-controllersecret

所有节点测速都超时,是节点全部失效了吗?

不一定。测试 URL 可能在当前网络环境中不可达,或者 URL 编码、节点名称编码存在问题。先用浏览器或 curl 单独验证测试地址,再检查接口返回的 HTTP 状态码。也可以更换一个稳定的轻量地址,并适当提高 timeout,但不要无限延长超时时间,否则脚本会长时间阻塞。

为什么脚本切换后,客户端又自动换回原节点?

最常见原因是代理组本身属于 url-test、故障转移或负载均衡类型,内核会按照自己的策略重新计算节点。此时应确认组类型和自动更新间隔;如果需要完全由脚本控制,可以建立一个手动选择组,并让脚本负责检测与切换。

可以把外部控制器开放给局域网设备吗?

技术上可以,但不建议直接监听公网或无保护地监听局域网。若确实需要远程管理,应使用强随机密钥、系统防火墙白名单、VPN 或安全反向代理,并限制可访问的 IP 范围。外部控制器拥有控制代理的权限,安全级别应按照管理接口而不是普通状态查询接口来对待。

通过 API 管理节点的价值,不只是节省几次点击,而是把“发现故障、评估线路、执行切换、记录结果”变成可重复的流程。建议先在本机手动运行脚本,确认 API 返回和节点名称都正确,再加入定时任务;当逻辑稳定后,再逐步增加多测试地址、失败重试、通知和日志保留功能。

立即免费下载 Clash,开启流畅上网新体验 →