Clash订阅本地转换到QuantumultX

在同一 Wi-Fi 下把 Clash 订阅本地转换成 Quantumult X 订阅

这篇教程适合已经在用 Clash、ClashX、Clash Verge 或 mihomo 订阅,但希望在 iPhone 的 Quantumult X 里使用同一份节点的人。

目标不是把 Mac 变成代理网关,而是让 Mac 在同一 Wi-Fi 下临时充当一个本地订阅转换器:

1
2
3
4
5
更新订阅时:
iPhone Quantumult X -> Mac 上的 Subconverter -> 上游 Clash 订阅 -> 返回 Quantumult X 节点列表

实际代理和测速时:
iPhone Quantumult X -> 远程代理节点 -> 目标网站

也就是说,订阅更新会访问 Mac;节点测速、日常代理、App 流量不会经过 Mac。

适用场景

这个方案适合以下情况:

  • 上游给的是 Clash、ClashX、Clash Verge 或 mihomo 可用的订阅。
  • 你希望 iPhone 上的 Quantumult X 使用同一批节点。
  • 你不想把订阅地址提交给公共订阅转换站。
  • iPhone 和 Mac 可以在同一 Wi-Fi 下更新订阅。
  • 你接受 Mac 开机且 Docker 容器运行时,手机才能刷新这条订阅。

它不适合以下情况:

  • 希望 iPhone 在任意网络下都能更新订阅。
  • 希望 Mac 持续为 iPhone 转发全部代理流量。
  • 希望生成完整 Quantumult X 分流配置、重写、MITM、策略组体系。

本文生成的是 Quantumult X 的服务器资源,也就是节点列表;分流规则、策略组、重写和证书相关配置仍然应该在 Quantumult X 自己的配置里维护。

准备条件

你需要:

  • 一台 Mac。
  • Mac 上安装 Docker。
  • iPhone 安装 Quantumult X。
  • iPhone 和 Mac 连接同一个 Wi-Fi。
  • 一条上游 Clash 订阅地址。

为了避免泄露订阅,本文统一使用占位符:

1
2
3
<MAC_LAN_IP>                       Mac 的局域网 IP
<UPSTREAM_CLASH_SUB_URL> 原始 Clash 订阅地址
<ENCODED_UPSTREAM_CLASH_SUB_URL> URL 编码后的 Clash 订阅地址

不要把真实订阅 URL、token、UUID、password、节点服务器域名或 IP 写进公开文章。

启动本地 Subconverter

在 Mac 上运行:

1
2
3
4
docker run -d --restart=always \
--name subconverter \
-p 25500:25500 \
tindy2013/subconverter:latest

这里使用 -p 25500:25500,是为了让同一 Wi-Fi 下的 iPhone 能访问 Mac 的 25500 端口。

如果只在 Mac 本机测试,可以绑定到 127.0.0.1

1
2
3
4
docker run -d --restart=always \
--name subconverter \
-p 127.0.0.1:25500:25500 \
tindy2013/subconverter:latest

但这种方式 iPhone 无法访问,因为 iPhone 上的 127.0.0.1 指的是 iPhone 自己,不是 Mac。

验证容器是否运行:

1
docker ps --filter name=subconverter

验证 Subconverter 是否可用:

1
curl http://127.0.0.1:25500/version

如果正常,会看到类似:

1
subconverter v0.9.0-xxxxxxx backend

获取 Mac 局域网 IP

在 Mac 上执行:

1
ipconfig getifaddr en0

如果没有输出,可以试:

1
ipconfig getifaddr en1

得到的地址就是后面 URL 里的 <MAC_LAN_IP>,例如:

1
192.168.x.x

在 iPhone Safari 里打开:

1
http://<MAC_LAN_IP>:25500/version

如果 iPhone 能看到 Subconverter 版本号,说明手机已经能访问 Mac 上的本地转换服务。

构造 Quantumult X 订阅链接

先把上游 Clash 订阅地址做 URL 编码。

原始订阅:

1
<UPSTREAM_CLASH_SUB_URL>

编码后:

1
<ENCODED_UPSTREAM_CLASH_SUB_URL>

可以用 Python 编码并复制到剪贴板:

1
2
3
4
5
6
python3 - <<'PY' | pbcopy
import urllib.parse

raw = "<UPSTREAM_CLASH_SUB_URL>"
print(urllib.parse.quote(raw, safe=""))
PY

如果不想让订阅地址留在 shell 历史里,可以先临时关闭命令历史,或者把命令放进只在本机使用的临时脚本里,执行后立即删除。

最终给 Quantumult X 使用的服务器资源订阅 URL:

1
http://<MAC_LAN_IP>:25500/sub?target=quanx&list=true&udp=true&tfo=true&sort=true&exclude=%28Traffic%7CExpire%7C%E6%B5%81%E9%87%8F%7C%E5%AE%98%E7%BD%91%7C%E5%89%A9%E4%BD%99%7C%E8%BF%87%E6%9C%9F%7C%E9%87%8D%E7%BD%AE%7CReset%7CDate%7CDays+Left%7CG+%5C%7C%29&url=<ENCODED_UPSTREAM_CLASH_SUB_URL>

这个 URL 可以直接填入 Quantumult X 的服务器资源订阅。

参数解释

核心参数如下:

1
target=quanx

把订阅转换成 Quantumult X 格式。

1
list=true

只输出节点列表。这个参数很重要。如果不加 list=true,Subconverter 可能输出完整 Quantumult X 配置,从 [general] 开始;这不适合作为服务器资源订阅导入。

1
udp=true

为支持的节点开启 UDP relay。

1
tfo=true

为支持的节点开启 TCP Fast Open。

