TUN — sing-box
sing-box 的 TUN 入站是 Go 语言生态的 规范实现 —— 多数其他实现(mihomo、Clash-Meta 等)都派生自它。入站创建 TUN 设备,在系统栈或 gVisor 栈中解析原始数据包,并把得到的连接交给路由引擎处理。
入站
type: "tun":
| 字段 | 类型 | 默认值 | 允许值 | 描述 |
|---|---|---|---|---|
interface_name | string | (auto) | <interface name> | TUN 设备名。为空时按操作系统默认选取(tun0、utun5 等)。 |
netns | string | (unset) | <network namespace tag / name / path> | 仅 Linux。在该网络命名空间中创建 TUN 接口 —— 可以是顶层 network_namespaces 中的 tag,也可以是命名空间名称或路径。此时 auto_route / auto_redirect 在命名空间内生效;若命名空间归当前用户所有则无需 root。与 platform 冲突。 |
mtu | uint32 | 65535 | <bytes> | 设备 MTU。未设置时为 65535;Android 上为 9000,Apple Network Extension 中为 4064。 |
address | badoption.Listable[netip.Prefix] | [] | <CIDR> | 接口地址(典型为一个 IPv4 + 一个 IPv6)。旧的 inet4_address / inet6_address 字段会在启动时被拒绝。 |
dns_mode | string | hijack | disabled | native | hijack | TUN 接口上的 DNS 处理方式。native 设置平台原生的接口 DNS(Linux 为 systemd-resolved,Windows / Apple 为按接口 DNS);hijack(默认)在此基础上再劫持 53 端口流量 —— Linux 上为一条 iproute2 规则,启用 auto_redirect 时为指向 dns_address 的 nftables DNAT,Windows 上配合 strict_route 时为 WFP 过滤器;disabled 两者都不做。 |
dns_address | badoption.Listable[netip.Addr] | (derived from address) | <IP> | dns_mode 所用的 DNS 服务器地址。未设置时,每个地址族取 address 首个条目的下一个 IP,并自动把发往这些地址的连接劫持进 DNS 模块(等同于 hijack-dns 规则)。一旦设置,这种自动劫持即关闭 —— 如仍需要,请显式添加 hijack-dns 路由规则。 |
auto_route | bool | false | true | false | 自动安装操作系统路由,把所有流量导向 TUN。 |
iproute2_table_index | int | 2022 | <int> | auto_route 使用的 Linux iproute2 表索引。 |
iproute2_rule_index | int | 9000 | <int> | Linux iproute2 规则索引。 |
auto_redirect | bool | false | true | false | Linux NFTables 自动重定向 —— 不改路由就把流量接入 TUN。在热 loopback 路径上比 auto_route 更快。 |
auto_redirect_input_mark | FwMark | 0 | <uint32> | 送入 TUN 的数据包附加的 fwmark。 |
auto_redirect_output_mark | FwMark | 0 | <uint32> | TUN 出口数据包附加的 fwmark。 |
auto_redirect_reset_mark | FwMark | 0 | <uint32> | 处理完成后清除的 fwmark。 |
auto_redirect_nfqueue | uint16 | 0 | <uint16> | auto-redirect 路径使用的 NFQUEUE 编号。 |
auto_redirect_iproute2_fallback_rule_index | int | 0 | <int> | auto-redirect 无法安装时使用的回退规则索引。 |
exclude_mptcp | bool | false | true | false | 跳过 MPTCP 流(让其走普通内核路径)。 |
loopback_address | badoption.Listable[netip.Addr] | [] | <IP> | 视作 loopback 的地址(不经 TUN)。 |
strict_route | bool | false | true | false | 阻止流量绕过 TUN 设备(在默认路由边界添加 DROP 规则)。 |
route_address | badoption.Listable[netip.Prefix] | [] | <CIDR> | 启用 auto_route 时,仅把这些 CIDR 经 TUN。默认全量。 |
route_address_set | badoption.Listable[string] | [] | <rule-set tag> | 按 rule-set 的 IP-CIDR 条目而非显式列表路由。 |
route_exclude_address | badoption.Listable[netip.Prefix] | [] | <CIDR> | 保留在默认接口上的 CIDR(逃生口)。 |
route_exclude_address_set | badoption.Listable[string] | [] | <rule-set tag> | 按 rule-set 的排除项。 |
include_interface | badoption.Listable[string] | [] | <interface> | 仅附着到这些接口(移动端多网卡)。 |
exclude_interface | badoption.Listable[string] | [] | <interface> | 排除这些接口。 |
include_uid | badoption.Listable[uint32] | [] | <uid> | Linux / macOS 上按 UID 包含。 |
include_uid_range | badoption.Listable[string] | [] | <from:to> | 按 UID 范围包含。 |
exclude_uid | badoption.Listable[uint32] | [] | <uid> | 按 UID 排除。 |
exclude_uid_range | badoption.Listable[string] | [] | <from:to> | 按 UID 范围排除。 |
include_android_user | badoption.Listable[int] | [] | <user id> | Android 多用户包含。 |
include_package | badoption.Listable[string] | [] | <package name> | Android 包名包含。 |
exclude_package | badoption.Listable[string] | [] | <package name> | Android 包名排除。 |
include_mac_address | badoption.Listable[string] | [] | <MAC address> | 仅 Linux 且启用 auto_route 与 auto_redirect。只路由来自这些源 MAC 地址的流量(例如路由器上的局域网设备)。与 exclude_mac_address 冲突。 |
exclude_mac_address | badoption.Listable[string] | [] | <MAC address> | 仅 Linux 且启用 auto_route 与 auto_redirect。排除这些源 MAC 地址。与 include_mac_address 冲突。 |
udp_timeout | UDPTimeoutCompat | 5m | <duration or seconds> | UDP 流的空闲超时。 |
udp_mapping | UDPNATBehavior | endpoint_independent | endpoint_independent | address_dependent | address_and_port_dependent | UDP NAT 映射行为:同一源地址与端口对所有目标复用同一映射(默认),或按目标地址 / 地址加端口分别建立映射。 |
udp_filtering | UDPNATBehavior | endpoint_independent | endpoint_independent | address_dependent | address_and_port_dependent | UDP NAT 过滤行为:接受任意远端的数据包(默认),或仅接受已发送过数据包的远端地址 / 地址加端口。 |
udp_nat_max | uint32 | 0 (auto) | <uint32> | UDP NAT 会话上限;达到上限时关闭最久未使用的会话。为 0 时:iOS 上为 4096,其他平台按总内存在 4096–16384 之间选取(无法检测时为 16384)。 |
stack | string | (mixed / system) | system | gvisor | mixed | TCP/IP 栈实现。system 使用内核网络栈;gvisor 跑用户态栈;mixed TCP 走系统、UDP 用 gVisor。启用 gVisor 构建时默认为 mixed,否则为 system。 |
platform | *TunPlatformOptions | (unset) | TunPlatformOptions | 平台专属覆盖(当前仅 http_proxy)。 |
源码: option/tun.go:14-72 · 锚定版本 v1.14.2 (af6e64c)
该结构体还内嵌 InboundOptions(sniff、sniff_override_dest、domain_strategy 等),但仅用于在启动时拒绝它们 —— 见“说明”。
协议栈选择
system—— 内核原生 TCP/IP。最快。需要 OS 暴露相应的 TUN ioctl(Linux 是;macOS utun 是;Windows 通过 wintun DLL)。gvisor—— Google 的用户态 TCP/IP 栈。较慢但可移植;在内核 TUN 支持不佳的平台上是唯一选择。mixed—— TCP 走系统栈(内核级吞吐用在连接密集的路径上),UDP 走 gVisor。在含 gVisor 的构建中是默认值(否则默认为system),也是大多数用户的选择。
路由模式
sing-box 的 TUN 支持两种路由方式:
auto_route: true(跨平台)。安装操作系统路由把所有流量导向 TUN。Linux 上使用 iproute2 表 + 规则索引;macOS 上调用route add;Windows 上直接编程路由表。auto_redirect: true(仅 Linux,需同时启用auto_route)。添加把流量重定向进 sing-box 的 nftables 规则 —— 路由与性能都优于单纯的auto_route或 tproxy,不与 Docker 桥接网络冲突,并自动集成 OpenWrt fw4。需要nft与匹配的内核模块。
strict_route: true 在外围接口添加 DROP 规则,防止流量绕过 TUN 泄露 —— 对 kill-switch 语义很重要。
示例
标准桌面(Linux / macOS):
{
"inbounds": [{
"type": "tun",
"tag": "tun-in",
"interface_name": "sing-tun",
"mtu": 9000,
"address": ["172.16.0.1/30", "fdfe:dcba:9876::1/126"],
"auto_route": true,
"strict_route": true,
"stack": "mixed"
}],
"route": {
"auto_detect_interface": true,
"rules": [
{ "action": "sniff" },
{ "protocol": "dns", "action": "hijack-dns" },
{ "ip_is_private": true, "outbound": "direct" }
],
"final": "proxy"
}
}Android 应用过滤 —— 只代理列出的包:
{
"inbounds": [{
"type": "tun",
"interface_name": "tun0",
"mtu": 9000,
"address": ["172.16.0.1/30"],
"auto_route": true,
"stack": "system",
"include_package": ["com.netflix.mediaclient", "com.spotify.music"]
}]
}繁忙主机上推荐使用的 Linux NFTables 自动重定向:
{
"inbounds": [{
"type": "tun",
"auto_route": true,
"auto_redirect": true,
"auto_redirect_input_mark": "0x100",
"auto_redirect_output_mark": "0x200",
"address": ["172.16.0.1/30"]
}]
}说明
- 默认的
dns_mode(hijack)会改动系统状态:sing-box 会设置 TUN 接口的原生 DNS,并安装 53 端口劫持。如需保持接口 DNS 与防火墙不变,请设置"dns_mode": "disabled"。 inet4_address/inet6_address字段、它们的inet4_*/inet6_*路由变体以及gso可以被解析,但会在启动时被拒绝;上表已将其隐藏。请使用address、route_address与route_exclude_address。- 该结构体内嵌的入站字段(
sniff、sniff_override_dest、domain_strategy等)会在启动时被拒绝 —— 请改用sniff/resolve路由规则 action。 endpoint_independent_nat会被解析但被忽略。UDP NAT 行为由udp_mapping/udp_filtering(默认与端点无关)设置,并受udp_nat_max限制。auto_redirect要求启用auto_route(仅 Linux),并与route.default_mark及拨号层的routing_mark冲突。- 启用
auto_route时,strict_route会让不受支持的网络不可达;在 Windows 上还能防止多宿主解析导致的 DNS 泄漏。Linux 上配合auto_redirect时,它还会把SO_BINDTODEVICE流量送入 sing-box。
跨内核说明
- Xray-core 的 TUN 入站是最小化的 —— 可通过
autoSystemRoutingTable安装路由,但没有 DNS 劫持与应用过滤。参见 TUN — Xray-core。 - mihomo 在顶层
tun:块下提供几乎相同的特性集,字段名为 kebab-case,并多了一个dns-hijack列表。参见 TUN — mihomo。
源码: option/tun.go:14-72 · v1.14.2 (af6e64c)
