TUN captures traffic, but that doesn’t mean every connection goes through a proxy

Clash TUN mode creates a virtual layer-3 network interface and uses routing rules to send matching IP packets to the core. The core reads the destination address, port, and any available domain information, then applies rules to choose DIRECT, a proxy node, or another policy. This lets command-line tools, games, and some desktop apps that ignore system proxy settings use the same rule-based routing as your browser.

“All traffic” in the title refers to the scope of traffic capture, not the client’s Global mode. You can keep Rule mode enabled with TUN: LAN connections can go DIRECT, selected domains can use a proxy, and the final MATCH rule determines how everything else is handled. Route exclusions, app-level VPNs, other network namespaces, and some system traffic may remain outside TUN’s reach.

System proxy vs. TUN: what traffic each can capture

CheckSystem proxyTUN
Traffic entry pointApps connect directly to an HTTP or SOCKS proxy portSystem routes send IP packets to a virtual network interface
App supportApps must read the system setting or have a proxy configured manuallyApps generally don’t need to support proxy protocols
UDP trafficNot covered by common system HTTP proxy settingsCan be captured, but the proxy node and protocol must also support UDP
PermissionsUsually only requires changing the user’s proxy settingsRequires creating a network interface, setting routes, or using the system VPN API
DNS pathApps or the operating system may still resolve domains independentlyCan use DNS hijacking and the core’s DNS, but this needs to be verified separately

TUN is not a network speed boost. A congested node, blocked UDP, or a misfiring rule won’t be fixed by switching to a virtual interface. First confirm that the same node works through a regular proxy, then expand the capture scope. This makes it easier to distinguish node issues from local routing problems.

Before you start: check the core, permissions, and configuration source

The YAML below targets mihomo, the core used by later versions of Clash Meta, and assumes support for the listed fields. Configuration support varies across older Clash cores, mobile clients, and desktop apps. A client having “Clash” in its name doesn’t mean it supports every setting shown here.

  1. Check which core is running. Save the version string from the client’s About or Core page. If you see errors such as unknown field or unsupported stack, check which fields that version supports instead of repeatedly switching nodes.
  2. Back up your working configuration. Keep a copy of the current config and screenshots of your Rule mode, DNS, and TUN settings. To roll back, turn TUN off first, then restore the previous settings.
  3. Know where to make changes. Subscription settings may be overwritten on update. Use the client’s override, config merge, or TUN settings panel where possible. Editing a cached subscription file directly often only works until the next update.
  4. Temporarily disconnect other VPNs. Start with just one traffic capture path. If a corporate VPN, accelerator, and another TUN client all modify the default route at once, it becomes much harder to identify the cause of a problem.

For the first test, you can turn off the system proxy and leave only TUN enabled. This avoids interference from browser connections still using the old proxy port. It’s a way to verify traffic capture, not a requirement that system proxy and TUN can never run together. After testing, follow your client’s guidance on whether to enable both.

mihomo configuration: TUN, Fake-IP, and auto-route

This is a top-level snippet to merge into an existing config, not a complete subscription. Keep your existing proxies, proxy-groups, and rules. If the file already has dns or tun sections, merge the relevant settings instead of adding duplicate top-level keys. This example uses mixed-port 7890 and DNS listening on 127.0.0.1:1053; they serve different purposes.

mixed-port: 7890
mode: rule

dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  fake-ip-filter:
    - "*.lan"
    - "*.local"
  nameserver:
    - https://dns.alidns.com/dns-query
    - https://doh.pub/dns-query

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true
  dns-hijack:
    - any:53
    - tcp://any:53

What each setting does

  • stack: mixed: On mihomo versions that support it, this combines the system and userspace network stacks. If your client doesn’t support this value, use system or gvisor as recommended in its core documentation. Switching stacks isn’t a universal fix.
  • auto-route: true: Lets the core set up the routes needed to send traffic into TUN. It doesn’t replace administrator permissions or guarantee that traffic from every external VPN will be captured.
  • auto-detect-interface: true: Attempts to identify the active outbound interface so proxy traffic isn’t routed back into TUN. Check the detected interface on systems with multiple network adapters, hotspots, or corporate VPNs.
  • dns-hijack: Sends matching standard DNS requests on port 53 that enter TUN to the core’s DNS. The example covers both UDP and TCP requests on port 53.
  • enhanced-mode: fake-ip: Returns a virtual IP address and stores the domain mapping in the core. When an app connects to that address, the core can recover the domain and apply routing rules.

198.18.0.1/16 is reserved for benchmarking, not used as a real website’s public IP. Getting an address in this range is expected with Fake-IP. If your network also uses this subnet, check for an address conflict. Don’t add a virtual address as a standard public IP in a static DIRECT route.

Fake-IP filters and the limits of encrypted DNS interception

fake-ip-filter makes matching domains resolve to their real addresses, but that doesn’t automatically route their connections DIRECT. Make sure your rules handle LAN services correctly. The example’s *.local entry also doesn’t replace mDNS multicast discovery. If printer or screen-casting discovery fails, check local network permissions and the multicast path.

Browsers usually send built-in DoH over port 443, while DoT commonly uses port 853. Neither is directly captured by the port 53 hijacking shown above. For troubleshooting, temporarily turn off the browser’s Secure DNS setting and Android Private DNS. Test the system DNS path first, then decide which resolution strategy to use long term.

How to enable TUN on each platform

