订阅(Subscription)
订阅用于在加载配置时,从外部来源拉取配置片段并合并到当前配置中。
目前订阅分三类:
full:预留接口,暂未实现(会记录 warning 并忽略)outbound:已实现,用于拉取并合并outboundsdatabase:已实现,用于订阅并覆盖 geodata 数据库文件(geoip.dat/geosite.dat)
SubscriptionObject
{
"subscription": {
"subscription-inbound": "sub-in",
"outbound": [
{
"name": "mySub",
"url": "https://example.com/sub",
"format": "auto",
"tagPrefix": "sub-",
"insert": "tail",
"interval": "30m",
"observatory": {
"enabled": true,
"testUrl": "https://connectivitycheck.gstatic.com/generate_204"
},
"enabled": true
}
],
"database": [
{
"type": "geoip",
"url": "https://example.com/geoip.dat",
"interval": "24h",
"enabled": true
},
{
"type": "geosite",
"url": "https://example.com/geosite.dat",
"cron": "0 3 * * *",
"enabled": true
}
]
}
}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
TIP
subscription.outbound / subscription.full / subscription.database 均支持写成“单个对象”或“数组”两种形式。
subscription-inbound: string
(可选)订阅拉取/更新的“虚拟 inboundTag”。配置后,订阅的 HTTP 请求会通过 Xray 内部路由模块发起:
- 路由规则可通过
inboundTag匹配该流量,并选择指定 outbound(例如让订阅走代理) - 未配置时:订阅 HTTP 拉取使用系统
net/http直接请求,不进入 Xray 路由模块
OutboundSubscriptionObject
subscription.outbound 用于将订阅内容解析为一组 outbounds 并合并到当前配置。
name: string
订阅名称(用于生成默认 tag、日志标识)。
url: string
订阅来源:
- 支持
http:///https:// - 支持本地文件路径(绝对路径或相对路径)
- 不允许
stdin:
相对路径解析优先级:
xray run -confdir <dir>的dir- 配置文件所在目录(单文件时为该文件目录;多文件时要求都在同一目录)
cwd(启动时工作目录)
format: string
订阅内容格式:
auto(默认):根据url的扩展名推断格式(.json/.jsonc-> json,.yaml/.yml-> yaml),推断失败默认按 json;若解析失败会自动尝试标准 share 订阅json:JSON / JSONCyaml/yml:YAML(会先转换为 JSON 再解析;为与全局 YAML 配置结构一致,要求以outbounds:包装)xray/share/sharelink/base64:标准 share 订阅(见下文)
WARNING
订阅目前不支持 TOML。即使文件扩展名为 .toml,format=auto 也无法正确解析。
tagPrefix: string
为订阅生成的 outbound tag 添加统一前缀(建议用来避免与本地 outbounds 冲突)。
insert: "head" | "tail"
合并位置:
tail(默认,亦接受append):追加到现有outbounds末尾head(亦接受prepend):插入到现有outbounds前面
enabled: true | false
是否启用该订阅。默认 true。
observatory: true | false | object
(可选)为该订阅启用 observatory 集成。
- 启用后:该订阅在每次运行时刷新成功后,会将本次订阅生成的节点 tag 注入 observatory 的观测目标(等价于动态加入
subjectSelector) true等价于{ "enabled": true }- 可写对象形式:
enabled: true | falsetestUrl: string(可选,订阅级探测地址)testURL/probeURL:testUrl的兼容别名
- 未配置订阅级
testUrl时:使用全局observatory.testUrl(若全局也未配置,再回退 observatory 内置默认值)
TIP
subscription.outbound.observatory 只负责把订阅节点接入 observatory;若配置中没有 observatory {},则不会进行实际探测。
interval: string
(可选)运行时定时刷新间隔(例如 "10m" / "1h")。与 cron/crontab 互斥。
cron: string
(可选)运行时定时刷新(crontab 表达式,标准 5 段:分 时 日 月 周,例如 "0 3 * * *")。也支持 @daily / @weekly / @every 1h 等描述符。
别名:crontab。
TIP
当配置了 subscription.subscription-inbound、设置了 interval/cron/crontab,或启用了 subscription.outbound.observatory 时,该订阅会在运行时拉取并应用;否则会在加载配置时拉取并合并。
DatabaseSubscriptionObject
subscription.database 用于订阅并覆盖 geodata 数据库文件:
geoip.dat(geoip:规则使用)geosite.dat(geosite:规则使用)
type: "geoip" | "geosite"
数据库类型:
geoip:覆盖geoip.datgeosite:覆盖geosite.dat
url: string
订阅来源。支持 http:// / https:// / 本地文件路径;相对路径解析规则同 subscription.outbound.url。
enabled: true | false
是否启用该订阅。默认 true。
interval: string
(可选)运行时定时刷新间隔(例如 "24h")。与 cron/crontab 互斥。
cron: string
(可选)运行时定时刷新。别名:crontab。
落盘位置:
- 下载成功后会写入资源文件目录,并覆盖原文件(详见 资源文件路径(geoip/geosite 等))。
WARNING
覆盖 .dat 文件后,已经加载并运行的路由规则不会自动重建;通常需要重启 core 或重载配置后才会使用新的 geodata。
订阅内容格式
JSON / JSONC
支持两种结构:
- 直接是 outbounds 列表:
[
{ "protocol": "freedom", "tag": "direct" },
{ "protocol": "blackhole", "tag": "block" }
]2
3
4
- 包装为对象(只读取其中的
outbounds):
{
"outbounds": [{ "protocol": "freedom", "tag": "direct" }]
}2
3
JSON 返回示例(包含 streamSettings)
[
{
"tag": "sub-vless-ws-tls",
"protocol": "vless",
"settings": {
"address": "vless.example.com",
"port": 443,
"id": "d4b9ad8a-1c7f-4b9c-b1f7-7b12e3e2c0a1",
"encryption": "none"
},
"streamSettings": {
"network": "ws",
"security": "tls",
"tlsSettings": { "serverName": "vless.example.com" },
"wsSettings": { "host": "cdn.example.com", "path": "/xrayws" }
}
},
{
"tag": "sub-trojan-grpc-tls",
"protocol": "trojan",
"settings": {
"address": "trojan.example.com",
"port": 443,
"password": "password123"
},
"streamSettings": {
"network": "grpc",
"security": "tls",
"tlsSettings": { "serverName": "trojan.example.com" },
"grpcSettings": { "serviceName": "grpc_service" }
}
}
]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
YAML
YAML 会先转换为 JSON,再按 JSON 规则解析;因此字段名需要与 JSON schema 保持一致(例如 streamSettings、tlsSettings 等)。
示例(与全局 YAML 配置一致,必须嵌套在 outbounds 下):
outbounds:
- protocol: freedom
tag: direct
- protocol: blackhole
tag: block2
3
4
5
YAML 返回示例(包含 streamSettings)
outbounds:
- tag: sub-vless-ws-tls
protocol: vless
settings:
address: vless.example.com
port: 443
id: "d4b9ad8a-1c7f-4b9c-b1f7-7b12e3e2c0a1"
encryption: none
streamSettings:
network: ws
security: tls
tlsSettings:
serverName: vless.example.com
wsSettings:
host: cdn.example.com
path: /xrayws
- tag: sub-trojan-grpc-tls
protocol: trojan
settings:
address: trojan.example.com
port: 443
password: "password123"
streamSettings:
network: grpc
security: tls
tlsSettings:
serverName: trojan.example.com
grpcSettings:
serviceName: grpc_service2
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
标准 share 订阅(Base64)
常见订阅服务会返回 Base64 编码的文本,解码后为多行 share links,例如(示例值不可用,仅演示格式):
vless://d4b9ad8a-1c7f-4b9c-b1f7-7b12e3e2c0a1@vless.example.com:443?encryption=none&security=tls&sni=vless.example.com&type=ws&host=cdn.example.com&path=%2Fxrayws#VLESS%20WS%20TLS
vmess://eyJwcyI6IlZNZXNzIFdTIFRMUyIsImFkZCI6InZtZXNzLmV4YW1wbGUuY29tIiwicG9ydCI6IjQ0MyIsImlkIjoiYTM0ODJlODgtNjg2YS00YTU4LTgxMjYtOTljOWRmNjRiN2JmIiwic2N5IjoiYXV0byIsIm5ldCI6IndzIiwiaG9zdCI6ImNkbi5leGFtcGxlLmNvbSIsInBhdGgiOiIvdm1lc3N3cyIsInRscyI6InRscyIsInNuaSI6InZtZXNzLmV4YW1wbGUuY29tIiwiYWxwbiI6ImgyLGh0dHAvMS4xIiwiZnAiOiJjaHJvbWUifQ==
trojan://password123@trojan.example.com:443?security=tls&sni=trojan.example.com&type=grpc&serviceName=grpc_service#Trojan%20gRPC%20TLS
ss://YWVzLTEyOC1nY206cGFzc3cwcmQ@ss.example.com:8388#SS%20AES-128-GCM2
3
4
Base64 返回体示例(HTTP 响应 body)
dmxlc3M6Ly9kNGI5YWQ4YS0xYzdmLTRiOWMtYjFmNy03YjEyZTNlMmMwYTFAdmxlc3MuZXhhbXBsZS5jb206NDQzP2VuY3J5cHRpb249bm9uZSZzZWN1cml0eT10bHMmc25pPXZsZXNzLmV4YW1wbGUuY29tJnR5cGU9d3MmaG9zdD1jZG4uZXhhbXBsZS5jb20mcGF0aD0lMkZ4cmF5d3MjVkxFU1MlMjBXUyUyMFRMUwp2bWVzczovL2V5SndjeUk2SWxaTlpYTnpJRmRUSUZSTVV5SXNJbUZrWkNJNkluWnRaWE56TG1WNFlXMXdiR1V1WTI5dElpd2ljRzl5ZENJNklqUTBNeUlzSW1sa0lqb2lZVE0wT0RKbE9EZ3ROamcyWVMwMFlUVTRMVGd4TWpZdE9UbGpPV1JtTmpSaU4ySm1JaXdpYzJONUlqb2lZWFYwYnlJc0ltNWxkQ0k2SW5keklpd2lhRzl6ZENJNkltTmtiaTVsZUdGdGNHeGxMbU52YlNJc0luQmhkR2dpT2lJdmRtMWxjM04zY3lJc0luUnNjeUk2SW5Sc2N5SXNJbk51YVNJNkluWnRaWE56TG1WNFlXMXdiR1V1WTI5dElpd2lZV3h3YmlJNkltZ3lMR2gwZEhBdk1TNHhJaXdpWm5BaU9pSmphSEp2YldVaWZRPT0KdHJvamFuOi8vcGFzc3dvcmQxMjNAdHJvamFuLmV4YW1wbGUuY29tOjQ0Mz9zZWN1cml0eT10bHMmc25pPXRyb2phbi5leGFtcGxlLmNvbSZ0eXBlPWdycGMmc2VydmljZU5hbWU9Z3JwY19zZXJ2aWNlI1Ryb2phbiUyMGdSUEMlMjBUTFMKc3M6Ly9ZV1Z6TFRFeU9DMW5ZMjA2Y0dGemMzY3djbVFAc3MuZXhhbXBsZS5jb206ODM4OCNTUyUyMEFFUy0xMjgtR0NNXray 会自动尝试:
- 将订阅内容作为 Base64 解码(同时兼容 Base64(JSON/YAML) 和 Base64(share links))
- 解析其中可识别的 share link 并转换为
outbounds合并
当前支持解析的 share scheme:
vless://vmess://(常见的 base64(json) 形式)trojan://ss://(暂不处理plugin参数)
WARNING
无法解析的行会记录 warning 并跳过;如果整个订阅里没有任何可识别的 share link,将报错并终止启动。
URL 为 Base64 的情况
如果你的 url 本身被 Base64 编码,可以用以下写法:
base64:<BASE64>b64:<BASE64>base64://<BASE64>b64://<BASE64>
示例:b64:aHR0cHM6Ly9leGFtcGxlLmNvbS9zdWI 等价于 https://example.com/sub。
程序会先解码得到真实 URL/路径,再进行拉取。
合并与 tag 规则
- 订阅解析得到的 outbound,如果
tag为空,会自动生成"<name>-<index>"(name为空时使用subscription作为默认名称)。 - 若设置了
tagPrefix,会在最终 tag 前追加该前缀。 - 合并时按
tag更新:与现有 outboundstag相同的项会覆盖更新;新的tag则按insert决定插入头部或尾部。 - 为便于订阅管理,订阅生成的每个 outbound 会自动写入
managed字段(并同时写入等价的subscription字段作为别名),值为订阅名(subscription.outbound.name,未填写时会自动生成/补全)。再次加载配置时,会先移除managed/subscription相同的 outbounds,再合并本次订阅结果,从而使订阅中的“删除/新增/更新”都能生效。
TIP
建议始终使用 tagPrefix,以避免订阅内容与本地配置发生 tag 冲突。
-dump 行为
xray run -dump 会执行订阅拉取与合并:
- 当订阅在加载配置时被展开时,输出中不会保留
subscription {}区块(已展开为 outbounds)。 - 当配置了运行时刷新(
subscription-inbound/interval/cron)时,subscription {}区块会保留,且输出不会包含运行时动态更新后的 outbounds。
通过 Metrics API 编辑 Subscription
可通过 metrics 的配置接口直接读写 subscription 区块:
GET /config/subscription:读取当前subscription与来源文件路径POST /config/subscription:写入/删除subscription
示例(写入):
{
"path": "/etc/xray/config.json",
"subscription": {
"subscription-inbound": "sub-in",
"outbound": [
{
"name": "my-sub",
"url": "https://example.com/sub",
"enabled": true
}
]
}
}2
3
4
5
6
7
8
9
10
11
12
13
示例(删除整个 subscription 区块):
{
"subscription": null
}2
3
TIP
该接口只负责修改配置文件;修改后需再执行 /core/hotreload 或 /core/restart 让运行中的 core 读取新配置。