跳到主要内容

5 篇博文 含有标签「clash」

查看所有标签

Clash TUN 模式下微信收发图片变慢:一次 IPv6 排查记录

· 阅读需 4 分钟
1adybug
子虚伊人

最近我在 Clash Verge / Mihomo 中开启了 TUN 模式后,发现微信收发图片明显变慢。一开始我怀疑是微信图片流量被代理服务器接管了,导致绕路。

但排查日志后发现,真正的问题并不是“微信走了代理”,而是 Clash 中开启 IPv6 后,让微信尝试了一条当前网络环境不可达的 IPv6 路径。

现象

开启 Clash TUN 模式后:

  • 微信文字消息基本正常
  • 接收和发送图片明显变慢
  • 关闭 Clash 中的 IPv6 后,微信图片恢复正常

排查过程

先查看 Clash / Mihomo 的规则和连接日志。

配置中微信相关进程已经被明确设置为直连:

- PROCESS-NAME,Weixin.exe,DIRECT
- PROCESS-NAME,WeixinUpdate.exe,DIRECT
- PROCESS-NAME,WeChatAppEx.exe,DIRECT
- PROCESS-NAME,WeixinExt.exe,DIRECT

随后在微信接收一张图片时,对比 Mihomo 日志,发现新增记录类似这样:

[TCP] dial DIRECT (match ProcessName/Weixin.exe)
Weixin.exe --> [240e:xxxx:xxxx::xxxx]:443
error: connect failed: dial tcp [240e:xxxx:xxxx::xxxx]:443:
A socket operation was attempted to an unreachable network.

关键信息有三个:

DIRECT
ProcessName/Weixin.exe
IPv6 unreachable network

也就是说,微信并没有走代理,而是命中了 DIRECT 规则。但它尝试访问腾讯/微信的 IPv6 地址时,当前网络环境下这条 IPv6 路径不可达,于是发生反复重试,最终造成图片收发很慢。

真正原因

问题不是:

  • 微信图片走了代理
  • 代理服务器太慢
  • 微信服务器慢

更准确的原因是:

Clash / Mihomo 中开启 IPv6 后,微信拿到了 IPv6 目标地址,并尝试直连;但当前 TUN / 网络环境无法真正访问这些 IPv6 地址,于是连接失败、重试、回落,造成明显延迟。

这是一种“看起来支持 IPv6,但实际路径不可达”的情况。

解决方式

在 Clash / Mihomo 中关闭 IPv6:

ipv6: false

dns:
ipv6: false

然后重启 Clash 内核。

注意,这里说的是关闭 Clash / Mihomo 内部的 IPv6 支持,不是去 Windows 网卡里全局禁用 IPv6。

关闭 Clash IPv6 会有什么影响?

关闭后,Clash 通常不再处理 IPv6 目标地址,也不会主动返回 IPv6 DNS 结果。大多数应用会回落到 IPv4。

影响一般是:

  • IPv4 代理规则仍然正常工作
  • 大多数网站和 App 不受影响
  • 少数 IPv6-only 服务可能无法访问
  • 如果某些服务 IPv6 路径原本更优,可能失去这部分优势
  • 但在当前网络 IPv6 不通的情况下,关闭反而更稳定

代理本身是否支持 IPv6?

不能只看代理节点入口 IP 来判断。

即使代理服务器入口是 IPv4,比如:

104.xxx.xxx.xxx:4431

它也可能支持代理 IPv6 目标地址。是否支持取决于:

  • 节点服务器是否有 IPv6 出站能力
  • 代理协议和服务端配置是否支持
  • Clash/Mihomo 是否开启 IPv6 处理

在这次问题里,微信本身命中的是 DIRECT,所以重点并不是“节点是否支持 IPv6”,而是“微信直连 IPv6 不可达”。

总结

这次微信图片慢的核心链路是:

Clash 开启 IPv6

微信拿到 IPv6 地址

微信按规则 DIRECT 直连

当前网络/TUN 环境 IPv6 不可达

