Mihomo (Clash Meta) Proxy Configuration
Setup mihomo proxy on Linux servers, especially for China mainland machines that need access to external services (Google, X/Twitter, AI APIs).
Trigger
- User asks to setup/configure proxy, clash, mihomo, or VPN on a Linux server
- User needs to access GitHub/X/Twitter/AI services from China
- User mentions "翻墙" or "代理"
Step 1: Download & Install
Direct GitHub access from China is blocked. Use acceleration mirrors:
mkdir -p ~/mihomo && cd ~/mihomo
VERSION="v1.19.8" # Check latest at https://github.com/MetaCubeX/mihomo/releases
# gh-proxy.com (primary mirror)
wget -O mihomo.gz "https://gh-proxy.com/https://github.com/MetaCubeX/mihomo/releases/download/${VERSION}/mihomo-linux-amd64-${VERSION}.gz"
# ghfast.top (fallback)
# wget -O mihomo.gz "https://ghfast.top/https://github.com/MetaCubeX/mihomo/releases/download/${VERSION}/mihomo-linux-amd64-${VERSION}.gz"
gunzip mihomo.gz && chmod +x mihomo && sudo cp mihomo /usr/local/bin/mihomo
mihomo -v
Pitfall: If gunzip says "not in gzip format", the file is an HTML error page (195 bytes). Check with file mihomo.gz — if "HTML document", the mirror URL is wrong. Try the other mirror.
Step 2: Config Template
Create ~/.config/mihomo/config.yaml:
# ============================================================
# Mihomo Config
# ============================================================
mixed-port: 7893
port: 7890
socks-port: 7891
allow-lan: false
bind-address: "*"
mode: rule
log-level: info
ipv6: false
external-controller: 0.0.0.0:9090
secret: "your_password" # REQUIRED for 0.0.0.0
external-ui: ui # Relative path, within config dir
external-ui-url: "https://gh-proxy.com/https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip"
geodata-mode: true
geox-url:
geoip: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
geosite: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
mmdb: "https://gh-proxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
# ---- DNS (Internal Network) ----
dns:
enable: true
ipv6: false
respect-rules: true # CRITICAL: DNS follows proxy rules
enhanced-mode: fake-ip
nameserver:
- 10.0.0.53 # <<<< Replace with your internal DNS
- 10.0.0.54
proxy-server-nameserver:
- 10.0.0.53
- 10.0.0.54
nameserver-policy:
"rule-set:ai":
- https://1.1.1.1/dns-query
- https://dns.google/dns-query
fake-ip-filter-mode: rule
fake-ip-filter:
- RULE-SET,ai,fake-ip
- MATCH,real-ip
# ---- Proxy Providers (Airport Subscription) ----
proxy-providers:
airport:
type: http
url: "" # <<<< Replace with subscription URL
path: ./providers/airport.yaml
interval: 3600
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
# ---- Proxies (Self-hosted / Special Nodes) ----
proxies:
- name: "claude-proxy"
type: vless
server: YOUR_SERVER_ADDRESS # <<<< Replace
port: 443
uuid: YOUR_UUID # <<<< Replace
network: tcp
tls: true
servername: your-servername.example.com
flow: xtls-rprx-vision
# ---- Proxy Groups (Country-based, no emojis) ----
proxy-groups:
- name: "PROXY"
type: select
use: [airport]
proxies: ["AUTO", "HK", "TW", "JP", "SG", "US", "KR", "EU", DIRECT]
- name: "AUTO"
type: url-test
use: [airport]
url: https://www.gstatic.com/generate_204
interval: 300
tolerance: 50
- name: "AI"
type: select
use: [airport]
filter: "(?i)美|us|美国|america"
proxies: ["claude-proxy", "JP", "HK", "SG", "AUTO"]
- name: "HK"
type: url-test
use: [airport]
filter: "(?i)港|hk|hong kong"
url: https://www.gstatic.com/generate_204
interval: 300
- name: "TW"
type: url-test
use: [airport]
filter: "(?i)台|tw|taiwan"
url: https://www.gstatic.com/generate_204
interval: 300
- name: "JP"
type: url-test
use: [airport]
filter: "(?i)日|jp|japan"
url: https://www.gstatic.com/generate_204
interval: 300
- name: "SG"
type: url-test
use: [airport]
filter: "(?i)新|sg|singapore"
url: https://www.gstatic.com/generate_204
interval: 300
- name: "US"
type: url-test
use: [airport]
filter: "(?i)美|us|美国|america"
url: https://www.gstatic.com/generate_204
interval: 300
- name: "KR"
type: url-test
use: [airport]
filter: "(?i)韩|kr|korea"
url: https://www.gstatic.com/generate_204
interval: 300
- name: "EU"
type: url-test
use: [airport]
filter: "(?i)英|德|法|荷兰|uk|de|fr|nl|europe|germany|france|netherlands"
url: https://www.gstatic.com/generate_204
interval: 300
# ---- Rule Providers (Only AI domains as local file) ----
rule-providers:
ai:
type: file
behavior: domain
path: ./ruleset/ai.yaml
# ---- Rules (Built-in GEOSITE/GEOIP + local ai.yaml) ----
rules:
- GEOSITE,private,DIRECT
- GEOIP,private,DIRECT,no-resolve
- RULE-SET,ai,AI
- GEOSITE,cn,DIRECT
- GEOSITE,geolocation-!cn,PROXY
- GEOIP,CN,DIRECT,no-resolve
- MATCH,PROXY
Step 3: AI Domains Rule Set
Create ~/.config/mihomo/ruleset/ai.yaml:
CRITICAL: Use +. prefix for all domains! Without +., openai.com only matches the bare domain, NOT subdomains like api.openai.com. With +.openai.com, all subdomains are matched.
payload:
# OpenAI
- '+.openai.com'
- '+.chatgpt.com'
- '+.oaiusercontent.com'
- '+.oaistatic.com'
# Anthropic / Claude
- '+.anthropic.com'
- '+.claude.ai'
- '+.claude.com'
- '+.claudeusercontent.com'
# Google AI
- '+.gemini.google.com'
- '+.ai.google.dev'
- '+.generativelanguage.googleapis.com'
# xAI / Grok
- '+.x.ai'
- '+.grok.com'
# Groq
- '+.groq.com'
# Cohere
- '+.cohere.com'
# Mistral
- '+.mistral.ai'
# Together AI
- '+.together.ai'
# Replicate
- '+.replicate.com'
# Perplexity
- '+.perplexity.ai'
# DeepSeek
- '+.deepseek.com'
# OpenRouter
- '+.openrouter.ai'
# Hugging Face
- '+.huggingface.co'
# Cursor
- '+.cursor.sh'
# Nous Research
- '+.nousresearch.com'
# Stability AI
- '+.stability.ai'
# Midjourney
- '+.midjourney.com'
# Runway
- '+.runwayml.com'
# Suno
- '+.suno.com'
- '+.suno.ai'
Pitfall: Without +. prefix, api.openai.com falls through to GEOSITE,geolocation-!cn → PROXY instead of matching RULE-SET,ai → AI. Always use +.domain.com format.
To add/remove domains: Just edit this file and systemctl --user restart mihomo. No need to touch config.yaml.
Step 4: Start & Verify
# Validate config
mihomo -d ~/.config/mihomo -t
# Frontend test
mihomo -d ~/.config/mihomo
# Systemd service (long-term)
cat > ~/.config/systemd/user/mihomo.service << 'EOF'
[Unit]
Description=Mihomo Proxy Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/mihomo -d %h/.config/mihomo
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable mihomo
systemctl --user start mihomo
# Verify AI routing
curl -x http://127.0.0.1:7890 -s https://api.openai.com -o /dev/null
journalctl --user -u mihomo --no-pager -n 3 | grep openai
# Should show: match RuleSet(ai) using AI[...]
Step 5: Hermes Proxy Integration
Add to ~/.hermes/.env:
HTTP_PROXY=http://127.0.0.1:7890
HTTPS_PROXY=http://127.0.0.1:7890
ALL_PROXY=socks5://127.0.0.1:7891
NO_PROXY=localhost,127.0.0.1,*.cn,*.corp.example.com
Then hermes gateway restart.
Pitfalls
- ALWAYS use
+.domain.comin ai.yaml — baredomain.comdoesn't match subdomains in file-based rule providers - NEVER fabricate URLs — rule provider URLs, GeoX URLs must be verified or use local files
global-client-fingerprintis REMOVED in newer mihomo versions — set per-proxy insteadexternal-uimust be relative path within config dir — absolute paths outside config dir are rejected- Use built-in GEOSITE/GEOIP — don't create external HTTP rule providers that may 404
- Internal DNS — don't use public DNS (223.5.5.5) as nameserver on internal networks
respect-rules: trueis critical — without it, DNS queries don't follow proxy rules- GitHub blocked in China — all download URLs need
gh-proxy.comorghfast.topmirrors - gunzip "not in gzip format" — download returned HTML error page, try different mirror
- No emojis in group names — use HK, TW, JP abbreviations
Private Documentation
Keep environment-specific DNS addresses, subscription URLs, and internal documentation links in private configuration or documentation. Do not commit them to a public Skill repository.