Files
GoProxy/POOL_DESIGN.md
isboyjc f03c3300b4 feat: implement custom proxy subscription management and enhance configuration
- Added support for importing Clash/V2ray subscriptions, including automatic format detection and integration with sing-box for protocol conversion.
- Introduced five proxy usage modes in the configuration, allowing flexible selection between mixed, custom-only, and free-only modes.
- Enhanced `.env.example` and `docker-compose.yml` to include new environment variables for custom proxy settings.
- Updated `CHANGELOG.md` to document new features and improvements related to subscription management.
- Improved WebUI for managing subscriptions and displaying proxy statistics.
- Implemented a background process for refreshing subscriptions and probing disabled proxies for reactivation.
2026-04-04 22:25:54 +08:00

203 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GoProxy 架构设计
## 系统概览
GoProxy 是一个单二进制的智能代理池系统,由多个协作的 goroutine 组成。核心设计理念:**免费池自动运转 + 订阅池按需导入,两池独立管理但统一对外服务**。
```
┌─────────────────────────┐
│ WebUI (:7778) │
│ 管理面板 / 订阅管理 / 设置 │
└──────────┬──────────────┘
┌──────────────────┐ ┌──────────┴──────────────┐ ┌──────────────────┐
│ 免费代理源 (20+) │──▶│ SQLite 代理池 │◀──│ 订阅源 (Clash/ │
│ 公开列表自动抓取 │ │ proxies / subscriptions │ │ V2ray/Base64) │
└──────────────────┘ └──────────┬──────────────┘ └──────────────────┘
│ │
┌──────────┴──────────────┐ ┌───────┴────────┐
│ 对外代理服务 │ │ sing-box │
│ HTTP (:7776 / :7777) │ │ 协议转换进程 │
│ SOCKS5 (:7779 / :7780) │ │ vmess/trojan │
└───────────────────────────┘ │ → local socks5│
└────────────────┘
```
## 模块依赖
```
main.go (orchestrator)
├── config/ 配置管理(环境变量 + config.jsonsync.RWMutex 线程安全
├── storage/ SQLite 持久化proxies + subscriptions + source_status
├── fetcher/ 免费代理抓取20+ 源,断路器保护)
├── validator/ 代理验证(连接 + 出口 IP + 地理位置 + 延迟 + HTTPS 隧道)
├── pool/ 池子管理slot 准入、替换逻辑、状态机)
├── checker/ 健康检查批次验证free 删除 / custom 禁用)
├── optimizer/ 质量优化(替换慢代理,仅作用于免费池)
├── custom/ 订阅管理
│ ├── parser.go 格式自动识别Clash YAML / V2ray 链接 / Base64 / 纯文本)
│ ├── singbox.go sing-box 进程管理(配置生成 + 启停 + 端口映射)
│ └── manager.go 刷新循环 + 探测唤醒 + 过期清理
├── proxy/ 对外代理服务
│ ├── server.go HTTP 代理(支持 CONNECT 隧道)
│ └── socks5_server.go SOCKS5 代理(原生协议实现)
├── webui/ 管理面板(嵌入式 HTML + REST API
└── logger/ 内存日志收集(供 WebUI 展示)
```
## 数据模型
### proxies 表
| 字段 | 类型 | 说明 |
|------|------|------|
| address | TEXT UNIQUE | 代理地址 (host:port) |
| protocol | TEXT | http / socks5 |
| source | TEXT | free / custom |
| subscription_id | INTEGER | 所属订阅 ID0=免费) |
| exit_ip | TEXT | 出口 IP |
| exit_location | TEXT | "国家代码 城市" |
| latency | INTEGER | 延迟 (ms) |
| quality_grade | TEXT | S(<=500ms) / A(<=1000) / B(<=2000) / C(>2000) |
| status | TEXT | active / degraded / disabled / candidate_replace |
| fail_count | INTEGER | 连续失败次数 |
| use_count / success_count | INTEGER | 使用统计 |
### subscriptions 表
| 字段 | 类型 | 说明 |
|------|------|------|
| url | TEXT | 订阅 URL |
| file_path | TEXT | 本地文件路径 |
| format | TEXT | auto全自动识别 |
| status | TEXT | active / paused |
| last_fetch | DATETIME | 最后拉取时间 |
| last_success | DATETIME | 最后有可用节点的时间 |
| contributed | INTEGER | 是否为访客贡献 |
## 免费池状态机
```
总量>95%
┌─────────────────────────────────────┐
│ ▼
┌──────┐ 总量<95% ┌─────────┐ 协议<20% ┌──────────┐ 缺失协议或<10% ┌───────────┐
│HEALTHY│──────────▶│ WARNING │───────────▶│ CRITICAL │─────────────────▶│ EMERGENCY │
└──────┘ └─────────┘ └──────────┘ └───────────┘
```
各状态对应的行为:
| 状态 | 延迟阈值 | 抓取模式 | 说明 |
|------|---------|---------|------|
| healthy | 2000ms | 不抓取 | 优化器定期替换慢代理 |
| warning | 4000ms | refill (快源) | 补充到 95% |
| critical | 4000ms | refill (快源) | 优先补充缺失协议 |
| emergency | 4000ms | emergency (全源) | 忽略断路器,全力抓取 |
## 订阅池生命周期
```
添加订阅 → 验证(拉取+解析) → 入库
┌───────────────────────┘
刷新订阅(定时/手动)
├── 拉取内容(直连 → 代理 fallback
├── 自动识别格式
├── 删除该订阅旧代理
├── 分类节点
│ ├── HTTP/SOCKS5 → 直接入池
│ └── vmess/trojan/... → sing-box 转换 → 本地 SOCKS5 入池
├── 验证入池代理(含地理过滤)
│ ├── 通过 → status=active, 更新 last_success
│ └── 失败/被过滤 → status=disabled
└── 更新订阅 proxy_count
```
### 探测唤醒
```
每 N 分钟(默认 10
├── 获取所有 source=custom AND status=disabled 的代理
├── 逐个验证
│ ├── 通过 + 未被地理过滤 → EnableProxy → 更新 last_success
│ └── 失败 或 被地理过滤 → 保持 disabled
└── 日志输出恢复数量
```
### 自动清理
每分钟检查:创建超过 7 天且 `last_success` 距今超过 7 天的订阅 → 删除订阅 + 关联代理 + 重建 sing-box。
## 代理选择策略
5 种模式通过 `CustomProxyMode` + `CustomPriority` + `CustomFreePriority` 三个配置组合:
| UI 选项 | Mode | Priority | FreePriority | 选择逻辑 |
|---------|------|----------|-------------|---------|
| 混合·订阅优先 | mixed | true | false | 先 custom无可用 fallback 全部 |
| 混合·免费优先 | mixed | false | true | 先 free无可用 fallback 全部 |
| 混合·平等 | mixed | false | false | sourceFilter="",不区分来源 |
| 仅订阅 | custom_only | - | - | sourceFilter="custom" |
| 仅免费 | free_only | - | - | sourceFilter="free" |
HTTP 代理服务可使用 HTTP 或 SOCKS5 上游代理。SOCKS5 代理服务仅使用 SOCKS5 上游代理。
## sing-box 集成
```
订阅节点 (vmess/vless/trojan/ss/hysteria2/anytls)
生成 sing-box JSON 配置:
inbounds: 每个节点一个本地 SOCKS5 端口 (20001, 20002, ...)
outbounds: 每个节点对应一个加密协议出站
route: inbound → outbound 一一映射
启动 sing-box 子进程 (sing-box run -c config.json)
本地 socks5://127.0.0.1:20001 ... 入池为 source=custom 代理
```
Docker 镜像自带 sing-box 二进制,支持 amd64/arm64。本地运行需手动安装。
## 后台 Goroutine
| Goroutine | 间隔 | 职责 |
|-----------|------|------|
| 状态监控 | 30s | 检查免费池状态,触发 smartFetchAndFill |
| 健康检查 | 5min | 批量验证代理free 删除 / custom 禁用 |
| 优化轮换 | 30min | 替换免费池中的慢代理 |
| 订阅刷新 | 1min tick | 检查到期订阅,执行刷新 |
| 探测唤醒 | 10min | 探测 disabled 的订阅代理 |
| 配置监听 | event | WebUI 配置变更后调整 slot |
## 地理过滤
全局生效,对两个池子行为不同:
| 操作 | 免费代理 | 订阅代理 |
|------|---------|---------|
| 启动清理 | DELETE | status → disabled |
| 验证时不通过 | 不入池 | 入池但 disabled |
| 探测唤醒 | - | 被过滤的不启用 |
| 配置变更 | 下次清理生效 | 下次清理生效 |
白名单(`AllowedCountries`)优先于黑名单(`BlockedCountries`)。
## 端口映射
| 端口 | 服务 | 模式 |
|------|------|------|
| 7776 | HTTP 代理 | 最低延迟 |
| 7777 | HTTP 代理 | 随机轮换 |
| 7778 | WebUI | 管理面板 |
| 7779 | SOCKS5 代理 | 随机轮换 |
| 7780 | SOCKS5 代理 | 最低延迟 |
| 20001+ | sing-box 本地 | 仅 127.0.0.1 |