Separate client status from web requests
When the Clash client says “Connected,” it usually means the core is running, the proxy is enabled, or a connectivity check succeeded. It doesn't mean every browser request is going through a proxy node. The full path includes the app's proxy settings, core rules, exit node, DNS resolution, and destination server. A problem anywhere along the way can leave a page spinning indefinitely.
Change just one variable at a time. Keep your current config and override files, and note the client name, core version, selected policy, and time of the error. Settings are named differently across clients, so the checks below refer to config fields, system settings, and observable results—not menu labels from a specific app.
- No apps can access the internet: Turn off the proxy and TUN, then check that Wi-Fi or Ethernet, the default gateway, and network authentication are working.
- Only the browser is affected: Check browser extensions, its own proxy settings, Secure DNS, and cache.
- Only some sites are affected: Check the matching rules, node egress, and restrictions on the destination site.
- The connection drops only when TUN is enabled: First establish a working baseline with the system proxy, then check how traffic is routed.
Step 1: Make sure the system proxy points to the listening port
A common system proxy address is 127.0.0.1:7890, but 7890 isn't required. Use the current running config's mixed-port value. It accepts both HTTP and SOCKS proxy connections. external-controller is the control interface, not a browser proxy port.
Check system and browser settings
- Windows 11: Go to Settings → Network & internet → Proxy and check the manual proxy address and port. If your client uses an automatic configuration script, check which proxy entry is actually enabled. Don't leave a manual proxy and an old script in conflict.
- macOS: Go to System Settings → Network → your current connection → Details → Proxies. Check that the HTTP, HTTPS, or SOCKS settings match your client.
- Firefox: Go to Settings → General → Network Settings → Settings. Make sure it uses the system proxy, or verify the address and port in the manual configuration.
- Mobile devices usually route traffic through a local VPN, so desktop system proxy steps don't apply. First check which VPN configuration is currently enabled in system settings.
Check that the port is actually listening
This Windows PowerShell command checks whether TCP port 7890 is listening and displays the process ID. No output means nothing is listening on that TCP port; don't assume the system proxy is connected to the core.
Get-NetTCPConnection -State Listen -LocalPort 7890 |
Select-Object LocalAddress, LocalPort, OwningProcess
On macOS or Linux with lsof installed, check the same port with:
lsof -nP -iTCP:7890 -sTCP:LISTEN
If you change the config to mixed-port: 7891, update the system proxy, command-line proxy, and any manual proxy settings in apps to use 7891 as well. Listening on the loopback address is normal for local use; you don't need to enable LAN access just to troubleshoot.
Step 2: Use an explicit proxy request to isolate browser issues
Temporarily turn off TUN but leave the core running, then explicitly specify the proxy in a command. This bypasses browser extensions and system proxy selection. On Windows, use curl.exe to avoid PowerShell environments that resolve curl to a different command. On macOS and Linux, use curl.
curl.exe --noproxy "" --proxy http://127.0.0.1:7890 --connect-timeout 10 --max-time 20 -I https://example.com
example.com is a public test domain, not a fixed speed-test target. --noproxy "" prevents the environment's proxy-bypass list from affecting the test. To test the route without an explicitly specified proxy, turn off TUN and run:
curl.exe --noproxy "*" --connect-timeout 10 --max-time 20 -I https://example.com
| What you see | What to check next |
|---|---|
| Can't connect to 127.0.0.1:7890 | Check the listening port, whether the core has stopped, and whether the client applied the current config. |
| Explicit proxy works, but the browser doesn't | Check the system proxy, extensions, browser-specific proxy settings, and Secure DNS. Test again with a new browser profile. |
| A 407 response appears | Check local proxy authentication and the username and password used by the request. |
| Timeout or TLS failure after connecting | Check the exit node, connection to the destination, system clock, and certificate error details. |
A 200 Connection established entry in an HTTPS proxy log only means the CONNECT tunnel was accepted. Check the subsequent TLS handshake and destination server response too. A 403 or 405 from the destination means an HTTP response was received, but doesn't prove the site is usable. If needed, test again with a regular GET request.
Step 3: Check the mode, rules, and actual exit node
Open the client's connection list, reload the failing page, and find its connection by domain or process. Check the matched rule, policy group, and final node—not just the node selected on the home screen. A rule may send the domain to DIRECT, REJECT, or another policy group.
rule: Rules are checked in order, and the first match determines the policy. Check earlier domain rules, rule sets, and the finalMATCH.global: Use this briefly for comparison, and confirm that theGLOBALpolicy has selected the expected node. Switching to global mode doesn't guarantee the node works.direct: Connections handled by the core go out directly. This mode can't tell you whether a proxy node is working.
If a URL works in global mode but fails in rule mode, check the actual exit used in rule mode. Common causes include subscription rules sending the destination direct or a nested policy group still selecting an unavailable node. After making changes, switch back to rule and confirm that a new connection uses the expected policy.
If the connection list is empty
Make sure the list isn't filtered, the page isn't loading directly from cache, and the core log covers the test period. If the request still doesn't appear, check the app's proxy entry point and TUN routing before rewriting rules. The browser may use its own proxy, a VPN, or another network extension, so the request never reaches the current core.
Step 4: Test the node—don't rely on latency alone
A latency result means the node completed the probe requested by the client. It doesn't confirm connectivity to every domain, UDP traffic, IPv6 routes, or long-lived connections. A probe can succeed while the exit node is blocked by the destination site, so normal latency doesn't guarantee the page will load.
- Test two nodes against the same URL. Don't change the node and the website at the same time.
- Check the subscription's expiration date, remaining data, and whether node details have been updated. Update only through a subscription source you already trust; don't submit your subscription URL to online testing sites.
- Look for specific errors in the logs, such as a node connection timeout, authentication failure, TLS handshake failure, or DNS resolution failure.
- Check the system date and time. An incorrect clock can cause certificate validation to fail; don't hide the problem by disabling certificate verification.
If every node times out while connecting to its server, check whether the current network blocks the relevant transport ports. Testing over a phone hotspot can help compare network paths, but it doesn't prove the node config is correct.
Step 5: Distinguish system DNS, core DNS, and browser Secure DNS
To troubleshoot DNS, first identify which resolver is doing the lookup. The system resolver, mihomo's DNS module, and the browser's encrypted DNS may use different paths. A successful system nslookup doesn't prove the core's DNS is working, and working core DNS doesn't mean the browser uses the same resolver.
Observe first; change nameservers only if needed
On Windows, start by checking the system's DNS response. The command shows which server was used and the returned addresses. If it times out, check whether that DNS server is reachable over the network.
nslookup example.com
If you're using mihomo and want to inspect core DNS separately, first make sure the port is free, then merge the snippet below into your existing dns section. It's for diagnostics only; it has no nodes, policy groups, or rules and can't run as a complete config.
dns:
enable: true
listen: 127.0.0.1:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 1.1.1.1
1.1.1.1 is an example of a regular DNS upstream; whether it's reachable depends on your network. If your organization or school requires its own DNS, keep the settings that suit your network. Public DNS isn't a universal fix. Once the config is active, use a terminal with dig installed to query the specified port:
dig @127.0.0.1 -p 1053 example.com A
In fake-ip mode, an address from the configured mapping range may be expected. It's used to associate a domain with a later connection, not as the destination site's real public IP address. If an app receives a mapped address but its subsequent connection bypasses the core, the page may fail. Check Fake-IP together with the actual traffic routing path.
- Node server uses a domain name: First make sure the server's domain resolves. mihomo's
proxy-server-nameservercan specify an upstream resolver for node server domains, avoiding a circular dependency on the proxy before it has connected. - Using fallback: It works with
fallback-filterto choose between DNS responses; it isn't a universal fallback for connection timeouts. - Using browser Secure DNS: Temporarily switch back to the system resolver for comparison, then restore your preferred setting. Don't change multiple upstreams in both the browser and core at once.
- Only some sites are slow: Compare A and AAAA records and check IPv6 connectivity. Test with
curl -4andcurl -6before making changes. Don't treat disabling IPv6 as the default fix.
On Windows, after changing DNS settings, run ipconfig /flushdns to clear the system DNS cache, then restart the browser. This won't clear every browser cache or the core's Fake-IP mappings, and it can't fix an unreachable DNS upstream.
Step 6: Once the system proxy works, check TUN and the firewall
If an explicit HTTP proxy test succeeds but traffic fails with TUN enabled, focus on traffic interception. TUN relies on a virtual network adapter, routes, and runtime permissions. An enabled switch in the client doesn't prove the routes were installed. Check startup logs for permission errors, device creation failures, or route conflicts.
Check traffic routing scope and DNS hijacking
In mihomo, tun.auto-route sets routes automatically, while tun.auto-detect-interface helps identify the outbound interface. Check support for your core version and platform. With multiple network adapters, another VPN, or virtual machine networking, automatic detection may not choose the expected interface.
tun.dns-hijack can send matching traditional DNS requests to the core's DNS module. A common entry is any:53. To match TCP port 53, configure tcp://any:53 if supported by your core. This doesn't automatically intercept encrypted DNS requests sent by the browser over HTTPS on port 443, and it can't replace a working upstream resolver.
- Temporarily exit other VPNs, accelerators, and duplicate proxy clients, then run only one traffic interception tool.
- Make sure the required client service is installed and running, or launch the client with the permissions it requires. Then check the logs.
- Use
route printon Windows orip routeon Linux to inspect routes and verify the actual outbound path. Don't delete system routes blindly. - In the firewall, check that the current core executable is allowed to access the network. A client update may change its file path, leaving old rules pointing to the wrong location.
- If only large downloads or some HTTPS pages stall under TUN, then investigate MTU, Path MTU Discovery, and UDP support. Don't keep switching network stacks without evidence.
Before resuming normal use: confirm the config is active and the result is reproducible
A client may have the original subscription, override config, and final running config. Editing a YAML file doesn't mean the core is reading it. First confirm the active config source in the client, then check the ports, DNS, and TUN fields actually applied.
If you're running mihomo directly, use this Windows command in the config directory to check the syntax. It assumes mihomo.exe and config.yaml are in the current directory. If you're using a GUI client, use its config validation tool instead; don't start a second core that could compete for the same port.
.\mihomo.exe -t -f .\config.yaml
A successful syntax check only means the config can be parsed; it doesn't guarantee that nodes, DNS, or network access work. After troubleshooting, wrap up in this order:
- Switch back to your usual rule mode and check the actual exit used by one direct destination and one proxied destination.
- Reopen the browser, retest the URL that failed, and check the connection log for the same time period.
- Restore temporary debug logging to your normal level and remove any test listening ports you no longer need.
- Record the final port, changed fields, and how the config was applied so a future subscription update doesn't overwrite the fix.
If you still can't find the cause, provide the client and core versions, OS version, time of the issue, system proxy and TUN status, and a redacted log for a single request. A clear, minimal reproduction is more useful than a screenshot that only says “Connected.” For basic setup, see the Getting Started guide. For config field details, see mihomo Advanced Config.