连接失败、重试、回落

收发图片变慢

关闭 Clash 中的 IPv6 后,微信更早走 IPv4,绕过不可达的 IPv6 路径,问题解决。

如果你也遇到 Clash TUN 模式下微信、QQ、国内 App 图片或资源加载很慢,可以优先检查 Mihomo 日志中是否存在类似:

DIRECT
IPv6
unreachable network

如果有,那么关闭 Clash / Mihomo 的 IPv6 很可能就是最直接的解决办法。

让应用程序绕过 Clash Verge 代理(TUN / 系统代理通用方案)

· 阅读需 2 分钟
1adybug
子虚伊人

背景

在开启 TUN 模式或系统代理模式时,部分应用(如微信、Radmin VPN)可能出现:

  • 文件传输缓慢或失败
  • 局域网通信异常
  • VPN 无法建立连接

本文提供一套通用方案,使指定应用绕过 Clash Verge 代理。


步骤 1:配置 TUN 排除进程

打开「订阅」→「全局扩展覆写配置」,覆盖粘贴:

# Profile Enhancement Merge Template for Clash Verge

profile:
store-selected: true

# ✅ 关键:让 Radmin VPN 不被 TUN 接管
tun:
exclude-process:
- AnyDesk.exe
- WeChatAppEx.exe
- WeixinUpdate.exe
- Weixin.exe
- WetypeInstaller.exe
- WeixinExt.exe
- RvRvpnGui.exe
- RvControlSvc.exe
- Radmin.exe
- drvinst.exe
- RvFwHelper.exe
- RvGuiStarter.exe

👉 作用:这些进程不会被 TUN 模式接管


步骤 2:添加规则强制直连

打开「全局扩展脚本」,覆盖粘贴:

// Define main function (script entry)

function main(config, profileName) {
// 为所有代理节点添加或设置 'udp: true'
if (config.proxies) config.proxies.forEach(proxy => (proxy.udp = true))

config.rules ??= []

// 保留原有的添加域名规则的逻辑
const name = config["proxy-groups"]?.at(0)?.name

const excludeProcesses = [
"AnyDesk.exe",
"WeChatAppEx.exe",
"WeixinUpdate.exe",
"Weixin.exe",
"WetypeInstaller.exe",
"WeixinExt.exe",
"RvRvpnGui.exe",
"RvControlSvc.exe",
"Radmin.exe",
"drvinst.exe",
"RvFwHelper.exe",
"RvGuiStarter.exe",
]

if (name) {
config.rules.unshift(`DOMAIN-SUFFIX,claude.ai,${name}`)
config.rules.unshift(`DOMAIN-SUFFIX,claude.com,${name}`)
config.rules.unshift(`IP-CIDR,26.0.0.0/8,DIRECT`)
excludeProcesses.forEach(item => config.rules.unshift(`PROCESS-NAME,${item},DIRECT`))
}

return config
}

👉 作用:

  • 强制指定进程走直连
  • 即使切换到“代理模式”仍然生效

步骤 3(可选):调整 DNS 模式

打开「设置」→「DNS 覆写」,将:

  • fake-ipredir-host

👉 适用于以下情况:

  • 微信传文件异常
  • 局域网通信不稳定

⚠️ 注意:

  • 此步骤为可选项
  • 如果修改后出现网络异常,可以恢复为 fake-ip

验证是否生效

可以通过以下方式确认:

1. 测试 Radmin VPN

ping 26.x.x.x

应正常通信。


2. 查看 Clash 日志

在日志中应看到:

26.x.x.x → DIRECT

原理说明

本方案基于三点:

  1. tun.exclude-process

    • 控制流量是否进入 Clash(入口)
  2. PROCESS-NAME,...,DIRECT

    • 控制流量走直连(出口)
  3. IP-CIDR,26.0.0.0/8,DIRECT

    • 确保 Radmin VPN 内网流量不被代理

总结

  • TUN 排除:避免应用被接管
  • 规则直连:保证任何模式下都不走代理
  • DNS 调整:作为兼容性优化手段

