1. Home
  2. Blog
  3. Clash Config File Explained: YAML Fields from port to rules, Section by Section

Clash Config File Explained: YAML Fields from port to rules, Section by Section

A section-by-section breakdown of the Clash config YAML structure: mixed ports, proxy groups, rules, and DNS fields explained with examples so you understand what every line does.

The config file at its core: a YAML document

Every behavior of the Clash and mihomo (Clash Meta) core is driven by a single YAML config file. The file your subscription link downloads is essentially a YAML document your provider has already written; the mode switches and node selections in your client's UI ultimately just edit fields in that same file. Once you understand the structure, changing ports, adding rules, or tweaking DNS is just a matter of finding the right section and editing a few lines.

YAML syntax boils down to three rules: use spaces only for indentation, never tabs, and indent by two spaces per level; keys and values are separated by a colon, and there must be a space after the colon; lines starting with a dash are list items, and anything after a # is a comment. A full config is built from several top-level fields, listed below along with what they do.

Top-level fieldPurpose
mixed-portMixed proxy port shared by HTTP and SOCKS5 requests
allow-lanWhether other devices on the LAN can connect
modeWorking mode: rule-based / global / direct
log-levelVerbosity of log output
external-controllerAddress the core's API listens on, used by web dashboards
dnsBuilt-in DNS resolution settings
proxiesList of proxy nodes
proxy-groupsProxy groups, the items you switch between in the client UI
rulesRouting rules, matched top to bottom
tunTUN virtual network adapter mode (mihomo only)

Of these, proxies, proxy-groups, and rules together decide how traffic is routed, and they're the focus of this article; dns decides how domains resolve; the remaining fields control ports and runtime behavior. Let's go through each section.

Ports and global fields: mixed-port through external-controller

mixed-port: 7890
allow-lan: false
bind-address: "*"
mode: rule
log-level: info
external-controller: 127.0.0.1:9090

mixed-port is the mixed port: both HTTP and SOCKS5 requests enter the core through it, and most clients and subscriptions default to 7890. Older configs that split this into port (HTTP only) and socks-port still work, but a new config only needs mixed-port.

  • allow-lan: when set to true, other phones or tablets on the same LAN can use this machine as a proxy gateway; bind-address controls which network interface it listens on. Keep this false on public networks.
  • mode: rule routes traffic per the rules section; global sends everything through the selected proxy group; direct sends everything straight through with no proxy. The mode switch in the client UI just changes this value.
  • log-level: info is fine for everyday use; switch to debug temporarily when troubleshooting connections; silent suppresses all output.
  • external-controller: the address the core's RESTful API listens on, used by web dashboards like metacubexd and yacd to read status and switch nodes; add a secret line to set an access key so the port can't be controlled by anyone who finds it exposed.

mihomo configs also commonly include extension fields like unified-delay, tcp-concurrent, and find-process-mode, which are exclusive to the Meta core; vanilla Clash will error out on keys it doesn't recognize, so be careful when switching between cores.

The dns section: how domains get resolved

dns:
  enable: true
  listen: 0.0.0.0:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
    - 119.29.29.29
  fallback:
    - tls://1.1.1.1
    - https://dns.google/dns-query
  fake-ip-filter:
    - "*.lan"
    - "*.local"

enable is the master switch and must be on when using TUN mode; listen is the address the built-in DNS service listens on — the system sends domain lookups here, and the core forwards them upstream per your config.

  • enhanced-mode: in fake-ip mode the core returns a fake IP first, then routes by domain once the connection is established, which is fast and accurate; redir-host is the legacy mode that's being phased out in newer cores, so stick with fake-ip.
  • fake-ip-range: the fake IP address pool, defaulting to 198.18.0.1/16; you generally don't need to change this.
  • nameserver: the default upstream resolver, supporting three formats — a plain IP uses UDP, a tls:// prefix uses DoT, and an https:// prefix uses DoH.
  • fallback: the upstream used for resolving overseas domains, a legacy approach; mihomo instead recommends nameserver-policy, which lets you assign different upstreams by domain suffix group.
  • fake-ip-filter: domains on this list never get a fake IP — commonly used for LAN hostnames and certain QR-code login domains.

When this actually applies

The dns section only matters when the core is handling your traffic. In plain system-proxy mode, the browser resolves domains itself and this section is bypassed; in TUN mode, every lookup passes through the core, so this section fully takes effect.

The proxies section: each dash is one node

proxies:
  - name: "Hong Kong 01"
    type: ss
    server: hk1.example.com
    port: 8388
    cipher: aes-128-gcm
    password: "example-password"
    udp: true
  - name: "Japan 01"
    type: vmess
    server: jp1.example.com
    port: 443
    uuid: 00000000-0000-0000-0000-000000000000
    alterId: 0
    cipher: auto
    tls: true
    network: ws

