subconverter 自建:在本机转换订阅,不交给公共转换站

subconverter 自建:在本机转换订阅,不交给公共转换站

Marcus Reid
2026年10月14日· 7 分钟阅读

subconverter 自建,就是在自己的电脑上把代理订阅转换成另一种客户端格式,而不把订阅链接发给公共转换网站。本文运行固定版本的 tindy2013/subconverter:0.9.0 Docker 镜像,只发布到 127.0.0.1,让链接不进入 shell 历史和容器日志,并在任何客户端导入之前核对输出。[1][2]

关键要点

  • 订阅链接就是凭据,公共转换站会拿到它的完整内容。
  • 容器要发布到 127.0.0.1,因为 Docker 默认在主机所有地址上发布端口。
  • 替换默认 API 令牌,并关闭容器日志:默认级别下日志会记录拉取的链接。
  • 0.9.0 版能解析 ss、ssr、vmess、trojan、socks 和 HTTP 链接,没有 VLESS 链接解析器。
  • 信任转换结果之前,先核对节点数、TLS、传输方式和 UDP 字段。

本文依据文末官方来源整理,未完成完整端到端实测。范围只限你自己控制的一台电脑,不涉及公共或共享的转换服务。可以先用自建任务与恢复清单判断本地工具是否适合你的场景。

公共转换站能看到什么?

转换接口通过 /sub 的 url 查询参数接收订阅地址,同时带上目标格式和可选的外部配置。[1] 因此运营这个接口的人会拿到完整链接,之后还能再次拉取,并看到链接返回的每个服务器、端口和密钥。该网站的日志、统计和缓存层也可能保存你永远不会知道的副本。

请求中的内容用公共转换站时谁会知道用本地容器时谁会知道
订阅链接及其中的令牌网站运营方及其日志只有你的电脑,以及订阅提供方
节点地址、端口和密钥网站运营方(拉取链接后)只有你的电脑
转换时你的 IP 地址网站运营方;提供方看到的是网站的地址只有订阅提供方
转换后的输出文件网站运营方(生成过程中)只有你的电脑

这就是为什么订阅链接应像密码一样保存和吊销。如果你已经把链接粘贴到公共转换站,先请提供方重置链接,再按本文操作。如果为大量节点修改转换后的配置所需的维护超出了你的实际需要,也可以先权衡自建服务器与托管 VPN。

应该运行哪个 subconverter 版本?

最新的带标签发布是 v0.9.0,Docker Hub 上有对应的 0.9.0 镜像标签;latest 标签则跟随主分支的较新构建。[2][3] 固定使用 0.9.0,让你审查过的代码就是实际运行的代码,并在每次使用前到仓库查看有没有新标签。

转换前先了解解析器的限制。在 v0.9.0 中,链接解析器识别 ssr://、vmess://、ss://、trojan://、socks 和 Telegram 风格的 HTTP 链接,以及 Netch://;没有处理 vless://、Hysteria2 或 TUIC 链接的分支。[4] 不受支持格式的节点会直接从输出中消失,而不是被转换。文档列出的目标格式包括 clash、surge、quanx、loon 和 v2ray;v0.9.0 的请求处理代码还包含一个 README 表格没有列出的 singbox 目标。[1][5]

步骤 1:准备私有工作目录和令牌

创建一个只有你的用户能读取的目录,并生成新的访问令牌,不要沿用默认值。示例配置文件自带 api_access_token=password,程序也会从环境变量读取 API_MODE 和 API_TOKEN。[6][7]

mkdir -m 700 -p ~/subconv && cd ~/subconv
umask 077
printf 'API_MODE=true\nAPI_TOKEN=%s\n' "$(openssl rand -hex 24)" > subconv.env

API_MODE=true 会阻止服务加载本地订阅或直接提供本地文件。[6] subconverter 的 API 令牌保护配置更新接口,Docker README 中调用该接口时带有 token 参数。[3] 把两者放在环境文件里,可以避免令牌出现在命令行上,从而不被 shell 历史和进程列表暴露。

