Git push works, but npm install times out; pip appears to ignore the proxy, while a browser on the same computer loads normally. These differences often come from how each program handles proxy settings. A browser may follow the operating system’s system proxy, while a command-line tool may require its own proxy variables or configuration. Clash TUN mode offers another approach: it creates a virtual network interface and routes eligible system traffic through the Clash or mihomo core, so many terminal tools can connect without per-tool proxy settings.

TUN is not a universal fix, and it does not guarantee that every process—including Docker’s virtualized workloads—will follow the same route. The result depends on the client, core, operating system, routing rules, DNS settings, and where the application actually runs. The steps below focus on verifying each layer rather than assuming that a connected status means every command is proxied.

What TUN changes for terminal tools

With a system proxy enabled, the operating system advertises a proxy endpoint—often an HTTP or SOCKS port such as 7890 or 7891—to applications that know how to use it. A terminal program may not consult that setting. It might instead require HTTP_PROXY, HTTPS_PROXY, or tool-specific settings, and some programs do not support proxying every protocol they use.

TUN takes a different path. The client asks the operating system to send selected network traffic to a virtual interface. The core then processes that traffic using its DNS handling, routing rules, and proxy groups. A command such as git fetch can therefore be routed even if Git has no proxy entry, provided the traffic reaches the tunnel and the matched rule selects a working proxy.

  • Git: HTTPS and SSH remotes use different protocols and ports. A rule that works for an HTTPS repository does not prove that an SSH connection to port 22 is routed or permitted.
  • npm and pip: Package managers may contact registries, mirrors, authentication services, and redirected download hosts. A rule for just one registry hostname may not cover the complete download.
  • DNS: TUN can route application traffic, but name resolution still depends on the core’s DNS configuration and the client’s handling of DNS requests. A command resolving the wrong address is not necessarily a proxy-node failure.
  • Docker: The Docker daemon and containers may run in a separate VM or network namespace. Host TUN mode does not automatically mean that every daemon, build step, and container connection uses the host’s Clash route.

TUN also does not convert every connection into HTTP. It captures network traffic at the operating-system level; the core still needs a usable route and a compatible outbound. System proxy and TUN are separate controls, so a terminal can bypass the system proxy while still being handled by TUN—or be excluded from TUN by a route or application-specific setting.

Enable TUN on your desktop platform

Before changing settings, record the client and core versions, active profile, current proxy mode, and local proxy ports. Back up local overrides. Quit other VPN or proxy clients during the first test: multiple virtual adapters, route managers, and DNS handlers can make a failure difficult to diagnose.

PlatformTypical setupWhat to verify
WindowsIn Clash Verge Rev, open Settings, enable the TUN option, and approve any service or administrator prompt. Menu labels differ between releases.The service is running, the virtual adapter appears, and no other VPN is controlling the routes.
macOSEnable TUN in the client and approve the requested network extension or system permission in macOS if prompted.The extension is allowed in Privacy & Security, and the client reports that the tunnel is active.
LinuxUse a client/core with TUN support and grant the required permission to access /dev/net/tun and configure routes.The TUN device exists, the service has the necessary privileges, and firewall or network-manager rules do not undo the route.

On Windows, a client may install a background service so the core can create an adapter and update routes. Approve only the service associated with the client you intentionally installed. If the toggle immediately turns off, inspect the client log and service status rather than repeatedly clicking it. Also check Windows Defender Firewall and any corporate endpoint security software, which may block a new adapter or route change.

On macOS, system-extension approval and administrator authentication can be required. After granting permission, fully quit and reopen the client if it does not recognize the extension. A client update or macOS update may require renewed approval. On Linux, running a whole desktop client permanently as root is not a good default. Prefer the permission or service setup documented by that client, and verify access to /dev/net/tun and route-management permissions.

If you use a mihomo configuration directly, a minimal TUN section may resemble the following, but it is not a complete configuration and should only be used with a core that supports these fields:

tun:
  enable: true
  stack: mixed
  auto-route: true
  auto-detect-interface: true

Client-managed configurations may generate or override this section. Avoid editing a generated runtime file if the client will replace it on the next reload. Start with the client’s own TUN switch, then inspect the effective configuration or startup log to confirm the core accepted the settings. An unsupported field or a YAML indentation error can prevent the tunnel from starting.

Choose routing rules for development traffic

Use the least complicated routing policy that matches your goal. In Rule mode, a domain rule can route known package registries or code-hosting services through a proxy group. A final rule such as MATCH,DIRECT sends anything not matched earlier directly; MATCH,Proxy sends all remaining traffic to the selected proxy group. Neither choice is automatically best for every workstation.

For a development machine, a practical starting point is to keep private and local destinations direct, route the services you need through a proxy group, and review the final rule. Preserve access to your company network, local package mirrors, and development servers. If you select Global mode for a short diagnostic, remember that it can send internal hostnames and private services through the proxy too.

  • Use observable domains: Check the client’s Connections or Logs view while running a single command. Record the destination hostname, matched rule, policy group, and selected node. Add or adjust a rule only after confirming which hostname actually failed.
  • Do not assume one registry hostname is enough: npm packages can reference tarball hosts, and pip indexes can redirect files to a separate storage domain. If metadata loads but a package download stalls, inspect the failing connection and route that destination as well.
  • Keep local networks reachable: LAN devices, loopback services, private Git servers, and internal DNS may need a direct route. Test those destinations after enabling TUN instead of assuming that a broad proxy rule will preserve them.
  • Be cautious with process rules: Process-name matching depends on core support, operating-system permissions, and the client’s implementation. It can behave differently on Windows, macOS, and Linux, and it may not identify traffic inside a VM or container. Domain and destination rules are generally easier to verify.

