Why Clash and a Browser Switch Both Touch Traffic

Clash can own traffic in two common ways. First, the client asks the operating system to send “HTTP/HTTPS by default” through a system proxy on 127.0.0.1 and a port your YAML calls mixed-port (or split HTTP and SOCKS). Second, TUN mode captures many flows at a lower layer so the kernel sends packets into the core, which is closer to a transparent path than a browser setting. A separate article walks the capture model in depth: Clash TUN mode deep dive. A Chromium browser extension such as SwitchyOmega is a third place that can decide “this tab uses proxy A, that tab is direct,” independent of the OS. None of the three is automatically aware of the others. When all three are enabled at once, you have not “stacked more safety”; you have stacked independent decision makers that can hand the same request to the local listener twice, or point at the wrong 127.0.0.1 port. If you are still choosing which Clash build and mode you want long term, the cross-platform Clash client comparison helps you avoid running two full cores because each installer ships its own default port and tray helper.

The mental model: pick one control plane for the browser—either the OS (system proxy or TUN) or the extension’s fixed profile, not “both in conflicting modes.” Rule-based split between domestic and international sites belongs in the Clash profile, not in a hand-maintained list inside the extension, when you already trust YAML and policy groups. For matching order, providers, and defaults, the baseline reference is Clash rules and routing best practices—it pairs naturally with the simplification you want after you stop double-wrapping.

Double Proxy, Loopback Pointers, and Routing Loops

Double proxying is what it sounds like: the browser’s first hop is an HTTP or SOCKS client that forwards to 127.0.0.1:N, and the OS (or a second switch) also forwards browser traffic to the same listener, so a single user action can traverse the inbound twice. The page may still load, slowly; TLS handshakes and certificate checks may look flaky; or the tab spins forever. A routing loop on the loopback is worse: configuration mistakes can send traffic from the proxy back into the proxy, or from a PAC script into a path that re-enters the same proxy condition in a way that never reaches a real remote peer. The symptoms are not subtle—admin UIs for routers or local services “never finish,” and developer tools may show long chains of 127.0.0.1 connections. These are local topologies, not “your airport is down.”

Another frequent foot-gun: SwitchyOmega set to a fixed HTTP proxy at 127.0.0.1:7890 while Clash is actually listening on a number you changed after fixing a port-in-use error. The extension still points at the old port, so the first hop is refused or connects to a different program. Align numbers everywhere, or—better—get out of the business of retyping ports in the extension when the OS can carry the one true value. On macOS, system extension approval and the order between TUN and proxy toggles are easy to get wrong; if symptoms persist after you simplify layers, macOS TUN, system extension, and proxy conflict troubleshooting is the specialized companion.

Do not stack PAC on top of a conflicting proxy chain. A PAC file that returns a proxy for “everything” while the system already forces all HTTP through 127.0.0.1 is a classic way to build confusing recursion. Simplify to one source of truth before debugging remote sites.

SwitchyOmega Modes: System, Direct, and Fixed Server

In SwitchyOmega (or close equivalents), the high-level options map roughly as follows. Direct tells the extension not to add its own HTTP proxy layer: the browser uses whatever the OS would use for a “no extension” profile—direct internet or the system proxy if the OS is configured, depending on the browser. System proxy (wording may vary) makes the extension explicitly follow the OS’s proxy table—useful when Clash has set system proxy to the correct local mixed port. Auto switch and per-domain rules inside the extension duplicate what many users already express in Clash with DOMAIN / GEOSITE / policy groups. When TUN is on, those per-tab rules in the extension often add noise: the kernel is already sending traffic to the core, so an extension that forces another 127.0.0.1 path is the wrong layer to fight policy battles.

Fixed server (HTTP or SOCKS) is the most dangerous mode when the OS is already proxied, because you have defined two explicit proxy steps unless you have been meticulous about the relationship between the extension profile and the OS profile. A sane pattern: if you are all-in on TUN, set the extension to Direct for daily browsing, let TUN and your YAML route the world, and use rule order and policy groups for exceptions. If you are all-in on system proxy from Clash without TUN, set the extension to System proxy or Direct (depending on how your browser applies OS settings) so the browser is not re-applying a second fixed upstream.

