Start by identifying how a developer tool reaches Clash

A terminal command can fail even while a browser works through Clash. The browser may follow the operating system’s system-proxy setting, while Git, npm, pip, a shell script, or a container uses its own networking stack. Before changing proxy variables or editing rules, identify which path the failing request takes.

TUN and an application proxy are different ways to route traffic. TUN creates a virtual network interface and asks the operating system to route selected IP traffic through the Clash-compatible core. An application proxy instead tells a particular program to send HTTP or SOCKS requests to a local listening port, often 127.0.0.1:7890. TUN can cover applications that do not understand proxy variables, but it depends on route installation, DNS handling, permissions, and the client’s active configuration.

  • The browser works, but a terminal command does not: Check whether the command-line program honors system proxy settings. It may need explicit environment variables, its own proxy setting, or TUN routing.
  • Git works, but a Docker build does not: The build may run inside a container or an isolated network namespace. Host TUN routing and container DNS are related but are not the same configuration.
  • Names fail to resolve, but IP connections work: Check which DNS resolver the process uses and whether DNS queries are reaching mihomo’s DNS module.
  • The request appears in Clash but times out: The application reached the core. Check the matched rule, selected proxy group, node connectivity, and destination restrictions.

Clash is commonly used as the name for a group of clients and compatible cores. This guide uses mihomo for core-specific configuration examples. Menu names vary between Clash Verge, Clash Verge Rev, and other clients, and some clients generate or override fields from their UI. Check the configuration actually loaded by the running core rather than assuming the original subscription file is unchanged.

Enable TUN in the client and verify the route

First confirm that the client is running a core with TUN support. In the client’s settings, look for a TUN, VPN, or virtual-interface option. On Windows, the client may need administrator permission to create an interface or change routes. On macOS, approve the requested network extension or VPN permission in system settings. On Linux, TUN device access and route-management permissions must be available to the process.

  1. Save a copy of the current profile or export the active configuration so that you can restore it.
  2. Stop other proxy clients and VPNs temporarily. Multiple applications can compete to install routes, DNS settings, or network extensions.
  3. Enable TUN from the client’s UI if the client provides a supported control for it. Accept the operating-system permission prompt only for the client you intend to use.
  4. Wait for the client to report that TUN is running. Check its logs for permission errors, failed interface creation, or route conflicts before testing developer tools.
  5. Test one ordinary destination, then one destination that should use a proxy. Confirm that requests appear in the client’s Connections page and that the expected rule and proxy group are selected.

If you manage mihomo YAML directly, these fields are a starting point for a TUN section, not a complete configuration. Merge them into the existing top-level configuration; do not create a second tun: key if one already exists.

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

auto-route asks the core to install routes for TUN traffic, while auto-detect-interface helps it select the outbound interface and avoid routing its own proxy connection back into the tunnel. strict-route changes how routes are applied and can affect local network access or applications that rely on unusual routing. dns-hijack handles matching DNS traffic; it does not make every application use the same resolver in every operating system.

Field support and defaults depend on the mihomo version and client integration. If the client has its own TUN controls, use those first and inspect the generated configuration or logs before adding YAML overrides. Do not copy a complete TUN snippet from an unrelated profile and replace the rest of your configuration: proxy groups, DNS settings, rules, and listeners may be lost.

CheckWhat to verifyWhy it matters
Core and permissionThe active core supports TUN and the operating system granted the required permissionA UI toggle alone does not prove the virtual interface was created
Route installationThe client reports routes are active; no second VPN is replacing themWithout the expected route, traffic may bypass TUN or use another tunnel
DNS pathThe client logs show DNS requests, and the configured resolver can resolve the test domainSuccessful IP routing cannot fix a hostname lookup that never reaches a working resolver
Rules and groupsThe connection matches the intended rule and a usable proxy group or nodeTUN transports traffic into the core; rules still decide whether it is proxied or direct

Test Git, npm, pip, and shell commands

Use a small, repeatable test before changing several developer tools at once. In the client’s Connections view, keep it open while running a command that makes a request. A visible connection confirms that the request entered Clash, but you should also check its destination, rule, and outbound. If no connection appears, investigate the application’s proxy settings, operating-system route, or container boundary before changing proxy rules.