proxies is the node list, where each dash-prefixed entry is one node. name is the display name, type is the protocol, and server plus port give the server address; the remaining fields depend on the protocol: ss needs cipher and password; vmess needs uuid, alterId, and cipher; vless needs uuid; trojan needs password and sni; hysteria2 needs password. udp: true allows UDP traffic to be forwarded.

mihomo supports more protocols than vanilla Clash: the original supports ss, ssr, vmess, trojan, snell, and a few others, while the Meta core adds vless, hysteria, hysteria2, tuic, and more. This section is almost always auto-generated by your subscription, so before editing it by hand, keep one thing in mind: any manual changes get overwritten the next time the subscription updates.

The proxy-groups section: what you actually switch in the UI

proxy-groups:
  - name: "Auto Select"
    type: url-test
    proxies:
      - "Hong Kong 01"
      - "Japan 01"
    url: "http://www.gstatic.com/generate_204"
    interval: 300
    tolerance: 50
  - name: "Manual Select"
    type: select
    proxies:
      - "Auto Select"
      - "Hong Kong 01"
      - "Japan 01"
      - DIRECT

What you click in the client UI is never a single node — it's a proxy group. type comes in four flavors: select for manual choice; url-test to auto-pick the fastest by latency; fallback to switch through nodes in order based on availability; load-balance to spread connections across multiple nodes.

  • url: the target address used for latency testing, commonly http://www.gstatic.com/generate_204.
  • interval: the auto speed-test interval in seconds; 300 means testing every five minutes.
  • tolerance: the tolerance margin in milliseconds — a newly tested node has to be faster than the current one by more than this amount before the group switches, which prevents flip-flopping.

A group's proxies list can contain either node names or other group names, letting you nest them like "Manual Select → Auto Select → several nodes"; you can also include the built-in DIRECT and REJECT policies. Rules reference group names, so as nodes get swapped out by subscription updates, the group structure stays the same.

The rules section: top to bottom, first match wins

rules:
  - DOMAIN-SUFFIX,ads.example.com,REJECT
  - DOMAIN-KEYWORD,bilibili,DIRECT
  - GEOSITE,cn,DIRECT
  - IP-CIDR,10.0.0.0/8,DIRECT,no-resolve
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,Manual Select

Rules are matched top to bottom, and matching stops at the first hit — so order is priority. The MATCH rule at the very end is the catch-all, picking up any traffic that didn't match an earlier rule. Each rule has three parts: type, match value, and target policy. The target policy can be a proxy group name, a node name, or the built-in DIRECT or REJECT.

Rule typeMatches againstExample
DOMAINExact domainDOMAIN,www.example.com,PROXY
DOMAIN-SUFFIXDomain suffixDOMAIN-SUFFIX,google.com,PROXY
DOMAIN-KEYWORDDomain keywordDOMAIN-KEYWORD,bilibili,DIRECT
GEOSITEDomain category database (mihomo only)GEOSITE,cn,DIRECT
IP-CIDRDestination IP rangeIP-CIDR,10.0.0.0/8,DIRECT,no-resolve
GEOIPIP geolocationGEOIP,CN,DIRECT
DST-PORTDestination portDST-PORT,443,PROXY
PROCESS-NAMEProcess namePROCESS-NAME,telegram.exe,PROXY
MATCHCatch-all, matches everythingMATCH,PROXY

Two things trip people up. First, IP-based rules like IP-CIDR and GEOIP trigger a DNS lookup when matched against a domain request; adding the no-resolve parameter avoids resolving early and leaves the decision to later domain-based rules. Second, GEOSITE is only supported by mihomo and depends on the geosite data file — vanilla Clash will error out if it encounters one; GEOIP is supported by both cores, though the data file format differs between them.

How changes take effect, and common errors

On a desktop client, just hit reload on the config page after editing — mihomo supports hot reload, so there's no need to restart the app; a command-line mihomo instance can push a new config through the API to update.

Where YAML errors usually come from

Tabs mixed into the indentation; a full-width colon typed by mistake; a missing space after a colon; a list item indented differently from the one above it; a node name containing a colon or special character without quotes around it. When the client fails to start and shows "yaml: line xx", go back and check these exact things at that line — that's where almost every issue lives.

Two other common issues: first, port conflicts — if something else is already using 7890, the core fails to start, so change mixed-port or close the conflicting process; second, edited rules that don't seem to take effect, usually because a broader rule earlier in the list is matching first — set log-level to debug, and the rule-matching entries in the log will show exactly which rule each connection actually hit.

The config file structure really only has these pieces: the port fields define the entry point, dns handles resolution, proxies is the node list, proxy-groups are the switches you toggle, and rules is the dispatch table. Read through your own subscription config in that order and every line will make sense.

Download Clash Client

Clients and cores for every platform, organized by OS with version numbers listed.

Download Clash