1
sort=true

按节点名排序,方便在 Quantumult X 里查看。

1
exclude=...

排除流量、到期时间、官网、重置时间等可能被误识别为节点的订阅信息行。

本文示例使用的排除规则含义是:

1
(Traffic|Expire|流量|官网|剩余|过期|重置|Reset|Date|Days Left|G \|)

实际写进 URL 时需要 URL 编码。

1
url=<ENCODED_UPSTREAM_CLASH_SUB_URL>

上游 Clash 订阅地址。这里必须放 URL 编码后的结果。

在 Quantumult X 中添加订阅

在 Quantumult X 里添加服务器资源,填入上面构造的 URL:

1
http://<MAC_LAN_IP>:25500/sub?target=quanx&list=true&udp=true&tfo=true&sort=true&exclude=...&url=<ENCODED_UPSTREAM_CLASH_SUB_URL>

添加后刷新资源。如果转换成功,Quantumult X 会拿到一批节点。

如果你直接用配置文件形式,也可以把它写成类似:

1
2
[server_remote]
http://<MAC_LAN_IP>:25500/sub?target=quanx&list=true&udp=true&tfo=true&sort=true&exclude=...&url=<ENCODED_UPSTREAM_CLASH_SUB_URL>, tag=本地转换节点, update-interval=86400, opt-parser=false, enabled=true

验证方式

先验证手机能访问 Mac:

1
http://<MAC_LAN_IP>:25500/version

再验证订阅 URL 能返回 Quantumult X 节点列表。正常内容会类似:

1
trojan = <SERVER_HOST>:<PORT>, password=<PASSWORD>, over-tls=true, ...

公开文章不要展示真实节点行。节点行里通常包含服务器地址、端口、密码、TLS host 等敏感信息。

最后在 Quantumult X 里更新订阅并测试节点延迟或速度。

测速时的数据链路是:

1
iPhone Quantumult X -> 远程代理节点 -> 测速目标

不再经过 Mac 上的 Subconverter。Mac 只参与订阅更新。

常见故障排查

打不开 http://<MAC_LAN_IP>:25500/

Subconverter 没有可用的首页 UI。测试服务是否正常应该访问:

1
http://<MAC_LAN_IP>:25500/version

Mac 本机能打开,iPhone 打不开

优先检查:

  • iPhone 和 Mac 是否在同一个 Wi-Fi。
  • iPhone 是否开着 VPN 或代理,导致局域网请求被转发走。
  • Mac 的局域网 IP 是否变了。
  • Docker 是否仍在运行。
  • Mac 防火墙是否阻止了入站连接。

可以在 Mac 上重新查看 IP:

1
ipconfig getifaddr en0

并查看容器:

1
docker ps --filter name=subconverter

Quantumult X 导入后内容像完整配置

检查 URL 里有没有:

1
list=true

没有这个参数时,target=quanx 可能输出完整配置,而不是服务器资源需要的纯节点列表。

订阅里出现流量、到期时间这类伪节点

增加或调整 exclude 参数。例如:

1
(Traffic|Expire|流量|官网|剩余|过期|重置|Reset|Date|Days Left|G \|)

写进 URL 前要 URL 编码。

手机离开家后更新失败

这是预期结果。这个方案只适合同一 Wi-Fi 下更新。

如果需要外网更新,可以考虑 Tailscale、ZeroTier、内网穿透或自建带认证的转换服务。但这已经不是本文的 “ 同一 Wi-Fi 本地转换 “ 方案,安全边界也完全不同。

QX 测速是不是走 Mac

不是。Mac 只提供订阅转换服务。

订阅更新时:

1
iPhone -> Mac Subconverter -> 上游订阅

实际代理和测速时:

1
iPhone -> 远程节点

安全和脱敏建议

不要把以下内容写入公开文章、截图或 Issue:

  • 原始订阅 URL。
  • URL 编码后的订阅 URL。
  • token、UUID、password。
  • 节点服务器域名或 IP。
  • 完整 Quantumult X 节点行。

建议公开文章只写占位符:

1
2
3
4
5
<MAC_LAN_IP>
<UPSTREAM_CLASH_SUB_URL>
<ENCODED_UPSTREAM_CLASH_SUB_URL>
<SERVER_HOST>
<PASSWORD>

如果必须截图,先遮住浏览器地址栏、Quantumult X 订阅 URL、节点详情和服务商信息。

也不建议把 25500 端口暴露到公网。本文的默认边界是同一 Wi-Fi 下使用。

我的实际配置示例

我的测试环境是:

1
2
3
4
Mac + Docker + Subconverter
iPhone + Quantumult X
同一 Wi-Fi
上游订阅原本可被 Clash/Clash Verge 使用

当时 Mac 的局域网 IP 是:

1
<MAC_LAN_IP>

最终订阅 URL 结构是:

1
http://<MAC_LAN_IP>:25500/sub?target=quanx&list=true&udp=true&tfo=true&sort=true&exclude=%28Traffic%7CExpire%7C%E6%B5%81%E9%87%8F%7C%E5%AE%98%E7%BD%91%7C%E5%89%A9%E4%BD%99%7C%E8%BF%87%E6%9C%9F%7C%E9%87%8D%E7%BD%AE%7CReset%7CDate%7CDays+Left%7CG+%5C%7C%29&url=<ENCODED_UPSTREAM_CLASH_SUB_URL>

转换成功后,Quantumult X 拿到的是服务器资源节点列表。后续测速和代理连接由 iPhone 直接访问远程节点,Mac 不再参与。

参考资料

如果这篇文章对你有帮助,不介意的话,请作者喝杯咖啡吧
levon 微信 微信
levon 支付宝 支付宝