Clash Sniffer Not Working? Fix mihomo Sniffing and Rules for Streaming Apps
What the Sniffer Does (and What It Does Not)
In Mihomo (the core inside most modern Clash GUIs), the Sniffer watches connections that would otherwise be matched only by IP address. Many flows arrive as IP:port because the client already resolved a name elsewhere, or because the tunnel saw a packet before your rules pipeline had a domain string to work with. The Sniffer tries to recover a hostname by inspecting cleartext metadata—most often TLS ClientHello SNI for TCP 443, and QUIC initial packets for UDP 443—so downstream logic can run DOMAIN and DOMAIN-SUFFIX matches instead of falling through to IP-CIDR or GEOIP.
That sounds like a magic switch, which is why people enable it and still complain that “Clash Sniffer does nothing.” In practice, Sniffer is one moving part in a chain: DNS mode (fake-ip versus redir-host), override-destination, rule order, TUN versus system proxy, and whether the app uses protocols Sniffer understands. If any link disagrees with the rest, your DOMAIN-SUFFIX rows for streaming services never see the hostname you think they should see.
This guide walks the checklist in the order that saves time: confirm sniffing is actually producing hostnames, ensure those hostnames participate in routing decisions, then align DNS so the story stays consistent. For big-picture routing theory after Sniffer is stable, pair this with our rule-based routing guide and, when capture mode matters, the TUN mode tutorial.
Symptoms That Look Like a Broken Sniffer
Before editing YAML for the tenth time, separate symptoms. Case A: the connection log shows a real public IP as the destination, the rule hit is GEOIP or MATCH, and no hostname appears even after you open a browser tab. That often means Sniffer is off, filtered out by skip-domain / skip-src-address, or the traffic is not TLS/QUIC on a port you sniff.
Case B: a hostname appears in logs, but the flow still uses the wrong proxy-groups entry. That is usually rule priority: an earlier IP-CIDR, GEOIP, or broad DOMAIN-KEYWORD row wins because Mihomo evaluates rules top to bottom and stops at the first match. Sniffer did its job; your ordering did not.
Case C: video apps work in a browser but fail inside a native client, or Android behaves differently from desktop. Mobile apps may pin certificates, use hard-coded resolvers, or ship QUIC stacks that need both QUIC sniff and override-destination. Region-specific guides such as our Disney+ split rules article focus on domain lists and nodes; this article focuses on the sniffing pipeline those lists depend on.
Step 1: Enable Sniffer and the Right Protocol Ports
Start from a minimal, explicit sniffer: block. GUI users may find toggles that write equivalent YAML; manual editors should keep indentation strict under the root key. A representative pattern enables the feature, declares parsers for TLS and QUIC, and keeps mapping compatible with DNS fake-ip (more on that in Step 4):
sniffer:
enable: true
sniff:
TLS:
ports: [443, 8443]
QUIC:
ports: [443]
force-dns-mapping: true
parse-pure-ip: true
parse-pure-ip asks the core to keep working when the only hint is an IP tuple—exactly the streaming case where the OS resolver bypassed Clash. force-dns-mapping ties sniff results back into the fake-ip mapping table when you use fake-ip mode, which prevents absurd mismatches between DNS returns and connection tables.
If you import a subscription that already contains a sniffer: section, merge carefully. Duplicate keys or a second sniffer: stub hidden at the file bottom can silently override your intent. After saving, reload the profile and watch the dashboard or log for sniff-related errors rather than assuming success because the toggle is green.
Step 2: Override Destination and QUIC Reality
Recovering a hostname from a packet is not the same as using it for policy. Mihomo exposes override-destination (wording may vary slightly by release) so that, after a successful sniff, the logical destination for rule matching becomes the sniffed domain rather than the raw IP. Without this, you can see the correct name in diagnostics while the matcher still evaluates an IP-only path.
sniffer:
enable: true
override-destination: true
sniff:
TLS:
ports: [443, 8443]
QUIC:
ports: [443]
QUIC and HTTP/3 are not optional details for many streaming stacks. If you only sniff TLS on TCP but the app moves long video over QUIC on UDP, you get partial success: thumbnails load, playback stutters or falls back to an unexpected region. Include QUIC ports, confirm your tun stack forwards the relevant UDP, and remember that some corporate filters block QUIC entirely—Symptoms then mimic Sniffer failure.
Privacy and policy. Sniffer inspects connection metadata to route traffic. Use it for troubleshooting and lawful personal networking only; respect streaming terms of service and local regulations.
Step 3: Put Streaming DOMAIN-SUFFIX Rules Where They Can Win
Mihomo uses first match wins. A catch-all GEOIP line or a huge DOMAIN-KEYWORD,google style row above your streaming section steers traffic before Sniffer-derived names ever matter. Move explicit DOMAIN / DOMAIN-SUFFIX entries for services you care about above broad geographic buckets.
Illustrative excerpt—adapt names to your own proxy-groups:
rules:
- DOMAIN-SUFFIX,example-cdn.net,STREAMING
- DOMAIN-SUFFIX,playback.vendor.example,STREAMING
- GEOIP,CN,DIRECT
- MATCH,PROXY
Replace placeholders with domains you actually observe in logs; provider rule-sets help, but blind imports can reorder poorly. When debugging, temporarily add a narrow DOMAIN test host and confirm it hits STREAMING before you trust a hundred-line DOMAIN-SUFFIX list. Our split-traffic article expands on rule-providers and logical groups if you outgrow inline lists.
Step 4: DNS Mode, Fake-IP, and Hijack
Fake-ip mode returns synthetic addresses for matched queries so the client can open a connection that Mihomo intercepts, then map the IP back to a domain for rules. It is fast and popular, but it assumes the client actually uses the resolver you control. System-wide TUN plus DNS hijack (or equivalent GUI switches) keeps smart TVs, browsers, and stubborn binaries on the same page; without hijack, one app resolves via DoH straight to Cloudflare while another uses Clash, and Sniffer logs look schizophrenic.
If you switch to redir-host for diagnosis, routing semantics change: you trade some fake-ip conveniences for clearer domain strings in certain logs. Many users run fake-ip in steady state and flip temporarily when hunting a specific bug. Whichever you pick, align three things: the dns: section, the tunnel or system proxy path, and sniffer.force-dns-mapping when fake-ip is on.
When Sniffer “works in curl but not in the app,” DNS is the usual villain. Double-check that the operating system points to the local Clash DNS inbound while testing, then revert to your preferred resolver layout once verified.
Copy-Paste Snippets: Streaming Group + Sniffer Together
Below is a consolidated skeleton you can merge into an existing profile. It is not a one-size-fits-all unlock list—streaming domains change—but it shows how proxy-groups, rules, sniffer, and dns reference each other without naming conflicts.
proxy-groups:
- name: STREAMING
type: select
proxies:
- NODE-A
- NODE-B
- DIRECT
dns:
enable: true
enhanced-mode: fake-ip
nameserver:
- 1.1.1.1
fake-ip-range: 198.18.0.1/16
sniffer:
enable: true
override-destination: true
force-dns-mapping: true
parse-pure-ip: true
sniff:
TLS:
ports: [443, 8443]
QUIC:
ports: [443]
rules:
- DOMAIN-SUFFIX,netflix.com,STREAMING
- DOMAIN-SUFFIX,nflxvideo.net,STREAMING
- GEOIP,CN,DIRECT
- MATCH,PROXY
Trim or expand DOMAIN-SUFFIX rows based on your logs. Subscription maintainers sometimes ship streaming lists; verify their order relative to your GEOIP lines after every merge.
TUN, System Proxy, and Where Sniffer Sees Packets
Under system proxy, only applications that honor OS proxy settings funnel TLS neatly through the local forwarder. Everything else still carries raw tuples until something captures it—often TUN. If Sniffer “never fires” while you are on system proxy mode, test the same rule set under TUN with DNS hijack enabled. The TUN guide explains adapter permissions and DNS alignment across Windows, macOS, and Linux; those details matter because Sniffer only sees what the tunnel feeds it.
On Android, VPNService-based clients approximate TUN behavior; Sniffer still needs compatible ports and QUIC coverage. Mobile vendors may restrict background DNS; whitelist the client before concluding Sniffer is broken.
Verification: Logs, Connection Table, and Sanity Checks
Work like a network engineer, not a guesswork chef. After each change, open the live connections panel if your GUI offers one, or tail the core log. You want to see sniffed hostnames next to flows that previously showed bare IPs. If hostnames appear but the wrong group activates, scroll your rules: list: the first matching line is the law.
Run controlled tests: one browser profile, one streaming tab, one app version. Change only one variable at a time—Sniffer on/off, override on/off, single extra DOMAIN row—to avoid phantom correlations. Keep notes; future you will thank present you when a subscription update reshuffles rules overnight.
Kernel freshness. Legacy cores lack modern Sniffer behaviors. If options are missing or logs show parse failures, upgrade the app bundle from our download page before chasing obscure YAML keys.
When Sniffer Cannot Fix the Problem
Some stacks encrypt early with no visible SNI equivalent Sniffer can read, or they tunnel inside a carrier protocol your build does not dissect. Pinning, custom certificate stores, or split-horizon DNS at the router can all bypass what a local proxy sees. In those cases, no amount of override-destination helps—you need different capture (full TUN with correct routes), different resolvers, or to accept IP-based rules with honest IP-CIDR / GEOIP trade-offs.
Also remember Sniffer does not replace a healthy proxies: list. If every node is down, the best sniff in the world only sends failures through a prettier path. Confirm subscriptions load before tuning Sniffer; the subscription import guide covers that baseline.
Closing: Sniffer as Part of a System, Not a Single Toggle
Treating Clash Sniffer as the one knob for streaming misses how Mihomo actually works: sniffing reveals names, override-destination lets rules consume them, DOMAIN-SUFFIX rows must sit ahead of blunt GEOIP matches, and DNS fake-ip plus hijack keeps resolver behavior from fighting the tunnel. When those pieces line up, apps that once looked “impossible to route” start landing in the right proxy-groups without constant profile surgery.
Compared with endlessly duplicating IP lists that go stale after a CDN shift, a disciplined Sniffer plus ordered domain rules tends to age better—fewer midnight emergencies when a provider adds a new edge hostname. Pair that stability with a maintained GUI on the mihomo train and you spend less time wondering whether magic broke and more time watching the show.
→ Download Clash for free and experience the difference.
Want YAML references beyond Sniffer? Browse the documentation hub for next steps. Go to the download page →