缥缈墟

sing-box 规则集配置教程:最小可运行示例、1.14 写法与不生效排查

更新于 2026-11-12 · piaomiaoxu.online

简答:规则写了却不生效、远程规则集下载失败,或日志提示 download_detour 已弃用时,先不要修改整套代理配置。sing-box 规则集的正确关系是:在 route.rule_set 定义带 tag 的规则集,再在 route.rules 中引用同一个 tag,并用 action 决定放行、拒绝或转发。本文从一个包含 mixed 入站的最小配置开始,再扩展到 local、remote、DNS 规则和版本迁移。

定义:sing-box 规则集是可被 route.rules 或 DNS 规则引用的一组匹配条件,支持 inline、local、remote 三种载入方式,规则文件可采用 source JSON 或 binary SRS 格式。

先跑通:带 mixed 入站的最小规则集配置

如果目标是验证规则是否真的命中,只有 route.rule_set 和 route.rules 还不够,因为没有入站流量可以触发匹配。下面的示例增加了 mixed 入站、debug 日志、direct 出站,并用 action: reject 拒绝 example.com 及其子域名;没有再使用已弃用或已移除的特殊 block 出站。mixed 入站同时支持 SOCKS 和 HTTP,具体监听字段可参阅sing-box mixed 入站官方文档。

{"log":{"level":"debug"},"inbounds":[{"type":"mixed","tag":"mixed-in","listen":"127.0.0.1","listen_port":2080}],"outbounds":[{"type":"direct","tag":"direct"}],"route":{"rule_set":[{"type":"inline","tag":"demo-domains","rules":[{"domain_suffix":["example.com"]}]}],"rules":[{"action":"sniff"},{"rule_set":["demo-domains"],"action":"reject"}],"final":"direct"}}

保存后,将 config.json 替换为实际文件名,先执行 sing-box check -c config.json。检查通过后启动核心,把应用或浏览器的 SOCKS/HTTP 代理指向 127.0.0.1:2080,再访问测试域名。日志中应能看到连接进入 mixed-in,并在规则命中后被拒绝。规则动作和 reject 的字段以sing-box Route Rule Action 官方文档为准。

这个示例只验证规则集与路由关系,不代表完整的 TUN、DNS 或远程节点配置。若使用图形客户端,命令行检查的文件必须与客户端实际加载的配置一致;否则可能出现“check 通过但客户端仍不生效”。

规则集的三种类型与两种文件格式

sing-box 规则集类型与格式速查
项目含义适合场景注意事项
inline规则直接写在配置的 rules 数组中少量自定义域名、首次验证字段多条规则可直接放入同一规则集;多个 tag 与 inline 冲突
local从本地路径读取规则集文件自维护域名、离线使用、固定版本检查路径、权限、format 和文件内容;文件被修改后,sing-box 1.10.0 起支持自动重新加载
remote从 URL 下载规则集需要周期更新的远程资源额外检查 DNS、TLS、HTTP 状态、缓存、initial_path 和 HTTP client
source可读的 JSON 规则集编写、审阅和修改规则根部需要 version 与 rules
binary二进制 SRS 规则集编译后加载、分发或远程使用不能把普通 JSON 文件标成 binary

官方规则集文档明确说明,inline、local、remote 是载入方式;local 和 remote 需要 format,除非路径或 URL 已使用 .json 或 .srs 扩展名。规则集的多个匹配项之间通常是“或”关系;当一条规则内同时出现域名、端口等字段时,具体组合逻辑要按sing-box 路由规则官方文档判断。不同 rule-set 在 route 规则中也保持 OR 语义。

“多个 tag 不适用于 inline”指的是:从 sing-box 1.14.0 起,local 或 remote 可以用一个配置对象定义多个 tag,并通过 {tag} 占位符生成不同路径或 URL;但多个 tag 与 type: inline 冲突。不要把它理解成 inline 只能写一条匹配规则。

local source:编写、校验并编译自己的规则集

先创建例如 rules/custom-domains.json 的 source 文件。根据官方 source format 文档,规则集 version 与核心版本有明确对应关系:

规则集 source version 与 sing-box 核心版本
source version核心版本新增内容
11.8.0初始规则集版本
21.10.0优化 binary 规则集中的 domain_suffix 内存使用
31.11.0增加 network_type、network_is_expensive、network_is_constrainted 规则项
41.13.0增加 network_interface_address、default_interface_address
51.14.0增加 package_name_regex