通过以上配置,可以实现 Clash Verge 与微信、Radmin VPN 等应用的稳定共存。

在 Docker 中使用 Clash

· 阅读需 6 分钟
1adybug
子虚伊人

在图形化的操作系统中,我们可以使用 Clash Verge 来使用代理,但是在服务器上,就没有这么方便了。这时候我们可以使用 Clash 的核心 mihomo 来实现代理。然而,mihomo 的安装也是比较麻烦,所以我们可以使用 Docker 来安装 mihomo

安装教程

  1. 安装 Docker

  2. 创建 config.yaml 文件

    # url 里填写自己的订阅,名称不能重复
    proxy-providers:
    <你的订阅名称>:
    url: "<你的订阅链接>"
    type: http
    interval: 86400
    health-check: { enable: true, url: "https://www.gstatic.com/generate_204", interval: 300 }

    proxies:
    - name: "直连"
    type: direct
    udp: true

    mixed-port: 7890
    ipv6: true
    allow-lan: true
    unified-delay: false
    tcp-concurrent: true
    external-controller: 0.0.0.0:9090
    external-ui: ui
    external-ui-url: "https://github.com/MetaCubeX/metacubexd/archive/refs/heads/gh-pages.zip"
    # 如果你的端口开放了所有 IP 访问,建议取消注释 secret 并设置密码
    # secret: <你的密码>

    geodata-mode: true
    geox-url:
    geoip: "https://mirror.ghproxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip-lite.dat"
    geosite: "https://mirror.ghproxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.dat"
    mmdb: "https://mirror.ghproxy.com/https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/country-lite.mmdb"
    asn: "https://mirror.ghproxy.com/https://github.com/xishang0128/geoip/releases/download/latest/GeoLite2-ASN.mmdb"

    find-process-mode: strict
    global-client-fingerprint: chrome

    profile:
    store-selected: true
    store-fake-ip: true

    sniffer:
    enable: true
    sniff:
    HTTP:
    ports: [80, 8080-8880]
    override-destination: true
    TLS:
    ports: [443, 8443]
    QUIC:
    ports: [443, 8443]
    skip-domain:
    - "Mijia Cloud"
    - "+.push.apple.com"

    tun:
    enable: true
    stack: mixed
    dns-hijack:
    - "any:53"
    - "tcp://any:53"
    auto-route: true
    auto-redirect: true
    auto-detect-interface: true

    dns:
    enable: true
    ipv6: true
    enhanced-mode: fake-ip
    fake-ip-filter:
    - "*"
    - "+.lan"
    - "+.local"
    - "+.market.xiaomi.com"
    default-nameserver:
    - tls://223.5.5.5
    - tls://223.6.6.6
    nameserver:
    - https://doh.pub/dns-query
    - https://dns.alidns.com/dns-query

    proxy-groups:
    - name: 默认
    type: select
    proxies: [自动选择, 直连, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点]

    - name: Google
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: Telegram
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: Twitter
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: 哔哩哔哩
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: 巴哈姆特
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: YouTube
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: NETFLIX
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: Spotify
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: Github
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    - name: 国内
    type: select
    proxies: [直连, 默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择]

    - name: 其他
    type: select
    proxies: [默认, 香港, 台湾, 日本, 新加坡, 美国, 其它地区, 全部节点, 自动选择, 直连]

    #分隔,下面是地区分组
    - name: 香港
    type: select
    include-all: true
    exclude-type: direct
    filter: "(?i)港|hk|hongkong|hong kong"

    - name: 台湾
    type: select
    include-all: true
    exclude-type: direct
    filter: "(?i)台|tw|taiwan"

    - name: 日本
    type: select
    include-all: true
    exclude-type: direct
    filter: "(?i)日|jp|japan"

    - name: 美国
    type: select
    include-all: true
    exclude-type: direct
    filter: "(?i)美|us|unitedstates|united states"

    - name: 新加坡
    type: select
    include-all: true
    exclude-type: direct
    filter: "(?i)(新|sg|singapore)"

    - name: 其它地区
    type: select
    include-all: true
    exclude-type: direct
    filter: "(?i)^(?!.*(?:🇭🇰|🇯🇵|🇺🇸|🇸🇬|🇨🇳|港|hk|hongkong|台|tw|taiwan|日|jp|japan|新|sg|singapore|美|us|unitedstates)).*"

    - name: 全部节点
    type: select
    include-all: true
    exclude-type: direct

    - name: 自动选择
    type: url-test
    include-all: true
    exclude-type: direct
    tolerance: 10

    rules:
    - GEOIP,lan,直连,no-resolve
    - GEOSITE,github,Github
    - GEOSITE,twitter,Twitter
    - GEOSITE,youtube,YouTube
    - GEOSITE,google,Google
    - GEOSITE,telegram,Telegram
    - GEOSITE,netflix,NETFLIX
    - GEOSITE,bilibili,哔哩哔哩
    - GEOSITE,bahamut,巴哈姆特
    - GEOSITE,spotify,Spotify
    - GEOSITE,CN,国内
    - GEOSITE,geolocation-!cn,其他

    - GEOIP,google,Google
    - GEOIP,netflix,NETFLIX
    - GEOIP,telegram,Telegram
    - GEOIP,twitter,Twitter
    - GEOIP,CN,国内
    - MATCH,其他
  3. 创建 docker-compose.yaml 文件

    version: "3"

    services:
    metacubexd:
    container_name: metacubexd
    image: ghcr.io/metacubex/metacubexd
    restart: always
    ports:
    - "9097:80"

    mihomo:
    container_name: mihomo
    image: docker.io/metacubex/mihomo:latest
    restart: always
    ports:
    # 尽量使用 127.0.0.1 而不是 0.0.0.0,否则可能让代理暴露在公网
    - "127.0.0.1:7890:7890"
    - "9090:9090"
    volumes:
    - <保存 config.yaml 文件的目录>:/root/.config/mihomo
  4. 启动容器 docker compose up -d

