最后更新于:2026年06月

订阅转换
subconverter 订阅转换指南

当你管理多节点、多协议、多用户订阅时,原始订阅链接往往格式不统一、节点数量杂乱无章。订阅转换正是解决这个问题的利器——它能把各种格式的订阅链接统一转换成 Clash/Mihomo/Shadowrocket 等客户端支持的格式,同时应用自定义规则策略、重命名节点、启用 Emoji 美化,一键生成整洁可用的配置文件。

本文将带你从零了解 subconverter 的工作原理,手动搭建本地订阅转换服务,定制 ACL 分流规则,并实现 CI/CD 自动化订阅管理。


🔑 订阅转换基础:为什么需要它?

原始订阅的问题

不同机场/服务商使用的订阅协议五花八门:

PLAINTEXT
┌────────────────────────────────────────────────────┐
│  原始订阅格式                                    │
│                                                   │
│  [SS 订阅] - SIP008 JSON 格式                     │
│  [Trojan 订阅] - Base64 + URL scheme             │
│  [VLESS 订阅] - vless://xxx 链接                 │
│  [混合订阅] - 多种协议链接的混合 Base64 编码       │
│  [Shadowrocket 订阅] - 私有格式                   │
│                                                   │
│  问题:                                          │
│  - 节点数量庞大,难以管理                         │
│  - 无规则策略,所有流量默认走代理                  │
│  - 节点名称无标准化                               │
│  - 无法跨客户端共享                              │
└────────────────────────────────────────────────────┘

订阅转换的价值

PLAINTEXT
┌────────────────────────────────────────────────────┐
│  订阅转换能做什么                                 │
│                                                   │
│  1. 协议统一                                      │
│     SSR/SS/VLESS/Trojan/Wireguard/UDP           │
│     → 统一转换为 Clash/Mihomo/sing-box 配置       │
│                                                   │
│  2. 规则注入                                      │
│     加入分流规则(国内直连、国外代理、广告拦截)   │
│                                                   │
│  3. 节点管理                                      │
│     去重、重命名、排序、标记、过滤协议类型         │
│                                                   │
│  4. 策略组配置                                    │
│     自动/手动选择、故障转移、负载均衡             │
│                                                   │
│  5. 订阅合并                                      │
│     多个订阅链接合并为一个订阅                     │
│                                                   │
│  6. 规则订阅                                      │
│     引用远程规则(Loyalsoldier/clash-rules 等)   │
└────────────────────────────────────────────────────┘

📦 subconverter:开源订阅转换核心

subconverter 是什么?

subconverter 是目前最流行的开源订阅转换工具,由 Chinese 社区开发维护,C++ 编写,性能优异。

PLAINTEXT
核心架构:

┌──────────────┐      ┌──────────────────────┐     ┌───────────────┐
│ 原始订阅链接 │ ──► │ subconverter 转换引擎 │ ──►│ 目标格式配置  │
│ (多种格式)   │      │  - 协议解析           │     │ (Clash/Mihomo)│
└──────────────┘      │  - 节点标准化         │     └───────────────┘
                       │  - 规则模板应用        │
                       │  - 策略组注入          │
                       │  - Emoji/国旗标记      │
                       └──────────────────────┘

特点:

subconverter 安装部署

方式一:Docker 部署(推荐,最简单)

BASH
# 拉取最新镜像
docker pull tindy2013/subconverter:latest

# 启动容器
docker run -d \
  --name=subconverter \
  --restart=always \
  -p 25500:25500 \
  tindy2013/subconverter:latest

# 测试是否正常
curl http://127.0.0.1:25500/sub?target=clash
# 应返回一个 JSON 格式的 Clash 配置骨架

方式二:二进制文件安装