With TUN enabled and working, many ordinary TCP connections can be routed without setting a proxy variable for each tool. Still, explicit proxy settings can be useful when TUN is unavailable, when testing the local proxy independently, or when a particular application bypasses the operating-system route. Use the actual listener address and port displayed by your client; 7890 is only a common example, not a guaranteed value.

For a temporary shell test with an HTTP or mixed listener, set variables only in the current terminal session. On macOS or Linux:

export HTTP_PROXY="http://127.0.0.1:7890"
export HTTPS_PROXY="http://127.0.0.1:7890"
export ALL_PROXY="socks5h://127.0.0.1:7891"
export NO_PROXY="localhost,127.0.0.1,::1"

git ls-remote https://example.com/owner/project.git
npm view lodash version
python -m pip index versions requests

Here, 7890 represents an HTTP-capable listener and 7891 represents a SOCKS listener, if your client exposes one. The socks5h scheme asks the proxy to resolve the destination hostname; support varies by tool. If your client exposes only an HTTP or mixed port, use that supported listener instead of assuming a SOCKS port exists. NO_PROXY keeps local addresses out of the proxy, but add internal domains only when you deliberately want them to connect directly.

In Windows PowerShell, the equivalent session-only environment variables are:

$env:HTTP_PROXY = "http://127.0.0.1:7890"
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
$env:ALL_PROXY = "socks5h://127.0.0.1:7891"
$env:NO_PROXY = "localhost,127.0.0.1,::1"

git ls-remote https://example.com/owner/project.git
npm view lodash version
py -m pip index versions requests

These variables are inherited by programs launched from that shell, but they do not necessarily affect applications already running or services started by another process. To remove them from the current PowerShell session, run Remove-Item Env:HTTP_PROXY, Env:HTTPS_PROXY, Env:ALL_PROXY, Env:NO_PROXY. In a POSIX shell, run unset HTTP_PROXY HTTPS_PROXY ALL_PROXY NO_PROXY.

Use tool-specific settings only when needed

Git can store a proxy setting for a particular URL or globally. For a reversible test, prefer a command-scoped setting rather than changing every repository:

git -c http.proxy=http://127.0.0.1:7890 ls-remote https://example.com/owner/project.git

If this works but the normal command fails, compare Git’s configuration sources with git config --show-origin --get-regexp 'http\..*proxy|http.proxy'. A stale proxy entry can conflict with TUN or with the current listener. Remove only the incorrect entry at the scope where it was set; do not paste credentials into a global setting or a shared repository configuration.

npm accepts proxy configuration through environment variables and npm configuration. Check the current values with npm config get proxy and npm config get https-proxy. If a previous setup left an unwanted value, remove that setting with npm config delete proxy or npm config delete https-proxy at the relevant scope. Avoid disabling TLS verification to “fix” a proxy error: it weakens certificate checks and hides the cause.

pip can use proxy-related environment variables or a --proxy option. For a one-off diagnostic, use the proxy URL supported by your local listener and then compare with a TUN-only request. Don’t place a proxy password in shell history or a checked-in pip.conf. If a package index is configured through a work or school network, preserve its approved index URL and authentication method.

A shell script may launch a child process with a different environment, clear proxy variables, or call a tool that ignores them. Check the environment within the same shell that runs the failing command. If a tool has no proxy support, TUN may provide the route, but DNS, firewall policy, and the application’s own network stack still matter.

Handle Docker, registries, and local development traffic

Docker introduces an important boundary: a command on the host, a Docker daemon, a build container, and a running container are separate processes with potentially different proxy settings and DNS paths. A host terminal command succeeding through TUN does not prove that docker pull, a build step, or a process inside a container uses the same route.

  • Image pull fails: The Docker daemon performs the registry connection. Check the daemon’s proxy configuration and logs, then restart the daemon if its configuration was changed. A shell variable set in one terminal may not reach a system service.
  • Build step fails: Build-time network access may need proxy build arguments or builder-specific configuration. Pass only the settings required for that build, and avoid baking credentials into image layers or build history.
  • Container cannot resolve names: Inspect the container’s DNS configuration and test whether the host can resolve the same name. Docker may use an embedded resolver or its own network configuration rather than the host’s ordinary resolver path.
  • Container can reach public sites but not the host: Check the intended host address and container network mode. 127.0.0.1 inside a container refers to that container, not automatically to the host’s Clash listener.
  • Local services stop working: Review TUN route and DNS behavior for private subnets, local domains, and development endpoints. Add narrow direct rules only when you know which destinations should bypass the proxy.