步骤 2:只在本机回环上运行固定镜像

如果不指定地址,Docker 会在主机所有地址(0.0.0.0 和 [::])上发布容器端口,也就把服务暴露给你所在的网络。[8] 明确绑定到回环地址,完成 subconverter Docker 部署:

docker run -d --name subconv-local --restart unless-stopped \
  --log-driver none --memory 256m \
  --cap-drop ALL --security-opt no-new-privileges \
  --env-file ./subconv.env \
  -p 127.0.0.1:25500:25500 \
  tindy2013/subconverter:0.9.0

用 curl -fsS http://127.0.0.1:25500/version 检查;按 Docker README 的说明,输出应包含 subconverter 后端名称和版本。[3] 再用 sudo ss -lntp | grep 25500 确认主机只监听 127.0.0.1:25500,这个本机绑定正是挡住其它设备的关键。

在早于 28.0.0 的 Docker Engine 版本中,同一二层网段内的主机可以访问发布到 localhost 的端口。[8] 在共享网络中依赖回环绑定之前,先运行 docker version 检查并升级。

步骤 3:转换一次,不让链接进入 shell 历史

用隐藏输入把链接写进私有文件,再让 curl 对文件内容做 URL 编码:

read -rs SUB_URL && printf '%s' "$SUB_URL" > sub.txt && unset SUB_URL
curl -fsS -G http://127.0.0.1:25500/sub \
  --data-urlencode target=clash \
  --data-urlencode url@sub.txt \
  -o converted.yaml
rm sub.txt

subconverter 订阅转换时,订阅由容器自己去拉取。示例配置中的 proxy_subscription=NONE 表示这次拉取直接发出,不经过配置的代理。[6] 因此订阅提供方看到的是你电脑的地址,和客户端更新链接时一样。

为什么要关闭容器日志

在 v0.9.0 中,处理代码会写一条 info 级别日志,内容包含它拉取的每个订阅链接。[5] 如果使用 Docker 默认日志,这一行就会留在 docker logs 的输出里。none 日志驱动不保存容器日志,docker logs 不会返回任何内容。[9] 调试时确实需要日志,就临时运行一个开启日志的容器,用完删除。

步骤 4:逐字段核对输出

HTTP 请求成功,不代表每个节点都转换正确。用本地编辑器打开 converted.yaml,按提供方对每个节点的说明逐项核对。

字段核对内容出现以下情况就停止
节点数与来源相同,减去你有意排除的节点节点无故缺失
协议类型与来源节点一致节点换了协议或消失
服务器与端口与来源完全相同任何地址或端口不同
TLS 与服务器名TLS 仍开启、SNI 相同、没有新增 skip-cert-verify: true证书校验被关闭
传输与路径WebSocket 或其它传输的路径和主机相同路径或主机为空或不同
UDP 标记与服务器实际支持一致为不支持 UDP 的服务器开启了 UDP

示例配置设置了 exclude_remarks=(到期|剩余流量|时间|官网|产品|平台),会丢弃名称中含有其中任一词的节点。[6] 它针对的是部分提供方加入的信息条目,但名称恰好匹配的真实节点也会消失。默认配置还会添加代理组和规则集,所以除了代理条目,也要检查路由规则。

把 converted.yaml 当作机密:它包含订阅里的全部凭据。导入时参考导入配置而不泄漏凭据中的注意事项;如果客户端会保存自己的副本,就删除本地文件。

如何长期保持 subconverter 自建服务的私密性?

只有本机进程能连接发布在回环地址上的端口,但这包括本机的所有用户和应用。请在单用户电脑上运行,转换完成后停止容器。同样的道理也适用于其它本地控制接口,例如 Mihomo 控制器 API:回环地址限制谁能连接,强密钥限制连上的进程能做什么。

让 subconv.env 和工作目录保持 0700 或 0600 权限。不要为了让其它设备访问而添加反向代理、端口转发或隧道,那会把私人工具重新变成一个持有所有人链接的转换服务。如果客户端需要自动更新,就在同一台电脑上定时转换,让客户端读取本地文件。