如果只使用普通域名和 IP 规则,可以根据实际核心支持的版本选择对应 version;如果使用了较新的字段,就不能只看客户端界面版本,必须核对其内置 sing-box 核心版本。官方对应关系见sing-box 规则集 source format 官方文档。

{"version":5,"rules":[{"domain_suffix":["example.com","example.net"]},{"domain":["api.example.org"]}]}

上面示例使用 version 5,仅适用于已经包含 1.14.0 规则集格式能力的核心。如果不确定核心版本,可先用客户端显示的核心版本或执行 sing-box version 核对;无法确认时,删去新字段并使用与实际核心对应的 version,不要盲目照抄。

主配置中的 local 引用可以写成:

{"route":{"rule_set":[{"type":"local","tag":"custom-domains","format":"source","path":"rules/custom-domains.json"}],"rules":[{"rule_set":["custom-domains"],"action":"route","outbound":"direct"}],"final":"direct"}}

路径不存在、权限不足或相对路径基准目录错误,都会被误认为规则格式错误。排查时先改用绝对路径,确认运行用户有读取权限,再执行 sing-box check -c config.json。local 文件被修改后,官方文档说明 sing-box 1.10.0 起会自动重新加载;图形客户端是否实际使用该核心能力,仍需结合客户端实现检查。

需要转换为 SRS 时,执行:

sing-box rule-set compile --output custom-domains.srs custom-domains.json

然后将引用改为:

{"type":"local","tag":"custom-domains","format":"binary","path":"rules/custom-domains.srs"}

source 负责编辑,SRS 负责编译后的加载和分发。编译失败时先检查 source 的 version、rules 数组和字段拼写,不要只根据文件扩展名判断格式。

remote 规则集:1.14.0 的 http_client 新写法

sing-box 1.14.0 起,remote 规则集支持 http_client 与 initial_path。官方同时将旧的 download_detour 标记为弃用,并说明该旧字段将在 sing-box 1.16.0 移除;隐式默认 HTTP client 也将在 1.16.0 移除。迁移时不要把“下载规则集的出站”直接当成新的 http_client 字段。

download_detour 到 http_client 的迁移对照
旧写法新写法核对重点
download_detour 指向出站 tag规则集的 http_client 指向共享 HTTP client tag,或直接写 HTTP client 对象这是 HTTP 下载客户端,不是简单的 outbound tag 替换
依赖隐式默认行为顶层定义 http_clients,并可用 route.default_http_client 指定默认 client显式配置,避免未来版本移除隐式行为
无初始文件使用 initial_path 提供首次启动时的本地规则集仅在无缓存规则集时使用,字段自 1.14.0 起可用

一个结构完整的示例是:

{"http_clients":[{"tag":"rule-http"}],"outbounds":[{"type":"direct","tag":"direct"}],"route":{"default_http_client":"rule-http","rule_set":[{"type":"remote","tag":"custom-remote","format":"binary","url":"https://example.com/rules/custom.srs","initial_path":"rules/custom.srs","update_interval":"1d","http_client":"rule-http"}],"rules":[{"rule_set":["custom-remote"],"action":"route","outbound":"direct"}],"final":"direct"}}

其中 https://example.com/rules/custom.srs 只是字段格式占位,不能当作已核验的可用资源。顶层 http_clients 的详细结构包括 HTTP 版本、TLS、headers 和 Dial Fields,具体字段应按sing-box HTTP Client 官方文档填写。

如果规则集对象已经显式写了 http_client,它会使用该 client;如果为空,则使用 route.default_http_client 指定的 client,若该字段也为空,则使用顶层 http_clients 的第一个条目。不要在多个层级重复指定不同 client 后再凭猜测判断优先级。

缓存不是自动等于 initial_path。官方文档说明,remote 规则集只有在启用 experimental.cache_file.enabled 后才使用规则集缓存;缓存路径和权限应按sing-box Cache File 官方文档检查。

route.rules、规则顺序与 TUN 场景的 sniff

route.rule_set 负责定义规则集,route.rules 负责引用 tag 并执行 action。最常见的转发写法是:

