sing-box TUN 模式配置后断网?先查权限、DNS 和路由环回
简答:sing-box TUN 开启后断网,先确认节点单独可连接,再依次检查 TUN 权限、DNS 处理和路由环回。配置必须使用当前二进制支持的字段,节点域名还要配置可用的 domain_resolver。
定义:sing-box TUN 模式是通过虚拟网卡接管系统或指定应用流量,再交给 DNS、路由规则和出站处理的透明代理方式。
先试这一步:四个结果快速定位断网原因
如果 sing-box TUN 一开启就断网,先不要同时修改 MTU、DNS 和路由。按下面顺序测试:先确认是否创建了 TUN 接口,再确认节点能否单独连接,然后测试 IP,最后测试域名。这样能把问题缩小到权限、出站、DNS 或路由环回中的一个环节。
| 检查顺序 | 怎么判断 | 结果异常时优先处理 |
|---|---|---|
| 1. TUN 接口 | 客户端日志显示创建成功,系统能看到虚拟接口 | 权限、客户端能力、接口名称和系统网络扩展 |
| 2. 节点单独连接 | 关闭 TUN 后,现有出站能够连接 | 节点地址、端口、认证信息或出站配置 |
| 3. IP 访问 | 能访问一个已知 IP 测试目标 | auto_route、默认网卡绑定或路由环回 |
| 4. 域名访问 | DNS 查询无超时,域名能返回地址 | dns_mode、dns_address、DNS 规则和 hijack-dns |
本文是与 sing-box 项目及开发者无隶属关系的第三方使用指南。字段依据sing-box 官方 Tun 文档、官方路由文档和官方变更记录整理;截至 facts.today,官方变更日志列出的 1.15.0 仍为 alpha 系列条目,因此不要把“1.15.x”直接当作当前稳定版,实际字段应以你运行的二进制版本为准。示例中的节点域名、端口和认证信息均须替换。
最小可校验配置:不要再复制旧 DNS 格式
下面示例只用于验证 TUN、DNS、路由和占位出站的结构。它不包含真实节点参数,不能直接作为可用线路配置。与旧式 {"tag":"local","address":"local"} 不同,当前官方 DNS 服务器格式使用 type 字段;官方文档说明新格式自 sing-box 1.12.0 起使用,旧格式兼容性后来被移除。
{
"log": {
"level": "info"
},
"dns": {
"servers": [
{
"type": "local",
"tag": "local"
}
],
"final": "local"
},
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"address": [
"172.18.0.1/30",
"fdfe:dcba:9876::1/126"
],
"dns_mode": "hijack",
"auto_route": true,
"strict_route": false
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
},
{
"type": "socks",
"tag": "proxy",
"server": "替换为你的节点域名或 IP",
"server_port": 1080,
"domain_resolver": "local"
}
],
"route": {
"auto_detect_interface": true,
"default_domain_resolver": "local",
"final": "proxy"
}
}address 是 TUN 地址字段,示例同时放入 IPv4 和 IPv6 前缀;interface_name 没有写入,以便系统自动选择,避免把 Linux 的 tun0 误套到 macOS。官方 Tun 文档说明 interface_name 留空时会自动选择虚拟设备名称。
节点服务器使用域名时,必须让 sing-box 知道用哪个 DNS 解析。官方拨号字段文档说明,从 1.14.0 起,服务器地址使用域名的出站或端点需要配置 domain_resolver 或全局的 route.default_domain_resolver;只有配置了一个 DNS 服务器时才可以省略。这里两处都写出,是为了降低合并订阅配置时的歧义。相关字段见官方拨号字段文档。
配置保存后,用与你实际运行相同版本的 sing-box 执行:
sing-box check -c config.json这条命令的目的仅是校验 JSON 和字段。正常标准是命令退出时没有 JSON 解析错误、unknown field、缺少必填字段或出站参数错误;如果二进制不支持某字段,应先核对版本和官方变更记录,不要用删除字段的方式掩盖错误。
DNS 只能访问 IP 时:补齐 dns_address 与 hijack-dns
dns_mode 的官方取值是 disabled、native 和 hijack。其中 disabled 不设置原生 DNS,也不劫持 DNS;native 尽可能设置系统接口 DNS;hijack 在此基础上处理 53 端口 DNS。启用 auto_route 时,官方默认使用 hijack,但你仍应根据平台和日志验证实际行为。
如果显式填写 dns_address,官方要求再用 hijack-dns 路由动作处理发往这些地址的 DNS 流量。可以用下面的结构替换 TUN 入站和 route 相关部分:
{
"dns": {
"servers": [
{
"type": "local",
"tag": "local"
}
],
"final": "local"
},
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"address": [
"172.18.0.1/30",
"fdfe:dcba:9876::1/126"
],
"dns_mode": "hijack",
"dns_address": [
"172.18.0.2",
"fdfe:dcba:9876::2"
],
"auto_route": true,
"strict_route": false
}
],
"route": {
"auto_detect_interface": true,
"default_domain_resolver": "local",
"rules": [
{
"action": "sniff"
},
{
"protocol": "dns",
"action": "hijack-dns"
}
],
"final": "proxy"
}
}sniff 的作用是执行协议识别,随后通过 protocol: dns 匹配 DNS 连接;hijack-dns 会把请求交给 sing-box DNS 模块。两种动作均可在官方路由规则动作文档核对。
如果没有显式设置 dns_address,官方说明会使用 TUN address 中对应的下一个 IPv4 和 IPv6 地址,并按 hijack-dns 处理,因此最小配置可以不写这组字段。排查时不要同时使用两套 DNS 逻辑,否则很难判断是系统 DNS、TUN 地址还是规则动作产生了问题。
测试方法是先运行 nslookup example.com 或系统对应的 DNS 查询工具,再查看 sing-box 前台日志。example.com 只是示例域名,请替换成你确认应当能解析的测试域名;无超时并返回 A 或 AAAA 记录,只能说明 DNS 基本工作,不能单独证明全部流量都经过 TUN。
路由环回、局域网和分流:三个配置目标分开处理
开启 auto_route 后,节点连接本身也可能被送回 TUN。官方建议使用 route.auto_detect_interface、route.default_interface 或出站的 bind_interface 避免环回。Windows、macOS 和 Linux 支持 auto_detect_interface;Android 的 override_android_vpn 只表示在启用自动网卡检测时接受 Android VPN 作为上游网卡,并不是所有 Android TUN 场景都必须开启。
局域网排除应使用 TUN 的 route_exclude_address,并根据你的实际网络修改,不要机械照抄:
"route_exclude_address": [
"192.168.0.0/16",
"10.0.0.0/8",
"172.16.0.0/12",
"fc00::/7"
]这组地址覆盖常见私有 IPv4 和 IPv6 ULA 范围,但你的办公网、打印机网段或虚拟机网段可能不同。判定标准是:加入排除规则后,局域网设备恢复访问,同时互联网测试仍能正常连接;如果只有局域网恢复、互联网异常,说明排除范围过大,应逐段缩小。
| 目标 | 核心写法 | 适用提醒 |
|---|---|---|
| 全局代理 | route.final 指向 proxy | 先验证节点、DNS 和环回,再作为默认方案 |
| 按域名分流 | 在 route.rules 中使用 domain 或 domain_suffix | 规则按顺序匹配,未命中的请求走 final |
| 局域网直连 | 使用 route_exclude_address 或 IP 规则指向 direct | 网段必须按实际网络核对 |
| 仅代理指定应用 | Android 使用 include_package;桌面端可用 package_name、process_name 等路由匹配字段 | 包名或进程名必须从设备和系统中核对 |
官方路由规则文档列出了 process_name、process_path、package_name 等匹配字段;Android TUN 文档则明确说明 include_package 和 exclude_package 用于限制或排除 Android 应用包名。若使用 Android 应用筛选,还必须保留 auto_route。
"include_package": [
"替换为真实 Android 包名"
]Linux 用户还可考虑 auto_redirect。官方说明它只支持 Linux、需要启用 auto_route,依赖 nftables 改善路由和性能,并可减少与 Docker 桥接网络的冲突;预匹配功能还需要内核支持 nfnetlink_queue。Windows 和 macOS 不要照抄这个字段。
按平台速查:权限、字段和检查命令
| 平台 | 先确认什么 | 可执行检查 | 不应直接照抄 |
|---|---|---|---|
| Windows | 客户端有管理员权限,TUN 或网络驱动已创建 | route print、ipconfig | Linux 的 nftables、auto_redirect |
| macOS | 已允许网络扩展或 VPN 配置,系统出现 utun 接口 | ifconfig、netstat -rn | 固定的 interface_name: tun0 |
| Linux | 具有创建 TUN、修改路由和 nftables 的权限 | ip link show、ip route、nft list ruleset | 没有 nftables 时直接启用 auto_redirect |
| Android | 已授予系统 VPN 权限;root 模式只在需要 auto_redirect 等能力时考虑 | 查看客户端日志和实际 VPN 状态 | 把桌面端进程规则当作应用包名规则 |
Windows 的 route print 用于查看路由表,正常时应能看到与 TUN 或默认路由相关的变化;macOS 的 ifconfig 用于确认 utun 接口,netstat -rn 用于查看路由;Linux 的 ip link show 应能看到 TUN 接口,ip route 应有对应路由,nft list ruleset 仅用于确认 Linux 防火墙规则,均可能需要管理员或 root 权限。
如果你使用 Android VPN 作为上游,先明确目标:官方文档说明启用 auto_route 时,VPN 默认优先于 TUN;要让 TUN 经过 VPN,需要启用 route.override_android_vpn,并同时满足 auto_detect_interface 的使用条件。不要仅因为“Android 连不上”就无条件添加这个字段。
版本迁移和最终自查:哪些旧字段不要再复制
当前官方资料中,以下迁移点可以直接核对:
dns_mode、dns_address属于 sing-box 1.14.0 的 TUN 变更项,取值应为disabled、native或hijack。stack在 sing-box 1.15.0 起弃用,官方变更日志说明 sing-tun 使用自有 TCP/IP 栈,并计划在 1.17.0 移除,因此新配置不应继续依赖它。inet4_address、inet6_address已合并到address,不要在新配置中混用。- DNS 服务器应使用带
type的新格式,例如{"type":"local","tag":"local"}。 - 出站服务器地址使用域名时,优先配置
domain_resolver或route.default_domain_resolver。 - 旧式 outbound DNS 规则已迁移到 domain resolver 机制,不能把旧字段继续当作 1.15 语法基础。
发布前按下面清单执行:一是确认二进制版本;二是删除未在该版本文档中确认的旧字段;三是执行 sing-box check -c config.json;四是关闭 TUN 单独验证节点;五是依次测试 TUN 接口、IP、域名和局域网;六是每次只改一个变量。
如果 TUN 接口存在、节点单独可连、IP 正常但域名失败,优先回到 DNS 章节;如果节点本身也超时,优先回到 auto_detect_interface、default_interface 或 bind_interface;如果互联网正常而局域网异常,优先检查 route_exclude_address 和 strict_route。
常见问题
sing-box TUN 模式中的 dns_mode 可以写哪些值?
官方 Tun 文档列出的值是 disabled、native 和 hijack。disabled 不设置原生 DNS且不劫持;native 尽可能设置平台接口 DNS;hijack 在 native 基础上处理 53 端口 DNS。
为什么 TUN 开启后节点也连接不上?
优先排查路由环回。开启 auto_route 后,节点连接可能也被送入 TUN。先关闭 TUN确认节点单独可连,再保留 route.auto_detect_interface,必要时检查 default_interface 或出站 bind_interface。
dns_address 写了以后为什么还要 hijack-dns?
官方文档要求:显式设置 dns_address 后,应配置 hijack-dns 路由动作处理发往这些地址的 DNS 流量。可以先用 sniff 识别协议,再用 protocol:dns 匹配并执行 hijack-dns。
strict_route 一开始应该设为 true 吗?
不建议把 true 作为所有环境的排障起点。可以先设为 false,确认节点、互联网和局域网均正常后,再单独测试严格路由;如果局域网或虚拟机异常,应优先检查该字段和排除网段。
Linux 是否必须开启 auto_redirect?
不是所有场景都必须,但官方在 Tun 文档中推荐 Linux 在启用 auto_route 时考虑 auto_redirect。它依赖 nftables,预匹配还需要内核支持 nfnetlink_queue;Windows 和 macOS 不应照抄。
Android 如何只让指定应用进入 TUN?
在 TUN 入站中使用 include_package 限制包名,或用 exclude_package 排除包名;这些字段仅用于 Android 应用包名筛选,并且需要 auto_route。真实包名必须从设备或客户端信息中核对。
macOS 为什么不能直接使用 interface_name:tun0?
tun0 是常见的 Linux 接口示例,macOS 通常由系统分配 utun 接口。通用配置可以省略 interface_name,让系统自动选择;如果必须指定名称,应先以实际客户端和系统行为为准。