Why Developer Traffic Needs Clash TUN Mode
When a browser opens a repository page but git clone fails, the problem is usually not the repository itself. Developers use several network stacks during one task: a browser may follow the operating system proxy, Git may use its own HTTP settings, a package manager may read environment variables, and Docker may contact a daemon running in a separate process. Enabling a system proxy can therefore make documentation load while leaving Git, npm, pnpm, pip, Maven, Go modules, and container image pulls on a direct route.
Clash TUN mode addresses that gap by creating a virtual network interface and capturing IP traffic before individual applications decide whether to honor an HTTP or SOCKS proxy. The Clash or Mihomo core then applies your profile rules to those connections. From a developer’s perspective, this is important because a command-line tool does not need native Clash support to benefit from routing. A terminal process that opens a normal TCP or UDP socket can still be classified by the same policy used for other system traffic.
This does not mean TUN mode is a universal “make everything work” switch. It changes the routing boundary, so DNS behaviour, local network access, container networking, VPN conflicts, and administrator permissions all matter. A reliable developer proxy setup should make the capture path understandable: identify which process is failing, confirm which hostname it contacts, inspect the matched Clash rule, and only then adjust the profile. That approach is safer than adding a long list of guessed domains or forcing every connection through one unstable proxy group.
Scope note: TUN mode routes traffic through your Clash rules; it does not provide a subscription, bypass access controls, or guarantee that every registry and container mirror is reachable. Use a legitimate provider and keep credentials, tokens, and private repositories protected.
What TUN Captures—and What It Does Not
A standard mixed port normally exposes HTTP and SOCKS listeners on a local address such as 127.0.0.1:7890. Applications must be configured to use that listener. Git can be configured with git config, curl can receive proxy environment variables, and many package managers can use their own proxy options. This method is precise and easy to disable, but it depends on every tool being configured correctly. It also becomes awkward when a build invokes a nested tool, a language runtime launches a helper process, or a graphical IDE uses a background service with different settings.
TUN mode works at a lower level. Mihomo presents a virtual interface, receives packets from the operating system, resolves or observes destinations according to its DNS mode, and forwards eligible traffic through the rule engine. The connection list can then show useful evidence: the process or destination, the selected rule, the proxy group, and whether the connection was sent through DIRECT or a remote node. This is why TUN is often the practical answer for CLI networking with Clash: the application does not have to know that a proxy exists.
There are still important boundaries. A Docker container may use a separate network namespace, while Docker Desktop may place its daemon inside a lightweight virtual machine. A corporate VPN can install its own routes with a higher priority than the TUN interface. Local services such as a database at 127.0.0.1, a development server on localhost, or a private subnet such as 192.168.1.0/24 should normally remain direct. If you proxy those destinations accidentally, a local application can become slow or unreachable even though public websites work.
DNS deserves special attention. A hostname can resolve to an address before Clash sees the request, or the client can send DNS queries through the TUN stack and apply fake-IP or redirection logic. If your rules depend on domain names but the operating system resolves everything first, the rule view may show an IP-based decision instead of the hostname you expected. Conversely, fake-IP handling can make a local hostname appear unfamiliar. Do not change several DNS options at once. Record the current mode, test one command, inspect the connection log, and make one controlled adjustment.
Prepare a Profile for Repositories and Dependencies
Before enabling TUN, check that the active profile contains usable proxy groups and that the selected group is not empty. A profile can be syntactically valid yet unusable when all nodes have expired, the provider has changed a transport field, or the group references a proxy name that no longer exists. In the client’s profile or configuration view, verify the active core, the current subscription timestamp, and the group selected for developer traffic.
Start with a small rule set rather than rewriting the entire provider configuration. Development traffic commonly includes source control hosts, package registries, release storage, language module services, and image registries. The exact hostnames depend on your stack, but typical examples include:
- Git hosting:
github.com,api.github.com,raw.githubusercontent.com, release asset domains, and the host used by your organization’s Git service. - JavaScript packages:
registry.npmjs.org, the configured pnpm or npm registry, and the CDN hostname returned for package tarballs. - Python packages:
pypi.org,files.pythonhosted.org, and any private index configured inpip.confor environment variables. - Container images:
registry-1.docker.io,auth.docker.io, vendor registries, and the storage host that serves image layers. - Language modules: Go proxy endpoints, Rust crate registries, Maven repositories, Gradle distribution hosts, or internal artifact servers.
Do not assume that one visible website represents the whole transaction. A package manager may first contact a metadata registry, then follow a redirect to a CDN. Docker authentication can use one hostname while image manifests and layers arrive from another. Git over HTTPS may contact the repository host, while SSH uses a different address and port. Use the connection log during a real command to discover the destinations that your rule list actually needs.
A practical profile separates developer traffic into a named group such as DEV-PROXY or Developer. That group can point to a stable node selection instead of the same general-purpose group used for video or browsing. Keep private company domains and local services in a direct or corporate-VPN group when required. For example, a conceptual rule order might look like this:
rules:
- DOMAIN-SUFFIX,github.com,Developer
- DOMAIN-SUFFIX,githubusercontent.com,Developer
- DOMAIN,registry.npmjs.org,Developer
- DOMAIN-SUFFIX,pythonhosted.org,Developer
- DOMAIN,registry-1.docker.io,Developer
- DOMAIN-SUFFIX,company.internal,DIRECT
- GEOIP,LAN,DIRECT
- MATCH,Default
The syntax and group names must match your actual Mihomo profile. Put specific domain rules before broad geographic or final match rules. A rule placed after MATCH, or after a broad GEOIP decision that already wins, will never be reached. Treat the sample as a planning model, not a list to paste blindly.
Enable TUN Mode and Test a Real Workflow
Use the following sequence on Clash Verge Rev, Mihomo Party, or another Mihomo-based client. Labels differ slightly between applications, but the required ideas are the same: activate the profile, grant elevated permission, enable the TUN stack, preserve local routes, and test with observable commands.
- Activate and validate the profile: Select the intended subscription, confirm that the Mihomo core is running, and choose a working proxy group for developer traffic. If the client provides a configuration validation action, run it before changing the network mode.
- Open the TUN settings: Find Settings, General, or Network, then locate the TUN section. Enable the virtual interface and accept the administrator or system-extension prompt required by your operating system.
- Preserve local connectivity: Turn on options such as auto route and strict route only when they match your platform and client documentation. Keep bypasses for loopback, private LAN ranges, your local gateway, and any corporate VPN networks that must remain reachable.
- Choose DNS behaviour deliberately: Use the client’s recommended DNS mode first. If domain rules do not match as expected, inspect the DNS and fake-IP settings instead of adding random IP rules. Exclude internal DNS suffixes when your workplace requires a private resolver.
- Run a low-risk connectivity check: Test a public endpoint with
curl -I https://github.comor another non-sensitive request. Then rungit ls-remoteagainst a repository you are allowed to access. Watch the Clash connection panel while each command is running. - Test the package and container lanes separately: Use a harmless metadata command such as
npm view,python -m pip index versionswhere supported, ordocker manifest inspect. Do not begin with a large image pull or a production deployment; first confirm which domains appear and which rules win. - Record the result before tuning: Note the operating system, client, core version, TUN status, DNS mode, destination hostname, matched rule, and selected group. This short record makes later troubleshooting much faster than relying on memory.
Use a clean comparison: Run one command with TUN disabled, one with TUN enabled, and one with explicit HTTPS_PROXY variables if appropriate. Comparing these paths tells you whether the failure is caused by application configuration, Clash capture, DNS classification, or the upstream node.
Configure Git, Package Managers, and Docker Without Creating Conflicts
Even when TUN mode is enabled, explicit application proxy settings can be useful for debugging. They can also create loops or double-proxy behaviour if configured carelessly. Pick one primary path for normal operation: either let TUN capture the socket, or configure the application to use the local mixed port. Avoid pointing an application at a remote proxy address while TUN is also rewriting the same connection unless you understand the resulting route.
Git over HTTPS and SSH
For HTTPS repositories, Git can use its own proxy setting. Check the current values with git config --global --get-regexp 'http.*proxy'. If you want TUN to handle Git, remove stale proxy entries and let the socket be captured. If you need a controlled comparison, configure the local Clash mixed port temporarily, then remove it after testing. A common mistake is leaving an old proxy URL from a previous client, causing Git to connect to a closed port while the new TUN interface is healthy.
SSH is different. A Git remote such as [email protected]:team/project.git normally opens TCP port 22, while many networks block or interfere with that port. TUN can capture the connection, but the route still depends on your rule set and the node’s ability to carry it. Some developers use an HTTPS remote for simpler proxy behaviour; others configure an SSH host alias that uses an alternate supported endpoint. Do not expose private keys or paste authentication output into public logs while testing.
npm, pnpm, pip, Go, and Maven
Package managers often perform multiple requests per command. For npm or pnpm, inspect the configured registry with npm config get registry and check whether shell variables such as HTTP_PROXY, HTTPS_PROXY, or NO_PROXY are set. Metadata may work while the package tarball fails, which usually means the redirect or CDN hostname is missing from the effective route. A successful browser visit to the registry homepage does not validate the complete install path.
Python’s pip may use an index URL, a trusted-host exception, a corporate certificate bundle, or a proxy value inside configuration files. Go can use GOPROXY and GONOSUMDB, while Maven and Gradle may read proxy settings from separate XML or properties files. TUN mode reduces the number of per-tool settings, but it does not override application-level TLS verification or authentication. If a command reports a certificate error, first distinguish a routing timeout from a trust-store problem.
Docker Desktop and Container Registries
Docker is one of the most confusing developer cases because the CLI and daemon are not always in the same network environment. With Docker Desktop, the engine may run inside a managed VM; changing the host shell’s proxy variables may affect the CLI but not the daemon’s image download path. Configure Docker’s documented proxy settings when required, then verify with a small public image or a manifest request. For a self-hosted Linux daemon, inspect the service environment and restart policy rather than assuming the interactive shell controls it.
When an image pull fails, read the exact hostname in the error. Authentication, manifest lookup, and blob downloads may use different endpoints. A rule for only docker.io may not cover the token service or content delivery host. Add narrow rules based on observed traffic, keep internal registries on the route they require, and avoid sending confidential image names through an unapproved external node.
Diagnose “Connected but Still Failing” Problems
The most useful first question is whether the process reached Clash. If the connection panel remains empty while a command is clearly attempting a network request, the traffic may be bypassing TUN, using a separate VM, or failing before DNS and socket creation. Check that the virtual interface is present, the client has permission to manage routes, and no second VPN or proxy client has replaced the default route. Restarting the client can help after a permission change, but repeated restarts should not replace diagnosis.
If the connection appears with DIRECT, inspect rule order and the destination type. A broad final rule, an unexpected IP address, or a DNS mode that hides the original hostname can explain the result. If the connection uses the intended group but times out, compare another node in the same group and check whether the failure affects only long downloads. Package tarballs and Docker layers can expose bandwidth, MTU, or connection-reset issues that a quick homepage request never reveals.
For slow commands, separate latency from throughput. Git metadata may be quick while a large repository stalls because one node handles many parallel object requests poorly. npm may resolve dependencies quickly but download several large archives through a congested CDN route. Docker may authenticate immediately and then fail on a layer transfer. Use a small reproducible request, avoid changing the selected group during an active transfer, and record timestamps. Switching nodes repeatedly can destroy the evidence because each new connection may match a different route.
Common causes include a stale explicit proxy variable, a wrong NO_PROXY entry, an unavailable local DNS server, a corporate certificate inspection layer, a full disk that looks like a network failure, and a provider rule set that sends engineering domains to DIRECT. On Windows, security software may block the virtual adapter or helper service. On macOS, a system extension or network permission may need approval. On Linux, firewall rules, NetworkManager, and policy routing can interact with the TUN interface. Always test local services after enabling TUN; a working public request is not enough if your development database or Kubernetes API has become unreachable.
Do not disable security controls blindly. If antivirus, Gatekeeper, SmartScreen, or a corporate endpoint policy blocks a helper component, verify the client source, inspect the reported file, and follow the approved exception process. A proxy client with system-level routing privileges deserves the same caution as any other privileged network software.
Build a Repeatable Daily Workflow
Once the initial test succeeds, keep the setup boring. Use one primary Clash client and one active TUN implementation. Keep the profile updated, but review changes to developer rules rather than accepting every remote override without inspection. Name the developer proxy group clearly, select a stable route for long downloads, and leave streaming or gaming groups separate so an unrelated activity does not change the path of a package install.
Maintain a small diagnostic checklist in your project notes: the active client and core, TUN status, DNS mode, mixed port, proxy group, NO_PROXY values, Git transport, package registry, and Docker engine location. When a build fails, capture the command’s hostname and the corresponding Clash rule before editing configuration. This makes support conversations more precise and helps you decide whether the issue belongs to the application, local network, provider, or remote service.
Use exclusions intentionally. Localhost, private development domains, service discovery names, Kubernetes cluster addresses, and internal Git servers may need direct or VPN routing. Conversely, a broad exclusion such as *.local can accidentally match a public development domain, while an overly broad private-range rule can bypass a required corporate gateway. Review NO_PROXY alongside Clash bypass rules because the application may skip the TUN path before the core has any chance to classify it.
Finally, treat credentials as part of network hygiene. Subscription URLs, registry tokens, Git credentials, Docker login files, and private package indexes should never be included in screenshots or shell history shared for troubleshooting. TUN mode can make more traffic visible in a connection log, but it does not make secrets safe by itself. Use least-privilege tokens, rotate exposed credentials, and prefer private routes for internal repositories whenever your organization provides them.
Compared with browser-only proxy extensions, per-tool environment variables, or older clients that require a separate configuration for every terminal program, the TUN approach gives developers one observable capture path for mixed CLI workloads; its trade-off is that route permissions, DNS, Docker’s separate engine, and local-network exclusions require more deliberate setup. Clash Official Site keeps that process practical with Mihomo-compatible routing concepts, clear client guidance, and troubleshooting steps that connect a failed command to the rule and destination behind it rather than asking you to guess. If you want to reproduce the workflow with a supported Clash client, download a Clash client and start with the profile, TUN, and verification sequence above.