Start with the request flow: an app sends traffic to a local port, and the core handles it according to the current mode. In rule mode, rules choose a policy, then proxy-groups determine the actual route. dns handles name resolution, while TUN changes how traffic reaches the core. These features work together, but they are not interchangeable switches.
This guide follows the order commonly used in configuration files. The basic fields apply across the Clash configuration ecosystem. For TUN, DNS extensions, and newer protocols, support depends on the core in use. Clash Meta was later renamed mihomo, and client UI labels may differ from core terminology. A client calling itself “Clash” does not guarantee that every field is supported.
1. Find the Right File and Check How It Takes Effect
config.yaml may not be the complete configuration currently loaded by your client. GUI clients may store the original subscription, user settings, override snippets, and final runtime configuration separately. Editing a generated runtime file directly may not stick; it can be regenerated the next time you switch subscriptions or restart.
- Open the client's “Configuration” or “Profiles” page and check which profile is active—not just which one was imported most recently.
- Use that profile's “Edit” or “Open File” option, and save a copy of the original before making changes. Button labels vary by client version.
- Check whether the client offers “Override,” “Merge,” or a similar feature. Use these options to add local rules you want to keep long term.
- After saving, choose “Reload Configuration” or re-enable the profile, then check the logs for parsing errors.
Check for YAML Syntax Errors First
- Use spaces for indentation, never tabs. This guide uses two spaces per indentation level.
- Leave a space after the colon, for example
mode: rule, notmode:rule. - Start each list item with
-; keep nodes, proxy groups, and rules at the same level aligned. - Write Boolean values as
trueorfalse. Quote names, passwords, and addresses that contain special characters.
If you see yaml: line 12: mapping values are not allowed in this context, check the colon, quotes, and indentation on line 12 and the line above it. The configuration hasn't reached the network connection stage yet, so switching nodes repeatedly won't help.
2. Ports and Mode: Where Requests Enter
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false
mixed-port accepts both HTTP proxy and SOCKS5 requests. In this example, set the app's proxy server to 127.0.0.1 and the port to 7890. These are example values; use the port shown by your client if it differs.
| Field | Purpose | Common point of confusion |
|---|---|---|
port | HTTP proxy listening port | Not a DNS port or a remote node port. |
socks-port | SOCKS proxy listening port | The app must use the matching proxy protocol. |
mixed-port | One port for both HTTP and SOCKS | No need to bind another listener to the same address and port. |
external-controller | Control interface listening address | Used by the UI to control the core; not a proxy address to enter in a browser. |
mode: rule routes traffic according to rules; global uses the global policy; direct connects directly. If changes to rules have no effect, first check whether the UI is still in “Global” or “Direct” mode.
allow-lan: false prevents devices on your local network from connecting. To share the proxy with other devices on the same network, also check the listening address, system firewall, and authentication settings. Don't expose the control interface to the public internet just to connect a phone to the proxy.
log-level: info is a good starting point for everyday troubleshooting. If you temporarily switch to debug, restore the previous setting promptly; logs may include visited domains. ipv6: false does not disable IPv6 in your operating system and is not a substitute for system network settings.
3. DNS: Listening, Upstream Servers, and fake-ip
dns:
enable: true
listen: 127.0.0.1:1053
ipv6: false
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
default-nameserver:
- 223.5.5.5
- 119.29.29.29
nameserver:
- https://dns.alidns.com/dns-query
enable turns on the core's DNS module; listen sets where the DNS server listens. Setting it to 127.0.0.1:1053 only creates a local DNS endpoint—it does not mean the system sends all DNS requests to it. Standard system DNS settings generally can't specify a custom port like 1053, so you'll also need DNS interception, forwarding, or TUN settings in the client.
default-nameserver Is Not a General-Purpose Backup List
When nameserver uses an encrypted DNS address specified by hostname, the core first needs to resolve the DNS server's own hostname. default-nameserver is mainly used for this bootstrap lookup; nameserver provides upstream servers for regular queries. Putting every address into one list makes troubleshooting harder.
fake-ip Returns a Mapped Address
In fake-ip mode, domains are assigned mapped addresses so the core can associate connections with domain names. An address in the 198.18.0.0/16 range is not necessarily evidence of DNS poisoning. These addresses are used for internal mapping; they are not the destination site's real public IP.
If a LAN service, printer, or app doesn't work with fake-ip, add a specific fake-ip-filter entry to the existing dns section. Identify the affected domain first, then use a matching syntax supported by your core. Don't exclude every domain; that would change DNS behavior across the board.
4. proxies and proxy-providers: Where Nodes Come From
proxies is a list of nodes defined directly in the configuration. The type of each node determines which fields it needs. Common fields include name, server, and port, but passwords, UUIDs, TLS, and transport settings must match the server. Don't copy fields from a different protocol.
proxy-providers defines a node provider that can load a node collection from a remote URL or local file. You can't assume any subscription link will work here: the provider file format, subscription response, and core support must all match. A full configuration containing rules or dns is not a plain node list.
- Reference directly defined nodes by name using
proxiesinproxy-groups. - Nodes from a provider are usually referenced by provider name through a proxy group's
usefield. - Names must match exactly, including spaces, capitalization, and punctuation.
- Don't include subscription URLs, passwords, UUIDs, or control interface keys in public screenshots or logs.
If the logs say a proxy doesn't exist, check the references first, then confirm the subscription updated successfully. Removing a node or renaming it can also break validation if an existing proxy group still references the old name.
5. proxy-groups: Organize Nodes into Selectable Routes
proxy-groups:
- name: Manual Selection
type: select
proxies:
- DIRECT
- name: Default Route
type: select
proxies:
- Manual Selection
- DIRECT
This snippet shows only how references work. DIRECT is a built-in direct-connection policy, not a proxy node. Copying this example won't provide a remote proxy. In a working configuration, add existing node names or provider references to the proxy group.
The “Default Route” group can be referenced by rules and can include “Manual Selection” as a member. This structure keeps routing rules separate from specific nodes: rules can point to a stable group name, while you change the selected node on the Proxies page without editing each rule.
| Type | How it works | Configuration notes |
|---|---|---|
select | Manually choose an available route. | Candidates can be nodes or other proxy groups. |
url-test | Automatically select a route based on test results. | Set an appropriate test URL, interval, and tolerance for switching. |
fallback | Choose an available route in candidate order. | Prioritizes order and failover, not the lowest latency. |
load-balance | Distribute connections according to a specified policy. | Doesn't combine multiple nodes' bandwidth for a single download. |
The probe time shown for an automatic group reflects its connection to the test target at that moment; it doesn't represent the speed of every website. A shorter probe interval isn't always better. For example, interval: 300 means 300 seconds. Check provider limits and your needs before changing it.
Avoid circular references too—for example, group A includes group B, and group B includes group A. The hierarchy may look complete, but the core can't determine a valid final route.
6. rules: First Match Wins, from Top to Bottom
rules:
- DOMAIN,example.com,Default Route
- DOMAIN-SUFFIX,example.org,DIRECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- MATCH,Default Route
This example uses a reserved example domain to illustrate the syntax; it isn't a recommended rule for real traffic. DOMAIN matches one exact domain; DOMAIN-SUFFIX matches that domain and its subdomains; IP-CIDR matches an IP address range. The third field is the policy to apply: a group name or a built-in policy such as DIRECT or REJECT.
Keep MATCH as the Fallback Rule
MATCH catches requests that didn't match any preceding rule. If it's on the first line, later domain and IP range rules won't run. To route a domain directly, place the rule before any broader rule that would match it—not automatically at the end of the file.
no-resolve Doesn't Disable All DNS
After IP-CIDR, no-resolve means the core shouldn't resolve a domain just to check that IP rule. If the target IP is already known, it can still match by IP. This doesn't disable the DNS module or automatically restore connectivity for apps that rely on domain resolution.
When using GEOIP or other rules based on geographic data, check that the required data file is available and supported by your core. For related errors, see GeoIP troubleshooting. For rule sets, also check the rule-providers type, content format, and the name referenced by RULE-SET.
7. TUN and Client Overrides: Confirm Traffic Is Being Captured
TUN is a virtual network interface entry point, not another proxy node list. The following fields are commonly used with mihomo. Before enabling them, check the client's service permissions, system routes, and the status of any other VPNs.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
auto-route configures routes automatically, while auto-detect-interface selects an outbound interface automatically. Support varies by operating system and core version. If the virtual network interface can't be created, check the client's service mode or authorization process; randomly changing DNS addresses won't fix a permissions issue.
The dns-hijack example applies to traditional DNS traffic on port 53 that enters the captured route. It doesn't intercept all encrypted DNS. Browser DoH, routing from other VPNs, and an app's own networking implementation can all affect the actual traffic path.
The client may also override mixed-port, mode, dns, or tun settings in the file. If a value reverts after saving, check the client's “Runtime Configuration” or equivalent and compare the effective configuration with the original subscription. Avoid editing several files in succession; it makes it hard to tell which layer is overriding another.
8. Verify Changes in Order: Syntax, Loading, Traffic, and Rules
- First, check that the configuration parses. If you're using the mihomo command-line core, run the validation command below. In a GUI client, use its built-in configuration checker if available.
- Confirm the configuration reloaded successfully. Check the logs for any previous errors, and verify the listening port and current mode. Saving a file alone may not trigger a reload.
- Test the entry point with a single request. With TUN off, explicitly use the local HTTP proxy for testing. This keeps system proxy settings from complicating the same troubleshooting step.
- Check the connection details. Verify the destination domain, matched rule, proxy group, and final node. Even if the group name is correct, selecting
DIRECTwithin it still sends traffic directly. - Finally, verify the changes persist. Restart the client and update the subscription once to confirm your overrides remain. If they disappear, fix the merge method rather than repeatedly adding them by hand.
# Run this from the directory containing the configuration file; mihomo must be on your command search path
mihomo -t -f config.yaml
# Send a request through the local HTTP proxy on port 7890
curl -I --proxy http://127.0.0.1:7890 https://example.com
Run validation with the same core version as the client, and watch for relative path dependencies. A successful check only proves that the core accepts the configuration; it doesn't guarantee that nodes are reachable, subscriptions can update, or destination websites are accessible. The curl request above tests only that request's proxy route—it doesn't prove that all apps are being captured.
If you see bind: address already in use, find the process using the port, or change the listening port and the app's proxy port together. If a node connection times out, check the node address, network reachability, and service status. See connection timeout troubleshooting.
For safer changes, edit one layer at a time: start with ports and mode, then DNS, proxy groups and rules, and finally TUN. Keep each working version so you can roll back if something goes wrong. To recheck the active subscription, mode, and local ports, follow the Getting Started guide.