{"route":{"rules":[{"action":"sniff"},{"rule_set":["custom-domains"],"action":"route","outbound":"proxy"},{"ip_is_private":true,"action":"route","outbound":"direct"}],"final":"direct"}}

这里的 proxy 必须是现有 outbounds 中真实存在的 tag。规则应按“需要优先处理的自定义规则在前、兜底规则在后”排列。前面的规则执行了 route、reject 或其他终止动作后,后面的规则不会再次改变同一连接;final 是没有匹配规则时使用的最终出站。

在 TUN 或透明代理场景中,连接可能只带 IP 地址,规则集中的 domain 或 domain_suffix 因而无法匹配。可以把 {"action":"sniff"} 放在相关 route.rules 前部,让核心尝试从 HTTP Host、TLS Server Name 或 QUIC Server Name 中识别域名。官方支持的协议和可提取字段见sing-box Protocol Sniff 官方文档。不过 sniff 不是所有流量都能得到域名;日志仍显示 IP 时,应改用 IP 规则、DNS 规则或检查应用是否使用独立解析路径。

如果只是想拒绝规则集中的域名,使用 action: reject;如果需要转发,使用 action: route 加 outbound。新版 route rule 已将旧的顶层 outbound 字段迁移到 action 中,避免继续混用旧写法。

DNS 规则如何引用同一个 rule_set

DNS 规则和 route.rules 可以引用同一个规则集 tag,但它们解决的是不同问题:route.rules 决定连接如何转发,dns.rules 决定 DNS 查询使用哪个 DNS server 或执行什么 DNS action。下面示例将 custom-domains 中的域名交给 local-dns:

{"dns":{"servers":[{"type":"local","tag":"local-dns"}],"rules":[{"rule_set":["custom-domains"],"action":"route","server":"local-dns"}],"final":"local-dns"}}

如果规则集同时被 route 和 DNS 使用,必须保证两处都能访问同一个 tag。DNS server tag、DNS rule 的 action: route 和 server 字段可参阅sing-box DNS Rule 官方文档以及sing-box Local DNS Server 官方文档。

DNS 规则不等于连接路由规则。即使 DNS 查询被正确分流,应用后续建立连接时仍可能因 route.rules、TUN 路由、sniff 或出站 tag 配置不正确而失败。因此验证时分别看 DNS 日志和连接日志,不要只根据“域名能解析”判断 route 规则已生效。

local 自动更新与定时编译脚本

local source 文件适合维护,SRS 文件适合实际加载。若希望定期把 source 编译成 SRS,可以使用一个最小 shell 脚本,但脚本只负责本地文件替换,不会自动解决远程资源下载、权限或配置回滚问题。

#!/bin/sh
set -eu
cd /path/to/rules
sing-box rule-set compile --output custom-domains.new.srs custom-domains.json
mv custom-domains.new.srs custom-domains.srs

用 cron 执行前,先手动运行脚本并确认运行用户有写入目录的权限;再检查生成文件是否能被主配置读取。建议先写入临时文件,编译成功后再使用 mv 原子替换,避免核心在文件写入一半时读取到不完整 SRS。sing-box 1.10.0 起 local rule-set 支持检测文件修改并重新加载,但具体图形客户端是否允许该行为、配置文件路径是否映射到同一目录,仍需在客户端日志中核对。

最短排错清单:现象→检查→判断→处理→回滚

规则集下载失败

检查:先确认设备能解析规则集域名,再用浏览器或命令行查看 URL 返回的 HTTP 状态和响应类型;之后查看 debug 日志中的 TLS、HTTP client、缓存路径和文件权限。判断:DNS 失败是解析链路问题,403 或 404 是 URL 或权限问题,返回 HTML 或登录页是资源内容问题,SRS 解析失败才是格式问题。处理:确认 remote 使用正确的 format,显式配置 http_client,检查 initial_path 和 cache file 目录。回滚:先改成已存在的 local source 或 inline,验证 route 逻辑后再恢复 remote。

download_detour 报弃用

检查:确认日志中的字段确实是 download_detour,并核对核心版本。判断:这是配置迁移提示,不等于节点、DNS 或 TLS 故障。处理:按 1.14.0 文档改为显式 HTTP client;旧核心是否支持新字段需核实。回滚:修改前保留配置副本,若客户端暂不支持新字段,先恢复原配置并确认升级路径。

