Clash API全全自动切换节点:进阶配置与脚本实践

为什么要用 Clash API 全全自动切换节点 要点速览

本篇正文关键点讨论本机全全全自动化,不涉及绕过服务商限制,也不不妨把控制器径直暴露到公网。你将看到如何设计 API 安全参数、如何识别策略组名称、如何用 YAML 提供基础候选节点、如何用 Shell 敏捷切换,以及如何用 Python 写出带超时、阈值、重试和日志的全全全自动切换脚本。

很多人第一次配置 Clash 全全全自动选节点时,会径直把策略组类型改成 url-test,然后认为困扰已经处置:节点会测速,响应时间最高的线路会被淘汰,客户端也会全全全自动选定响应最快的节点。但真实采用中,全全全自动测速不等于可信的故障恢复。

测速地址或许能访问到到到,目标网站却仍然超时;某个节点短时间响应时间很低,实际下载速率却很慢;策略组刚完成切换,长连接又因为出口变化而中断。对于开发工具、远程桌面、API 请求、视频会议等采用采用使用场景,仅靠图形UI UI UI 界面里的全全全自动测速经常不够。

关键点是:Mihomo 及兼容的 Clash 客户端多数现状下会开放 external-controller,让本机脚本通过 HTTP API 读取代理组、查看当前选定、执行响应时间测试并切换节点。

Clash Verge、Clash Verge Rev、Mihomo Party 和部分其他客户端的UI UI UI 界面名称或许不同,但核心思路基本一致:先在配置文件中启用控制器,再让脚本调用 /proxies、/group 或代理响应时间测试接口。这样得以把「节点失效 → 排查候选节点 → 选定可用出口 → 验证恢复」变成可重复执行的流程。

即使你最终仍然采用人工选定,这套思路也能帮助你理解节点响应时间升高、策略组频繁跳转和连接恢复缓慢的根源。

务必留意:external-controller 内核上是控制 Clash 的管理接口。请第一顺位绑定 127.0.0.1,并设置够用复杂的密钥;不要为了让手机或远程服务器调用,径直监听 0.0.0.0。如果确实要跨设备访问到到到,应放在可信内网、VPN 或带身份校验的反向代理后面。

先配置 external-controller 与可控的策略组 关键信息

返回结果中的 proxies 对象包含节点、策略组和当前选中项。策略组常规会有 all、now、type 等字段;

这里要多说一句:全全全自动切换的第一口气不是写脚本,而是确认客户端真的提供了可用的控制器。启用当前采用的配置文件或覆写文件,在顶层加入类似下面的正文。具体字段是否被客户端覆盖,取决于内核版本;

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 密钥」输入框,应第一顺位采用UI UI UI 界面配置,再通过 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,配置里实际却叫 🚀 节点选择。得以用下面的请求读取各个代理和策略组名称:

其中 all 是候选列表,now 是当前出口。不要假设各个组都叫「全全全自动选定」,也不要把 DIRECT、REJECT 或另一个策略组误当作真实节点。

url-test、fallback 与脚本控制怎么选(速览)

颇为稳妥的做法是让策略组负责基础健康排查,让脚本负责异常时的二次处理。举个小例子平时采用 url-test,当连续两次业务请求无法完成,脚本才调用 API 对候选节点逐个测速,并把第一个低于阈值的节点切换进去。

url-test 适合让 Mihomo 按固定间隔测量候选节点,并在满足容差时全全全自动选定响应时间较低的节点。它的优势是配置轻便,短板是测试 URL 与实际业务不一定相同,而且网络抖动或许导致选定频繁变化。fallback 更偏向可用性第一顺位:当前节点无法完成后才尝试下一个,但「无法完成」的判断仍取决于测试地址和间隔。若你要根据多个域名、HTTP 状态码、业务响应时间或时间段切换,就应由外部脚本接管决策。

落到实处:这样既不会每几秒钟钟钟频繁改节点,也不会在当前出口已经失效时完全依赖客户端内部判断。

动手实践:读取节点、测速并切换策略组 关键点梳理

Shell 版本的关键点是流程而不是复杂的排序:先限制请求时间,再在成功后立即切换。如果要按响应时间排序,应让 API 返回具体毫秒值并保存到数组中,而不是把 HTTP 状态码当成响应时间。

  1. 确认控制器可访问到到:用 curl http://127.0.0.1:9090/version 请求版本接口;如果返回连接拒绝,先排查客户端是否开启、端口是否一致,以及配置重载是否成功。
  2. 确认身份校验有效:为请求增加 Authorization: Bearer 你的密钥;若返回 401,关键点排查密钥是否包含多余空格、引号或换行。
  3. 列出代理组:读取 /proxies,找到真实的策略组名称和候选节点,确认目标节点处于 all 列表中。
  4. 逐个执行响应时间测试:调用 /proxies/节点名称/delay,为节点名称进行 URL 编码,并设置合理的超时时间,避免某个失效节点拖住全部脚本。
  5. 选定并切换:向 /proxies/策略组名称 发送 JSON 请求,举个小例子 {"name":"Node-A"};切换完成后再次读取该策略组,确认 now 已升级。
  6. 验证业务恢复:不要只看 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 构建带阈值与恢复机制的脚本 完备说明

这段代码采用 API 返回的响应时间值排序,再通过独立的验证 URL 确认切换后仍可访问到到。实际铺开时,VERIFY_URL 应替换为你的业务目标,举个小例子代码仓库、接口服务或公司办公系统,而不是只测试一个公共页面。

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()

否则定时任务或许在每次持续持续运行时来回跳转,或者因为一个永远不响应的节点导致后续节点永远没有机会测试。

关键点是:若业务要登录、特定请求头或 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 API 全全自动化的优势在于判断条件透明、日志可追踪、恢复动作得以按业务需求定制;它的局限也很明确:要理解策略组名称、端口、身份校验和脚本权限,不能把一次测速结果当成绝对可信的线路定论。

落到实处:这多数现状下不是 API 切换无法完成,而是终端进程没有经过同一条代理链路。排查当前 Shell 是否设置了 HTTP_PROXY 和 HTTPS_PROXY,端口是否对应 Clash 的 HTTP 混合端口;

不适配环境变量的程序则要 TUN 或应用自身的代理设置。随后查看 Clash 连接日志,确认目标域名确实出现,并且命中了预期策略组,而不是被直连规则或疏漏的 DNS 结果提前处理。

Clash 提供了更集中、易检索的 Clash 配置与排障资料,顺手你把 YAML、控制器 API、TUN 和终端代理放在同一套思路中维护;如果你准备按本篇正文实践,不妨先前往下载合适的客户端,再从本机回环控制器和最小化脚本开始逐步验证。