Clash config.yaml Explained: Ports, DNS, Proxy Groups, and Rules

Follow a complete config.yaml from top to bottom. Learn what each section does, how sections reference one another, and where configuration mistakes commonly occur.

Check the core and configuration source first

config.yaml is a configuration file read by the proxy core. The core establishes connections and routes traffic; the client provides an interface for importing and switching configurations and viewing logs. A client may merge port settings or override rules before loading, so the file you edit may not contain everything that ultimately takes effect.

This guide focuses on common mihomo fields, including those from the former Clash Meta core. Traditional Clash and mihomo share some syntax, but not every feature is interchangeable—especially TUN, DNS, and newer proxy protocols. Check the core name and version in the client's About or core information page, then consult the documentation for that version. Don't assume compatibility just because the window says Clash.

Keep three things in view as you read

  • Ingress: Ports and TUN determine how traffic enters the core.
  • Egress: proxies defines connections, while proxy-groups organizes them into selectable groups.
  • Routing: rules routes connections to a proxy group or built-in action based on conditions such as domain or IP.

The top-to-bottom order is mainly for readability. The top-level rules section doesn't need to sit next to the proxy groups it references. What matters is that names match, fields are nested correctly, and rules appear in the right order within the list.

A complete config.yaml you can inspect

Here is a mihomo configuration for reading and local testing. It has no remote proxy nodes, so all connections allowed through are sent directly; it can't be used to check whether a remote proxy works. This keeps the focus on how ports, DNS, proxy groups, and rules fit together without introducing unreachable demo servers.

# Local proxy entry points
mixed-port: 7890
allow-lan: false
bind-address: 127.0.0.1

# Runtime mode and logging
mode: rule
log-level: info
ipv6: false

# Local DNS service
dns:
  enable: true
  listen: 127.0.0.1:1053
  ipv6: false
  enhanced-mode: redir-host
  nameserver:
    - 223.5.5.5
    - 1.1.1.1

# TUN is disabled for now
tun:
  enable: false

# No remote proxy nodes
proxies: []

# The proxy group uses the built-in DIRECT action
proxy-groups:
  - name: "Proxy Selection"
    type: select
    proxies:
      - DIRECT

# Rules are checked top to bottom; the last rule is the fallback
rules:
  - DOMAIN-SUFFIX,example.com,Proxy Selection
  - 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,Proxy Selection

example.com is a reserved example domain used here to demonstrate a domain rule. The two DNS servers are specific public resolvers and may not be reachable on every network. Before loading the configuration, make sure no other application is using local ports 7890 or 1053.

Read YAML indentation before looking at the fields

YAML indentation shows which fields belong to which section. This example consistently uses two spaces; avoid tabs. dns: starts at the top level, while enable: is indented one level to show that it belongs to the DNS configuration. A - introduces a list item; [] denotes an empty list.

  • Leave a space after the colon, as in mode: rule.
  • Use consistent indentation for fields at the same level. Don't indent top-level rules: under a proxy group.
  • Quote strings containing special characters such as # so the rest of the line isn't treated as a comment.
  • Don't define dns or rules more than once at the same level. Some parsers reject duplicate keys; others keep only one of them.

Ports and mode: connect apps to the right entry point

mixed-port: 7890 accepts both HTTP proxy and SOCKS5 connections on the same port. To configure an app to use the proxy manually, enter 127.0.0.1 as the address and 7890 as the port, then choose the protocol supported by the app. These are example values, not fixed defaults for every client.

FieldPurposeWhat it means here
mixed-portShared HTTP and SOCKS entry pointLocal port 7890
portSeparate HTTP proxy entry pointNot set in this example
socks-portSeparate SOCKS proxy entry pointNot set in this example
allow-lanAllow devices on the local network to connectfalse; local connections only
modeChoose how traffic is routedrule: route traffic according to rules

mode: rule enables the rule-based mode covered here. Global mode generally sends traffic through the global policy, while direct mode connects without using a proxy. In either mode, changing regular rules won't have the expected effect. If the client overrides the mode, the actual runtime state is what matters.

log-level: info is suitable for routine monitoring. To investigate an issue, temporarily switch to debug, reproduce it, then switch back. Detailed logs may contain visited domain names, so remove sensitive information before sharing them.

DNS and TUN: treat name resolution and traffic capture separately

DNS resolves domain names to IP addresses. This example enables the core's DNS service and listens on 127.0.0.1:1053; that doesn't automatically send every DNS request from the operating system to this service. The actual path depends on system settings, client integration, and whether TUN is capturing traffic.

nameserver and DNS modes

nameserver is the list of upstream servers used for DNS resolution. The plain IP addresses in this example use regular DNS without encryption. For DoH (DNS over HTTPS), configure a server address using syntax supported by your core version, and check its connection route and bootstrap DNS requirements.

enhanced-mode: redir-host returns real addresses in DNS responses. Another common mode, fake-ip, returns virtual addresses mapped by the core back to domain names. These aren't speed settings. After switching modes, old DNS cache entries and existing connections may affect what you observe; clear the cache and restart affected apps if needed.

TUN isn't another proxy node

