Why Your Browser Is Proxied but Your Terminal Keeps Sliding Past
If you switched on System Proxy and watched Discord or Chrome glide through relays while git clone still crawls—or npm install times out—you are witnessing the mismatch between HTTP-friendly OS hooks and blunt TCP sockets launched from shells. Graphic apps that respect WININET proxies on Windows or Automatic Proxy Configuration on macOS willingly forward HTTPS through Clash-managed listeners. Typical CLIs compiled against native networking stacks bypass those tables entirely unless libraries such as curl read http_proxy environment variables voluntarily.
Engineers compensate by exporting gigantic .zshrc blobs that sprinkle HTTPS_PROXY=http://127.0.0.1:7890 everywhere until container jobs and language-specific package managers collide. Maintenance snowballs quickly: Yarn Classic versus Corepack versus corporate registry mirrors disagree on SOCKS versus HTTP backends. Some Go binaries ignore env proxies unless built with defaults enabled. SSH-based git remotes bypass HTTP layers completely. Rather than patching every toolchain, placing interception at layer three restores a single choke point where Mihomo-compatible cores already enforce your YAML.
Analogy: System proxy is akin to politely asking applications to funnel through doorway A. TUN is installing a revolving gate on the pavement before anyone reaches the freeway on-ramp: even runners who pretend not to notice signs still traverse the choke point.
What TUN Means in Practical Terms
TUN (network tunnel) adapters present a synthetic interface to your operating system. When a modern Clash-derived client activates TUN, it instructs drivers—Wintun or similar on Windows, utun sockets on Apple platforms, TAP/TUN kernels on Linux—to carry IP packets originating from arbitrary processes. Instead of juggling every application’s SOCKS awareness, outbound flows hit the routing table entries the client manages, divert into user space once, then exit through proxies or DIRECT per your sorted rules: section.
Because interception happens before distinctions such as SOCKS versus HTTP CONNECT matter, UDP, DNS queries, QUIC handshakes, ephemeral Node fetch calls, and Electron bundlers converge on the same decision tree that already handles browser tabs. Complexity migrates upward into profile tuning—which destinations deserve a GEOIP,CN,DIRECT style rule versus overseas buckets—rather than downward into patching each developer toolchain.
Trade-offs deserve honesty. TUN touches drivers that historically required administrator UAC consent on Windows and VPN-style entitlements on macOS. Misconfigured profiles can starve local LAN printers or split-tunnel corporate SaaS if default routes fight each other. Still, for anyone whose daily stack blends GitHub, crates.io, PyPI, and Docker registry pulls, the payoff is coherence: observable rule hits logged per connection, identical to what you see in graphical dashboards.
TUN Compared with System Proxy and Environment Variables
System proxy wins on simplicity: reversible toggles, negligible battery drag, and fewer permission prompts. Everyday browsing seldom needs deeper plumbing. Conversely, TUN shines whenever traffic bypass manifests: language runtimes spawning child processes, ephemeral ports, or sandboxed Electron IDEs that refuse inherited environment blocks.
Environment-variable tricks remain valid auxiliary tools—exporters still help curl fall back cleanly when TUN is disabled for auditing. Combining both rarely breaks anything except duplicate chained proxies: remember to unset manual exports after enabling TUN to avoid unintended double relays or suspicion from upstream providers.
| Mechanism | Typical CLI coverage | Ops overhead |
|---|---|---|
| System Proxy | Tools explicitly honoring WinHTTP PAC or POSIX proxy env stacks | Low until you babysit exporters |
Manual HTTPS_PROXY / ALL_PROXY |
Uneven: Node fetch behaves differently than raw Go binaries | High—per shell per CI image |
| TUN interception | Broad TCP/UDP routed through the Clash core | Medium—elevated setup once per OS user |
Platform Notes: Windows macOS Linux
Windows
First enablement generally raises UAC because Wintun creates a virtual NIC. Approve it once; subsequent launches should be smoother if the helper service installs correctly. Windows Defender SmartScreen may flag lesser-known builds—verify checksums from trusted release pages. Enterprise MDM sometimes locks proxy tables; TUN circumvents some but not all Group Policy restrictions if routing policies override interface metrics.
macOS
Expect System Settings prompts describing VPN configurations or network extensions. Apple treats packet tunnel providers seriously for privacy; denying them blocks TUN entirely. Sequoia-era permission resets occasionally disable login items—revisit privacy panes if the menu bar helper vanishes after OS updates.
Linux
Capabilities or temporary sudo hops may be necessary depending on packaged helper design. Distro-specific AppArmor or SELinux profiles might refuse raw socket bridging until you carve exceptions responsibly. Containers and rootless Docker often isolate namespaces, so host-level TUN does not magically proxy workloads inside unpublished bridge networks—you may still need daemon.json registry mirrors or Compose-level HTTP proxies alongside host TUN.
Enabling TUN in a Maintained Graphical Client
Although raw Mihomo kernels expose YAML tun: stanzas, most readers lean on graphical shells such as Clash Verge Rev. After importing subscriptions and activating Rule mode, open Settings, locate TUN Mode or equivalent wording—the UI occasionally relocates widgets between minor releases—toggle it on, then accept prompts. Optionally keep System Proxy enabled for redundancy; Mihomo merges sensibly unless double-chaining appears.
Lawful use: Respect jurisdictional telecommunications rules and organizational acceptable-use policies. TUN modifies networking stack behavior in broad ways—inappropriate use can violate contractual obligations even when technically feasible.
How CLI Traffic Hits the Rule Engine Once TUN Runs
After interception, the chain resembles browser flows: outbound packets classify by destination IP or reconstructed hostname snapshots, depending on resolver mode (FULL, FAKE IP, and so on), then attach to policies such as DIRECT, REJECT, or outbound proxy groups. Each decision logs with rule labels inside connection inspectors—a lifesaver when a sluggish git pull needs root-cause triage.
Because evaluation order runs top-first until one rule fires, domestic CDNs should sit higher than a catch-all overseas MATCH line; otherwise benign npm mirrors might egress abroad accidentally and inflate latency. Layer domain-specific allowlists above broad RULE-SET entries when diagnosing mis-tagged IPs.
Tool-Specific Quirks: git npm curl and Friends
git: SSH Versus HTTPS
TUN transparently relays TCP for both but SSH handshakes do not magically convert to SOCKS unless you purposely wrap ProxyCommand helpers. HTTPS remotes cooperate immediately because they resemble ordinary TLS flows once DNS resolves. Mixed teams often standardize on HTTPS remotes during travel then revert post-VPN; document whichever pattern your org selects to avoid mysterious auth failures when port 22 blocks.
npm and package registries
Modern npm sits on Node’s networking stack and historically honored proxy environment variables inconsistently, which left novices baffled. With TUN, tarball downloads follow OS routing, which simplifies life when corporate registries are mirrored across continents—just ensure private @scope: registries resolve to addresses your rule bundles classify correctly.
curl quick checks
Running curl -fsSL https://api.ipify.org from a sterile shell with no HTTPS_PROXY exported prints the WAN address Clash currently presents—an ideal litmus test for distinguishing direct ISP egress from relayed paths. Watch IPv6 as well: dual-stack quirks occasionally bypass expectations until you add matching IP-CIDR6 safeguards.
wget, grpcurl, Terraform provider downloads, and Compose image pulls share the same storyline: once the kernel routes through TUN, the heavy lifting retreats into YAML—not dozens of brittle shell exports.
DNS fake-ip Stacks and Resolver Pitfalls
Profiles advertising dns.enhanced-mode: fake-ip return synthetic LAN-range answers promptly, cutting cold-start latency. When misconfigured, stray CLI resolvers that query public DNS upstreams may collide with intercepted flows and produce split-brain mismatches. Symptoms include intermittent NXDOMAIN flashes or GEOIP wrongly classifying foreign CDNs. Keep resolver modes consistent, and align nameserver-policy keys with the SaaS endpoints you prioritize.
Use the client Connections panel while reproducing a stuck npm job: the live row highlights whether traffic stayed DIRECT accidentally or tripped unintended REJECT lines.
Conflicts With Other VPN Layers Docker Bridges and WSL
Running several competing full-tunnel VPNs may starve Mihomo adapters: pings can succeed while TCP SYNs flap. Disable or downgrade corporate VPN split tunneling selectively before blaming Clash, and exclude corporate SaaS subnets using provider guidance instead of guesswork. Docker Desktop’s Linux VM isolates workloads, so host TUN proxies container-bound traffic differently—consult bridge-mode documentation for your setup. Under WSL2, Windows maintains a separate NAT boundary; switching mirrored networking modes can synchronize expectations when you test from both sides.
Verification Checklist You Can Paste Into Notes
- Disable temporary
export HTTPS_PROXY=...lines in shells to isolate TUN efficacy. - Launch Clash dashboards confirm TUN badge active without red error overlays.
- Run
curlagainst an IP-echo endpoint compare output with browser-based IP testers. - Clone a moderately sized public Git repo over HTTPS observing throughput stability.
- Trigger
npm view react versionor similar innocuous registry read confirm metadata arrives. - Inspect rule hits ensure domestic domains map
DIRECTwhile overseas tooling flows through intentional proxy buckets.
Troubleshooting Playbook When CLI Still Acts Direct
Hard-coded ignore-proxy binaries
Rare statically linked binaries ship without resolver awareness and may refuse routing-table redirects entirely. Mitigations involve wrapping SOCKS ports manually or patching upstream—not something TUN cures universally, though the case is uncommon.
Stale GEOIP RULE-SET manifests
Refreshing provider bundles plus geo databases prevents mis-bucketing IPs that swung across regions after BGP updates.
Path MTU and IPv6 quirks
Some WAN links demand clamped MSS values mirrored inside advanced tun sections. Official Mihomo tuning references describe how adjusting those knobs alleviates spooky TLS handshake stalls that masquerade as generic proxy failures.
Frequently Asked Questions
Must I elevate every boot? Typically no after drivers install—only major OS upgrades or permission resets re-prompt.
Does TUN slow gaming latency? Domestic games pinned to DIRECT should match pre-proxy baselines if rules stay tight. Watch over-broad MATCH lines that punish everything through distant relays.
Mobile parity? Android VPN permission models differ. This article emphasizes desktop ecosystems, yet conceptual overlap exists with FlClash-style VPN profiles—consult platform-specific FAQs.
Audit logging? Connection logs suffice for workspace debugging; never exfiltrate sensitive metadata across untrusted relays.
Cleaner CLI Routing Without Turning Every Repo Into a Makefile of Proxy Vars
Single-binary VPN storefronts obsess over flashy connect buttons, meanwhile developers waste afternoons toggling brittle environment variables, juggling corporate TLS inspection, and hoping CI mirrors stay aligned. Browser-only SOCKS extensions cannot see background daemons that patch Node or Rust crates. Clash-era clients instead unify transparent routing, expressive split policies, and actionable logs underneath one open-source-friendly umbrella.
Compared with abandoned forks whose cores froze mid-decade, Mihomo-aligned builds continue shipping modern transports, scheduled rule-provider refreshers, and thoughtfully surfaced TUN controls. If you want identical YAML semantics for Chrome tabs and midnight terminal batch jobs—without another shell function that tries to keep proxy state in sync—fetch current verified installers from our hub instead of orphan forum attachments:
Download Clash for every platform and keep CLI traffic on the same rules as your browser →