For an HTTP proxy available on the host, a container usually needs a host-reachable address, not the container’s own loopback address. The correct address differs by Docker Desktop, native Linux Docker, network mode, and host firewall. Do not assume that a hostname such as host.docker.internal is available in every environment. Confirm that the host listener is reachable from the container without exposing it to an untrusted network.

For private package registries, code hosting, and internal APIs, decide explicitly whether each destination should be proxied or direct. A broad rule change can send internal traffic to an external node or make local services unreachable. Check the matched rule in Clash for the exact hostname or IP, and use narrow domain or CIDR exceptions only where appropriate. Keep local loopback and LAN access functional, especially when development tools communicate with local databases, emulators, or callback servers.

Troubleshoot failures without weakening security

When a request fails, capture its exact error and compare the same command with TUN off and on, changing only that one condition. Do not simultaneously switch nodes, change DNS, add global mode, and modify tool settings. A controlled comparison makes it possible to identify whether the failure is at the application, route, DNS, rule, or proxy-node layer.

SymptomLikely areaFirst diagnostic step
Could not resolve host or name lookup timeoutDNS configuration, DNS interception, or resolver reachabilityCompare lookup results with TUN on and off; inspect DNS logs and the active resolver settings
Connection refused at 127.0.0.1:7890Wrong local port, listener disabled, or incorrect proxy typeCheck the client’s listener settings and use its actual HTTP, mixed, or SOCKS port
TCP timeout with a connection shown in ClashRule, proxy group, node, or destination availabilityInspect the matched rule and outbound, then test a different known-working node
Certificate verification failureSystem clock, TLS inspection, CA trust, or wrong endpointVerify the system time and certificate details; do not disable certificate verification
Works on host, fails in DockerDaemon proxy, build environment, container DNS, or host addressingIdentify which Docker process made the request and test from that same environment
Local development host becomes unreachableRoute conflict, DNS rule, or proxy bypass listCheck whether the target is loopback, LAN, or a private domain and inspect the matched rule

For a basic route check, compare a request to a known public HTTPS endpoint with a request to the destination that fails. Use a short timeout so a stuck command does not look like progress. For example, curl -I --max-time 15 https://example.com/ tests a simple HTTPS request, but its result alone does not prove that Git, npm, or Docker uses the same network path. Run the actual failing tool as well and watch the Clash connection log.

If the client shows no connection, first verify TUN status, operating-system permission, and route conflicts. If a connection appears but uses the wrong policy, inspect the rule order and the selected group. If it uses the intended proxy and still fails, test the node and destination separately. If only DNS fails, investigate the DNS path instead of repeatedly changing the proxy port.

FAQ: developer tools and Clash TUN

If TUN is enabled, do I still need proxy environment variables?

Usually not for ordinary traffic that the operating system routes through TUN, but tool behavior varies and explicit proxy settings can take precedence or create a conflicting path. Test with variables unset first. Add them only if the application needs an explicit proxy or you are deliberately testing the local listener.

Why does Git fail while the browser works?

The browser may use the system proxy while Git uses its own configuration, environment variables, or direct connections. Check Git’s effective proxy settings and watch the Clash Connections page while running the failing Git command. Remove stale proxy configuration only after identifying where it was set.

Does host TUN automatically proxy every Docker request?

No. The Docker daemon, build environment, and containers may have distinct networking and DNS behavior. Check the specific process that makes the request, configure its proxy if needed, and verify that it can reach the host listener or intended route.

Why does a container’s 127.0.0.1 not reach Clash on the host?

Inside a container, loopback points to the container itself. Use an address that is reachable from that container and allowed by the host’s listener and firewall configuration. The correct host address depends on the Docker platform and network mode.