sing-box 规则配置不生效?先查 Rule Set、规则顺序和 DNS
简答:先运行 sing-box check 确认配置可解析,再核对 Rule Set 是否定义并在 route.rules 中引用,最后检查规则顺序、DNS 规则和 final 兜底。远程规则集必须替换为真实地址。
定义:sing-box 规则配置是通过 route.rules、Rule Set、DNS rules 和 final,将域名、IP、协议或网络类型分配给指定出站的 JSON 配置。
先试这一步:用本地规则验证 route.rules 是否正常
如果 sing-box 规则“不生效”,不要一开始就启用远程 Rule Set、DoH 和 TUN。先复制下面这份只使用 inline Rule Set 的基础配置,再按实际客户端补充出站。示例中的 proxy 出站是占位结构,使用前必须替换为你已有且可用的代理出站;只验证规则结构时,可以先删除引用 proxy 的规则。
{
"log": {
"level": "info",
"timestamp": true
},
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "127.0.0.1",
"listen_port": 2080
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
},
{
"type": "block",
"tag": "block"
}
],
"route": {
"rule_set": [
{
"type": "inline",
"tag": "ads",
"rules": [
{
"domain_suffix": [".ads.example"]
}
]
},
{
"type": "inline",
"tag": "domestic",
"rules": [
{
"domain_suffix": [".cn"]
}
]
}
],
"rules": [
{
"rule_set": ["ads"],
"action": "reject"
},
{
"rule_set": ["domestic"],
"action": "route",
"outbound": "direct"
},
{
"domain_suffix": [".lan", ".local"],
"action": "route",
"outbound": "direct"
},
{
"ip_is_private": true,
"action": "route",
"outbound": "direct"
}
],
"final": "direct",
"auto_detect_interface": true
}
}.ads.example 是测试占位后缀,不代表真实广告规则源;测试时请替换为你明确知道的域名,或删除这条广告规则。.cn 只演示按域名后缀直连,不等于完整的国内域名清单。运行 sing-box check -c /替换为配置文件路径/config.json,正常判定是退出码为 0,且没有 unknown field、decode config 或标签引用错误。
规则集必须先在 route.rule_set 中定义,再由 route.rules 使用相同的 tag 引用。官方文档说明,规则按默认字段组合逻辑匹配,route、reject 和 hijack-dns 属于结束当前规则评估的动作;sniff、resolve 等动作执行后还会继续匹配。详见sing-box 官方路由规则文档与sing-box 官方规则动作文档。
Rule Set 的定义、引用与远程加载
Rule Set 常见有三种形式:inline 直接写入配置,local 从本地文件读取,remote 从 URL 下载并缓存。source 适合可读的 JSON 规则文件,binary 适合已经编译的二进制规则集。无论使用哪种形式,tag 都必须唯一,并且在 route.rules 中逐字一致引用。
{
"http_clients": [
{
"tag": "rule-set-client"
}
],
"route": {
"rule_set": [
{
"type": "remote",
"tag": "overseas",
"format": "source",
"url": "https://替换为真实可访问地址/rules.json",
"initial_path": "/替换为本地初始规则文件.json",
"http_client": "rule-set-client",
"update_interval": "1d"
}
],
"rules": [
{
"rule_set": ["overseas"],
"action": "route",
"outbound": "proxy"
}
],
"final": "direct"
}
}这段远程示例不能原样启动:URL、initial_path 和 proxy 都必须替换为真实配置。若暂时没有可访问的规则源,先使用上一节的 inline 版本验证路由,再改成 local,最后才启用 remote。initial_path 只有在本地文件真实存在时才有意义,否则应删除,而不是保留不存在的路径。
自 sing-box 1.14.0 起,远程规则集可使用 http_client、initial_path 和 update_interval。download_detour 已在 1.14.0 废弃,并计划在 1.16.0 移除;新配置应定义顶层 http_clients,再通过 http_client 引用。字段以sing-box 官方规则集文档为准。
规则字段怎么选:同类条件是或,不同类条件是与
| 字段 | 适用场景 | 使用建议 |
|---|---|---|
domain | 匹配完整域名 | 适合单个主机名的精确规则 |
domain_suffix | 匹配域名后缀及子域名 | 适合一组站点后缀,通常比正则直观 |
domain_keyword | 按关键词匹配域名 | 范围较宽,可能误匹配,需缩小关键词 |
domain_regex | 复杂模式匹配 | 只在普通域名字段无法表达时使用 |
ip_cidr | 目标网段或固定 IP | 适合办公网、局域网和明确的地址段 |
rule_set | 大量域名或 IP 的集中维护 | 必须先定义 Rule Set,再在规则中引用 tag |
普通规则的组合逻辑可以直接记为:同一类字段之间是“或”,不同类条件之间是“与”。例如同一条规则写 domain_suffix: [".example", ".test"] 和 network: "tcp",表示匹配两个后缀之一且网络类型为 TCP。相反,如果把“域名后缀走直连”和“UDP 走代理”写成同一条规则,它们不会自动表示两个独立场景,因为域名条件与 UDP 条件会形成同时满足的组合。需要分开写规则,或使用 type: logical 明确表达 and、or。官方逻辑见路由规则字段说明。
可直接改的场景模板:直连、代理、广告、UDP 和内网
下面片段都放在 route.rules 中。更具体的规则放前面,宽泛规则放后面;final 只处理前面没有命中的流量。
国内域名或办公网直连
{
"rule_set": ["domestic"],
"action": "route",
"outbound": "direct"
}domestic 必须先在 route.rule_set 中定义。若没有可信的国内域名规则文件,可先使用上一节的 domain_suffix: [".cn"] 测试;不要把未核实的第三方列表当成完整国内清单。
{
"ip_cidr": ["192.168.0.0/16", "10.0.0.0/8"],
"action": "route",
"outbound": "direct"
}海外规则集走代理
{
"rule_set": ["overseas"],
"action": "route",
"outbound": "proxy"
}overseas 和 proxy 都必须已经定义;否则 check 或启动阶段会出现标签引用问题。
广告规则集拒绝
{
"rule_set": ["ads"],
"action": "reject"
}游戏或实时应用按 UDP 规则处理
{
"network": "udp",
"action": "route",
"outbound": "proxy"
}自 sing-box 1.13.0 起,network 可匹配 tcp、udp 和 icmp。这只是按网络类型选择出站,不代表目标应用一定支持 UDP,也不代表连接一定成功;验证时应观察实际日志和应用表现。
DNS 分流:给每个 DNS 服务器定义 tag,并配置域名解析器
DNS 分流与路由分流是两套规则。先在 dns.servers 定义服务器,再在 dns.rules 使用 action: route 和目标 server。下面示例把局域网域名交给本地 DNS,把 overseas Rule Set 命中的域名交给 DoH。
{
"dns": {
"servers": [
{
"type": "local",
"tag": "dns-local"
},
{
"type": "https",
"tag": "dns-remote",
"server": "替换为DoH服务器域名",
"server_port": 443,
"path": "/dns-query",
"tls": {},
"domain_resolver": "dns-local"
}
],
"rules": [
{
"domain_suffix": [".lan", ".local"],
"action": "route",
"server": "dns-local"
},
{
"rule_set": ["overseas"],
"action": "route",
"server": "dns-remote"
}
],
"final": "dns-remote"
}
}DoH 的 server 如果写域名,必须配置 domain_resolver;这是新 DoH 结构中的拨号字段。若 DNS 服务器本身需要通过特定出站连接,还要根据实际网络配置拨号字段,而不是只填写 URL。相关字段见sing-box 官方 DoH 文档与sing-box 官方 DNS 规则动作文档。
检查 DNS 是否走错时,把日志级别临时改为 debug,观察查询最终使用的 DNS server tag。若配置了 dns-remote,但日志始终显示 dns-local,先检查规则顺序、Rule Set 是否命中、dns.final 是否提前兜底。不要只更换 DNS 地址而不检查匹配条件。
TUN 与 DNS 劫持:必须有条件,不能把 hijack-dns 单独放在首条
TUN 入站至少要明确 address、dns_mode、auto_route 等字段。sing-box 1.14.0 起,dns_mode 可取 disabled、native 或 hijack;启用 auto_route 时默认倾向使用 hijack。下面是结构示例,地址仅用于演示,必须与你的 TUN 配置和系统环境保持一致。
{
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"interface_name": "tun0",
"address": ["172.18.0.1/30"],
"dns_mode": "hijack",
"dns_address": ["172.18.0.2"],
"auto_route": true,
"strict_route": true
}
],
"route": {
"rules": [
{
"action": "sniff"
},
{
"protocol": "dns",
"action": "hijack-dns"
},
{
"ip_cidr": ["172.18.0.2/32"],
"action": "hijack-dns"
}
]
}
}不要把没有匹配条件的 {"action":"hijack-dns"} 当作通用规则直接放入配置;它可能把所有连接都送入 DNS 劫持。上例先用 sniff 识别协议,再仅对 DNS 协议或 dns_address 对应地址执行劫持。官方文档明确说明:当显式设置 dns_address 时,应配置 hijack-dns 规则处理发往这些地址的 DNS 流量。
strict_route 在 Windows 上可阻止非 TUN 接口的 DNS 泄漏,但也可能导致部分应用无法工作;在 Linux 上会让不支持的网络不可达,并影响某些 SO_BINDTODEVICE 流量。遇到虚拟机、容器或局域网异常时,先关闭该项做单变量对照。不要把它描述成所有多网卡问题的通用开关。字段与行为见sing-box 官方 TUN 文档。
版本速查卡:先改字段,再检查当前核心版本
| 字段或现象 | 官方版本信息 | 处理方式 |
|---|---|---|
download_detour | 1.14.0 废弃,计划 1.16.0 移除 | 改为顶层 http_clients 与规则集的 http_client |
initial_path | 1.14.0 起支持 | 只填写真实存在的本地初始文件,否则删除 |
geosite、geoip | 1.8.0 废弃,1.12.0 移除 | 迁移到 Rule Set,不要在新核心中继续使用 |
rule_set_ip_cidr_accept_empty | 1.14.0 废弃,计划 1.16.0 移除 | 按新版响应匹配方式重新设计,不要作为新配置核心 |
| DNS 旧地址筛选字段 | geoip 在 1.12.0 移除;ip_cidr、ip_is_private 作为旧地址筛选字段在 1.14.0 废弃 | 优先使用 evaluate、match_response 等新版响应匹配结构 |
旧配置出现未知字段、解析失败或启动行为变化时,先确认运行核心版本,再逐项迁移。不要把“字段已经废弃”和“当前仍会给出警告”混为一谈:geosite、geoip 在 1.12.0 已移除,当前核心通常会表现为未知字段或解析错误。版本信息以官方 GeoIP 文档、官方 DNS 规则文档和官方变更记录为准。
排错清单:看到什么现象,就回到哪一节
- check 失败:若出现 JSON 语法、未知字段或类型错误,先回到“先试这一步”和“版本速查卡”,不要继续查节点或网络。
- check 成功但规则不命中:核对
route.rule_set中的 tag、route.rules的引用、规则文件格式和规则顺序。 - 出站不符合预期:给测试域名单独写一条最前面的
domain规则,并指定容易识别的出站 tag。日志中应能看到该连接进入对应出站;若仍进入final,说明测试规则没有命中。 - 远程 Rule Set 加载失败:确认运行 sing-box 的设备能访问 URL,下载内容与
source或binary一致,initial_path存在,并且http_client已定义。 - DNS 服务器不对:把日志临时改为
debug,查看 DNS 请求使用的 server tag;若未出现预期 tag,检查dns.rules顺序和dns.final。 - TUN 开启后异常:先关闭 TUN 验证普通入站,再单独开启 TUN;随后分别对照
dns_mode、dns_address、hijack-dns和strict_route,一次只改一个变量。
最终判定不要只看“客户端显示已连接”。更可靠的标准是:check 退出码为 0;测试域名进入预期 outbound tag;DNS 日志显示预期 server tag;未命中的流量进入明确的 final。这样可以区分配置解析、规则匹配、DNS 分流和实际出口问题。
本文与 sing-box 项目及其开发者无隶属关系,内容依据截至 2026-10-23 可核对的公开文档整理;不同客户端对 TUN 权限、日志入口和 JSON 文件位置的操作仍可能不同。
常见问题
sing-box 规则按什么顺序执行?
规则按列表顺序匹配,更具体的 domain、ip_cidr 或 rule_set 应放在前面,宽泛规则放后面,route.final 负责未命中流量。route、reject、hijack-dns 会结束当前规则评估,sniff、resolve 执行后还会继续匹配。
Rule Set 已经定义,为什么 route.rules 仍然不生效?
先检查 route.rule_set 与 route.rules 中的 tag 是否完全一致,再检查 format 是否匹配文件内容、远程 URL 或 initial_path 是否可读,最后确认前面没有更宽泛的规则提前命中。
sing-box 1.14.0 以后还能使用 download_detour 吗?
官方文档已将 download_detour 标记为 1.14.0 废弃,并计划在 1.16.0 移除。新配置应定义 http_clients,再通过规则集的 http_client 引用。
DNS rules 怎么按 Rule Set 选择不同 DNS?
先在 dns.servers 中定义不同 tag 的 DNS 服务器,再在 dns.rules 中使用 rule_set、action: route 和目标 server tag,最后用 dns.final 设置未命中时的默认服务器。DoH 的 server 如果写域名,还要设置 domain_resolver。
TUN 开启后 DNS 泄漏或解析异常怎么查?
先确认 dns_mode、dns_address 与 hijack-dns 规则是否匹配,再把日志临时调为 debug,观察 DNS server tag。Windows 还应对照 strict_route 开启和关闭后的结果;不要只更换 DNS 地址。
国内直连规则一定要使用 geosite 或 geoip 吗?
不建议在新核心中继续依赖 geosite 或 geoip,它们已分别经历废弃和移除。可以使用经过核实的 Rule Set,或先用明确的 domain_suffix、ip_cidr 和局域网规则验证配置结构。