Skip to content

TUN — sing-box

sing-box's TUN inbound is the canonical implementation of a Go-land TUN — most other implementations (mihomo's, Clash-Meta, others) are derived from it. The inbound creates a TUN device, parses raw packets in either the system or gVisor stack, and dispatches resulting connections to the routing engine.

Inbound

type: "tun":

FieldTypeDefaultAllowed valuesDescription
interface_namestring(auto)<interface name>TUN device name. Empty picks an OS-default (`tun0`, `utun5`, etc.).
mtuuint329000<bytes>MTU for the device. 9000 is sing-box's default — high to amortize packet overhead.
addressbadoption.Listable[netip.Prefix][]<CIDR>Interface addresses (one IPv4 + one IPv6 typical). Replaces the deprecated `inet4_address` / `inet6_address` pair.
auto_routeboolfalsetrue | falseAuto-install OS routes that direct all traffic to the TUN device.
iproute2_table_indexint2022<int>Linux iproute2 table index used by `auto_route`.
iproute2_rule_indexint9000<int>Linux iproute2 rule index.
auto_redirectboolfalsetrue | falseLinux NFTables auto-redirect — splice traffic into TUN without changing routes. Faster than auto_route on hot loopback paths.
auto_redirect_input_markFwMark0<uint32>fwmark applied to TUN-bound packets.
auto_redirect_output_markFwMark0<uint32>fwmark applied to TUN-egress packets.
auto_redirect_reset_markFwMark0<uint32>fwmark to remove after processing.
auto_redirect_nfqueueuint160<uint16>NFQUEUE number for the auto-redirect path.
auto_redirect_iproute2_fallback_rule_indexint0<int>Fallback rule index when auto-redirect can't be installed.
exclude_mptcpboolfalsetrue | falseSkip MPTCP flows (let them use the normal kernel path).
loopback_addressbadoption.Listable[netip.Addr][]<IP>Addresses treated as loopback (don't route through TUN).
strict_routeboolfalsetrue | falseBlock traffic from leaking around the TUN device (DROP rules on the default-route boundary).
route_addressbadoption.Listable[netip.Prefix][]<CIDR>When `auto_route` is on, route only these CIDRs through TUN. Default routes everything.
route_address_setbadoption.Listable[string][]<rule-set tag>Route based on rule-set IP-CIDR entries instead of an explicit list.
route_exclude_addressbadoption.Listable[netip.Prefix][]<CIDR>CIDRs to keep on the default interface (escape hatch).
route_exclude_address_setbadoption.Listable[string][]<rule-set tag>Rule-set-driven exclusion.
include_interfacebadoption.Listable[string][]<interface>Only attach to these interfaces (mobile multi-NIC).
exclude_interfacebadoption.Listable[string][]<interface>Exclude these interfaces.
include_uidbadoption.Listable[uint32][]<uid>Linux/macOS UID inclusion.
include_uid_rangebadoption.Listable[string][]<from:to>UID range inclusion.
exclude_uidbadoption.Listable[uint32][]<uid>UID exclusion.
exclude_uid_rangebadoption.Listable[string][]<from:to>UID range exclusion.
include_android_userbadoption.Listable[int][]<user id>Android multi-user inclusion.
include_packagebadoption.Listable[string][]<package name>Android package inclusion.
exclude_packagebadoption.Listable[string][]<package name>Android package exclusion.
udp_timeoutUDPTimeoutCompat5m<duration or seconds>Idle timeout for UDP flows.
stackstringmixedsystem | gvisor | mixedTCP/IP stack implementation. `system` uses the kernel's network stack; `gvisor` runs a userspace stack; `mixed` uses gVisor for TCP and the system for UDP.
platform*TunPlatformOptions(unset)TunPlatformOptionsPlatform-specific overrides (currently just `http_proxy`).
gsoboolDeprecated: removed
inet4_addressbadoption.Listable[netip.Prefix]Deprecated: merged to Address
inet6_addressbadoption.Listable[netip.Prefix]Deprecated: merged to Address
inet4_route_addressbadoption.Listable[netip.Prefix]Deprecated: merged to RouteAddress
inet6_route_addressbadoption.Listable[netip.Prefix]Deprecated: merged to RouteAddress
inet4_route_exclude_addressbadoption.Listable[netip.Prefix]Deprecated: merged to RouteExcludeAddress
inet6_route_exclude_addressbadoption.Listable[netip.Prefix]Deprecated: merged to RouteExcludeAddress
endpoint_independent_natboolDeprecated: removed

Source: option/tun.go:13-63 · pinned at v1.13.11 (553cfa1)

The struct also embeds InboundOptions (sniff, sniff_override_dest, domain_strategy, …).

Stack choice

  • system — kernel's native TCP/IP. Fastest. Requires the OS to expose the right TUN ioctls (Linux: yes; macOS: utun yes; Windows: wintun via DLL).
  • gvisor — Google's userspace TCP/IP stack. Slower but portable; the only choice on platforms without good kernel TUN support.
  • mixed — gVisor for TCP (where userspace state-machine bugs matter less), system for UDP (where it matters more). The default and what most users want.

Routing models

sing-box's TUN supports two routing approaches:

  1. auto_route: true (cross-platform). Installs OS routes directing all traffic to the TUN. On Linux, uses iproute2 table + rule indices. On macOS, programs route add. On Windows, programs the routing table directly.

  2. auto_redirect: true (Linux only). Installs NFTables redirect rules instead of changing routes. Faster on hot-loopback paths because there's no extra hop. Requires nft and matching kernel modules.

strict_route: true adds DROP rules on the surrounding interface to prevent traffic leaking around the TUN — important for kill-switch semantics.

Examples

Standard desktop setup (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",
    "sniff": true,
    "sniff_override_dest": true
  }],
  "route": {
    "auto_detect_interface": true,
    "rules": [
      { "action": "sniff" },
      { "protocol": "dns", "action": "hijack-dns" },
      { "ip_is_private": true, "outbound": "direct" }
    ],
    "final": "proxy"
  }
}

Android app filtering — proxy only the listed packages:

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 with NFTables auto-redirect (preferred over auto-route on busy hosts):

json
{
  "inbounds": [{
    "type": "tun",
    "auto_redirect": true,
    "auto_redirect_input_mark": "0x100",
    "auto_redirect_output_mark": "0x200",
    "address": ["172.16.0.1/30"]
  }]
}

Notes

  • address was previously two fields (inet4_address / inet6_address). Both still parse but emit deprecation warnings — configs should use the new combined address list.
  • endpoint_independent_nat was removed. Set it on the route rule action instead (via udp_disable_domain_unmapping).
  • gso was removed — kernel GSO is auto-detected.
  • auto_route and auto_redirect are mutually exclusive. Pick one.
  • strict_route on Linux uses NFTables when available, falls back to iptables. Both require root.

Cross-core notes

  • Xray-core has a minimal TUN inbound — no auto-route, no DNS hijack, no app filtering. See TUN — Xray-core.
  • mihomo has a nearly identical feature set under the top-level tun: block, with kebab-case field names and an extra dns-hijack list. See TUN — mihomo.

Source: option/tun.go:13-63 · v1.13.11 (553cfa1)

Core Tutorial by Argsment