Windows: install the service before enabling the virtual interface

  1. Import your config, select Rule mode, and verify the node through the system proxy first.
  2. Look for a Service Mode option in the client settings. If there’s an Install Service button, follow the prompts to grant administrator permission. Clients without a service mode may need to be run as administrator.
  3. Turn on the option labeled TUN Mode or Virtual Network Interface. Menu names vary by client; the System Proxy toggle is not the same as TUN.
  4. Check the logs for messages confirming that the virtual interface was created and routes were set successfully. Then turn off the system proxy to test TUN on its own.

Run route print to inspect the routing table. Interface names and route prefixes vary by core and Windows version, so don’t expect a specific adapter name. If the logs show access denied or operation not permitted, fix the permissions or service status first rather than changing DNS addresses.

macOS: check helper services and routing permissions

Install the helper service required by your TUN-compatible client, then enable TUN. If macOS prompts you to approve a network extension or background service, verify the app name before allowing it. Not all clients use the same authorization process. After switching between Wi-Fi, Ethernet, or a hotspot, check that the correct outbound interface is still selected.

In Terminal, run netstat -rn to inspect routes and scutil --dns to check system resolvers. macOS may have several utun interfaces at once. Seeing an utun interface alone doesn’t confirm that Clash has captured traffic; check the client’s connection logs too.

Linux: distinguish the TUN device from network permissions

Check that /dev/net/tun exists. Automatic route setup typically requires network administration permissions, such as CAP_NET_ADMIN granted through a controlled service. Don’t give the entire desktop client unnecessary elevated privileges just to get it running. Containers also need explicit access to the TUN device and the required permissions; working on the host doesn’t mean it will work inside a container.

Use ip rule, ip route show table all, and resolvectl status to check policy routing, all routing tables, and DNS resolution status. The main routing table alone may not show policy routes created by the core.

Android and iOS: authorize access through the system VPN

On Android, compatible clients typically use VpnService to capture traffic. Tap Connect and approve the system VPN request. Check whether per-app proxy settings exclude the app you’re testing. Battery restrictions can interrupt the connection when the screen is locked. Always-on VPN and Block connections without VPN are additional system policies; enable them only after the basic connection is stable.

On iOS and iPadOS, choose a client that supports the relevant config format and authorize its network extension through the system VPN settings. Don’t follow desktop instructions for installing drivers or obtaining administrator privileges. Mobile clients may manage routes and DNS themselves, or ignore desktop tun fields entirely; check the client’s supported settings. A connected system VPN doesn’t guarantee that every rule in your subscription is compatible.

Verify traffic capture: check the entry point, DNS, and route

Opening a webpage only proves that one connection works. It doesn’t confirm that TUN, DNS, and routing rules are all behaving as expected. Test in the order below, changing one condition at a time. Record the app, destination domain, matched rule, and actual route.

  1. Test an app without proxy settings. Turn off the system proxy, clear terminal variables such as HTTP_PROXY, HTTPS_PROXY, and ALL_PROXY, then run the command below. The connection should appear in the client’s logs.
  2. Test the core’s DNS. Query the local port 1053 and check the result. In Fake-IP mode, ordinary domains that aren’t filtered usually resolve to an address in the 198.18 range.
  3. Test system DNS. Run a query using the system’s default resolver and check the logs to see whether it passes through the core. A successful query to port 1053 only confirms that the DNS listener works; it doesn’t prove that system requests are being hijacked.
  4. Check the routing rules. Visit destinations expected to go DIRECT and through a proxy, then check the matched rule and policy group in the connection logs. Don’t mistake traffic reaching the core for traffic using a proxy node.
# Windows PowerShell: confirm this session has no proxy environment variables
Get-ChildItem Env: | Where-Object Name -Match 'proxy'
curl.exe --noproxy "*" -I https://example.com
nslookup example.com

# macOS / Linux: curl's --noproxy bypasses explicit proxies, not TUN
curl --noproxy '*' -I https://example.com
dig @127.0.0.1 -p 1053 example.com A
nslookup example.com

If a tool isn’t installed, don’t change your system just to run these commands; use the client’s DNS lookup feature instead. To test UDP, use a node and an app scenario confirmed to support UDP. A working HTTPS webpage doesn’t prove that game traffic over UDP or QUIC works.

Troubleshooting: check permissions, routes, then DNS

SymptomCheck firstWhat to do
Network drops as soon as TUN is enabledService permissions, outbound interface, other VPNsTurn off TUN to restore the connection, then check startup logs and routing errors
IP addresses work, but domain names failDNS upstream reachability, port 53 captureTest local port 1053 and system DNS separately to find where resolution fails
Browser works, but games don’t connectUDP support, per-app exclusions, matched rulesCheck connection logs, then test whether the node supports UDP
Can’t access devices on the local networkPrivate network routes, DIRECT rules, address conflictsAdd a DIRECT rule for the actual LAN subnet first, then check whether route exclusions are also needed
Connection fails after sleep or switching networksWhether the default interface changed, background service statusReconnect TUN and check interface detection and DNS status

Don’t add strict-route blindly at the start

Some mihomo configurations support strict-route to enforce tighter routing constraints; on certain platforms, it can also affect the DNS path. It may change access to LAN devices, virtual machines, or other VPNs. Start with a minimal config, then add it only if your core’s documentation and your needs call for it. It’s not a universal setting for making proxy routing “more complete.”

Restore connectivity if the network stays offline after you quit

Turn off TUN in the client first so the core can remove its routes cleanly, then quit the client. Check whether the system proxy still points to 127.0.0.1:7890 after its listener has stopped, and check for leftover manual DNS settings. Reconnect to the network afterward; if needed, use the client’s service repair option. On corporate devices, don’t flush the entire routing table, as this could remove routes needed for work.