共计 13560 个字符,预计需要花费 34 分钟才能阅读完成。
2023 年 11 月,Clash 核心及其衍生项目的 GitHub 仓库突然被删除,这在圈子里引起了不小的震动。虽然“删库”事件让很多人感到惋惜,但也侧面证明了这个工具的影响力。好在,Clash 的生态并没有因此消亡,各种分支版本(如 Clash Meta)依然活跃。
这件事让我更加确信一个观点:工具可能会消失,但掌握工具背后的配置逻辑是永不过时的。
最近我在整理自己的网络环境时,发现单纯依赖订阅链接生成的配置文件有时候并不能完全满足我的需求。比如,我希望某些特定的国内服务直连,或者某些流媒体服务走指定的节点,而默认的规则往往一刀切。
这让我重新翻开了 Clash 的(归档)官方文档,尤其是那份详尽的配置指南。虽然现在有很多图形化工具帮我们托管了配置,但我始终觉得,只有真正理解了底层的 config.yaml,才能算是真正掌控了自己的网络入口。今天就想和大家聊聊 Clash 的配置逻辑,希望能帮你理清那些看似复杂的 YAML 语法。
为什么要手写或修改配置
对于大多数朋友来说,拿到一个订阅链接,导入软件,开启系统代理,一切似乎就结束了。但这只是 Clash 强大功能的冰山一角。
Clash 本质上是一个基于规则的跨平台代理核心(Core)。无论是 Windows 上的 Clash for Windows,还是 macOS 上的 ClashX,或者是 Android 上的客户端,它们背后运行的都是这个核心。而指挥这个核心如何工作的,就是 config.yaml 文件。
理解这个文件,意味着你可以:
- 精准分流:让该走代理的走代理,该直连的直连,互不干扰。
- 自动择优:让 Clash 自动帮你选择延迟最低的节点。
- 局域网共享:让家里的 Switch、PS5 或者手机通过电脑的网络畅游。
- 隐私保护:通过 DNS 设置防止 DNS 泄露。
配置文件结构全解
打开一个标准的 config.yaml,你会发现它其实非常有条理。我们可以把它想象成一个公司的组织架构:通用设置是公司的行政规定,代理节点是干活的员工,策略组是部门经理,而规则就是分发任务的调度中心。
基础设置 General
文件的最开头通常是一些全局的设置。这里有几个参数是我觉得特别关键的:
port: 7890
socks-port: 7891
# 透明代理,仅支持 Linux 和 macOS
redir-port: 7892
# 透明代理 Linux
tproxy-port: 7893
# HTTP(S) and SOCKS5 server on the same port
mixed-port: 7890
allow-lan: true
mode: rule
log-level: info
external-controller: '0.0.0.0:9090'
- port & socks-port: 这是 Clash 监听的 HTTP 和 SOCKS5 端口。默认通常是 7890 和 7891。如果你在使用其他软件配置代理时,填的就是这两个。
- allow-lan: 这个选项我非常喜欢。设置为
true后,Clash 就会允许局域网内的其他设备连接你的代理端口。这在给不支持代理设置的设备(比如某些游戏主机)提供网络环境时非常有用。 - mode: 运行模式。通常我们用
rule(规则模式),根据规则智能判断;有时候调试会用到global(全局模式)或者direct(直连模式)。 - external-controller: 这是给外部控制面板(Dashboard)用的接口。如果你想用浏览器或者第三方应用来管理 Clash,就需要开启这个。
allow-lan: false # allow other devices access
bind-address: "*" # access by lan with a/some specific IP addresses
# "*": bind all IP addresses
# 192.168.122.11: bind a single IPv4 address
# "[aaaa::a8aa:ff:fe09:57d8]": bind a single IPv6 address
authentication: # authentication of local SOCKS5/HTTP(S) server
- "user1:pass1"
- "user2:pass2"
允许其他设备通过 Clash 本地 LAN 连接。
log-level: info # silent / error / warning / info / debug
定义 Clash 的日志级别:在 debug 的情况下,会显示所有 DNS 请求。
external-controller: 127.0.0.1:9090
secret: "" # Secret for RESTful API (Optional)
允许外部控制器通过 RESTful API 访问和控制 Clash。
external-ui: folder #input is a relative path to the configuration directory or an absolute path
定义外部 UI,静态的 Web 字段,比如 clash-dashboard,可以通过 API/ui 来访问。
interface-name: en0 # outbound interface name
网络接口名,出口流量。
routing-mark: 6666
定义 Linux 下的流出连接 default mark
ebpf:
redirect-to-tun:
- eth0
eBPF 是一项起源于 Linux 内核的革命性技术,可以在操作系统内核中运行沙盒程序。它用于安全有效地扩展内核的功能,而无需更改内核源代码或加载内核模块。
只有 auto-route 冲突时才需要配置。
Profile
在配置文件的角落里,还有一个经常被忽略但非常实用的板块 —— profile。如果说前面的设置决定了 Clash 如何处理即时的流量,那么 profile 就决定了它如何“记忆”你的习惯。Clash 会将 select 结果保存在 $HOME/.cache 下,当重启时,Clash 会自动应用这些结果。
profile:
store-selected: true
store-fake-ip: true
你有没有遇到过这种情况:每次重启 Clash,之前手动切换好的“低延迟节点”又变回了默认的第一项?或者刚重启软件,打开网页总感觉比平时慢半拍?这就需要 profile 来帮忙了。
- store-selected:把它设为
true,Clash 就会自动记录你在各个策略组(Selector)中最后选择的节点。下次启动或者重载配置时,它会贴心地帮你恢复到之前的状态,不用再一次次手动去点。 - store-fake-ip:如果你启用了增强型的
fake-ipDNS 模式,这个选项能将 IP 映射关系持久化保存到本地。这意味着重启后,Clash 不用重新建立映射,能有效减少冷启动时的连接卡顿。
代理节点 Proxies
这里定义了所有可用的服务器节点。每个节点都是一个独立的对象,包含名字、类型、服务器地址、端口和加密方式等。
proxies:
- name: "ss1"
type: ss
server: server1.example.com
port: 443
cipher: chacha20-ietf-poly1305
password: "password"
- name: "vmess1"
type: vmess
server: server2.example.com
# ... 其他参数
虽然手动填写这些节点很繁琐(通常我们都用订阅转换工具生成),但理解其结构有助于你在节点出问题时进行排查。比如,有时候节点连不上仅仅是因为 server 域名解析出了问题,改成 IP 也许就好了。
策略组 Proxy Groups
这是我觉得 Clash 最迷人的地方。策略组把上面的“散兵游勇”(Proxies)组织成了有纪律的“正规军”。
常见的策略组类型有:
- Select:手动选择。最传统的模式,你自己决定走哪个节点。
- URL-Test:自动测速。这是我最常用的。你可以设置一个测试地址(比如
http://www.gstatic.com/generate_204),Clash 会自动定时测试组内节点的延迟,并自动切换到最快的那一个。这对于追求极致速度的体验至关重要。 - Fallback:故障转移。如果第一个节点挂了,自动切换到第二个。保证高可用。
proxy-groups:
- name: "Auto-Select"
type: url-test
proxies:
- ss1
- vmess1
url: 'http://www.gstatic.com/generate_204'
interval: 300
我通常会设置一个名为 "Proxy" 的主策略组,里面包含手动选择和自动选择的子策略组,这样既能享受自动化的便利,关键时刻也能手动介入。
规则 Rules
最后是规则部分,这是流量的“分发中心”。规则是从上到下匹配的,一旦匹配成功,就不再往下看。所以,顺序非常重要。
rules:
- DOMAIN-SUFFIX,google.com,Proxy
- DOMAIN-KEYWORD,google,Proxy
- DOMAIN,ad.com,REJECT
- IP-CIDR,127.0.0.0/8,DIRECT
- GEOIP,CN,DIRECT
- MATCH,Proxy
- DOMAIN-SUFFIX:匹配域名后缀。比如
google.com匹配所有谷歌相关的域名。 - GEOIP:根据 IP 的地理位置判断。
GEOIP,CN,DIRECT这条规则简直是神来之笔,它能确保所有国内的流量都不走代理,保证了访问国内网站的速度。 - MATCH:全匹配。通常放在最后一行,意思是“如果前面都没匹配上,就走这条路”。一般设置为
Proxy或者Final策略组,作为兜底。
实践中的一些小心得
在使用 Clash 配置的过程中,我踩过不少坑,也总结了一些经验。
巧用 Mixin 或预处理
如果你像我一样使用 Clash for Windows 或类似客户端,不要直接修改订阅下载下来的 config.yaml,因为下次更新订阅时,你的修改会被覆盖。
我建议利用客户端提供的 Mixin(混合配置) 或 Parsers(预处理) 功能。通过这些功能,你可以在不破坏原有订阅结构的情况下,注入你自己的自定义规则。比如,我始终在 Mixin 中强制开启 allow-lan: true,这样无论我切换哪个机场的订阅,我的局域网共享功能永远是打开的。
调试与日志
当发现某个网站打不开,或者明明该走代理却直连了,Log Level 就派上用场了。把 log-level 设置为 debug,然后观察控制台的输出。你会清晰地看到每一个网络请求匹配到了哪条规则,走了哪个策略组。这比盲目猜测要高效得多。
隐私与 DNS
虽然本文重点在基础配置,但提一句 DNS。Clash 的 DNS 模块非常强大,可以防止 DNS 污染。如果你的配置中没有启用 dns 字段,Clash 可能会使用系统默认 DNS,这在某些网络环境下可能导致域名解析错误。建议在进阶配置中研究一下 fake-ip 模式,体验会更流畅。
最后
Clash 的配置文件就像是一门编程语言,虽然刚开始看 config.yaml 可能会觉得头大,全是缩进和英文,但一旦你掌握了它的逻辑,你就会发现它赋予了你对网络流量无与伦比的掌控力。
这种掌控力不仅仅是为了“能访问”某个网站,更是为了在一个复杂的网络环境中,获得最稳定、最快速、最无感的上网体验。希望这篇文章能成为你定制完美网络环境的起点。如果你有更巧妙的配置思路,欢迎在评论区或者邮件告诉我,我们一起探讨。
附录
一份完整的配置示例
# Port of HTTP(S) proxy server on the local end
port: 7890
# Port of SOCKS5 proxy server on the local end
socks-port: 7891
# Transparent proxy server port for Linux and macOS (Redirect TCP and TProxy UDP)
# redir-port: 7892
# Transparent proxy server port for Linux (TProxy TCP and TProxy UDP)
# tproxy-port: 7893
# HTTP(S) and SOCKS4(A)/SOCKS5 server on the same port
# mixed-port: 7890
# authentication of local SOCKS5/HTTP(S) server
# authentication:
# - "user1:pass1"
# - "user2:pass2"
# Set to true to allow connections to the local-end server from
# other LAN IP addresses
allow-lan: false
# This is only applicable when `allow-lan` is `true`
# '*': bind all IP addresses
# 192.168.122.11: bind a single IPv4 address
# "[aaaa::a8aa:ff:fe09:57d8]": bind a single IPv6 address
bind-address: '*'
# Clash router working mode
# rule: rule-based packet routing
# global: all packets will be forwarded to a single endpoint
# direct: directly forward the packets to the Internet
mode: rule
# Clash by default prints logs to STDOUT
# info / warning / error / debug / silent
log-level: info
# When set to false, resolver won't translate hostnames to IPv6 addresses
ipv6: false
# RESTful web API listening address
external-controller: 127.0.0.1:9090
# A relative path to the configuration directory or an absolute path to a
# directory in which you put some static web resource. Clash core will then
# serve it at `http://{{external-controller}}/ui`.
external-ui: folder
# Secret for the RESTful API (optional)
# Authenticate by spedifying HTTP header `Authorization: Bearer ${secret}`
# ALWAYS set a secret if RESTful API is listening on 0.0.0.0
# secret: ""
# Outbound interface name
interface-name: en0
# fwmark on Linux only
routing-mark: 6666
# Static hosts for DNS server and connection establishment (like /etc/hosts)
#
# Wildcard hostnames are supported (e.g. *.clash.dev, *.foo.*.example.com)
# Non-wildcard domain names have a higher priority than wildcard domain names
# e.g. foo.example.com > *.example.com > .example.com
# P.S. +.foo.com equals to .foo.com and foo.com
hosts:
# '*.clash.dev': 127.0.0.1
# '.dev': 127.0.0.1
# 'alpha.clash.dev': '::1'
profile:
# Store the `select` results in $HOME/.config/clash/.cache
# set false If you don't want this behavior
# when two different configurations have groups with the same name, the selected values are shared
store-selected: false
# persistence fakeip
store-fake-ip: true
# DNS server settings
# This section is optional. When not present, the DNS server will be disabled.
dns:
enable: false
listen: 0.0.0.0:53
# ipv6: false # when the false, response to AAAA questions will be empty
# These nameservers are used to resolve the DNS nameserver hostnames below.
# Specify IP addresses only
default-nameserver:
- 114.114.114.114
- 8.8.8.8
enhanced-mode: fake-ip # or redir-host (not recommended)
fake-ip-range: 198.18.0.1/16 # Fake IP addresses pool CIDR
# use-hosts: true # lookup hosts and return IP record
# Hostnames in this list will not be resolved with fake IPs
# i.e. questions to these domain names will always be answered with their
# real IP addresses
# fake-ip-filter:
# - '*.lan'
# - localhost.ptlogin2.qq.com
# Supports UDP, TCP, DoT, DoH. You can specify the port to connect to.
# All DNS questions are sent directly to the nameserver, without proxies
# involved. Clash answers the DNS question with the first result gathered.
nameserver:
- 114.114.114.114 # default value
- 8.8.8.8 # default value
- tls://dns.rubyfish.cn:853 # DNS over TLS
- https://1.1.1.1/dns-query # DNS over HTTPS
- dhcp://en0 # dns from dhcp
# - '8.8.8.8#en0'
# When `fallback` is present, the DNS server will send concurrent requests
# to the servers in this section along with servers in `nameservers`.
# The answers from fallback servers are used when the GEOIP country
# is not `CN`.
# fallback:
# - tcp://1.1.1.1
# - 'tcp://1.1.1.1#en0'
# If IP addresses resolved with servers in `nameservers` are in the specified
# subnets below, they are considered invalid and results from `fallback`
# servers are used instead.
#
# IP address resolved with servers in `nameserver` is used when
# `fallback-filter.geoip` is true and when GEOIP of the IP address is `CN`.
#
# If `fallback-filter.geoip` is false, results from `nameserver` nameservers
# are always used if not match `fallback-filter.ipcidr`.
#
# This is a countermeasure against DNS pollution attacks.
# fallback-filter:
# geoip: true
# geoip-code: CN
# ipcidr:
# - 240.0.0.0/4
# domain:
# - '+.google.com'
# - '+.facebook.com'
# - '+.youtube.com'
# Lookup domains via specific nameservers
# nameserver-policy:
# 'www.baidu.com': '114.114.114.114'
# '+.internal.crop.com': '10.0.0.1'
proxies:
# Shadowsocks
# The supported ciphers (encryption methods):
# aes-128-gcm aes-192-gcm aes-256-gcm
# aes-128-cfb aes-192-cfb aes-256-cfb
# aes-128-ctr aes-192-ctr aes-256-ctr
# rc4-md5 chacha20-ietf xchacha20
# chacha20-ietf-poly1305 xchacha20-ietf-poly1305
- name: "ss1"
type: ss
server: server
port: 443
cipher: chacha20-ietf-poly1305
password: "password"
# udp: true
- name: "ss2"
type: ss
server: server
port: 443
cipher: chacha20-ietf-poly1305
password: "password"
plugin: obfs
plugin-opts:
mode: tls # or http
# host: bing.com
- name: "ss3"
type: ss
server: server
port: 443
cipher: chacha20-ietf-poly1305
password: "password"
plugin: v2ray-plugin
plugin-opts:
mode: websocket # no QUIC now
# tls: true # wss
# skip-cert-verify: true
# host: bing.com
# path: "/"
# mux: true
# headers:
# custom: value
# vmess
# cipher support auto/aes-128-gcm/chacha20-poly1305/none
- name: "vmess"
type: vmess
server: server
port: 443
uuid: uuid
alterId: 32
cipher: auto
# udp: true
# tls: true
# skip-cert-verify: true
# servername: example.com # priority over wss host
# network: ws
# ws-opts:
# path: /path
# headers:
# Host: v2ray.com
# max-early-data: 2048
# early-data-header-name: Sec-WebSocket-Protocol
- name: "vmess-h2"
type: vmess
server: server
port: 443
uuid: uuid
alterId: 32
cipher: auto
network: h2
tls: true
h2-opts:
host:
- http.example.com
- http-alt.example.com
path: /
- name: "vmess-http"
type: vmess
server: server
port: 443
uuid: uuid
alterId: 32
cipher: auto
# udp: true
# network: http
# http-opts:
# # method: "GET"
# # path:
# # - '/'
# # - '/video'
# # headers:
# # Connection:
# # - keep-alive
- name: vmess-grpc
server: server
port: 443
type: vmess
uuid: uuid
alterId: 32
cipher: auto
network: grpc
tls: true
servername: example.com
# skip-cert-verify: true
grpc-opts:
grpc-service-name: "example"
# socks5
- name: "socks"
type: socks5
server: server
port: 443
# username: username
# password: password
# tls: true
# skip-cert-verify: true
# udp: true
# http
- name: "http"
type: http
server: server
port: 443
# username: username
# password: password
# tls: true # https
# skip-cert-verify: true
# sni: custom.com
# Snell
# Beware that there's currently no UDP support yet
- name: "snell"
type: snell
server: server
port: 44046
psk: yourpsk
# version: 2
# obfs-opts:
# mode: http # or tls
# host: bing.com
# Trojan
- name: "trojan"
type: trojan
server: server
port: 443
password: yourpsk
# udp: true
# sni: example.com # aka server name
# alpn:
# - h2
# - http/1.1
# skip-cert-verify: true
- name: trojan-grpc
server: server
port: 443
type: trojan
password: "example"
network: grpc
sni: example.com
# skip-cert-verify: true
udp: true
grpc-opts:
grpc-service-name: "example"
- name: trojan-ws
server: server
port: 443
type: trojan
password: "example"
network: ws
sni: example.com
# skip-cert-verify: true
udp: true
# ws-opts:
# path: /path
# headers:
# Host: example.com
# ShadowsocksR
# The supported ciphers (encryption methods): all stream ciphers in ss
# The supported obfses:
# plain http_simple http_post
# random_head tls1.2_ticket_auth tls1.2_ticket_fastauth
# The supported supported protocols:
# origin auth_sha1_v4 auth_aes128_md5
# auth_aes128_sha1 auth_chain_a auth_chain_b
- name: "ssr"
type: ssr
server: server
port: 443
cipher: chacha20-ietf
password: "password"
obfs: tls1.2_ticket_auth
protocol: auth_sha1_v4
# obfs-param: domain.tld
# protocol-param: "#"
# udp: true
proxy-groups:
# relay chains the proxies. proxies shall not contain a relay. No UDP support.
# Traffic: clash <-> http <-> vmess <-> ss1 <-> ss2 <-> Internet
- name: "relay"
type: relay
proxies:
- http
- vmess
- ss1
- ss2
# url-test select which proxy will be used by benchmarking speed to a URL.
- name: "auto"
type: url-test
proxies:
- ss1
- ss2
- vmess1
# tolerance: 150
# lazy: true
url: 'http://www.gstatic.com/generate_204'
interval: 300
# fallback selects an available policy by priority. The availability is tested by accessing an URL, just like an auto url-test group.
- name: "fallback-auto"
type: fallback
proxies:
- ss1
- ss2
- vmess1
url: 'http://www.gstatic.com/generate_204'
interval: 300
# load-balance: The request of the same eTLD+1 will be dial to the same proxy.
- name: "load-balance"
type: load-balance
proxies:
- ss1
- ss2
- vmess1
url: 'http://www.gstatic.com/generate_204'
interval: 300
# strategy: consistent-hashing # or round-robin
# select is used for selecting proxy or proxy group
# you can use RESTful API to switch proxy is recommended for use in GUI.
- name: Proxy
type: select
# disable-udp: true
proxies:
- ss1
- ss2
- vmess1
- auto
# direct to another infacename or fwmark, also supported on proxy
- name: en1
type: select
interface-name: en1
routing-mark: 6667
proxies:
- DIRECT
- name: UseProvider
type: select
use:
- provider1
proxies:
- Proxy
- DIRECT
proxy-providers:
provider1:
type: http
url: "url"
interval: 3600
path: ./provider1.yaml
health-check:
enable: true
interval: 600
# lazy: true
url: http://www.gstatic.com/generate_204
test:
type: file
path: /test.yaml
health-check:
enable: true
interval: 36000
url: http://www.gstatic.com/generate_204
tunnels:
# one line config
- tcp/udp,127.0.0.1:6553,114.114.114.114:53,proxy
- tcp,127.0.0.1:6666,rds.mysql.com:3306,vpn
# full yaml config
- network: [tcp, udp]
address: 127.0.0.1:7777
target: target.com
proxy: proxy
rules:
- DOMAIN-SUFFIX,google.com,auto
- DOMAIN-KEYWORD,google,auto
- DOMAIN,google.com,auto
- DOMAIN-SUFFIX,ad.com,REJECT
- SRC-IP-CIDR,192.168.1.201/32,DIRECT
# optional param "no-resolve" for IP rules (GEOIP, IP-CIDR, IP-CIDR6)
- IP-CIDR,127.0.0.0/8,DIRECT
- GEOIP,CN,DIRECT
- DST-PORT,80,DIRECT
- SRC-PORT,7777,DIRECT
- RULE-SET,apple,REJECT # Premium only
- MATCH,auto
reference

