The instant you flip the TUN switch, three things happen on your system: a network adapter appears, the routing table is rewritten, and port 53 is hijacked.
Understand those three and every awkward TUN problem has a direction to investigate.
1. Creating the virtual adapter
TUN is a kind of virtual network device provided by the operating system. As far as the system is concerned it is an ordinary adapter, except the other end is not a physical cable but a userspace program — here, the Mihomo core.
Per-platform implementations:
| Platform | Implementation | Privileges required |
|---|---|---|
| Windows | The wintun driver | Administrator (installing a driver plus a system service) |
| macOS | The utun kernel extension | root (a privileged helper) |
| Linux | /dev/net/tun | CAP_NET_ADMIN |
Clash Verge's "service mode" exists precisely to avoid asking for elevation every time — install the system service once and it performs the privileged operations from then on.
2. Rewriting the routing table
An adapter alone is not enough; the system has to be told to send traffic to it. That is done by modifying routes.
With auto-route: true, the core adds routes like:
0.0.0.0/1 → TUN adapter
128.0.0.0/1 → TUN adapterWhy two /1 routes rather than one 0.0.0.0/0?
Because route matching follows longest-prefix-first. The system's existing default route is 0.0.0.0/0; if TUN also claimed 0.0.0.0/0, two routes of equal length would be ambiguous. Split into two /1 routes, the prefix is longer, so they reliably beat the original default — while leaving that default in place, so the core's own outbound traffic can still get out normally.
auto-detect-interface: true lets the core work out the real outbound adapter (Wi-Fi or Ethernet) so it follows along when you change networks.
What strict-route does
tun:
strict-route: trueThis adds stricter routing rules and firewall policy so nothing can slip past TUN. The side effect is a higher chance of conflict with other VPN software.
Turn it off when you need to coexist with a VPN.
Excluding a specific adapter
For coexistence with a corporate VPN:
tun:
exclude-interface: ["ppp0", "Cisco AnyConnect"]3. DNS hijacking
tun:
dns-hijack:
- any:53Meaning: any DNS query sent to port 53, whatever server it was addressed to, is intercepted and answered by the core's own resolver.
Why this is necessary: some programs hard-code a DNS server (querying 8.8.8.8 directly, say), bypassing your system settings. Without hijacking, those queries take the original path out, which means:
- Inaccurate answers (possibly poisoned)
- Lost domain information, leaving the core to match rules on IP alone
- A DNS leak — your ISP can see which names you looked up
4. The stack: gvisor, system or mixed
TUN receives raw IP packets, so it needs a TCP/IP stack to reassemble them into connections. Three implementations:
Guidance:
| Situation | Choose |
|---|---|
| Unsure / first-time setup | mixed |
| Strange connection problems | gvisor |
| Soft router, chasing throughput | system |
| UDP problems on macOS | gvisor |
5. MTU and fragmentation
tun:
mtu: 1500MTU is the maximum size of a single packet. Set the TUN adapter's MTU larger than the real link supports and packets get fragmented, hurting performance; set it too small and transfer efficiency drops.
1500 is the Ethernet standard and usually needs no change. But if your node runs over a link that already carries encapsulation overhead (certain relays, a PPPoE connection), the usable MTU is below 1500 and you may need 1400–1450.
6. A complete TUN configuration
tun:
enable: true
stack: mixed
device: Mihomo
auto-route: true
auto-detect-interface: true
auto-redirect: false # extra redirection on Linux
strict-route: false
mtu: 1500
dns-hijack:
- any:53
- tcp://any:53
# exclude adapters to avoid VPN conflicts
# exclude-interface: ["ppp0"]
# exclude specific apps (Mihomo)
# exclude-package: ["com.example.app"] # AndroidThe DNS configuration that goes with it:
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
fake-ip-filter:
- "*.lan"
- "*.local"
- "+.pool.ntp.org"
- "+.msftconnecttest.com"
- "+.msftncsi.com"
nameserver: [223.5.5.5, https://doh.pub/dns-query]DNS has to be configured alongside — TUN has taken over all traffic, so if DNS is wrong nothing resolves at all.
The underlying cause of common problems
| Symptom | Underlying cause | Fix |
|---|---|---|
| Everything dies after enabling TUN | Routes were rewritten but the core's own traffic loops back | Confirm auto-detect-interface: true; restart |
| Network does not recover after closing the app | The process was force-killed so routes were never withdrawn | Start Clash Verge again and quit properly, or reboot |
| LAN devices unreachable | No direct rule for private ranges | Add IP-CIDR,192.168.0.0/16,DIRECT,no-resolve |
| NAS or printer not found | mDNS names caught by fake-ip | Add "*.local" and "*.lan" to fake-ip-filter |
| Conflicts with the corporate VPN | Both rewrite the routing table | Turn off strict-route, use exclude-interface |
| System reports "no internet connection" | The connectivity-check name went through fake-ip | Add "+.msftconnecttest.com" to the filter |
| Large downloads stall | Oversized MTU causing fragment loss | Set mtu to 1400 |
| UDP games will not connect | The node does not support UDP, or the stack is wrong | Confirm udp: true on the node, switch the stack to gvisor |
| High CPU use | All traffic passes through a userspace stack | Switch the stack to system, or drop TUN and use the system proxy |
Verifying that TUN is really working
Look at the adapter:
# Windows
Get-NetAdapter | Where-Object {$_.InterfaceDescription -like "*wintun*"}# Linux / macOS
ip link show # or ifconfigYou should see an adapter named Mihomo or utunX.
Look at the routes:
# Windows
route print -4# Linux
ip route showYou should see two /1 routes pointing at the TUN adapter.
Check that traffic really goes through:
Open the connections page in Clash Verge and use a program that definitely ignores the system proxy — command-line curl with no environment variables set, for instance — to reach the internet. An entry appearing on the connections page means TUN is in effect.
In short
The three things TUN does:
- A virtual adapter — needs a driver and privileges, which service mode handles
- The routing table — two
/1routes take over everything, with node IPs pinned to the physical adapter - DNS hijacking — stops hard-coded resolvers from bypassing the core
When something breaks, work through those three layers: is the adapter there → are the routes right → does DNS work.
Related: DNS and fake-ip explained and split tunnelling in practice.
Related docs
How fake-ip actually works, how it differs from redir-host, the division of labour between nameserver and fallback, how to prevent DNS leaks, and why internal hostnames stop resolving.
What makes game traffic different: why UDP needs TUN, what NAT type actually means, why packet loss hurts more than latency, and a configuration checklist aimed at low latency.
What each column means and how to use it: tracking down the program eating your data, why the connection count explodes, where throughput is bottlenecked, and continuous monitoring through the API.