高级订阅管理工具Sub-Store

最近发现一直在使用的 lite-test 似乎不太好用了,作者不打算再更新,并推荐了使用 sub-store + http-meta

简介

什么是 Sub-Store ?

Sub-Store 是一个高级订阅聚合和转换工具,专为需要精细化管理多个代理订阅的用户设计。它支持对多种格式的订阅链接(如 ClashSurgeV2Ray 等)进行聚合、筛选、重命名、排序和格式转换,最终输出为目标客户端(如 QXLoonSurgeStashEgern 等)可用的标准化订阅。

主要特点

  • 多协议支持:广泛支持市面上主流的代理协议和订阅格式。
  • 灵活的订阅聚合:可以将多个订阅链接合并成一个,方便管理。
  • 强大的节点过滤:支持通过正则表达式、区域、类型等多种方式筛选节点。
  • 节点编辑:支持对节点进行重命名、排序、设置属性等操作。
  • 格式转换:可将任意格式的输入转换为多种主流客户端支持的输出格式。
  • 配置备份:支持通过 Gist 将前端配置备份到 GitHub

应用场景

Sub-Store 特别适合以下用户:

  • 拥有多个来源的订阅链接,希望将它们整合成一个进行管理。
  • 希望剔除订阅中不需要的地区或类型的节点。
  • 需要对节点进行统一的重命名或排序。
  • 需要在不同的客户端(如 SurgeClash)之间共享同一份订阅源。

Sub-Store 提供了强大而灵活的功能,使得各种用户能够更高效地管理和使用网络代理资源。

安装

在群晖上以 Docker 方式安装。

在注册表中搜索 xream ,选择 xream/sub-store,版本选择带 http-meta 的镜像,可直接使用需要 HTTP-META 功能的脚本,例如 节点测活

latest 版相比,http-meta 版要稍微大一点

docker 文件夹中,创建一个新文件夹 sub-store,并在其中建一个子文件夹 data

文件夹 装载路径 说明
docker/sub-store/data /opt/app/data 存放 Sub-Store 的所有数据和配置

端口

本地端口不冲突就行。

本地端口 容器端口
3011 3001

默认没有对外暴露端口

需要点 + 号自行添加

环境

Sub-Store 依赖环境变量进行核心配置,请务必根据自己的情况修改。

变量 值(示例) 说明
SUB_STORE_FRONTEND_BACKEND_PATH /mcHoE7D8hG9PAs5t3NHw 必需,后端 API 路径,请设置为一个随机字符串。

命令行安装

如果你熟悉命令行,可能用 docker cli 更快捷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 新建文件夹 sub-store 和 子目录
mkdir -p /volume1/docker/sub-store/data

# 进入 sub-store 目录
cd /volume1/docker/sub-store

# 运行容器
docker run -d \
--restart unless-stopped \
--name sub-store \
-p 3011:3001 \
-v $(pwd)/data:/opt/app/data \
-e SUB_STORE_FRONTEND_BACKEND_PATH=/mcHoE7D8hG9PAs5t3NHw \
xream/sub-store:http-meta

也可以用 docker-compose 安装,将下面的内容保存为 docker-compose.yml 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
version: "3.8"

services:
sub-store:
image: xream/sub-store:http-meta
container_name: sub-store
restart: unless-stopped
ports:
- "3011:3001" # 前端访问端口
volumes:
- ./data:/opt/app/data # 数据持久化目录
environment:
# 必须设置:前后端通信路径(20位随机英数字)
- SUB_STORE_FRONTEND_BACKEND_PATH=/mcHoE7D8hG9PAs5t3NHw

然后执行下面的命令启动:

1
2
3
4
5
6
7
8
9
10
# 新建文件夹 sub-store 和 子目录
mkdir -p /volume1/docker/sub-store/data

# 进入 sub-store 目录
cd /volume1/docker/sub-store

# 将 docker-compose.yml 放入当前目录

# 启动容器
docker-compose up -d

运行与使用

在浏览器中输入 http://群晖IP:3011 即可看到 Sub-Store 的前端界面

首次使用时,需要在 后端设置 页面填入你的后端地址,格式为:http://群晖IP:3011/mcHoE7D8hG9PAs5t3NHw (请确保路径与环境变量 SUB_STORE_FRONTEND_BACKEND_PATH 的值一致)。

如果设置地址没错,会连接成功

以后直接打开 http://群晖IP:3011 就可以

单条订阅

通过 订阅管理 –> 单条订阅,可以将订阅地址加到 Sub-Store

主要的就三项必填

  • 名称:必须唯一,而且不能用 /
  • 来源:一个是远程订阅,一个是本地订阅
  • 链接:填入机场的订阅地址

添加了一些之后

组合订阅

建一个 组合订阅

可以将前面的单条订阅都包含进去

节点操作增加了去重和脚本

下面是 AI 帮写的过滤脚本

官方提供了一些可参考的脚本:https://github.com/sub-store-org/Sub-Store/tree/master/scripts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
async function operator(proxies) {
// === 配置参数 ===
const TEST_URL = 'http://www.gstatic.com/generate_204'; // 稳定测试地址,可换成 https://connectivitycheck.gstatic.com/generate_204
const TIMEOUT = 5000; // 超时 ms
const MAX_DELAY = 800; // 最大允许延迟 ms(超过过滤掉)
const CONCURRENCY = 8; // 并发测试数(服务器弱调到 4-6)

// === 步骤1: 筛选候选节点(地域 + 基本有效) ===
const candidates = proxies.filter(p =>
/香港|HK|US|美国|日本|JP|新加坡|SG/i.test(p.name) &&
p.server && p.port
);

if (candidates.length === 0) {
// 没候选节点,直接返回原列表避免空订阅
return proxies.map(p => { p.name = '[无候选] ' + p.name; return p; });
}

// === 步骤2: 真实测试(xream/http-meta 支持的内置方式) ===
// 注意:如果下面 produceHTTP 报错,说明你的镜像不支持或版本旧 → 更新镜像
try {
const tester = await produceHTTP({
url: TEST_URL,
method: 'head', // head 最快
timeout: TIMEOUT,
headers: { 'User-Agent': 'Mozilla/5.0' }
});

const testResults = await tester.proxiesTest(candidates, { concurrency: CONCURRENCY });

// 记录延迟
candidates.forEach((proxy, index) => {
const result = testResults[index];
proxy._health = result?.alive ? Math.round(result.delay) : 999999;
});
} catch (e) {
// 如果 produceHTTP 不存在或报错,用随机模拟(调试用)
console.error('测试失败,使用模拟延迟: ' + e);
candidates.forEach(p => {
p._health = Math.floor(Math.random() * 600) + 50; // 模拟 50-650ms
});
}

// === 步骤3: 过滤 + 排序 + 加前缀 ===
return candidates
.filter(p => p._health <= MAX_DELAY && p._health < 999999)
.sort((a, b) => a._health - b._health)
.map(p => {
p.name = `[${p._health}ms] ${p.name}`;
return p;
});
}

预览会看到过滤掉了大部分节点,并在可用节点前面增加了 [xxxms]

点击这条组合订阅,会弹出订阅类型,可根据自己的客户端选择

还可以设置分享的时间

参考文档

sub-store-org/Sub-Store: Advanced Subscription Manager for QX, Loon, Surge, Stash and Shadowrocket!
地址:https://github.com/sub-store-org/Sub-Store

Home · sub-store-org/Sub-Store Wiki
地址:https://github.com/sub-store-org/Sub-Store/wiki