规则集加载成功但没有命中

检查:逐字比较 rule_set 定义 tag 与 route.rules 或 dns.rules 中的引用,检查规则顺序,并确认请求是否经过预期入站;TUN 场景再查看是否有 sniff 结果。判断:如果日志显示加载成功但请求走 final,通常是域名没有识别、匹配字段不成立、规则被前项处理,或实际使用的是 DNS 规则而不是 route 规则。处理:先用明确的 domain 或 domain_suffix 做单条测试,再加入逻辑条件和 IP 条件。回滚:保留 sniff 和一条最小规则,逐项恢复其余规则。

source 或 binary 格式错误

检查:source 文件确认根部存在 version 与 rules;binary 文件确认由 sing-box rule-set compile 生成,并且 format 与内容一致。判断:扩展名正确不代表文件内容正确。处理:从 source 重新编译,或将 format 改为实际格式。回滚:使用 inline 规则确认核心、入站和 route 本身可用。

DNS 已分流但网页仍打不开

检查:分别查看 DNS rule 命中、route rule 命中、出站 tag 和 TUN 或系统代理状态。判断:DNS server 选择正确,不代表后续连接已经走目标 outbound。处理:将 DNS 排查与连接排查分开,必要时先用 mixed 入站复现,再恢复 TUN。回滚:暂时只保留 local DNS、direct 出站和一条 route 规则,逐层加回配置。

配置前后的版本核对方法

本文按已核验的 sing-box 官方资料整理,涉及的关键版本点是:source version 5 对应 1.14.0;remote 的 http_client 与 initial_path 自 1.14.0 起提供;download_detour 在 1.14.0 弃用,并计划在 1.16.0 移除;local rule-set 文件自动重新加载自 1.10.0 起提供。这里的版本是字段能力对应关系,不等于你的图形客户端已经内置该核心。

实际操作前建议执行 sing-box version,查看客户端关于核心版本的说明,并用 sing-box check -c config.json 校验配置。若编辑器支持 JSON Schema,还可以按照sing-box JSON Schema 官方文档生成与当前 binary 匹配的 schema,减少字段拼写和类型错误。

常见问题

sing-box 规则集中的 source 和 binary 有什么区别?

source 是可读 JSON,适合编辑和审阅;binary 通常是由 sing-box rule-set compile 生成的 SRS 文件,适合加载和分发。配置中的 format 必须与文件实际内容一致。

inline、local、remote 应该怎么选?

少量自定义规则先用 inline;需要自己维护或离线使用时用 local;需要从 URL 定期更新时用 remote。remote 还要额外检查 DNS、TLS、HTTP 状态、缓存和 HTTP client。

为什么规则集加载成功,连接仍然走 final?

先核对 route.rules 中的 rule_set tag,再检查 domain 或 domain_suffix 是否真正匹配、规则顺序是否提前结束,以及 TUN 或透明代理场景是否执行 sniff。

download_detour 还能继续使用吗?

官方已将 download_detour 标记为 sing-box 1.14.0 弃用,并说明将在 1.16.0 移除。新配置应核对并使用 http_client;旧客户端能否使用新字段,需要根据实际核心版本确认。

DNS 规则和 route.rules 可以共用一个规则集吗?

可以共用同一个 tag,但两者处理对象不同:dns.rules 决定 DNS 查询使用哪个 server,route.rules 决定连接使用哪个 outbound。验证时应分别查看 DNS 日志和连接路由日志。

local 规则集修改后会自动生效吗?

官方文档说明 sing-box 1.10.0 起支持 local rule-set 文件变更自动重新加载,但图形客户端是否使用该能力、实际配置目录是否一致,需要结合客户端日志和核心版本核对。

相关阅读

参考资料

  1. sing-box 官方:规则集
  2. sing-box 官方:规则集 source 格式
  3. sing-box 官方:路由规则
  4. sing-box 官方:路由规则动作
  5. sing-box 官方:协议嗅探
  6. sing-box 官方:DNS 规则
  7. sing-box 官方:Local DNS Server
  8. sing-box 官方:HTTP Client
  9. sing-box 官方:Cache File
  10. sing-box 官方:JSON Schema
  11. sing-box 官方:Deprecated Feature List
  12. sing-box 官方:Mixed 入站