如何更新或删除?

更新时,到仓库查看新发布并阅读说明,再拉取新的固定标签。用 docker rm -f subconv-local 停止并删除旧容器,用同样的命令启动新标签,然后重复 /version、监听地址和输出核对。

彻底删除时,运行 docker rm -f subconv-local,用 docker image rm tindy2013/subconverter:0.9.0 删除镜像,再删除 ~/subconv。如果订阅链接曾经经过任何共享或公共系统,事后请找提供方重置。

总结

  • 本地转换让订阅链接和输出都留在你控制的电脑上。
  • 固定镜像版本、绑定 127.0.0.1、替换令牌,并关闭会记录链接的日志。
  • 0.9.0 版无法转换 VLESS、Hysteria2 和 TUIC 链接,要检查输出是否缺节点。
  • 导入前核对 TLS、传输与 UDP 字段,并把结果当作机密保存。

常见问题

本地运行 subconverter 对订阅链接就完全安全吗?

它把公共网站从链路中去掉了,但你的电脑、本机其他用户和订阅提供方仍然是风险点。工作文件和日志同样需要保护,不能只关注转换这一步。

为什么固定 0.9.0,而不是用 latest?

固定标签让你能阅读对应的发布说明,清楚自己运行的是哪个解析器和哪些默认值。latest 标签可能在两次转换之间悄悄变化,让审查过的内容失效。

为什么转换后我的 VLESS 节点不见了?

0.9.0 版的链接解析器没有处理 vless 链接的分支,所以这些条目会被跳过。请改用能直接读取原始订阅格式的客户端,不要依赖转换结果。

端口只在本机,还需要改默认 API 令牌吗?

需要。本机任何进程都能访问这个端口,而默认值是文档公开写明的 password,任何人都能立刻猜到,所以必须换成随机生成的长令牌。

容器日志会在哪里暴露订阅链接?

在默认的 info 级别下,0.9.0 版会记录每个被拉取的订阅链接。Docker 默认日志会保存这一行,所以本文直接关闭了容器日志,避免链接落盘。

可以把转换器开放给家里局域网的其他设备吗?

本文的配置不适合这样做。发布到网络后,每个用户的订阅链接都会暴露给这个服务,以及所有能访问它的人,等于重新建了一个转换站。

转换后的文件需要和链接一样保护吗?

需要。它包含订阅中的每个服务器地址、端口和密钥,请私密保存,并删除客户端已不再需要的副本,避免凭据在多个位置残留。

免责声明: 本文仅供一般信息参考,不构成法律、技术或其他专业建议。我们不保证内容的准确性、完整性或时效性。

来源:

  1. subconverter README — https://github.com/tindy2013/subconverter
  2. subconverter release v0.9.0 — https://github.com/tindy2013/subconverter/releases/tag/v0.9.0
  3. subconverter Docker README at v0.9.0 — https://github.com/tindy2013/subconverter/blob/v0.9.0/README-docker.md
  4. subconverter v0.9.0 subscription parser source — https://github.com/tindy2013/subconverter/blob/v0.9.0/src/parser/subparser.cpp
  5. subconverter v0.9.0 request handler source — https://github.com/tindy2013/subconverter/blob/v0.9.0/src/handler/interfaces.cpp
  6. subconverter v0.9.0 example preferences — https://github.com/tindy2013/subconverter/blob/v0.9.0/base/pref.example.ini
  7. subconverter v0.9.0 startup source — https://github.com/tindy2013/subconverter/blob/v0.9.0/src/main.cpp
  8. Docker Docs: Port publishing and mapping — https://docs.docker.com/engine/network/port-publishing/
  9. Docker Docs: Configure logging drivers — https://docs.docker.com/engine/logging/configure/

Sources checked 2026 年 10 月 14 日。

延伸阅读:

开启 3 天免费试用

注册即可免费体验全部高级功能。

*仅限新用户;每位用户只能获得一次试用。

subconverter 自建:在本机转换订阅,不交给公共转换站 | AethoVPN