Check the core first, then follow the references
A configuration has three core layers: proxy nodes provide outbound routes, policy groups organize those routes, and rules decide which route handles each connection. proxies is not a rule list, and proxy-groups does not automatically send every connection through a proxy. A configured choice takes effect only when the client captures a connection and it matches a rule.
Clash is a common name for this configuration ecosystem, but supported fields vary between cores. The complete example in this guide targets mihomo, formerly the Clash.Meta core; inline rule sets and other syntax shown here should not be assumed to work with every older Clash core. Check the core name in the client's About or core information page, then consult the documentation for that core.
proxies: Stores each node's protocol, server, port, and authentication parameters.proxy-groups: Organizes outbound routes into selectable policies using node or group names.rule-providers: Defines reusable rule sets sourced from files, HTTP, or inline lists.rules: Matches connections in order and assigns them toDIRECT,REJECT, or a policy group.
A loadable config.yaml example
Below is a complete mihomo demo configuration. It contains no remote proxy nodes and defaults to DIRECT. Use it to see how configuration loading, policy-group selection, and rule matching work; it cannot provide a proxy connection on its own. Once the structure loads, add real nodes supplied by your service provider.
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
ipv6: false
dns:
enable: true
listen: 127.0.0.1:1053
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- 223.5.5.5
- 1.1.1.1
proxies: []
proxy-groups:
- name: "Manual Select"
type: select
proxies:
- DIRECT
- REJECT
rule-providers:
local-demo:
type: inline
behavior: classical
payload:
- DOMAIN-SUFFIX,example.org
rules:
- DOMAIN,example.com,DIRECT
- RULE-SET,local-demo,DIRECT
- IP-CIDR,127.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
- IP-CIDR,172.16.0.0/12,DIRECT,no-resolve
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- MATCH,Manual Select
Reading order is not execution order
The top-level fields are arranged as “general settings → DNS → nodes → policy groups → rule sets → rules” for readability; they don't have to be written in this order. What directly affects the result is the order of entries in rules and the policy group's initial selection. Referenced names must match exactly, including spaces, letter case, and Chinese characters.
YAML uses spaces for indentation; don't mix in tabs. This guide uses two spaces at each level, with list items starting with a hyphen and a space. Put names or passwords containing special characters in quotes. Passwords that consist only of digits should also be quoted as strings to prevent their type from changing during parsing.
General settings: ports, mode, and traffic capture
| Field | Example value | What it does |
|---|---|---|
mixed-port | 7890 | Accepts HTTP and SOCKS proxy connections on the same listening port. |
allow-lan | false | Keeps the service unavailable to LAN devices; a suitable starting point for local testing. |
mode | rule | Routes traffic according to rules; global mode does not assign routes using these rules one by one. |
log-level | info | Records routine runtime information; switch to debug briefly when troubleshooting. |
ipv6 | false | Disables IPv6 support in this core; it does not disable IPv6 across the operating system. |
mixed-port: 7890 only means the core is ready to provide a proxy service on that port. It does not mean the system or every app is using it. Some apps follow the system proxy settings; others ignore them. TUN captures more traffic through a virtual network interface, but whether it works depends on system permissions, routing, and the client implementation.
This guide does not enable TUN. To test the entry point, set an application's HTTP proxy to 127.0.0.1:7890. If another program is using the port, the log will usually show address already in use. Close the conflicting program or update both the configuration and the app's proxy port—for example, change both to 7891.
dns: how resolution and rule matching work together
The dns section manages domain name resolution in the core. This example enables fake-ip and uses 198.18.0.1/16 as a virtual address pool. These addresses map to domain names; they are not the real addresses of website servers. The core can retain the mappings and restore domain names for later connections, helping domain rules match.
1053 is the listening port, not an upstream DNS address
listen: 127.0.0.1:1053 specifies the local DNS service endpoint. The two IPs under nameserver are the upstream resolvers. This example uses ordinary DNS to make the structure easy to inspect. Choose upstream servers based on network reachability and privacy needs; no single public DNS provider is right for every network.
- Enabling only
dns.enabledoes not automatically send every system DNS request to the core. - System DNS settings usually cannot accept an address with a custom port, such as
127.0.0.1:1053; traffic capture requires the client or a local forwarder. - DNS hijacking in TUN is a separate configuration layer. Don't copy TUN parameters for another operating system just to make DNS work.
- Encrypted DNS built into an app can change the resolution path. If domain rules don't match, also check the browser's Secure DNS settings and the actual connection records.
This example does not include fake-ip-filter. If a LAN service or app doesn't work well with virtual addresses, use the logs to identify the specific domain, add it to the filter list, and test again with a new connection. Avoid broad wildcards that could change resolution for many connections.
proxies: node parameters must match the server
proxies: [] means the node list is empty. To add a node, replace it with a list. The example below shows only the field structure for Shadowsocks: 192.0.2.10 is a documentation example address, and the password is sample text. Neither can be used for a real connection. Get actual parameters from your subscription or service provider; don't just replace the server address while leaving the other fields unchanged.
proxies:
- name: "SS-Example"
type: ss
server: 192.0.2.10
port: 8388
cipher: aes-128-gcm
password: "demo-only-not-a-real-password"
udp: true
name is the identifier referenced by policy groups; server and port point to the remote service; cipher and password must match the server. The 8388 value here is the remote port, not the local 7890 port.
udp: true allows the node to use the relevant UDP capabilities, but does not guarantee that the entire route supports UDP. The server, protocol, traffic capture method, and destination network can all affect the outcome. Other protocols have their own fields; don't put VMess, VLESS, or Trojan parameters under type: ss.
Use unique node names
Choose short, stable names that are easy to identify, such as a region and purpose, and keep them unique. If a subscription update changes a node name, an old name in a hand-written policy group may no longer work. For larger node lists, consider using proxy-providers to manage node sources. It manages nodes, unlike rule-providers, which manages matching conditions.
proxy-groups: organize nodes into policies for rules
After adding real nodes to proxies, add them to a policy group. The group below references the node by name from the previous section. The selected entry can connect only after you replace the example with valid node parameters.
proxy-groups:
- name: "Manual Select"
type: select
proxies:
- "SS-Example"
- DIRECT
select is a manual selection group. Clients generally display it on the Proxy or policy group page; select an entry to choose an outbound route. On first load, with no saved selection, the first item is usually used. If selection persistence is enabled, the previous choice may be restored on reload instead.
| Group type | Selection method | Notes |
|---|---|---|
select | User manually selects a member | Useful for testing nodes before choosing a route to keep using. |
url-test | Probe results for a test URL | Test latency does not represent download speeds on every website. |
fallback | Selects an available member in list order | Better for primary/backup switching; it does not always choose the lowest latency. |
load-balance | Distributes connections according to the configured strategy | It does not simply add together the bandwidth of a single download connection. |
A policy group can reference another policy group, but the references must not form a loop. For example, “Daily Route” can reference “Manual Select,” but the two groups should not reference each other. If you see an error such as proxy not found, first check that the name matches and that the referenced item exists.
rule-providers and rules: rule sets and matching order
local-demo in the complete example is an inline rule set. behavior: classical means its entries use rule types. It contains DOMAIN-SUFFIX,example.org, which matches both example.org and its subdomains. The rule set stores matching conditions; the RULE-SET,local-demo,DIRECT entry in rules specifies the outbound route.
Don't mix the three rule-set behaviors
classical: Entries include a rule type, such asDOMAIN-SUFFIX,example.org.domain: Entries are domains or supported domain-matching expressions; don't use the full classical format.ipcidr: Entries are IP ranges, such as192.168.0.0/16.
If you switch to type: http, you also need a reachable url, plus fields such as the cache path and update interval required by the format you use. For example, interval: 86400 means 86,400 seconds, or 24 hours. Remote content must match the declared behavior and format; a successful download does not guarantee that the content can be parsed.
rules run from top to bottom and stop at the first match
The first example rule matches example.com exactly and sends it direct. The second applies a rule set, followed by several local IP ranges, with MATCH,Manual Select as the fallback. MATCH catches all remaining connections, so put it last. If it appears first, the rules below it will never get a chance to match.
rules:
- DOMAIN,example.com,DIRECT
- DOMAIN-SUFFIX,example.org,Manual Select
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- MATCH,Manual Select
DOMAIN matches an exact domain; DOMAIN-SUFFIX matches a suffix. Don't use them interchangeably. For IP rules, no-resolve means not to actively resolve a domain just to evaluate that rule. If the connection already has a destination IP, it can still be matched against the rule. It does not disable DNS entirely or add a separate switch to force direct connections to that range.
Also note that adding GEOIP or GEOSITE to your rules introduces a dependency on the relevant geolocation data. This minimal example deliberately omits both types to avoid failures on the first load due to missing or outdated data files.
Save, validate, and load: troubleshoot in three steps
Step 1: Check syntax and references with the core
If you have installed mihomo separately, run the following command from the configuration directory. In Windows PowerShell, programs in the current directory are usually written as .\mihomo.exe; use the actual executable name on your system.
mihomo -t -f ./config.yaml
# Windows PowerShell
.\mihomo.exe -t -f .\config.yaml
A successful check means only that the current core accepts the configuration. It does not mean the node is online, the password is correct, or DNS is reachable. If the command succeeds but the client fails, check whether they use the same core and file, and whether the client applies additional settings.
Step 2: Confirm the active values after loading
- Import the local YAML file from the client's Configuration page and select it. If the interface has an Edit option, save your changes and reload the configuration afterward.
- Find the Manual Select group on the Proxy page and confirm that its members are present. If you haven't added real nodes, keep
DIRECTselected. - Set the running mode to Rule and confirm that the active mixed port is
7890. Menu names vary between clients. - Test with a request that explicitly uses the proxy entry point, then check the Connections and Logs pages rather than relying only on whether a browser can open a webpage.
curl -I --proxy http://127.0.0.1:7890 https://example.com
# Windows: use curl.exe to avoid command alias differences
curl.exe -I --proxy http://127.0.0.1:7890 https://example.com
According to the example, this request should match DOMAIN,example.com,DIRECT. Receiving an HTTP response also depends on your local network. To check whether the rule worked, focus on the rule and final route in the connection details. This command tests the HTTP proxy entry point, not TUN or system DNS capture.
Step 3: Check the relevant area for each error; change one thing at a time
| Symptom | Check first | Next step |
|---|---|---|
| YAML parsing failed | Indentation, tabs, colons, and quotes | Review the reported line and the line above it, then run the configuration check again. |
| Node or policy not found | Whether group and node names match exactly | Copy the name from its definition instead of retyping it. |
| Listening port failed | Whether port 7890 or 1053 is in use | Close the conflicting program or update both sides of the configuration. |
| Rule did not match | Whether Rule mode is enabled and the connection passes through the core | Check earlier rules, close the existing connection, and try again. |
| Rule is correct but connection times out | Selected node, authentication parameters, and destination network | Test one node at a time to distinguish rule issues from connection issues. |