TUN Mode vs System Proxy: How Traffic Is Intercepted at Different Layers

Compare system proxy, which relies on apps reading proxy settings, with TUN mode, which intercepts all IP traffic through a virtual network adapter. Learn why CLI tools, games, and UDP apps behave differently and which mode fits each scenario.

The Bottom Line First

System proxy and TUN mode operate at different layers. System proxy is an application-layer convention: the OS writes the proxy address into settings, and apps have to read it and use it before traffic goes through the proxy. TUN mode is a network-layer takeover: mihomo creates a virtual network adapter, and the kernel routes matching IP packets into it. Apps don't know the proxy exists and can't bypass it.

In short: system proxy depends on app cooperation, TUN mode depends on kernel routing. That's exactly why CLI tools, games, and UDP traffic behave so differently between the two modes.

System Proxy: Only Works When Apps Read the Settings

When system proxy is enabled, Windows writes the address under Settings > Network & Internet > Proxy, and macOS writes the same info under System Settings > Network > Proxy. By default, mihomo listens on the mixed port at 127.0.0.1:7890, accepting both HTTP and SOCKS5 connections.

The key is the second step: apps must actively query the system for proxy settings and actually use that address to establish connections. This splits apps into four categories:

  • Browsers and most Electron apps use the system network API, so they read the settings and system proxy works for them.
  • Game engines often create sockets directly without checking system proxy, so they connect straight through.
  • On Windows and macOS, curl, wget, and git don't read system proxy by default; they only honor the http_proxy / https_proxy environment variables.
  • All UDP traffic: HTTP proxy only carries TCP; although SOCKS5 has the UDP ASSOCIATE extension, most apps never implement it.

So if "the proxy is on but curl in the terminal still connects directly," that's not a broken config — it's the boundary of how system proxy works. Here's the comparison:

Traffic TypeSystem ProxyTUN Mode
Browser HTTP/HTTPSInterceptedIntercepted
CLI curl / git / brewNot intercepted (needs env vars)Intercepted
Games & voice UDPNot interceptedIntercepted
QUIC / HTTP/3Not intercepted (browser falls back to TCP)Intercepted
LAN device accessUnaffectedNeeds LAN exclusions

TUN Mode: Virtual Adapter Takes Over the IP Layer

TUN is a virtual network device provided by the kernel. When TUN is enabled, mihomo creates a virtual adapter — wintun on Windows, utun on macOS, tun on Linux — then modifies the routing table so IP packets destined for non-local addresses are sent to this adapter.

The traffic path changes accordingly:

  1. The app hands data to the kernel;
  2. The kernel routes it into the virtual adapter;
  3. mihomo reads the full IP packet in user space;
  4. It extracts TCP or UDP and matches it against the rules;
  5. The traffic is forwarded out through the node.

The interception happens at the network layer (L3), not the application layer (L7). mihomo doesn't care how apps send data; it only sees IP packets. Three direct consequences: apps have no idea they're being proxied; TCP and UDP are treated equally; and no matter what language or network library a process uses, it can't escape the routing table.

The costs are just as clear: creating a virtual adapter requires admin or root privileges, and since the routing table is modified, LAN and intranet access need extra allowances.

DNS is the other half of TUN mode that's easy to overlook. The dns-hijack setting in the TUN config intercepts all queries to port 53 and resolves them locally. Combined with enhanced-mode: fake-ip, domain resolution also goes through the proxy chain, preventing DNS leaks. Here's the default Clash Verge config as an example:

tun:
  enable: true
  stack: mixed
  dns-hijack:
    - any:53

dns:
  enable: true
  enhanced-mode: fake-ip
  nameserver:
    - https://doh.pub/dns-query

Once enabled, resolving a domain that can't be reached directly returns a Fake-IP from the 198.18.0.0/16 range, while the real resolution is done by a remote DoH server — a quick visual check that TUN is actually working.

CLI, Games, and UDP: The Dividing Line Between the Two Modes

Command-Line Tools

With system proxy enabled, git clone, curl, brew, npm, and go install all connect directly. To cover them with system proxy, you need to export the environment variables manually:

export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890

Port 7890 is the mixed port shared by HTTP and SOCKS5, so the three lines above route git, curl, and npm through the same entry point. In TUN mode this step isn't needed; leftover environment variables can actually cause double proxying, so it's best to clear them.

Games and UDP

Game matchmaking, voice chat, and status sync rely heavily on UDP. System proxy doesn't carry UDP at the protocol level; even with SOCKS5 enabled, game clients won't implement UDP ASSOCIATE. That's why you get half-broken states like "can log in but can't find matches" or "voice keeps cutting out." TUN takes UDP packets into the virtual adapter as-is and forwards them by the rules, so behavior is close to a direct connection.

QUIC and HTTP/3

Chrome and Safari prefer QUIC (UDP/443) for sites that support HTTP/3. With system proxy, the browser detects that the proxy doesn't support UDP and automatically falls back to TCP; with TUN, QUIC traffic is intercepted directly and never downgraded.

Scenario Guide: Which Mode to Use When

ScenarioRecommended ModeReason
Everyday web browsingSystem ProxyNo admin rights needed, low resource usage
Development and CLI workTUN ModeCovers git / npm / curl in one shot
Games, voice, and video callsTUN ModeUDP must be handled at the network layer
Corporate intranet alongside proxySystem proxy + rulesLAN segments aren't intercepted, more controllable policies
Apps can't request admin privilegesSystem ProxyTUN requires elevated privileges to create the adapter
Global packet capture and full testingTUN ModeOne uniform path for all processes

Checklist Before Switching

  • Connectivity: verify with curl -I https://www.gstatic.com/generate_204 — don't use ping, because whether ICMP is intercepted depends on the node and stack and can't prove the proxy is working.
  • DNS: resolve a domain that can't be reached directly. A 198.18.x.x response means Fake-IP is active; a real IP means checking dns-hijack and enhanced-mode.
  • LAN: printers, NAS devices, and router admin pages may be captured by TUN. Add route-exclude-address: 192.168.0.0/16 under the tun section, or use rules to force direct connections.
  • Windows compatibility: if games or P2P can't connect, cycle through stack: systemgvisormixed and test again.
  • Leftover env vars: in system proxy mode, run env | grep -i proxy in the terminal; if anything remains, unset it, otherwise CLI tools will keep using the old proxy.

A common mistake: enabling TUN and then also turning on system proxy. They don't stack — browser traffic just takes an extra detour into port 7890 and back out. In TUN mode, turn off the system proxy switch for the shortest path and cleaner troubleshooting.

Download Clash Verge