使用教程

在需要使用代理的地方,设置代理为 http://127.0.0.1:7890 即可。

比如为终端设置代理:

  1. 编辑 ~/.bashrc 文件,添加以下内容:

    export http_proxy="http://127.0.0.1:7890"
    export https_proxy="http://127.0.0.1:7890"
    export all_proxy="socks5://127.0.0.1:7890"
    export no_proxy="localhost,127.0.0.1,*.local"
  2. 保存并退出,然后执行 source ~/.bashrc 使配置生效。

  3. 使用 curl https://www.google.com 测试是否成功。

注意事项

  1. 尽量不要使用 MobaXterm 等终端创建或者编辑配置文件,可以会出现默认编码非 UTF-8 或者缺少字符集的问题,导致配置文件无法正常使用。
  2. config.yamlexternal-controller 的端口和 docker-compose.yamlmetacubexd 的端口都需要在防火墙中开放,建议只允许特定 IP 访问,如果全放开的话,建议取消注释 secret 并设置密码。
  3. docker-compose.yamlmihomovolumes 需要指向 config.yaml 文件在主机的目录而非文件。
  4. 如果 mihomo 的容器的日志中出现了下载文件的错误,请到 meta-rules-dat 仓库中手动下载文件并保存到 config.yaml 所在的目录

WSL 网络设置

· 阅读需 1 分钟
1adybug
子虚伊人

wsl 默认使用的是 NAT 模式的网络,无法直接访问外部网络,可以通过修改 wsl 的网络设置,将其设置为 mirrored,使其能够直接访问外部网络。

C:\Users\用户名 目录下创建 .wslconfig 文件,内容如下:

[wsl2]
networkingMode=mirrored

wsl 中查看网络配置:

ifconfig

如果 ip 地址已经和主机在同一个网段,那么网络设置已经生效。

重启 wsl 使设置生效:

wsl --shutdown

代理可能需要重新设置,或者重启代理软件或者主机

