1. The narrow-failure pattern: why you should suspect Sniffer first
When people describe “Clash was fine, then I turned on advanced options and a few HTTPS sites died,” the failure mode is often extremely specific. The browser still loads most of the public internet, video CDNs, and even other financial-adjacent pages. The broken cases cluster around high-trust sites: a national tax portal, a state unemployment site, a university SAML login, a payment processor iframe, or a mobile banking app that opens an in-app WebView to a certificate-heavy domain. The visual symptoms repeat: ERR_CERT_ style warnings in Chromium, a frozen blank tab after redirect chains, a CAPTCHA that never finishes, or a two-factor step that never reaches the SMS gateway because the first script host never fully establishes TLS.
That is different from a bad proxy node, where you usually see wide latency, many unrelated domains timing out, or a provider dashboard full of red health checks. It is also different from a pure DNS outage, where the symptom typically tracks every device on the network or every hostname in a class. A Sniffer issue tends to be per-flow and per-hostname: the core has started rewriting how it understands the destination, and a picky site disagrees. Before you add megabytes of DOMAIN-SUFFIX rules, write down the one session you care about, keep everything else static, and confirm whether the Sniffer toggle moves the failure in a clean A/B test. That one habit saves hours and keeps your configuration documentation aligned with what you can actually prove in logs.
2. What the Sniffer actually changes on the path to HTTPS
In a modern Clash / Mihomo-class core, the Sniffer module attempts to recover a hostname when the first packets do not present the friendly domain your rules expect. For TLS on port 443, the usual signal is the Server Name Indication (SNI) in the ClientHello. The stack may also look at cleartext HTTP for legacy ports, QUIC ALPN, or other hints depending on the build and the feature flags you have enabled. The goal is to let policy routing stay accurate even when the client is effectively talking to an address (for example, after fake-IP mapping) instead of a literal DNS A record the application printed in its own logs.
Where banking and government stacks get unhappy is the second-order effect: once the sniffer and related destination overrides are in play, the internal representation of where a connection is “going” may diverge from what the app’s own TLS or cookie logic assumes. Certificate pinning is rarer in ordinary web browsers today, but strict redirect chains, anti-bot middleware, and split cookie domains are not. A portal might load an HTML document from www while post-auth XHRs hit api or a regional edge that only works when the client’s SNI, DNS, and routing views stay consistent. If sniffing, fake addresses, and rule hits disagree about which host the connection conceptually is, the site may not show a “clean” public error. It can simply hang at white screen because a blocking script from a third host never completed.
Another practical detail: some templates enable force-dns-mapping and parse-pure-ip together with a broad override-destination. On paper that keeps routing clever; in the field, it is exactly the kind of stacked “helpfulness” that makes debugging harder. The rest of this article keeps saying one variable at a time because these toggles are interactive, not independent. For a deeper look at the fake-address side of the same family of symptoms, our fake-IP, fake-ip-filter, and DNS walkthrough is the companion piece—read it after you confirm Sniffer is implicated, not instead of a focused A/B on sniffing.
3. A/B test: prove that Sniffer is the trigger, not the exit country
Start from a repro you can trigger in under a minute. Example: “Open the retail banking site in a fresh private window, click login, the spinner never resolves.” Do not “fix” the subscription, do not change nodes, and do not paste a new remote rule set yet. The first experiment is to turn Sniffer off entirely in the GUI, or set sniffer.enable to false in the effective YAML, then reload the core so the change is not half-applied. Retry the same URL. If the session suddenly completes, you have a high-confidence signal that the sniffing path interacts badly with that site, independent of the proxy hop.
Second run: re-enable the Sniffer globally, but add only the apex and obvious subdomains for that institution to a skip list (next section) if your build supports it, or turn off override-destination while keeping lightweight SNI read-only behavior if the UI allows that split. The goal is to learn whether the failure tracks all sniff metadata or destination rewriting in particular. Many users conflate the two because both live under a single “Sniffing” page in clients; separating them in testing is the difference between a two-line config fix and a week of forum scrolling.
Third run: with Sniffer in your desired final state, temporarily bypass Clash for DNS only on a test profile (not forever—just a diagnostic) to see whether a parallel resolver path still breaks the portal. If bypassing only DNS fixes the page while Sniffer is on, you are no longer in “pure sniff” territory: you are looking at a multi-layer interaction between resolver policy and tunnel routing. In that case, read the fake-IP article before you add more skip-domain lines. The point of ordering tests this way is to avoid a common trap: you “fix” the site by changing three things, then a subscription refresh brings the old bug back and you have no record of the real root cause.
4. Per-domain skip lists: the usual Mihomo-style shape
Once you are confident the Sniffer is involved, the maintenance-friendly response is to stop sniffing the smallest set of names that need exemption. In recent Meta / Mihomo configurations, a sniffer block can declare a sniff map (TLS, HTTP) with ports, plus a skip-domain list. Syntax varies slightly by version; your client’s generated YAML and upstream release notes are authoritative. A representative shape looks like the following, shown as a starting point, not a copy-paste mandate:
sniffer:
enable: true
sniff:
TLS:
ports: [443, 8443]
HTTP:
ports: [80, 8080-8880]
skip-domain:
- "+.example-bank.com"
- "+.tax-portal.example.gov"
- "sso.university.example"
Suffix style entries such as +.example.com cover the obvious subdomains, but you should still watch for separate API hosts, static asset CDNs, and 3-D Secure iframes that do not share the same suffix. A payment step might pull JavaScript from a paymentsdk host that is easy to miss if you only whitelisted the marketing apex. In DevTools, open the Network panel, filter to doc and js, and sort failed rows by status or blocked to see the first broken dependency.
If your build does not expose an inline skip list in YAML, the GUI may still support per-domain “do not override destination” or “exclude from sniffing” in advanced tables—same idea, different storage. The operational outcome you want is: the sensitive flows avoid destination rewriting that disagrees with the client’s TLS or redirect expectations, while everything else on your network keeps the benefit of SNI-based routing. Add entries in small batches, reload, and re-test. Giant skip lists that resemble ad-block subscriptions defeat the point of a precision tool and make future debugging noisy.
6. Why fake-IP, DNS, and Sniffer are usually read together in real incidents
It is possible for only Sniffer to be wrong. It is also common for a bank portal to fail only when fake-IP + Sniffer + a particular upstream DNS policy are all on. Fake-IP makes the first hop look like a private placeholder address, while the real resolution and routing are deferred. Sniffer’s job is to get names back in view for rules. If those two layers do not line up, you may get rule hits that “look” correct in the panel while the app still has a lousy time because another part of the stack—JavaScript, WebSocket, or a native client TLS library—sees a different story.
When the symptom is TLS warnings that mention a surprising name or issuer, you may be pulled toward certificate trust issues, but in Clash’s world, start by proving which hostname the core thinks it is serving vs. which SNI the browser sent. A mismatch at that layer is often resolvable in configuration rather than by importing corporate roots into the OS trust store (which is a high-risk endgame and usually unnecessary for public banking sites if routing is clean).
Our dedicated fake-IP, fake-ip-filter, and DNS article walks fake-ip-filter, nameserver policy, and fallback in detail. The correct reading order for mixed symptoms is: (1) confirm Sniffer A/B, (2) add skip-domain, (3) if anything still wobbles, run the fake-IP checklist, because otherwise you can chase nameserver entries that were never the real problem.
7. TUN mode, system proxy, and stacked VPNs magnify the confusion
TUN captures at a different layer from classic system proxy. That is good for games and stubborn binaries, but it also means a broken helper service or an exclusion list that fails open can split your DNS, IPv6, and TCP fast-open assumptions in half. Government portals and SSO stacks are a frequent place where one script host is accidentally excluded from the tunnel while another is inside it, or where IPv6 AAAA answers point at a path that the proxy stack does not follow coherently. If the Sniffer A/B and skip list work on system-proxy mode but not on TUN, you are looking at a routing and capture problem first.
Use the TUN material in Clash TUN on Windows: routing and firewall to make sure the adapter is not silently starving the connection before you declare Sniffer “done.” The same day, check whether another VPN or zero-trust client has inserted its own filtering driver. Two filters in the same path can yield “TLS works in curl but not in the browser” because the browser process is on a different split route or DNS profile.
On macOS, Network Extension and system proxy can disagree after sleep or dock changes; on Linux, systemd-resolved and a desktop GUI may race for port 53. The Sniffer is rarely the sole story when those environmental factors are in play, but the symptoms still arrive as “it broke when I ticked a box in Clash,” because that box was the last change you could name. A sober workflow: get one clean transport mode working with Sniffer exemptions, then reintroduce the fancy modes.
8. How to collect hostnames and verify in logs like an operator
Start at the browser’s address bar and DevTools before you open the Clash log. You want: top document URL, the first red or blocked subresource, the wss:// host if a soft token or chat widget is in the way, and any federated login hop that bounces to a new apex. Copy those into a text file, then add them to the skip list in groups that match the same owner—there is no prize for the shortest YAML on disk, only for the least surprising YAML in production.
On the core side, raise logging enough to see connection, rule, and DNS lines without printing secrets. The exact log tokens depend on the build, but the pattern to look for is: this flow had SNI foo, sniffer said bar, the dial went to baz—mismatches in that triplet are a gift because they are actionable. If you are using a mobile app instead of a browser, the hostnames are harder to read; a split-capture on the router, a temporary desktop login of the same account, or the vendor’s published API doc may be the honest way to get names without violating terms of service or local law.
End each troubleshooting session with a written rollback plan: if this subscription merge adds a sniffer: block again, which file in your repo holds the institutional skip list so it survives updates? A surprising number of “it came back after update” issues are git hygiene issues, not kernel bugs. When the profile is under source control, treat skip lists like firewall exceptions: time-stamped, justified, and reviewed when a domain changes owner or CDN. That discipline pairs naturally with a reliable client; if you have not already, the site’s download page for Clash and Mihomo-based GUIs is the right place to pick a current build, then apply your exemptions on top of a known baseline.
| You observe | Check next |
|---|---|
| One institution’s login never finishes | Sniffer A/B, then a minimal skip-domain set, then 3rd-party js hostnames in DevTools |
| Certificate name mismatch, but only in Clash | override-destination off vs. on; force-dns-mapping and fake-IP together; compare SNI in logs to dial path |
| OK on system proxy, broken on TUN | Routing, exclusions, and IPv6 in TUN material before more YAML |
9. Summary: narrow exemptions beat global “just turn it all off”
Clash’s Sniffer is a power tool for rule quality when traffic does not present a clean hostname at the first instant. The trade-off is that the same heuristics that rescue streaming and gaming flows can upset a small number of high-assurance HTTPS properties that already carry their own assumptions about SNI, redirects, and partner domains. The fix that ages well is not “disable sniffer forever.” It is to identify the exact hostnames in the real page load, add a tight skip-domain (or equivalent) family, and then—only if the portal still flinches—walk the related fake-IP and DNS layers with the companion guide and TLS handshake and SNI troubleshooting so you are not misreading a node problem as a sniff problem. Compared with chasing random subscription servers, a disciplined, logged sequence keeps everyday browsing, developer tooling, and the occasional “must not fail” portal all on a single sustainable profile. When you are ready to standardize the client and baseline your YAML before layering exceptions, you can Download Clash for free and experience the difference on the stack you just debugged with intent rather than superstition.