When TUN is enabled and working: treat the network stack as “already in Clash.” The browser is just another app; the extension should not insert another local proxy hop. In practice, set SwitchyOmega to Direct (or disable the extension for a day while you test). You still get per-site policy from Clash because the packets already hit the core. If you have ever quit a client and lost general connectivity because OS proxy settings lingered, the reset procedure in no internet after closing Clash: clear system proxy and TUN is the same class of cleanup—TUN and system proxy are different leftovers.

When TUN is off and you rely on system proxy from Clash: keep one story: the OS points to 127.0.0.1:your_mixed_port, and the extension either defers to the OS or stays out of the way. Avoid “Clash set system proxy to 127.0.0.1:7890 + SwitchyOmega fixed server also 127.0.0.1:7890 with its own auto rules” unless you are deliberately layering for a very specific test. If the browser and the OS disagree, the first sign is often a site that works in curl -x but not in the browser, or the opposite, because the extension profile is the odd one out. After you remove the extra layer, if you need confidence that the browser is not leaking around your policy, add WebRTC and browser leak checks to your verification, because transport leaks are orthogonal to the loop problem but look similar in “why is my IP wrong?” threads.

When Localhost and Intranet Pages Look “Dead”

Local development servers (localhost:3000), router admin UIs, and some corporate intranet hostnames are exactly where double-proxy mistakes hurt. A request that should stay on the LAN can get dragged through 127.0.0.1 and then out to a remote node, or fail because the Clash policy does not know your RFC1918 name. TUN + sane bypass rules in YAML usually fixes “router page never loads” more reliably than an extension that forces all tabs through a fixed server. Put bypass patterns in the core: private IP ranges, *.local where appropriate, and explicit DOMAIN-SUFFIX for your home NAS. The rules article above covers precedence; the important habit is: do not use the extension to “punch out” of bad routing with another proxy hop—fix the Clash rule table instead.

If you are testing “what happens with only the extension,” disable system proxy and TUN in the Clash client temporarily, reload, and compare. A/B tests like that expose which layer is responsible within minutes. If you do not want to juggle, stick to one—most readers who already run a modern GUI will find TUN or system proxy plus extension-on-Direct the least noisy long-term.

Verify: One Hop, Clean Logs, and a Quick curl

Step 1 — Choose a mode for the day. Either TUN on + extension on Direct, or system proxy on + extension on System proxy/Direct without a competing fixed port. Step 2 — Restart the browser fully (not only close tabs). Extensions can cache a proxy selection until process exit. Step 3 — Compare browser vs curl. From a terminal, run curl -I https://www.example.com without -x first; then with -x http://127.0.0.1:PORT that matches Clash’s listener. The browser, with the extension simplified, should behave in line with the single-hop story you expect. Step 4 — Read the last mile. In your client’s connection log, a normal tab should not show two sequential connections both tagged as local proxy unless you really intend a multi-hop out to the internet. If you still see double entries on 127.0.0.1, the extension is still in fixed mode.

Step 5 — Localhost sanity. Open http://127.0.0.1 for a service you control; if the page that used to work under plain direct networking now fails, search your Clash logs for that destination and add a DIRECT or bypass rule, then re-test. That workflow matches how you would iterate routing policy for any new hostname—just remember that the extension is no longer the right place to special-case it when the core already has the real rule engine.

Wrap-Up

Clash and SwitchyOmega are both popular because they are powerful independently; that is also why double proxying and loopback routing loops are common support threads. The fix is not more toggles; it is one coherent path—TUN with the extension on Direct, or system proxy with the extension deferring to the OS—and the heavy lifting in YAML via Clash rules, not a parallel rule world in the browser. After you align layers, re-check how to clear proxy residue when the client stops so a future quit does not leave the machine in a half-proxied state. → Download Clash for free and experience the difference on a client that makes effective YAML, TUN, and system proxy state visible, so the next time something “spins,” you can see which layer is still in play.