Use the client’s connection log to distinguish a rule problem from an outbound problem. If a request is logged with DIRECT, the TUN may be working while the selected rule sends that destination direct. If it is assigned to a proxy group but fails to connect, test another node and check the core’s error message. A successful browser connection alone does not establish that the terminal request used the same rule or even the same hostname.

Test Git, npm, pip, and Docker methodically

First confirm that the tunnel is active and that a simple terminal request is visible in the client. Use the actual service hostname you need, not just a generic connectivity test. For example, run curl -I https://registry.npmjs.org/ or request the hostname of your package index. A response such as 200, 301, or 404 still proves that an HTTP server answered; a name-resolution error or connection timeout points to a different layer.

  1. Test DNS separately: Use nslookup registry.npmjs.org or your platform’s equivalent, then compare with the connection log. A resolved address does not prove that the subsequent connection follows the intended route.
  2. Test the application’s real protocol: For Git, run git ls-remote https://host/owner/repository.git for an HTTPS remote. If your remote uses SSH, test that exact remote separately; SSH may need an explicit supported route or a different transport.
  3. Inspect the failed destination: Start one install or fetch, then check every related hostname in Connections. A registry page can respond while a redirected tarball host is blocked or sent direct.
  4. Change one thing at a time: Keep the node, mode, and command the same while testing a rule or DNS change. Record the time and error message so you can match it to the core log.
  5. Remove stale per-tool settings only after comparison: Old HTTP_PROXY variables or Git proxy entries can send requests to a stopped local port. Check them with env | grep -i proxy on Unix-like shells or Get-ChildItem Env:*proxy* in PowerShell.

npm and pip can retain their own proxy configuration even when TUN is enabled. Inspect npm config get proxy, npm config get https-proxy, and pip config debug if the command still fails. Do not paste configuration output into public reports without checking it for credentials or private registry URLs. If an obsolete proxy points to 127.0.0.1:7890, either restore the intended local listener or remove that tool-specific setting; do not change it blindly if your organization requires it.

Docker needs a separate check. Determine whether the failing connection comes from the host-side Docker CLI, the Docker daemon, an image build, or a running container. Docker Desktop commonly uses a VM for containers, so the container’s DNS and outbound route may differ from the host’s. If an image build cannot reach a registry, configure the supported proxy settings for the daemon or build environment; if only a process inside the container fails, inspect that container’s DNS, routes, and environment. Test the host and container independently before changing Clash rules.

Common terminal TUN failures and fixes

SymptomLikely layerNext check
Browser works, terminal times outRule match, tool proxy setting, or different destinationRun the exact command and inspect all logged hostnames and matched rules.
Hostname lookup fails before connectingDNS configuration, system resolver, or tunnel DNS handlingCompare a DNS query with the core log and check the effective DNS settings.
Connection is logged as DIRECTRule order or final ruleCheck the matching rule and policy group; do not assume TUN is off.
TUN will not start or drops immediatelyPermission, service, extension, adapter, or unsupported core optionReview startup logs, system permission prompts, and the core version.
Host works but Docker does notVM, daemon, container DNS, or build proxy configurationTest host, daemon, build, and container traffic as separate paths.
Internal services become unreachablePrivate-network route or overly broad proxy ruleRestore local routes and add only the necessary direct exceptions.

When a failure begins immediately after enabling TUN, compare the system’s route and DNS behavior before and after the change. On Windows, inspect the active network adapters and routes with Get-NetRoute; on macOS, netstat -rn can help show route changes; on Linux, use ip route and check the TUN device. These commands are diagnostic snapshots, not instructions to delete routes manually. Let the client remove routes when disabling the tunnel, then restart the client if the operating system retains a stale adapter or route.

Finally, separate connectivity from speed. A successful request to a registry does not guarantee that a large package download will be fast. Check the selected node, the matched policy, repeated retries, and the destination hosting the actual file. Keep one test command and one node fixed while comparing results; otherwise, a route change and a node change can obscure the cause.

FAQ

Do I still need HTTP_PROXY or HTTPS_PROXY?

Not necessarily for traffic that the operating system routes into an active TUN and that the core can process. You may still need proxy variables for a shell environment outside the tunnel, a remote build system, or a tool that runs inside a container or VM with a separate network path. Avoid leaving stale variables that point to a local port that is no longer listening.

Should I enable both System Proxy and TUN?

They serve different purposes, but enabling both can make diagnosis less clear. System Proxy is useful for applications that honor the operating-system proxy setting; TUN handles eligible network traffic at the routing layer. Start with the method you need, verify the terminal connection, and add the other only if a specific application requires it. Watch for applications that may be proxied twice or use their own proxy configuration.

Why does Docker ignore the host’s TUN rules?

Docker Desktop can place the daemon and containers behind a virtual machine or separate network namespace. Their DNS requests and outbound connections may not appear as ordinary host processes. Configure and test the daemon, build, or container proxy path appropriate to the failing operation, and verify it from inside the affected environment.

Can TUN make terminal downloads slower?

It can add processing and routing overhead, but slow downloads may also result from the selected node, a blocked redirect host, DNS delays, or a package mirror’s own limits. Compare the same command, destination, node, and network with one routing change at a time. Use sustained transfer results rather than a single latency check.