TUN is a virtual network interface that receives traffic routed to it by the operating system. The example only sets tun.enable: false, so this traffic-capture path is disabled. Enabling the system proxy doesn't enable TUN: the system proxy mainly affects apps that follow the OS proxy settings, while TUN can capture more traffic when routing and permissions are configured correctly.

  • First test an app's manual proxy setting with 127.0.0.1:7890, then test the system proxy, and only consider TUN after that.
  • If you need TUN, follow your client's and operating system's requirements for administrator privileges, virtual interfaces, and routing.
  • dns-hijack captures matching DNS traffic, but it doesn't work for every type of encrypted DNS. An app's built-in DoH may use a separate connection.
  • IPv6 is disabled in this example to narrow down troubleshooting; that doesn't make it a suitable permanent setting for every network.

proxies and proxy groups: trace the route by name

proxies is the list of individual proxy connections. A real node typically includes a name, protocol type, server, port, and authentication parameters. Each protocol may require additional fields. Server addresses and passwords must come from the actual service configuration; don't combine fields from different protocols to create a node.

The proxies: [] entry explicitly means there are no remote nodes in this example. DIRECT is a built-in action for connecting directly and doesn't need to be declared in the node list. Similarly, REJECT is a built-in action that rejects connections.

select lets you choose; it doesn't test latency

proxy-groups organizes one or more egress options into groups. The example's type: select means you choose manually, and the group is named “Proxy Selection.” When you add real nodes, include their exact names in the group's proxies list to make them available for selection.

“Proxy Selection” in rules
        ↓ Names must match
The group whose name is “Proxy Selection” under proxy-groups
        ↓ Currently selected option
DIRECT, meaning connect to the destination directly

url-test is the proxy group type that selects an egress based on test results; it needs a suitable test URL and interval. A latency test measures the response to one specific destination, not download bandwidth, and doesn't guarantee that every site will load.

Subscriptions may also include proxy-providers, which loads a collection of nodes from a file or remote source. Proxy groups usually reference a provider by name using use, rather than adding the provider name as if it were a single node in proxies. For this type of configuration, also check the source, update path, and health check settings.

rules: read from the first entry through MATCH

Rules are generally checked in list order, and the first match determines where a connection goes. Put specific conditions first, broader ones later, and the fallback last. If MATCH is the first rule, the remaining rules won't get a chance to handle new connections.

Rule snippetMatchesAction
DOMAIN-SUFFIX,example.comexample.com and its subdomainsProxy Selection
IP-CIDR,127.0.0.0/8IPv4 loopback rangeDIRECT
IP-CIDR,10.0.0.0/8Private IP ranges starting with 10DIRECT
IP-CIDR,172.16.0.0/12Private IP range 172.16–172.31DIRECT
IP-CIDR,192.168.0.0/16Private IP ranges starting with 192.168DIRECT
MATCHConnections not matched by an earlier ruleProxy Selection

Keep domain rules and IP rules distinct

DOMAIN matches an exact domain; DOMAIN-SUFFIX matches a domain and its subdomains. Enter a domain in the rule, not a full URL. For example, https://example.com/path includes a protocol and path, so it can't be used directly as a domain condition.

In IP-CIDR, CIDR notation describes an IP range using a prefix length. The trailing no-resolve means the core shouldn't initiate a domain lookup to check this IP rule; it can still match if the connection metadata already includes a destination IP. It does not disable DNS altogether.

This example lists only some common local subnets, not a complete set of rules for special addresses. If you can't reach a printer, router, or corporate intranet, check the actual destination address and rule match logs. Don't assume every private network uses only 192.168.0.0/16.

For RULE-SET, follow the reference to its rule provider

RULE-SET refers to a rule collection defined under rule-providers, not a collection of proxy nodes. Check the provider name, source, format, and behavior type. A successful download only confirms that the content was retrieved; it doesn't mean the content format is suitable for the current configuration.

Check and verify the configuration before use

Passing a syntax check doesn't mean the network is working as expected. Break validation into four steps: the config loads, the core listens, rules match, and connections succeed. Change one thing at a time so it's easier to return to the last working state if something goes wrong.

  1. Check the file. Save a test copy as UTF-8 config.yaml and make sure its extension hasn't become .yaml.txt. Check indentation, duplicate keys, and proxy group names.
  2. Validate the core configuration. Use your client's built-in check, or run the test command below in an environment with the mihomo command-line program installed. In the current Windows directory, the executable is usually written as .\mihomo.exe.
  3. Load the configuration and check the logs. Look for syntax errors, missing proxy groups, or port-in-use warnings. If the client rewrites the configuration, inspect the configuration it actually generates as well.
  4. Send a request through a specific entry point. Specify the proxy port explicitly first to rule out interference from system proxy settings or browser configuration.
  5. Check the connection records. Confirm the matched rule, proxy group, and final egress for the test connection, then re-enable your original DNS or TUN settings one at a time.
# Validate the configuration; this command does not start a long-running proxy service
mihomo -t -f ./config.yaml

# After the configuration loads and the core is running, test the local HTTP proxy entry point
curl --proxy http://127.0.0.1:7890 --head https://example.com

The second command tests the route from the local proxy entry point to the example site. Because this example ultimately uses DIRECT, a successful request doesn't prove that a remote proxy node works. On Windows, if the terminal treats curl as a different command, run the installed curl.exe explicitly.

Use the same reading order for future maintenance: entry point settings, runtime mode, DNS, traffic capture, nodes, proxy groups, and rules. For detailed field descriptions, see this site's YAML manual. For the steps to import and enable a configuration, see the user guide. Keeping a verified configuration is easier than rewriting one from scratch every time something goes wrong.

Download Clash