2026-03-31 17:12:53 +08:00
2026-03-31 17:12:53 +08:00
opt
2026-03-31 17:00:00 +08:00
opt
2026-03-31 17:00:00 +08:00
2026-03-31 15:51:18 +08:00
2026-03-31 15:51:18 +08:00
2026-03-31 15:51:18 +08:00
opt
2026-03-31 17:00:00 +08:00
2026-03-31 15:51:18 +08:00
opt
2026-03-31 16:39:23 +08:00

sub-provider

一个可部署的订阅聚合后端模板,目标是同时支持两种输出方式:

  • 薄壳模式:客户端拉取 /clients/*.yaml,配置内继续引用远程 proxy-providers / rule-providers
  • 打包模式:客户端拉取 /bundle/*.yaml,服务端把节点、策略组、规则全部铺开成单文件 YAML

这一版已经补上:

  • 多机场源选择:?sources=airport-a,airport-b
  • 单机场或多机场时,始终取第一个源Subscription-Userinfo 返回给客户端
  • GETHEAD 都支持
  • provider 单源输出、merged provider 输出、thin client 输出、bundle 输出
  • 服务端内部继续解耦抓取、配额头解析、provider 构建、规则加载、profile 组装分层处理

当前版本会自动识别上游输入格式,支持:

  1. 已经能返回 Clash/Mihomo YAML proxies: 文件的地址
  2. base64 编码的 URI 订阅
  3. 明文 URI 订阅

当前已兼容常见的 anytls://vless://trojan://ss://vmess://


目录结构

sub-provider/
  app/
    config.py
    main.py
    models.py
    services/
      cache.py
      headers.py
      loader.py
      profiles.py
      rules.py
      subscriptions.py
  config/
    sources.yaml
    rules/
      reject.yaml
      direct.yaml
      proxy.yaml
      cn-ip.yaml
  data/
    cache/
  .env.example
  Dockerfile
  docker-compose.yaml
  requirements.txt

快速开始

  1. 复制环境变量文件:
cp .env.example .env
  1. 编辑 .env
  • PUBLIC_PATH 改成足够长的随机字符串
  • PUBLIC_BASE_URL 建议填写你反代后的最终访问地址,例如 https://sub.example.com
  • AIRPORT_A_URL / AIRPORT_B_URL 都可以直接填订阅地址,项目会自动判断是 YAML 还是 URI 订阅
  • 允许把其中一个留空;留空时这个机场会自动跳过
  1. 启动:
docker compose up -d --build
  1. 访问检查:
  • 健康检查:http://YOUR_HOST:18080/healthz
  • 单 provider https://YOUR_DOMAIN/<PUBLIC_PATH>/providers/airport-a.yaml
  • merged provider https://YOUR_DOMAIN/<PUBLIC_PATH>/providers/merged.yaml?sources=airport-a,airport-b
  • Mihomo/OpenClash 薄壳入口: https://YOUR_DOMAIN/<PUBLIC_PATH>/clients/mihomo.yaml?sources=airport-a,airport-b
  • Stash 薄壳入口: https://YOUR_DOMAIN/<PUBLIC_PATH>/clients/stash.yaml?sources=airport-a,airport-b
  • Mihomo/OpenClash bundle https://YOUR_DOMAIN/<PUBLIC_PATH>/bundle/mihomo.yaml?sources=airport-a,airport-b
  • Stash bundle https://YOUR_DOMAIN/<PUBLIC_PATH>/bundle/stash.yaml?sources=airport-a,airport-b

接口说明

1. 单 provider

GET /<PUBLIC_PATH>/providers/{name}.yaml
HEAD /<PUBLIC_PATH>/providers/{name}.yaml

返回指定机场源的 provider 文件,并携带这个源的 Subscription-Userinfo(如果上游有)。

2. merged provider

GET /<PUBLIC_PATH>/providers/merged.yaml?sources=airport-a,airport-b
HEAD /<PUBLIC_PATH>/providers/merged.yaml?sources=airport-a,airport-b

把多个 provider 合并成一个 proxies: 文件返回。响应头只取 sources 参数里第一个源的配额信息。

3. 薄壳客户端配置

GET /<PUBLIC_PATH>/clients/mihomo.yaml?sources=airport-a,airport-b
GET /<PUBLIC_PATH>/clients/stash.yaml?sources=airport-a,airport-b
HEAD /<PUBLIC_PATH>/clients/mihomo.yaml?sources=airport-a,airport-b
HEAD /<PUBLIC_PATH>/clients/stash.yaml?sources=airport-a,airport-b

特点:

  • 客户端收到的是轻量入口配置
  • 节点更新依赖远程 proxy-providers
  • 规则更新依赖远程 rule-providers
  • 响应头同样只取第一个源的 Subscription-Userinfo

4. bundle 单文件配置

GET /<PUBLIC_PATH>/bundle/mihomo.yaml?sources=airport-a,airport-b
GET /<PUBLIC_PATH>/bundle/stash.yaml?sources=airport-a,airport-b
HEAD /<PUBLIC_PATH>/bundle/mihomo.yaml?sources=airport-a,airport-b
HEAD /<PUBLIC_PATH>/bundle/stash.yaml?sources=airport-a,airport-b

特点:

  • 服务端把节点、策略组、规则全部展开到一个 YAML 里
  • 适合想直接给 Mihomo Party / Clash Party / Stash 一个最终链接的场景
  • 响应头同样只取第一个源的 Subscription-Userinfo

默认策略结构

当前默认生成的策略组是一个基础版:

  • ☁️ 机场选择
  • ♻️ 自动选择
  • 🚀 手动切换
  • 🇭🇰 香港自动
  • 🇸🇬 新加坡自动
  • 🇯🇵 日本自动
  • 🇺🇸 美国自动
  • 节点选择

其中:

  • ☁️ 机场选择 允许在“混合自动”和各机场单独自动组之间切换
  • 节点选择 是最终主策略组
  • bundle 模式会把节点名全部展开
  • thin 模式会保留 provider 引用关系

你后面要继续进阶的话,最值得加的是:

  • policies.yaml:把 Telegram / AI / YouTube / Netflix 这类业务组模板化
  • regions.yaml:把更多地区从 sources.yaml 独立出去
  • URI/base64 原始订阅解析
  • 鉴权层(例如前置 Caddy/Nginx Basic Auth 或仅 Tailscale 可访问)

配额头策略

为了避免聚合多个机场后“总流量怎么显示”语义混乱,这个版本统一采用:

  • sources 只填一个机场源:返回这个机场源的配额信息
  • sources 填多个机场源:只取第一个机场源的 Subscription-Userinfo

这样 Stash、Clash Party 这类客户端读取配置订阅头时,行为是稳定可预期的。

Description
No description provided
Readme 175 KiB
Languages
Python 99.2%
Dockerfile 0.8%