如果要在 NAT 模式下使用 clash 代理,可以参考 获取 Windows 在 wsl 中的 ip 这篇文章

vi ~/.bashrc

~/.bashrc 文件中添加以下内容:

export http_proxy=http://172.30.160.1:7890
export https_proxy=http://172.30.160.1:7890
export all_proxy=http://172.30.160.1:7890
export HTTP_PROXY=http://172.30.160.1:7890
export HTTPS_PROXY=http://172.30.160.1:7890
export ALL_PROXY=http://172.30.160.1:7890

重启终端,或者执行 source ~/.bashrc 使设置生效。

在 Clash 中添加全局规则

· 阅读需 3 分钟
1adybug
子虚伊人

有时候我们希望某些网站不走代理,这时候就需要添加自定义规则,右击订阅,选择扩展脚本:

// Define main function (script entry)

/**
* @param {object} config
* @param {string[]} config.rules
* @param {string} profileName
*/
function main(config, profileName) {
config.rules.unshift("DOMAIN-SUFFIX,axshare.com,DIRECT")
config.rules.unshift("DOMAIN-SUFFIX,bing.com,DIRECT")
config.rules.unshift("DOMAIN-SUFFIX,codesandbox.io,DIRECT")
config.rules.unshift("DOMAIN-SUFFIX,csbops.io,DIRECT")
config.rules.unshift("DOMAIN-SUFFIX,csb.app,DIRECT")
config.rules.unshift("DOMAIN-SUFFIX,gallerycdn.vsassets.io,节点选择")
config.rules.unshift("DOMAIN-SUFFIX,gallery.vsassets.io,节点选择")
config.rules.unshift("DOMAIN-SUFFIX,marketplace.visualstudio.com,节点选择")
return config
}

DOMAIN 是指定域名,DOMAIN-SUFFIX 是指定域名后缀,DIRECT节点选择 都是规则内的分组。

规则类型匹配逻辑匹配目标性能等级关键注意事项
DOMAIN精确域名匹配域名仅匹配完全相同的域名字符串。
DOMAIN-SUFFIX域名后缀匹配域名匹配指定后缀及其所有子域名。
DOMAIN-KEYWORD域名关键词匹配域名匹配域名中任何位置出现的关键词,可能产生误匹配。
IP-CIDR目标 IPv4 地址段目标 IPv4默认触发 DNS 解析。
IP-CIDR6目标 IPv6 地址段目标 IPv6默认触发 DNS 解析。
GEOIP目标 IP 地理位置目标 IP基于 MaxMind 数据库;默认触发 DNS 解析。
SRC-IP-CIDR源 IPv4 地址段源 IPv4主要用于网关模式,区分局域网内不同设备。
DST-PORT目标端口目标端口基于 TCP/UDP 目标端口进行匹配。
SRC-PORT源端口源端口基于 TCP/UDP 源端口进行匹配。
PROCESS-NAME进程名称进程名操作系统相关;适用于 Windows, macOS, Linux, FreeBSD。
PROCESS-PATH进程路径进程路径操作系统相关;比进程名更精确,但可移植性差。
IPSETLinux IP 集目标 IP低 (内核)仅 Linux 可用;需要 ipset 工具;性能极高。

有时候我们希望某些规则对于所有的订阅都生效,这时候我们可以右击 全局扩展脚本,选择编辑文件:

// Define main function (script entry)

/**
* @param {object} config
* @param {string[]} config.rules
* @param {string} profileName
*/
function main(config, profileName) {
/** @type string | undefined */
const name = config["proxy-groups"]?.at(0)?.name
config.rules.unshift(`DOMAIN-SUFFIX,neo4j.com,${name}`)
return config
}

这里的意思找到订阅的第一个分组(一般都是通用的代理规则),然后将这条规则添加到这个分组中。

如果需要对于脚本进行调试,可以添加 console.log,在保存脚本以后,会在 全局扩展脚本 下方出现一个日志按钮,点击以后会输出脚本的日志。