Clash Config File Structure Explained: port, proxies, rules Fields
Got a config.yaml but afraid to touch it? This article walks through general fields, the proxy list, proxy groups and the rules section in load order, with syntax and common patterns, before you edit.
Load order and overall structure of a config file
Both Clash and Clash Meta (core codename mihomo) read a plain-text YAML file, usually named config.yaml. When the client starts or switches a subscription, it parses the whole file into memory at once and applies each section by name — there is no strict "reads and applies as it goes" dependency. Still, it helps to read and troubleshoot sections in this order:
- General fields: port, run mode, log level, external controller, and so on — these decide how the client itself runs.
- The
dnssection: domain resolution behavior, which affects whether later rules match on a domain name or a resolved IP. - The
proxiessection: the node list — each entry describes one available proxy server. - The
proxy-groupssection: organizes the node list into proxy groups, deciding how "which node to use" is presented to the user. - The
rulessection: traffic-matching rules that decide which proxy group a given connection goes through.
Configs delivered via a subscription link use the same set of fields — they're just generated on the subscription provider's backend. Back up the original file before editing manually; a mistyped field can range from the client refusing to load, to rules silently failing so all traffic goes direct or all through the same node.
YAML is extremely sensitive to indentation. Use two spaces consistently, never mix in tabs, always leave a space after a colon, and start list items with a dash and a space. Ignoring these is the number one reason beginners break a config file.
General fields: port, mode, log-level, and external control
The top of the file usually holds a batch of unindented top-level fields that control how the client itself runs:
port: 7890
socks-port: 7891
redir-port: 7892
mixed-port: 7890
allow-lan: false
mode: rule
log-level: info
external-controller: 127.0.0.1:9090
secret: ""
port/socks-port: open an HTTP proxy port and a SOCKS5 proxy port respectively; the OS or browser picks whichever one it needs.mixed-port: a single port that accepts both HTTP and SOCKS5 requests. Most current client UIs default to exposing only this one port, simplifying system proxy setup.allow-lan: whether other devices on the local network can use this machine's proxy — turn this on when sharing the connection with a phone over LAN.mode: the core operating mode.ruleroutes traffic based on therulessection,globalsends all traffic through a single proxy group, anddirectsends everything straight out with no proxy.log-level: how verbose logging is. Switch todebugtemporarily when troubleshooting; for everyday use,infoorwarningkeeps log files from growing too fast.external-controller: the listening address for the RESTful API. Paired with thesecretkey, this is what the client's GUI and third-party dashboards rely on to read status and switch nodes.
Most of these fields have defaults, and GUI toggles usually override whatever is written in the YAML. But configs generated from a subscription link still follow the YAML fields — when in doubt, trust what the client actually loads.
The proxies section: how each node is described
proxies is a list; each item is one available node. Fields vary by protocol type, but the common ones stay the same:
proxies:
- name: "HK-01"
type: ss
server: 1.2.3.4
port: 8443
cipher: aes-256-gcm
password: "your-password"
udp: true
- name: "SG-Trojan"
type: trojan
server: example.com
port: 443
password: "your-password"
sni: example.com
skip-cert-verify: false
Common shared fields:
name: the node's display name — proxy groups reference nodes by this name, so duplicates cause ambiguity; keep names unique.type: the protocol type, commonlyss(Shadowsocks),ssr,vmess,trojan,hysteria2, etc. Each protocol requires its own set of extra fields.server/port: the node's server address and port — this directly determines the connection target.udp: whether the node forwards UDP traffic. Games and some real-time apps rely on UDP; if it's off, that traffic fails or is forced to go direct.skip-cert-verify: whether to skip TLS certificate verification. Only needed for self-signed certificate setups — leave it off for normal nodes for better security.
The most common mistake when writing nodes by hand is a password containing a colon or special character without being wrapped in quotes — the YAML parser will treat the colon as a new key-value separator. It's safer to always wrap passwords in double quotes.
The proxy-groups section: syntax and common types
proxy-groups organizes the nodes in proxies into groups that rules can reference. Common types look like this:
proxy-groups:
- name: "Auto"
type: url-test
proxies:
- HK-01
- SG-Trojan
url: "http://www.gstatic.com/generate_204"
interval: 300
- name: "Manual"
type: select
proxies:
- Auto
- HK-01
- SG-Trojan
- DIRECT
- name: "Fallback"
type: fallback
proxies:
- HK-01
- SG-Trojan
url: "http://www.gstatic.com/generate_204"
interval: 300
select: a manual switch group — shown as a dropdown in the UI, letting the user pick whichever node they want. Good as an outer fallback layer.url-test: an auto speed-test group that probes every node in the group everyintervalseconds and automatically picks the one with the lowest latency.fallback: tries nodes in list order; the first one that connects successfully is used, and it only moves to the next when the current one fails.load-balance: spreads connections across multiple nodes according to a strategy — useful when you have many nodes with similar performance.
Besides node names, a proxy group's proxies list can also contain the name of another proxy group, or the two built-in policies DIRECT and REJECT, meaning "connect directly" and "reject the connection" respectively. Groups can reference each other, but circular references aren't allowed — the client will throw an error on load if one exists.
The rules section: matching syntax and priority
rules is a list matched top to bottom. The first rule that matches wins immediately, with no further comparison down the list — so the order of rules is itself the priority:
rules:
- DOMAIN-SUFFIX,openai.com,Auto
- DOMAIN-KEYWORD,google,Auto
- DOMAIN,ads.example.com,REJECT
- IP-CIDR,192.168.0.0/16,DIRECT,no-resolve
- GEOIP,CN,DIRECT
- MATCH,Auto
Common rule types:
DOMAIN/DOMAIN-SUFFIX/DOMAIN-KEYWORD: match on a full domain, a domain suffix, or a keyword. Suffix matching is the most common, since it covers subdomains too.IP-CIDR/IP-CIDR6: match on an IP range, often paired withno-resolveto skip DNS lookups and judge directly against the connection target's literal IP.GEOIP: match on the country/region the IP belongs to —GEOIP,CN,DIRECTis the common pattern for routing mainland China traffic direct.PROCESS-NAME: match on the name of the process making the connection, commonly used on desktop for per-app splitting.MATCH: the catch-all rule placed last — any traffic that matched nothing above falls through to this one. Nearly every config file needs a closingMATCHline, otherwise unmatched traffic behaves unpredictably.
Any proxy group name referenced in a rule must exactly match the name in proxy-groups — case and spacing included — otherwise the client typically throws a "reference to an undefined policy" style error and refuses to load the whole config.
DNS resolution behavior affects whether IP-based rules even work: with fake-ip mode enabled, the connection target seen during rule matching is a virtual IP, which means IP-CIDR rules can misbehave. Usually you'd switch DNS mode to real resolution for specific domains — see our dedicated DNS article on this site for the detailed logic.
Common mistakes and how to troubleshoot
If the client doesn't apply your edits or throws an outright error, check these in order:
- Run the file through any online YAML validator or check indentation and colon spacing with a text editor's syntax highlighting — most "failed to load" errors are formatting issues, not logic issues.
- Confirm the node names referenced in
proxy-groupsexactly match thenamevalues inproxies— copy-paste often introduces stray spaces or full-width characters. - Confirm the proxy group names referenced in
rulesactually exist inproxy-groups— typoing a group name when adding a new rule is a frequent slip. - Temporarily switch
log-leveltodebugand restart the client to watch the log output — connection failures usually point to which section of the config is at fault. - If you suspect the subscription provider's generated config itself is at fault, check the raw subscription content inside the client and cross-check it field by field, rather than assuming the client is broken.
Once you understand these five sections and the load order, tackling a complex config from a subscription provider — or adding a custom routing rule by hand — usually just means editing the matching section's syntax, without rewriting the whole file.