Skip to content

TUN — sing-box ​

sing-box 的 TUN 入站是 Go 语言生态的 规范实现 —— 多数其他实现(mihomo、Clash-Meta 等)都派生自它。入站创建 TUN 设备,在系统栈或 gVisor 栈中解析原始数据包,并把得到的连接交给路由引擎处理。

入站 ​

type: "tun":

字段类型默认值允许值描述
interface_namestring(auto)<interface name>TUN 设备名。为空时按操作系统默认选取(tun0、utun5 等)。
netnsstring(unset)<network namespace tag / name / path>仅 Linux。在该网络命名空间中创建 TUN 接口 —— 可以是顶层 network_namespaces 中的 tag,也可以是命名空间名称或路径。此时 auto_route / auto_redirect 在命名空间内生效;若命名空间归当前用户所有则无需 root。与 platform 冲突。
mtuuint3265535<bytes>设备 MTU。未设置时为 65535;Android 上为 9000,Apple Network Extension 中为 4064。
addressbadoption.Listable[netip.Prefix][]<CIDR>接口地址(典型为一个 IPv4 + 一个 IPv6)。旧的 inet4_address / inet6_address 字段会在启动时被拒绝。
dns_modestringhijackdisabled | native | hijackTUN 接口上的 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_addressbadoption.Listable[netip.Addr](derived from address)<IP>dns_mode 所用的 DNS 服务器地址。未设置时,每个地址族取 address 首个条目的下一个 IP,并自动把发往这些地址的连接劫持进 DNS 模块(等同于 hijack-dns 规则)。一旦设置,这种自动劫持即关闭 —— 如仍需要,请显式添加 hijack-dns 路由规则。
auto_routeboolfalsetrue | false自动安装操作系统路由,把所有流量导向 TUN。
iproute2_table_indexint2022<int>auto_route 使用的 Linux iproute2 表索引。
iproute2_rule_indexint9000<int>Linux iproute2 规则索引。
auto_redirectboolfalsetrue | falseLinux NFTables 自动重定向 —— 不改路由就把流量接入 TUN。在热 loopback 路径上比 auto_route 更快。
auto_redirect_input_markFwMark0<uint32>送入 TUN 的数据包附加的 fwmark。
auto_redirect_output_markFwMark0<uint32>TUN 出口数据包附加的 fwmark。
auto_redirect_reset_markFwMark0<uint32>处理完成后清除的 fwmark。
auto_redirect_nfqueueuint160<uint16>auto-redirect 路径使用的 NFQUEUE 编号。
auto_redirect_iproute2_fallback_rule_indexint0<int>auto-redirect 无法安装时使用的回退规则索引。
exclude_mptcpboolfalsetrue | false跳过 MPTCP 流(让其走普通内核路径)。
loopback_addressbadoption.Listable[netip.Addr][]<IP>视作 loopback 的地址(不经 TUN)。
strict_routeboolfalsetrue | false阻止流量绕过 TUN 设备(在默认路由边界添加 DROP 规则)。
route_addressbadoption.Listable[netip.Prefix][]<CIDR>启用 auto_route 时,仅把这些 CIDR 经 TUN。默认全量。
route_address_setbadoption.Listable[string][]<rule-set tag>按 rule-set 的 IP-CIDR 条目而非显式列表路由。
route_exclude_addressbadoption.Listable[netip.Prefix][]<CIDR>保留在默认接口上的 CIDR(逃生口)。
route_exclude_address_setbadoption.Listable[string][]<rule-set tag>按 rule-set 的排除项。
include_interfacebadoption.Listable[string][]<interface>仅附着到这些接口(移动端多网卡)。
exclude_interfacebadoption.Listable[string][]<interface>排除这些接口。
include_uidbadoption.Listable[uint32][]<uid>Linux / macOS 上按 UID 包含。
include_uid_rangebadoption.Listable[string][]<from:to>按 UID 范围包含。
exclude_uidbadoption.Listable[uint32][]<uid>按 UID 排除。
exclude_uid_rangebadoption.Listable[string][]<from:to>按 UID 范围排除。
include_android_userbadoption.Listable[int][]<user id>Android 多用户包含。
include_packagebadoption.Listable[string][]<package name>Android 包名包含。
exclude_packagebadoption.Listable[string][]<package name>Android 包名排除。
include_mac_addressbadoption.Listable[string][]<MAC address>仅 Linux 且启用 auto_route 与 auto_redirect。只路由来自这些源 MAC 地址的流量(例如路由器上的局域网设备)。与 exclude_mac_address 冲突。
exclude_mac_addressbadoption.Listable[string][]<MAC address>仅 Linux 且启用 auto_route 与 auto_redirect。排除这些源 MAC 地址。与 include_mac_address 冲突。
udp_timeoutUDPTimeoutCompat5m<duration or seconds>UDP 流的空闲超时。
udp_mappingUDPNATBehaviorendpoint_independentendpoint_independent | address_dependent | address_and_port_dependentUDP NAT 映射行为:同一源地址与端口对所有目标复用同一映射(默认),或按目标地址 / 地址加端口分别建立映射。
udp_filteringUDPNATBehaviorendpoint_independentendpoint_independent | address_dependent | address_and_port_dependentUDP NAT 过滤行为:接受任意远端的数据包(默认),或仅接受已发送过数据包的远端地址 / 地址加端口。
udp_nat_maxuint320 (auto)<uint32>UDP NAT 会话上限;达到上限时关闭最久未使用的会话。为 0 时:iOS 上为 4096,其他平台按总内存在 4096–16384 之间选取(无法检测时为 16384)。
stackstring(mixed / system)system | gvisor | mixedTCP/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 支持两种路由方式:

  1. auto_route: true(跨平台)。安装操作系统路由把所有流量导向 TUN。Linux 上使用 iproute2 表 + 规则索引;macOS 上调用 route add;Windows 上直接编程路由表。

  2. 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):

json
{
  "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 应用过滤 —— 只代理列出的包:

json
{
  "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 自动重定向:

json
{
  "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)

由 Argsment 出品的 Core Tutorial