BASH
# 下载最新版本(Linux amd64)
VERSION=$(curl -s https://api.github.com/repos/tindy2013/subconverter/releases/latest | grep tag_name | cut -d '"' -f 4)
curl -fsSL https://github.com/tindy2013/subconverter/releases/download/$VERSION/subconverter_linux64.tar.gz

# 解压
tar -xzvf subconverter_linux64.tar.gz
cd subconverter/

# 启动
./subconverter --backend &

# 后台运行(使用 systemd)
cat > /etc/systemd/system/subconverter.service << 'EOF'
[Unit]
Description=subconverter service
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/opt/subconverter
ExecStart=/opt/subconverter/subconverter
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now subconverter

方式三:自建 Web UI 订阅转换(sub-web)

BASH
# 部署 sub-web(提供前端 UI)
docker run -d \
  --name=sub-web \
  --restart=always \
  -p 80:80 \
  -e API_URL=http://127.0.0.1:25500 \
  careywong/subweb:latest

# 访问 http://your-server-ip 即可使用图形界面

🔧 subconverter 核心参数详解

subconverter 通过 HTTP GET 请求的参数控制转换行为:

PLAINTEXT
完整请求模板:

http://127.0.0.1:25500/sub?
  target=clash&
  url=URL编码后的订阅链接&
  insert=true&
  config=ACL模板&
  emoji=true&
  list=true&
  sort=true&
  tfo=true&
  udp=true&
  scv=true&
  fdn=true&
  file=自定义文件名

参数详解

参数 取值 说明
target clash/clashr/clashmeta/mixed/singbox/surge/surfboard/kitsunebi 目标客户端格式
url Base64 编码的订阅链接(可用 ` ` 分隔多个)
config ACL 模板文件名 / URL 规则模板
emoji true/false 是否添加国旗 Emoji
list true/false 是否列出所有 Clash 支持的节点类型
sort true/false 是否按延迟/负载排序
tfo true/false 是否启用 TCP Fast Open
udp true/false 是否启用 UDP 支持
scv true/false 是否启用 TLS SNI
fdn true/false 使用自定义域名(过滤域名)
insert true/false 是否添加附加节点(DIRECT/REJECT 等)
file 字符串 自定义下载文件名

实战:基础订阅转换

BASH
# 示例 1: 转换单个订阅为 Clash 格式,添加国旗
curl "http://127.0.0.1:25500/sub?target=clash&url=aHR0cHM6Ly9leGFtcGxlLmNvbS9zdWJzY3JpcHRpb24&emoji=true&list=true" -o config.yaml

# 示例 2: 合并多个订阅为 Clash.Meta 格式
# 假设 sub1_url 和 sub2_url 是两个订阅链接
SUB1=$(echo -n "https://example1.com/subscription" | base64 -w0)
SUB2=$(echo -n "https://example2.com/subscription" | base64 -w0)

curl "http://127.0.0.1:25500/sub?target=clashmeta&url=${SUB1}|${SUB2}&config=ACL4SSR_Online_NoAuto.ini&emoji=true" \
  -o merged_config.yaml

# 示例 3: 指定 ACL 规则模板
curl "http://127.0.0.1:25500/sub?target=clash&url=${SUB_URL}&config=https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini&emoji=true" \
  -o custom_config.yaml

# 示例 4: 启用 TFO + UDP(高性能)
curl "http://127.0.0.1:25500/sub?target=clash&url=${SUB_URL}&tfo=true&udp=true&sort=true" \
  -o performance_config.yaml

🎯 ACL 规则模板:自定义分流策略

ACL 模板是什么?

ACL(Access Control List)模板定义了转换后的 Clash 配置结构:

常用 ACL 模板

BASH
# 方式一: 使用内置模板(subconverter 自带)
# 文件名: ACL4SSR_Online.ini、ACL4SSR_Online_Full.ini 等

# 方式二: 使用远程模板(实时更新)
# GitHub 上的高质量 ACL 模板:
# https://github.com/ACL4SSR/ACL4SSR/tree/master/Clash/config
# https://github.com/Loyalsoldier/clash-rules/tree/master
# https://github.com/GeQ1an/Rules/blob/master/Clash/ACL4SSR.ini

# 使用远程模板
curl "http://127.0.0.1:25500/sub?target=clash&url=${SUB_URL}&config=https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online_NoAuto.ini"

自定义 ACL 模板结构

INI
; 完整 ACL 模板示例(ACL4SSR_Online.ini)
; 说明:以分号开头的行为注释

; ─────────────────────────────────────────
; 1. [custom] 节点自定义配置
; ─────────────────────────────────────────

[custom]
; 是否添加 Emoji 标志(已通过 emoji 参数控制)
; 设置自定义参数,会覆盖全局设置

; ─────────────────────────────────────────
; 2. [common] 通用配置
; ─────────────────────────────────────────

[common]
; 端口配置
port=7890
socks-port=7891
allow-lan=true
mode=rule
log-level=warning
external-controller=127.0.0.1:9090

; DNS 配置
dns-server=223.5.5.5, 119.29.29.29, 8.8.8.8, https://1.1.1.1/dns-query

; 其他配置
tcp-fast-open=true
udp=true

; ─────────────────────────────────────────
; 3. [proxy_group] 策略组配置
; ─────────────────────────────────────────

; 格式: 组名, 组类型, 节点选择规则

[proxy_group]
; 主策略组:手动选择
🚀 节点选择,select,[]
⚡ 自动选择,url-test,[]
♻️ 故障转移,fallback,[]

; 按地区策略组
🇭🇰 香港节点,select,[]
🇯🇵 日本节点,select,[]
🇺🇸 美国节点,select,[]
🇸🇬 新加坡节点,select,[]
🇹🇼 台湾节点,select,[]

; 特殊策略
🎯 全球直连,select,[]
🐟 漏网之鱼,select,[]
🛑 广告拦截,select,[]

; ─────────────────────────────────────────
; 4. [rule] 规则配置
; ─────────────────────────────────────────

; 格式: 规则文件 URL, 策略组名, 规则类型, 是否优先

[rule]
; 广告与追踪拦截
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt,🛑 广告拦截
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/gfw.txt,🚀 节点选择

; 国内直连
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/cn.txt,🎯 全球直连
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/direct.txt,🎯 全球直连

; 代理规则
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/proxy.txt,🚀 节点选择
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/telegram.txt,🚀 节点选择
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/apple.txt,🚀 节点选择

; 流媒体规则
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/netflix.txt,🎬 流媒体
https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/spotify.txt,🎬 流媒体

; 默认规则(匹配所有未被上面规则命中的请求)
[]FINAL,🐟 漏网之鱼

规则集的组织方式

Clash 规则有两种类型:经典规则行和规则集(Rule Provider):

PLAINTEXT
规则结构对比:

┌──────────────────────────────────────────────────┐
│  传统规则(完整嵌入配置)                         │
│                                                   │
│  rules:                                           │
│    - DOMAIN-SUFFIX,google.com,🚀 节点选择         │
│    - DOMAIN-SUFFIX,youtube.com,🚀 节点选择        │
│    - ... (数百行,占文件体积大)                   │
│                                                   │
│  优点: 无需额外请求                                │
│  缺点: 文件大、更新需要重新生成配置                │
└──────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────┐
│  Rule Provider(规则集远程引用)                   │
│                                                   │
│  rule-providers:                                   │
│    reject:                                         │
│      type: http                                    │
│      behavior: domain                              │
│      url: https://example.com/reject.list         │
│      path: ./ruleset/reject.yaml                   │
│      interval: 86400                              │
│                                                   │
│  rules:                                           │
│    - RULE-SET,reject,🛑 广告拦截                  │
│    - RULE-SET,proxy,🚀 节点选择                   │
│    - ... (仅需少量引用行)                         │
│                                                   │
│  优点: 文件小、自动更新、易于维护                   │
│  缺点: 首次启动需要下载规则集                       │
└──────────────────────────────────────────────────┘

🎨 节点命名与管理

Emoji / 国旗标记

subconverter 能根据节点名称自动添加国旗 Emoji:

PLAINTEXT
原始节点名:              转换后:
HK-Node-01           →  🇭🇰 HK-Node-01
JP-Tokyo-01          →  🇯🇵 JP-Tokyo-01
US-LA-01             →  🇺🇸 US-LA-01
Singapore-01         →  🇸🇬 Singapore-01
Taiwan-01            →  🇹🇼 Taiwan-01
Shanghai             →  🇨🇳 Shanghai

参数控制:

BASH
# emoji=true          # 添加国旗
# list=true           # 使用完整规则列表(支持更多节点类型)
# sort=true           # 按节点名称排序

节点过滤与去重

BASH
# 通过参数或 ACL 过滤特定类型节点
# 1. 只保留特定协议节点(在 ACL 中配置)

# 2. 自定义过滤规则(在 ACL 的 [custom] 部分配置)
# 例如只保留香港、日本、美国节点
include=香港|日本|美国|新加坡|台湾
exclude=测试|过期|流量

# 3. 去重
# subconverter 自动根据服务器 IP + 端口去重

重命名规则

可以在 ACL 模板中自定义节点重命名规则:

PLAINTEXT
# 在 ACL 中自定义节点名称处理
# 配合 emoji 参数,把节点名变得更友好

原始: vless-tls-hk-node01.example.com:443
转换后: 🇭🇰 香港 01

🏗️ 自建订阅转换服务实战

方案一:VPS + Docker 完整部署

BASH
# 1. 部署 subconverter 后端
docker run -d \
  --name=subconverter \
  --restart=always \
  -p 25500:25500 \
  -v /opt/subconverter:/base \
  tindy2013/subconverter:latest

# 2. 部署 sub-web 前端
docker run -d \
  --name=sub-web \
  --restart=always \
  -p 80:80 \
  -e API_URL=http://127.0.0.1:25500 \
  careywong/subweb:latest

# 3. 添加 Nginx 反向代理(可选,便于 HTTPS)
# /etc/nginx/conf.d/subconverter.conf
server {
    listen 443 ssl http2;
    server_name sub.example.com;

    ssl_certificate /etc/letsencrypt/live/sub.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:25500;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

# 4. 测试
curl "https://sub.example.com/sub?target=clash&url=${SUB_URL}&config=ACL4SSR_Online.ini&emoji=true"

方案二:本地部署 + 定时生成配置

BASH
#!/bin/bash
# /opt/scripts/update_subscription.sh
# 定期更新订阅的脚本

# 配置变量
SUB_URL="https://your-airport.com/subscription/link"
SUB_BASE64=$(echo -n "$SUB_URL" | base64 -w0)
OUTPUT_DIR="/opt/subscriptions"
SUB_HOST="http://127.0.0.1:25500"

# 创建输出目录
mkdir -p "$OUTPUT_DIR"

# 生成不同目标格式
echo "[1/5] 生成 Clash 配置..."
curl -s "${SUB_HOST}/sub?target=clash&url=${SUB_BASE64}&config=ACL4SSR_Online.ini&emoji=true&list=true&tfo=true&udp=true" \
  -o "$OUTPUT_DIR/clash_config.yaml"

echo "[2/5] 生成 Clash.Meta 配置..."
curl -s "${SUB_HOST}/sub?target=clashmeta&url=${SUB_BASE64}&config=ACL4SSR_Online.ini&emoji=true&list=true&tfo=true&udp=true" \
  -o "$OUTPUT_DIR/clashmeta_config.yaml"

echo "[3/5] 生成 Mihomo 配置..."
curl -s "${SUB_HOST}/sub?target=mihomo&url=${SUB_BASE64}&config=ACL4SSR_Online.ini&emoji=true&list=true&tfo=true&udp=true" \
  -o "$OUTPUT_DIR/mihomo_config.yaml"

echo "[4/5] 生成 sing-box 配置..."
curl -s "${SUB_HOST}/sub?target=singbox&url=${SUB_BASE64}&config=ACL4SSR_Online.ini&emoji=true" \
  -o "$OUTPUT_DIR/singbox_config.json"

echo "[5/5] 生成 Shadowrocket 配置..."
curl -s "${SUB_HOST}/sub?target=shadowrocket&url=${SUB_BASE64}&emoji=true" \
  -o "$OUTPUT_DIR/shadowrocket_config.yaml"

# 输出统计
echo ""
echo "✅ 订阅更新完成: $(date +'%Y-%m-%d %H:%M:%S')"
ls -lh "$OUTPUT_DIR"/*.yaml "$OUTPUT_DIR"/*.json

设置定时任务:

BASH
# 添加到 crontab,每 6 小时更新一次
crontab -e
# 0 */6 * * * /opt/scripts/update_subscription.sh >> /var/log/subscription.log 2>&1

# 或者使用 systemd timer
cat > /etc/systemd/system/subscription.service << 'EOF'
[Unit]
Description=Update subscription configs
After=network.target

[Service]
Type=oneshot
ExecStart=/bin/bash /opt/scripts/update_subscription.sh

[Install]
WantedBy=multi-user.target
EOF

cat > /etc/systemd/system/subscription.timer << 'EOF'
[Unit]
Description=Update subscription every 6 hours

[Timer]
OnBootSec=5min
OnUnitActiveSec=6h
Unit=subscription.service

[Install]
WantedBy=timers.target
EOF

systemctl enable --now subscription.timer

🔄 订阅合并:多订阅统一管理

为什么要合并?

如果你同时使用多个机场/服务提供商的订阅,合并订阅能带来这些好处:

  1. 统一出口:所有节点在一个配置文件中
  2. 统一策略:一套规则应用到所有节点
  3. 故障切换:一个机场故障时自动切换到另一个
  4. 最佳节点:从多个服务商的节点中选择最快的

合并命令

BASH
# 方式一:通过 subconverter 直接合并
# 使用 | 分隔多个订阅链接

SUB1=$(echo -n "https://airport1.com/sub" | base64 -w0)
SUB2=$(echo -n "https://airport2.com/sub" | base64 -w0)
SUB3=$(echo -n "https://airport3.com/sub" | base64 -w0)

# 合并三个订阅为一个 Clash 配置
curl "http://127.0.0.1:25500/sub?target=clash&url=${SUB1}|${SUB2}|${SUB3}&config=ACL4SSR_Online.ini&emoji=true&sort=true" \
  -o merged_subscription.yaml

# 方式二:通过 shell 脚本合并(更灵活)
#!/bin/bash
# 合并多个订阅并保留各机场标记

MERGED=""

for i in 1 2 3; do
    SUB_URL="https://airport${i}.com/sub"
    SUB_B64=$(echo -n "$SUB_URL" | base64 -w0)

    # 为每个机场的节点添加机场前缀
    curl -s "http://127.0.0.1:25500/sub?target=clash&url=${SUB_B64}&emoji=true" \
      -o /tmp/airport_${i}.yaml

    # 从各配置中提取节点信息(复杂,需要 YAML 处理工具)
    # ...
done

# 方式三:使用 Python/YAML 处理合并
# 适合需要精细控制的场景

合并后的策略组设计

YAML
# 合并后的策略组结构示例

proxy-groups:
  - name: "🚀 节点选择"
    type: select
    proxies:
      - ⚡ 自动选择
      - 🛫 机场A
      - 🛫 机场B
      - 🛫 机场C

  - name: "⚡ 自动选择"
    type: url-test
    proxies:
      - 🛫 机场A
      - 🛫 机场B
      - 🛫 机场C

  - name: "🛫 机场A"
    type: select
    use:
      - airport_a_provider   # 来自订阅 A 的节点

  - name: "🛫 机场B"
    type: select
    use:
      - airport_b_provider   # 来自订阅 B 的节点

  - name: "🛫 机场C"
    type: select
    use:
      - airport_c_provider   # 来自订阅 C 的节点

# 使用 Proxy Provider 管理各机场的节点
proxy-providers:
  airport_a:
    type: http
    url: https://airport1.com/subscription
    path: ./proxy_providers/airport_a.yaml
    interval: 3600

  airport_b:
    type: http
    url: https://airport2.com/subscription
    path: ./proxy_providers/airport_b.yaml
    interval: 3600

🔧 高级功能:自定义规则与模板

自定义 Clash 配置(完整示例)

YAML
# 自定义 ACL 模板输出的完整 Clash 配置
# 文件名: /opt/subconverter/configs/my_custom.ini

[common]
port=7890
socks-port=7891
allow-lan=true
mode=rule
log-level=warning
ipv6=false
external-controller=127.0.0.1:9090
tcp-fast-open=true

[dns]
enable=true
ipv6=false
enhanced-mode=fake-ip
fake-ip-range=198.18.0.1/16
nameserver=223.5.5.5,119.29.29.29
fallback=1.1.1.1,8.8.8.8
fallback-filter=geoip:cn,ipcidr:240.0.0.0/4

[proxy_group]
🚀 节点选择,select
⚡ 自动选择,url-test
🇭🇰 香港节点,select
🇯🇵 日本节点,select
🇺🇸 美国节点,select
🎯 全球直连,select
🐟 漏网之鱼,select
🛑 广告拦截,select

[rule]
; 广告拦截
https://example.com/rules/reject.list,🛑 广告拦截

; 国内直连
https://example.com/rules/cn.list,🎯 全球直连
https://example.com/rules/direct.list,🎯 全球直连

; 代理规则
https://example.com/rules/gfw.list,🚀 节点选择
https://example.com/rules/proxy.list,🚀 节点选择

; 默认规则
[]FINAL,🐟 漏网之鱼

使用 Python 进行高级处理

适合对配置有完全控制需求的场景:

PYTHON
#!/usr/bin/env python3
# subscription_manager.py - 高级订阅管理器

import yaml
import requests
import base64
from datetime import datetime

class SubscriptionManager:
    def __init__(self, subconverter_host="http://127.0.0.1:25500"):
        self.host = subconverter_host

    def convert(self, sub_url, target="clash", config="ACL4SSR_Online.ini"):
        """转换单个订阅"""
        url_b64 = base64.b64encode(sub_url.encode()).decode()

        params = {
            "target": target,
            "url": url_b64,
            "config": config,
            "emoji": "true",
            "list": "true",
            "tfo": "true",
            "udp": "true",
        }

        resp = requests.get(f"{self.host}/sub", params=params)
        return resp.text

    def merge(self, subscriptions, output_path):
        """合并多个订阅为单个配置"""
        all_configs = []
        for name, url in subscriptions:
            config_text = self.convert(url, target="clash")
            config = yaml.safe_load(config_text)

            # 为节点名添加机场前缀,避免重名
            for proxy in config.get("proxies", []):
                proxy["name"] = f"[{name}] {proxy['name']}"

            all_configs.append(config)

        # 合并所有节点
        merged = {
            "port": 7890,
            "socks-port": 7891,
            "allow-lan": True,
            "mode": "rule",
            "log-level": "warning",
            "proxies": [],
            "proxy-groups": [
                {
                    "name": "🚀 节点选择",
                    "type": "select",
                    "proxies": [p["name"] for c in all_configs for p in c["proxies"]]
                }
            ],
            "rules": all_configs[0].get("rules", []) if all_configs else []
        }

        # 收集所有节点
        for config in all_configs:
            merged["proxies"].extend(config.get("proxies", []))

        # 写入文件
        with open(output_path, "w", encoding="utf-8") as f:
            yaml.dump(merged, f, allow_unicode=True, default_flow_style=False)

        print(f"✅ 合并完成: {output_path} ({len(merged['proxies'])} 个节点)")
        return output_path

    def generate_html_index(self, configs):
        """生成 HTML 索引页面(便于手机下载)"""
        html = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>我的订阅配置</title>
    <style>
        body {{ font-family: -apple-system, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }}
        h1 {{ color: #2c3e50; }}
        ul {{ list-style: none; padding: 0; }}
        li {{ margin: 10px 0; padding: 15px; background: #f8f9fa; border-radius: 8px; }}
        a {{ color: #3498db; text-decoration: none; font-weight: 600; }}
        a:hover {{ text-decoration: underline; }}
        .updated {{ color: #7f8c8d; font-size: 12px; margin-top: 20px; }}
    </style>
</head>
<body>
    <h1>📱 我的订阅配置</h1>
    <ul>
"""

        for name, filename in configs:
            html += f'        <li><a href="{filename}">{name}</a></li>\n'

        html += f"""    </ul>
    <div class="updated">最后更新: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</div>
</body>
</html>"""

        return html


# 使用示例
if __name__ == "__main__":
    manager = SubscriptionManager()

    # 合并多个订阅
    subscriptions = [
        ("机场A", "https://airport1.com/sub"),
        ("机场B", "https://airport2.com/sub"),
    ]

    merged = manager.merge(subscriptions, "/var/www/subscriptions/merged.yaml")
    html = manager.generate_html_index([("合并订阅", "merged.yaml")])

    # 保存索引页
    with open("/var/www/subscriptions/index.html", "w", encoding="utf-8") as f:
        f.write(html)

    print("完成!")

🔍 故障排查手册

问题 1:subconverter 无法连接

BASH
# 检查容器是否运行
docker ps | grep subconverter

# 检查端口监听
ss -tlnp | grep 25500

# 直接测试转换服务
curl -v http://127.0.0.1:25500/

# 检查日志
docker logs subconverter --tail 50

问题 2:订阅解析失败(返回空配置或错误)

PLAINTEXT
常见原因:
1. 订阅链接本身无法访问
   → 用 curl 直接测试订阅链接是否可下载
   curl -v "https://your-airport.com/subscription"

2. 订阅格式不被支持
   → 查看 subconverter 支持的格式
   → 尝试手动解析订阅内容(Base64 解码)

3. 编码问题
   → 确保 URL 中的订阅链接正确 Base64 编码
   → 如果订阅链接包含特殊字符,需要双重编码

4. 网络问题(VPS 无法访问订阅服务器)
   → 测试 VPS 的网络连通性
   → 检查 DNS 解析

问题 3:生成的配置无法使用

YAML
# 检查生成的 YAML 格式是否正确
python3 -c "import yaml; yaml.safe_load(open('config.yaml'))"

# 在 Clash/Mihomo 客户端测试
# 观察客户端日志中的错误信息

# 常见问题:
# 1. 节点名重复 → 在 ACL 中开启去重
# 2. 协议不被支持 → 更新客户端或调整转换目标
# 3. 规则集 URL 无法访问 → 检查 VPS 是否能访问 GitHub
# 4. DNS 配置问题 → 手动覆盖 DNS 配置部分

# 修复方法: 调整 ACL 模板
# 或者在生成的配置上进行后处理

问题 4:规则集无法下载

BASH
# 确保 VPS 能访问 GitHub
curl -I https://raw.githubusercontent.com/Loyalsoldier/clash-rules/release/reject.txt

# 如果无法访问,考虑使用镜像或 CDN
# 替换为 FastGit 等国内镜像
# https://raw.fastgit.org/Loyalsoldier/clash-rules/release/reject.txt

# 或者使用本地规则文件
# 1. 下载规则文件到本地
# 2. 在 subconverter 配置中使用本地路径

# 使用 sing-box 规则集(如果 sing-box 作为客户端)
# 格式与 Clash 有所不同,需要调整

问题 5:节点去重不工作

PLAINTEXT
在 ACL 模板的 [custom] 部分添加去重规则
或在请求参数中添加 sort=true

问题通常出现在:
1. 同一节点使用不同名称/端口(例如 IP vs 域名)
2. 不同机场共用同一节点(CDN 架构)
3. UDP 与 TCP 被识别为不同节点

解决方案:
→ 使用 YAML 工具后处理去重
→ 在 ACL 模板中添加 include/exclude 规则
→ 手动指定保留/排除名单

问题 6:Emoji/国旗标记不正确

PLAINTEXT
可能原因:
1. 节点名称不符合解析规则
2. subconverter 的国旗映射表不完整
3. 某些国家代码未被识别

解决方案:
→ 在 ACL 模板的 custom 部分自定义映射
→ 手动重命名节点(使用 Python/YAML 后处理)
→ 添加自定义国旗规则

配置示例:
在 subconverter 的配置中添加自定义节点名称处理:
[custom]
custom-host=
# 自定义节点名替换规则
custom=🇭🇰 香港|🇯🇵 日本|🇺🇸 美国|🇸🇬 新加坡|🇹🇼 台湾|🇬🇧 英国|🇩🇪 德国

📱 订阅订阅:手机端使用

iOS 端订阅

PLAINTEXT
Shadowrocket (小火箭):
1. 打开 Shadowrocket → 配置 → 导入配置
2. 从 URL 导入: https://your-domain.com/config.yaml
3. 或使用内置的订阅功能: 配置 → 订阅 → 添加
4. 填入转换后的 Clash 配置 URL

注意: 推荐使用 subconverter 的 shadowrocket 目标格式

Android 端订阅

PLAINTEXT
Clash for Android / Clash Meta for Android:
1. 配置 → 从 URL 导入
2. 填入: https://your-domain.com/clashmeta_config.yaml
3. 自动更新: 设置每 24 小时更新一次

NekoBox / sing-box:
1. 配置 → 分组或订阅
2. 添加转换后的配置 URL
3. sing-box 需要 sing-box 目标格式

自动更新订阅

YAML
# 在客户端配置中启用自动更新(Clash for Android)
# 1. 添加订阅配置
# 2. 设置更新间隔(推荐 6-12 小时)
# 3. 启用"自动更新"

# 使用 subconverter 的订阅链接格式:
https://your-subconverter-domain.com/sub?target=clashmeta&url=BASE64_URL&config=ACL4SSR_Online.ini&emoji=true&list=true&tfo=true&udp=true

# 客户端会周期性请求该 URL,获取最新配置

🚀 最佳实践总结

1. 推荐的部署架构

PLAINTEXT
┌──────────────────────────────────────────────────┐
│           完整订阅管理架构                        │
│                                                   │
│  原始订阅 (机场)                                  │
│      │                                            │
│      ▼                                            │
│  ┌─────────────────────────┐                      │
│  │  subconverter 转换服务  │ ← Docker 容器        │
│  │  + ACL 规则模板          │                      │
│  │  + Emoji 标记            │                      │
│  │  + 节点管理              │                      │
│  └─────────┬──────────────┘                      │
│            │                                     │
│    ┌──────┴─────────┐                           │
│    ▼                ▼                           │
│  静态文件服务器    管理脚本                        │
│  (Nginx)         (Cron/Systemd)                  │
│    │                │                            │
│    └────────┬───────┘                            │
│             ▼                                    │
│    生成的配置文件                                  │
│    - clash_config.yaml                           │
│    - clashmeta_config.yaml                       │
│    - singbox_config.json                         │
│    - shadowrocket_config.yaml                    │
│                                                   │
│   用户端(手机/电脑)                              │
│   - 配置 URL 自动更新                             │
│   - 6-12 小时刷新一次                            │
└──────────────────────────────────────────────────┘

2. 维护技巧

3. 安全注意事项

PLAINTEXT
⚠️  自建订阅转换服务的安全要点:

1. 限制访问来源
   - 使用 Nginx 的 allow/deny 规则
   - 或使用基本认证 (Basic Auth)

2. 避免暴露订阅链接
   - 不要在公开场合分享你的完整订阅链接
   - 订阅转换服务应该只在内部或受控网络中运行

3. 使用 HTTPS
   - 为订阅转换服务配置 TLS 证书
   - 使用 Let's Encrypt 自动续期

4. 定期更新 subconverter
   - 关注 GitHub Release
   - 使用 Docker 时: docker pull tindy2013/subconverter:latest && docker restart subconverter

5. 节点去重与隐私
   - 避免在节点名称中暴露敏感信息(如真实 IP)
   - 使用 ACL 模板过滤不需要的协议和节点

结语

订阅转换是代理管理的"最后一公里"——它让零散的订阅链接变成整洁可用的客户端配置。掌握 subconverter 和 ACL 模板,你可以:

建议的日常流程:

PLAINTEXT
每天/每 6 小时:
  subconverter 从各机场拉取订阅
  ↓
  应用 ACL 规则模板(规则集自动从 GitHub 更新)
  ↓
  生成不同客户端格式的配置文件
  ↓
  部署到静态文件服务器 (Nginx)
  ↓
  手机/电脑通过 URL 自动更新

订阅转换是一项"配置一次,长期受益"的工作。花几个小时搭建好你的私有订阅转换服务,就能获得自动化、稳定、灵活的代理配置管理体验。

愿你的订阅管理从此简单高效!🎯

版权声明

作者: 易邦

链接: https://blog.e8k.net/posts/subconverter-subscription-management/

许可证: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。