sing-box 怎么配置规则?完整模板、匹配顺序与版本迁移
简答:sing-box 配置规则主要写在 route.rules 中:先写域名、IP、端口或应用等匹配条件,再用 action 指定路由、拒绝或 DNS 劫持,最后用 route.final 处理没有命中的连接。若你只想先跑通配置,先复制本文的完整 JSON 模板,用 sing-box check 校验,再把 proxy 出站中的占位服务器替换为自己的节点信息。本文按 facts.today 核对到的官方字段说明整理,图形客户端实际支持的菜单和内核版本仍需以当前客户端为准。
定义:sing-box 分流规则是 route.rules 中由匹配条件和动作组成的规则列表,用于根据域名、IP、端口、进程、应用或规则集选择不同处理方式。
先复制这份完整 config.json:能校验,但代理出站仍需替换
下面是一份结构完整的 JSON 配置骨架,包含本机 mixed 入站、直连出站、占位 SOCKS 代理出站、路由规则和默认出站。192.0.2.1 与端口只是文档占位值,不会提供实际连接;你必须替换为自己的代理服务器、端口和认证信息。示例域名使用 example.org、example.net 和 ads.invalid,不要直接当作真实业务域名使用。
{
"$schema": "https://sing-box.sagernet.org/schema.json",
"log": {
"level": "info"
},
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "127.0.0.1",
"listen_port": 2080
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
},
{
"type": "socks",
"tag": "proxy",
"server": "192.0.2.1",
"server_port": 1080
}
],
"route": {
"rules": [
{
"domain_suffix": ["example.org"],
"action": "route",
"outbound": "proxy"
},
{
"domain_suffix": ["example.net"],
"action": "route",
"outbound": "direct"
},
{
"ip_is_private": true,
"action": "route",
"outbound": "direct"
},
{
"domain": ["ads.invalid"],
"action": "reject"
}
],
"final": "direct"
}
}
预期结果:本机应用连接到 127.0.0.1:2080 后,example.org 交给 proxy,example.net 和私有 IP 交给 direct,ads.invalid 被拒绝,其他连接由 final 交给 direct。配置文件的顶层结构、inbounds、outbounds 和 route 可对照sing-box 官方配置说明核对。
- 将内容保存为
config.json,先备份原配置。 - 替换
proxy出站中的服务器、端口及认证字段;不要把真实密码、UUID、证书或私钥发布到公开校验器。 - 运行
sing-box check -c config.json;如果你的构建不接受短参数,按当前命令帮助或客户端的配置检查入口执行。 - 检查通过后启动,再访问示例域名或查看连接日志确认规则是否命中。
官方配置页同时提供 sing-box check、sing-box format -w -c config.json -D config_directory 和 sing-box merge 命令;如果安装版本支持,还可以用 sing-box schema -o schema.json 生成与当前二进制匹配的 JSON Schema。详见配置与校验命令和官方 JSON Schema 文档。
route.rules 怎么写:匹配条件、动作和 final
一条普通路由规则可以理解为“匹配条件 + action”。常用条件包括:
| 需求 | 字段 | 说明 |
|---|---|---|
| 精确域名 | domain | 匹配完整域名,例如 example.org |
| 域名后缀 | domain_suffix | 匹配指定后缀及其子域名 |
| 域名关键词 | domain_keyword | 域名中包含关键词时匹配 |
| IP 网段 | ip_cidr | 按 IPv4 或 IPv6 网段匹配 |
| 私有地址 | ip_is_private | 匹配非公网 IP,常用于局域网直连 |
| 端口 | port、port_range | 按目标端口或范围匹配 |
| 桌面进程 | process_name、process_path | 仅适用于官方文档列出的 Linux、Windows 和 macOS 场景 |
| Android 应用 | package_name | 按 Android 包名匹配 |
| 规则集 | rule_set | 引用已声明的 inline、local 或 remote 规则集 |
普通规则的字段逻辑不是“所有数组字段全部同时满足”。官方说明是:域名类字段之间使用 OR,端口类字段之间使用 OR,来源地址类字段之间使用 OR,不同类别之间再使用 AND;例如同时写 domain_suffix 和 port,表示域名后缀与端口都满足时才命中。rule_set 还有合并匹配的特殊规则,不能简单按普通数组推断。详见官方 Route Rule 文档。
规则数组按列出的顺序参与判断。route、reject 和 hijack-dns 属于最终动作:命中后完成当前路由处理;route-options、sniff 和 resolve 属于非最终动作,执行后仍可能继续处理后续规则。官方动作页面明确把两类动作分为 Final actions 和 Non-final actions,因此不要把每个 action 都理解成“命中即结束”。
route.final 是没有前置规则命中时使用的默认出站;如果留空,官方文档规定会使用第一个出站。为避免 outbounds 顺序变化导致行为改变,建议始终明确写成 "final":"direct" 或你实际存在的出站标签。相关字段见官方 Route 文档。
直连、代理、阻断、DNS 劫持和逻辑规则示例
先确认 outbounds 中确实存在对应标签,再添加规则。标签名不是固定关键字,proxy、direct 只是示例名称。
- 指定域名走代理:
{"domain":["example.org"],"action":"route","outbound":"proxy"} - 指定后缀直连:
{"domain_suffix":["example.net"],"action":"route","outbound":"direct"} - 局域网地址直连:
{"ip_is_private":true,"action":"route","outbound":"direct"} - 按端口走代理:
{"port":[80,443],"action":"route","outbound":"proxy"} - 拒绝测试域名:
{"domain":["ads.invalid"],"action":"reject"} - 把 DNS 请求交给 sing-box DNS 模块:
{"protocol":"dns","action":"hijack-dns"}
hijack-dns 只是把 DNS 请求交给 sing-box DNS 模块,并不单独决定使用哪个 DNS 服务器。DNS 服务器选择需要在顶层 dns 配置及其规则中完成,所以不要只添加 DNS 劫持规则就断定已经完成 DNS 分流。官方路由动作和 DNS 配置分别见Route Rule Action与DNS Rule Action。
需要 AND 或 OR 组合时,可使用逻辑规则。例如下面表示“example.net 后缀或私有 IP 满足其一时直连”:
{"type":"logical","mode":"or","rules":[{"domain_suffix":["example.net"]},{"ip_is_private":true}],"action":"route","outbound":"direct"}
复杂逻辑建议先拆成多条普通规则。这样更容易在日志中定位命中条件,也更容易通过回滚排除变量。
sing-box 版本边界:旧式 outbound 与新版 action 怎么迁移
如果你看到网上旧配置把 outbound 直接写在规则顶层,需要先看内核版本。官方 Route Rule 文档将顶层 outbound 标记为 sing-box 1.11.0 起弃用,并移动到 Rule Action 中;新写法应优先使用 "action":"route","outbound":"proxy"。不要把旧字段和新版 action 随意叠加。
| 版本边界 | 变化 | 新配置建议 |
|---|---|---|
| 1.8.0 | 引入 rule-set;GeoIP 和 Geosite 进入弃用方向 | 新配置优先使用 inline、local 或 remote rule-set |
| 1.11.0 | 规则顶层 outbound 弃用,移动到 Rule Action | 使用 action:route 搭配 outbound |
| 1.12.0 | GeoIP、Geosite 和旧 DNS server 格式被移除 | 不要继续围绕 geoip、geosite 设计新配置 |
| 1.13.0 | 旧式 block、dns 特殊出站被移除 | 分别使用 reject 和 hijack-dns 动作 |
| 1.14.0 | remote rule-set 支持 initial_path、http_client;旧 download_detour 弃用 | 为远程规则集配置明确的 HTTP Client |
| 1.16.0 计划移除项 | 官方弃用页列出 download_detour 和隐式默认 HTTP Client 等旧行为将移除 | 不要把弃用字段作为长期配置方案 |
以上版本边界来自 sing-box 官方弃用列表、迁移说明和更新日志;不等于所有图形客户端都同步支持同一内核。遇到 unknown field,先查看客户端实际内核版本,再对照对应版本的官方文档,不要只删掉报错字段强行启动。官方资料见弃用字段列表、迁移说明和更新日志。
rule_set 怎么配置:inline、local、remote 与更新方式
rule_set 用于复用一组域名或 IP 规则,常见类型如下:
| 类型 | 内容位置 | 先检查什么 |
|---|---|---|
| inline | 直接写在配置中 | 标签是否唯一、规则字段是否正确 |
| local | 从本地文件读取 | 路径、权限和 format 是否匹配 |
| remote | 从 URL 下载并缓存 | URL、缓存文件、HTTP Client 和更新间隔 |
本地规则集的结构示例:
"route": {
"rule_set": [
{
"type": "local",
"tag": "demo-rules",
"format": "source",
"path": "./rule-sets/demo.json"
}
],
"rules": [
{
"rule_set": ["demo-rules"],
"action": "route",
"outbound": "proxy"
}
],
"final": "direct"
}
如果文件是 sing-box 二进制规则集,应使用对应的 binary 格式;不能只凭扩展名猜测。远程规则集在 1.14.0 起可使用 initial_path、http_client 和 update_interval。官方文档说明,download_detour 自 1.14.0 起弃用,并计划在 1.16.0 移除;没有显式配置 HTTP Client 时的隐式默认行为也在弃用范围内。远程规则集字段以官方 rule-set 文档和官方 HTTP Client 文档为准。
迁移步骤是:先备份配置;确认文件格式;给规则集设置唯一 tag;在 route.rules 中引用 tag;本地文件验证成功后再启用 remote 更新。远程文件无法加载时,先用本地有效文件验证路由逻辑,避免把网络下载问题和规则语法问题混在一起。
Windows、macOS、Android、iOS 与 TUN 模式的验证方法
规则字段的可用范围由 sing-box 内核和运行平台共同决定,不等于每个图形客户端都会提供相同菜单。
- Windows、macOS:
process_name、process_path和正则路径字段用于桌面进程匹配;先确认客户端实际运行的是支持进程搜索的内核,再查看日志中的进程信息。 - Android:应用分流优先核对应用包名,使用
package_name或 1.14.0 起支持的package_name_regex;不要把 Windows 进程名直接复制到 Android。 - iOS:网络类型等字段是否可用取决于图形客户端和内核,菜单通常围绕配置、Route、DNS、TUN 和日志展开,以当前客户端页面为准。
- TUN:如果出现回环或所有连接都失败,先检查
route.auto_detect_interface、默认出站和局域网直连规则。官方说明该字段在 Linux、Windows 和 macOS 上用于绑定默认网卡以避免 TUN 路由环路,Android 则有单独的 VPN 覆盖字段。
平台验证不要一次改多个变量。先用一个明确域名规则验证出站,再验证局域网地址,最后才检查 DNS、UDP、TUN 或应用级分流。字段支持可对照官方 Route Rule 平台限制和官方 Route 字段说明。
规则不生效时:按名称、规则集、日志和网络分层排查
- 名称层:确认 JSON 格式正确,
action、outbound、rule_set和final的标签真实存在且大小写一致。 - 顺序层:把测试规则放到靠前位置,只匹配一个示例域名,并指向明确的
direct或proxy。如果命中,说明原规则可能在前置条件、顺序或域名写法上有差异。 - 规则集层:查看本地路径、文件权限、格式和加载日志;remote 类型则额外检查 URL 返回内容、缓存和 HTTP Client。
- 动作层:确认使用的是新版
action结构,拒绝使用reject,DNS 请求使用hijack-dns,不要继续依赖已经移除的特殊出站。 - 网络层:先单独确认代理出站可用,再区分 DNS、TCP、TLS、UDP 和 TUN 问题。不要在规则未验证时同时更换节点、DNS、MTU 和网络模式。
“前面的规则已经命中”只是排查方向之一,不是统计结论。最可复现的验证方式是:临时加入唯一测试域名规则;观察启动和连接日志;逐条禁用可疑规则;确认结果后删除测试规则。失败时恢复备份,只重新修改一个变量。
如果配置检查通过但访问仍失败,说明 JSON 结构不一定有问题,下一步应检查代理出站的服务器、认证、TLS、DNS 或底层网络。配置校验只能判断字段和结构,不能替你证明某个节点或线路一定可用。
常见问题
sing-box 规则应该写在 route.rules 还是 DNS rules?
普通连接分流写在 route.rules;DNS 请求选择哪个服务器写在 DNS 配置的规则中。添加 route.rules 的 DNS 劫持动作,不等于已经完成 DNS 服务器分流。
为什么 sing-box 规则不生效?
先检查 JSON、outbound 标签和规则顺序,再用唯一测试域名规则查看日志;随后检查 rule_set 是否加载成功,最后区分 DNS、代理出站和 TUN 问题。前置规则已命中只是排查方向之一。
domain、domain_suffix 和 domain_keyword 有什么区别?
domain 用于完整域名匹配;domain_suffix 用于域名后缀及子域名匹配;domain_keyword 只检查域名是否包含关键词。能用精确域名或后缀时,优先使用更明确的字段。
旧配置里的 outbound 还能继续写吗?
官方 Route Rule 文档已将规则顶层 outbound 标为 sing-box 1.11.0 起弃用,并移动到 Rule Action。新配置使用 action:route 搭配 outbound;旧配置能否继续运行取决于实际内核版本。
GeoIP 和 Geosite 还能用于新配置吗?
官方资料显示两者在 1.8.0 起弃用,并在 1.12.0 移除。新配置应改用 rule_set;旧字段是否仍被某个图形客户端兼容,需要核对该客户端实际内核。
rule_set 应该选 source 还是 binary?
看规则集文件本身的格式。源 JSON 使用 source,sing-box 二进制规则集使用 binary,不能只凭文件扩展名判断。配置后要检查文件是否成功加载。
download_detour 还能使用吗?
官方弃用页将 remote rule-set 的 download_detour 标为 1.14.0 弃用,并列出 1.16.0 移除计划。新配置应使用 http_client,并结合实际内核版本核对字段。
修改规则后如何安全回滚?
先复制原配置,只改一组规则;运行 sing-box check,启动后查看日志和测试域名结果。失败就恢复备份,不要把真实订阅链接、密码、证书或私钥放进公开校验器。
相关阅读
- 先看 sing-box Windows 订阅导入与启动验证
- 继续检查 DNS 分流和 DNS 泄漏
- 遇到连接失败时查看分层排查清单
- 按 Windows、macOS、Android 或 iOS 查看设备设置
- 对比 Clash Meta 的规则与策略组写法