This commit is contained in:
riglen
2026-03-31 15:51:18 +08:00
parent e3cc26d4f6
commit 0d49398e2d
21 changed files with 1483 additions and 0 deletions

178
README.md
View File

@@ -1,2 +1,180 @@
# sub-provider
一个可部署的订阅聚合后端模板,目标是同时支持两种输出方式:
- **薄壳模式**:客户端拉取 `/clients/*.yaml`,配置内继续引用远程 `proxy-providers` / `rule-providers`
- **打包模式**:客户端拉取 `/bundle/*.yaml`,服务端把节点、策略组、规则全部铺开成单文件 YAML
这一版已经补上:
- 多机场源选择:`?sources=airport-a,airport-b`
- 单机场或多机场时,**始终取第一个源**的 `Subscription-Userinfo` 返回给客户端
- `GET``HEAD` 都支持
- provider 单源输出、merged provider 输出、thin client 输出、bundle 输出
- 服务端内部继续解耦抓取、配额头解析、provider 构建、规则加载、profile 组装分层处理
> 当前版本仍然只支持上游已经能返回 Clash/Mihomo YAML `proxies:` 文件的地址。
> 这很适合先接你现有的 `sub-wrapper` / `sub-store` / `subconverter(-extended)` 输出。
---
## 目录结构
```text
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. 复制环境变量文件:
```bash
cp .env.example .env
```
2. 编辑 `.env`
- `PUBLIC_PATH` 改成足够长的随机字符串
- `PUBLIC_BASE_URL` 建议填写你反代后的最终访问地址,例如 `https://sub.example.com`
- `AIRPORT_A_URL` / `AIRPORT_B_URL` 改成你的上游 YAML provider 地址
3. 启动:
```bash
docker compose up -d --build
```
4. 访问检查:
- 健康检查:`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
```text
GET /<PUBLIC_PATH>/providers/{name}.yaml
HEAD /<PUBLIC_PATH>/providers/{name}.yaml
```
返回指定机场源的 provider 文件,并携带这个源的 `Subscription-Userinfo`(如果上游有)。
### 2. merged provider
```text
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. 薄壳客户端配置
```text
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 单文件配置
```text
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 这类客户端读取配置订阅头时,行为是稳定可预期的。