Clash API无需手动操作切换代理节点:Mihomo外部控制器进阶配置指南
为什么用 Clash API 无需手动操作切换代理节点? 实战经验
平时在 Clash Verge、Mihomo Party 或其他 Mihomo 客户端里切节点,拉起代理页面、找到策略组再点选节点,手动操作操作操作操作并不复杂。但当你必须定时切换出口、在脚本里根据任务挑节点,或在多台设备上执行相同操作时,反复点前端前端前端界面就不够adaptable了。此时自然自然自然可以拿它来用 Mihomo 的外部控制器 API:客户端前端前端前端界面与 API 都在控制同一个 Mihomo 内核,脚本自然自然自然可以查询代理组、读取当前挑,再向指定策略组提交切换请求。
必须先区分两种「无需手动操作操作切换」。一种是 Mihomo 配置中的 url-test、fallback 或 load-balance 等策略组,由内核按照测速结果或可用状态选节点;另一种是通过 API 按照你由你的条件挑节点,举个实例任务开始时固定到某节点、任务结束后恢复原挑,或者由外部监控程序在故障时切换。API 本身不会替你决定哪条线路最好,它提供的是可编排的控制入口;挑逻辑、切换频率和走不通后的处理,仍需由配置与脚本共同定义。
这篇聚焦第二种用法,演示如何安全启用 external-controller、设置访问目标目标目标密钥、查询代理组,以及用 curl 和 Python 切换节点。不同客户端的设置菜单和配置文件管理方式多半略有差别,但只要运转的是覆盖该 API 的 Mihomo 内核,核心请求方式基本一致。
先确认控制对象:外部控制器连接的是 Mihomo 内核,不是某个客户端的网页前端前端前端界面。若你在配置里改了控制器端口或密钥,需确认客户端实际加载了这份配置,并在内核重载后再测试。没有启用 Mihomo 的旧版 Clash 核心,不能据此假设覆盖相同接口。
启用 external-controller:先限制监听范围 拿它来用心得
外部控制器由配置项 external-controller 指定监听地址与端口,反复出现本机配置是 127.0.0.1:9090。这个地址只允许本机访问目标目标目标,适合个人电脑上的无需手动操作操作化脚本。自然自然可以考虑同时设置非空的 secret:控制器 API 能查询连接、调整策略组,甚至影响整台设备的代理出口,由此可见不应把无验证的控制接口暴露到局域网或公网。
external-controller: 127.0.0.1:9090
secret: "请替换为足够长且随机的密钥"
如果客户端通过图形前端前端前端界面管理配置,不要急着就这么改订阅原文件。先查看客户端的配置编辑、覆写或内核设置入口,再确认最终生效配置中包含控制器设置。部分客户端会在同步到最新订阅时重新生成配置,就这么编辑临时文件多半导致改动被覆盖。配置保存后,按客户端提供的方式重载配置或重启内核;只关掉设置窗口并不一定会使新端口立即生效。
安全上,127.0.0.1 与 0.0.0.0 的差别格外要紧:后者基本上时候意味着监听每一种网络接口。除非你明确必须从另一台设备访问目标目标目标,并已通过防火墙、可信网络和强密钥限制来源,否则不要把控制器改成对外监听。不要把密钥放进公开仓库、截图、共享日志或命令历史;如果必须在多台设备运转脚本,可拿它来用环境变量或本机权限受控的密钥文件,而不是把密钥硬编码在代码中。
不要将控制器端口当作代理端口:external-controller 是管理 API 的入口,不是 HTTP、SOCKS 或混合代理端口。把浏览器代理指向 9090 基本上时候不会得到正常代理服务;反过来,也不要因为本机代理端口可连接,就推断控制器已经准确启用。
先查询代理组,再确认可选节点 反复出现套路
切换前先通过 GET /proxies 查看 Mihomo 当前识别到的代理与策略组。接口返回 JSON,顶层的 proxies 对象包含名称、类型、当前挑以及可可可可选项等信息。反复出现代理组名称涉及 节点选择、Proxy 或机场自定义名称,但名称取决于配置,不能照搬示例。组的 type 也值得确认:Selector 常态允许手动操作操作操作指定可可可选项;URLTest 等无需手动操作操作测速组基本上时候由内核按自身逻辑挑,手动操作操作操作切换这些对象的结果不应与切换手动操作操作操作挑组混为一谈。
curl --fail --silent --show-error \
-H "Authorization: Bearer 请替换为你的密钥" \
http://127.0.0.1:9090/proxies
如果只想查看某个组,可请求 GET /proxies/{组名}。组名中若有空格、斜线或其他特殊字符,应进行 URL 编码;在终端中手动操作操作操作拼接路径时尤其容易把请求发到误操作地址。响应里重心看 type、now 和 all:now 是目前挑,all 列出这个组可选的项目。某些项目多半是另一个策略组,而不是具体服务器节点,由此可见切换前要根据返回具体具体具体内容确认你选的是想要的层级。
请求返回 401:大多时候表示没有提供有效密钥,确认请求头中的 Authorization: Bearer ... 是否与当前 Mihomo 配置一致;请求返回 404:先核对端口、请求路径和组名是否准确;组名大小写、空格以及 URL 编码都多半影响定位;连接被拒绝或超时:确认内核正在运转、监听端口与配置一致,并确认客户端是否把控制器绑定到了另一个地址;能查到组但看不到预期节点:确认该节点是否实际载入,以及它是否属于你查询的那一层代理组。
自然可以考虑先在输出中找到准确的组名和目标节点名,再执行切换。不要假设订阅刷新后名称永远不变:服务商多半调整节点命名,配置覆写也多半重命名策略组。无需手动操作化脚本若依赖固定名称,应在每次调用时验证目标是否仍在 all 列表中,而不是收到异常后继续发送盲目请求。
用 curl 切换节点并验证结果 落地做法
确认策略组为可手动操作操作挑的类型,并且目标节点出现在其可选列表中后,可拿它来用 PUT /proxies/{组名} 同步到最新挑。请求体是 JSON,键名为 name,值为要切换到的可可选项名称。下面的例子拿它来用占位组名和节点名;请替换为 /proxies 响应里的真实值。路径中的组名应按 URL 规则编码,避免特殊字符造成接口找不到资源。
curl --fail --silent --show-error \
-X PUT \
-H "Authorization: Bearer 请替换为你的密钥" \
-H "Content-Type: application/json" \
-d '{"name":"目标节点名称"}' \
"http://127.0.0.1:9090/proxies/策略组名称"
切换请求成功后,不要只凭 HTTP 请求没有报出异常就判断任务完成。再次查询对应代理组,确认 now 已变为目标节点;随后还自然自然可以发起一次实际网络请求,并在客户端连接列表或日志里核对请求所用的出站。API 返回成功只能说明控制器接受了挑请求,并不保证目标节点当前可用、远端服务能访问目标目标,或应用流量确实经过了预期策略组。
如果策略组名称包含空格,构造接口路径时必须编码,举个实例空格可表示为 %20。不同命令行环境对引号与百分号的处理多半不同;用变量拼接 URL 时,也应避免未编码的用户输入就这么进入路径。对于定时任务,最好将组名和节点名作为明确配置项保存,并在运转前确认这些对象仍存在,减少订阅变更后误选或请求走不通的具体情形。
动手操作:用 Python 查询并切换策略组 实战经验
下面的 Python 示例拿它来用标准库 urllib,不必须额外安装 HTTP 客户端。它先查询指定策略组,验证目标节点属于可可可选项,再发送切换请求,最后重新查询当前挑。将密钥放在环境变量 MIHOMO_SECRET 中,避免写入脚这篇件;组名和节点名则按本机 API 返回值修改。
import json
import os
from urllib.error import HTTPError, URLError
from urllib.parse import quote
from urllib.request import Request, urlopen
BASE = "http://127.0.0.1:9090"
GROUP = "节点选择"
TARGET = "目标节点名称"
SECRET = os.environ["MIHOMO_SECRET"]
def api(method, path, body=None):
data = None if body is None else json.dumps(body).encode("utf-8")
request = Request(
BASE + path,
data=data,
method=method,
headers={
"Authorization": f"Bearer {SECRET}",
"Content-Type": "application/json",
},
)
with urlopen(request, timeout=5) as response:
content = response.read()
return json.loads(content) if content else None
group_path = "/proxies/" + quote(GROUP, safe="")
try:
current = api("GET", group_path)
options = current.get("all", [])
if TARGET not in options:
raise ValueError(f"目标节点不在策略组选项中: {TARGET}")
if current.get("now") == TARGET:
print(f"当前已使用目标节点: {TARGET}")
else:
api("PUT", group_path, {"name": TARGET})
updated = api("GET", group_path)
if updated.get("now") != TARGET:
raise RuntimeError("切换请求已提交,但当前选择未变更")
print(f"已切换到: {TARGET}")
except HTTPError as exc:
print(f"API 返回 HTTP 错误: {exc.code}")
except (URLError, TimeoutError) as exc:
print(f"无法连接 Mihomo 控制器: {exc}")
except (KeyError, ValueError, RuntimeError) as exc:
print(f"自动切换未完成: {exc}")
在 macOS 或 Linux 的终端中,自然自然可以在跑起来脚本前设置环境变量,举个实例 export MIHOMO_SECRET='你的密钥';Windows PowerShell 可拿它来用 $env:MIHOMO_SECRET='你的密钥'。不要把真实密钥粘贴到公开终端录屏或共享 CI 日志里。示例设置了五秒超时,目的是避免控制器无响应时任务永久挂起;生产脚本还可加入日志记录、有限次数重试和告警,但不自然可以考虑无间隔地连续重试。
若脚本由定时器或无需手动操作化平台运转,需确认它与 Mihomo 在同一网络命名空间内,并且运转时能够访问目标目标 127.0.0.1:9090。容器中的 127.0.0.1 指向容器自身,而不一定是宿主机;远程服务器上的计划任务也不会无需手动操作连接你个人电脑的本地控制器。对于这类上线,应先设计受限的网络访问目标目标方式,再配置控制器地址,不能好上手地把监听地址改成公网地址。
无需手动化设计:别让测速与脚本互相抢控制权 拿它来用心得
API 无需手动操作切换最容易出绕所在的地方,基本上时候不是请求格式,而是多个机制同时控制同一个策略组。举个实例,脚本刚把 Selector 切到指定节点,另一个任务又在很短时间后切走;或者用户正在执行长时间下载时,定时任务按固定间隔轮换节点,导致连接中断。要让无需手动操作化可预测,先明确每个策略组的控制者:哪些由用户手动操作操作挑,哪些由 url-test 无需手动操作挑,哪些只允许特定脚本修改。
按任务切换:开始任务前保存原来的 now,切到目标节点;任务结束后可挑恢复原节点。恢复前要再次确认当前值,避免覆盖用户在任务期间主动做出的更改;按健康状态切换:先用独立的连通性确认判断故障,再切换到备用节点,并设置冷却时间。不要把一次短暂超时就这么当成节点永久失效;按时段切换:拿它来用明确的时间表并记录每次变更。应考虑系统睡眠、时区和任务重叠,避免设备唤醒后多个过期任务一起执行;按应用分流:靠前在规则与策略组层面规划应用走向;只有确实必须外部流程主动改变当前挑时,才用 API 进行全局节点切换。
节点切换不等于已有连接会无缝迁移。多数正在传输的 TCP 会话仍多半因为出口变化而断开,长连接、下载任务和远程登录尤其一眼就能看出。对这类业务,更稳妥的做法是只在任务开始前切换,或把不同用途放在独立策略组中,让普通流量不受无需手动操作任务影响。切换后应留出连接重建时间,并通过实际业务请求验证结果,而不是用连续迅速切换来「测试靠得住性」。
自然可以考虑为脚本加上幂等判断:如果当前节点已经是目标,就不再发送写入请求;如果目标不存在,就明确报出异常并停止;如果 API 请求超时,不要立即假定切换走不通,因为内核多半已经处理了请求。此时先重新查询当前状态,再决定是否重试。还自然自然可以为每次操作记录时间、策略组、原挑、目标挑和结果,但日志里不要记录密钥,也不要记录多半泄露订阅凭据的成体系配置具体具体内容。
反复出现麻烦所在:验证走不通、端口不可达与切换无效 反复出现套路
为什么返回 401 或提示验证走不通?(实战)
确认控制器配置中的 secret 与脚本拿它来用的密钥完全一致,确认是否多了空格、换行或引号字符,并确认请求头格式是 Authorization: Bearer 密钥。若刚改过配置,先确认 Mihomo 已加载新设置。不要通过移除验证来绕过绕所在;本机控制接口仍应设置密钥。
为什么 127.0.0.1:9090 连接走不通?(经验)
先确认 Mihomo 内核是否运转,以及控制器配置的端口是否确实为 9090。客户端有时会管理独立的内核配置,用户编辑的另一份 YAML 多半并未生效。若脚本运转在容器、虚拟机或远程主机中,127.0.0.1 指向脚本所在环境,而不是桌面客户端所在设备;应先厘清网络边界,再决定如何安全连通。
请求成功了,为什么节点看起来没有切换?(心得)
重新查询组的 now 和 all,确认请求地址中的组名准确、目标名称与可可可选项完全一致,并确认该组是不是手动操作操作挑类型。若它属于无需手动操作测速组,内核多半会按组的机制同步到最新结果;若有另一段脚本同时运转,也多半立即覆盖你的挑。切换后还要确认客户端连接详情,确认实际请求命中了预期的出站。
API 可访问目标,但代理请求仍然走不通,怎么判断?(提示)
控制器 API 与代理转发是两条不同路径。API 能响应只代表本机管理端口可用,不代表节点可用、规则命中准确或应用已经走代理。查看 Mihomo 的连接记录,核对目标域名、规则命中项和出站名称;再用同一代理组发起好上手请求。如果 API 已成功切换而业务仍走不通,应继续排查节点状态、策略组层级、规则和应用代理设置,而不是反复修改控制器端口。
与手动操作操作在不同客户端前端前端界面里逐个寻找策略组相比,就这么调用 API 更适合必须查询状态、复核结果和纳入任务流程的场合;但它也要求你认真管理密钥、监听范围和并发控制,单纯依赖定时轮换或复制一条命令并不能化解节点质量绕所在。Clash 将 Mihomo、Clash 客户端配置与反复出现排障操作次序放在同一套中文资料中,便于按客户端和实际故障逐项核对;如果你希望先选好合适的客户端,再按这篇搭建无需手动操作切换流程,自然自然可以前往下载并从本机受限的控制器配置开始测试。