Android设备如何在Clash的客户端解决WebRTC泄露问题?

各位佬好,我遇到了一个WebRTC泄露的问题,折腾了两晚上没解决,来请教一下大家。

我用的是Android系统,常用的浏览器是基于内置WebView的Via浏览器。之前一直用Nekobox代理,也没有出现WebRTC泄露真实IP的问题。最近因为负载均衡等需求,就换成了Clash Meta for Android,用的是 Loyalsoldier/clash-rules 这个分流规则。

问题来了,DNS不漏,但WebRTC总是泄露。我在以下两个网站测试了一下:

结果发现真实IP都漏了。Android的VPN服务是几乎接管所有流量的模式,按理来说,WebRTC的STUN请求应该走代理,而不是直连才对。

为了确认是不是分流规则导致的WebRTC泄露,我直接把Clash规则简化到只保留一条“- MATCH,PROXY”,确保所有流量都走的PROXY出口。重新测试,结果真实IP还是漏了。想到WebRTC基于UDP,我又在 Proxy 和 Proxy Group 里禁用了所有UDP流量,并在规则里写了UDP Reject。结果还是一样,IP泄露。

更奇怪的是,当我恢复所有分流和规则,开启Global全局模式时,WebRTC居然不直连了。这是个什么情况?但不管怎样,Global模式总不能一直开,不然国内网站的延迟高得离谱,CDN资源还会反向优化到国外。

现在的问题是,不更换代理客户端和浏览器的前提下,Clash应该怎么设置才能Reject所有WebRTC连接?另外像桌面端有相关禁用WebRTC的插件,那Android基于WebView的浏览器(比如Via)有办法禁止WebRTC吗?

2 Likes

帮顶一下

帮顶

配置文件脱敏之后贴出来看看

原始状态如下,很简洁的一个配置文件

port: 7890
socks-port: 7891
allow-lan: true
mode: rule
log-level: info
external-controller: 127.0.0.1:9090

proxies:
  - name: test
    server: xxx
    port: 443
    client-fingerprint: random
    type: vless
    uuid: xxx
    tls: true
    tfo: false
    skip-cert-verify: false
    servername: xxx
    network: ws
    ws-opts:
      path: "/xxx"
      headers: 
        Host: xxx

proxy-groups:
  - name: PROXY
    type: select
    proxies:
      - test
      - DIRECT
      
rule-providers:
  reject:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/reject.txt"
    path: ./ruleset/reject.yaml
    interval: 86400

  icloud:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/icloud.txt"
    path: ./ruleset/icloud.yaml
    interval: 86400

  apple:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/apple.txt"
    path: ./ruleset/apple.yaml
    interval: 86400

  google:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/google.txt"
    path: ./ruleset/google.yaml
    interval: 86400

  proxy:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/proxy.txt"
    path: ./ruleset/proxy.yaml
    interval: 86400

  direct:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/direct.txt"
    path: ./ruleset/direct.yaml
    interval: 86400

  private:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/private.txt"
    path: ./ruleset/private.yaml
    interval: 86400

  gfw:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/gfw.txt"
    path: ./ruleset/gfw.yaml
    interval: 86400

  tld-not-cn:
    type: http
    behavior: domain
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/tld-not-cn.txt"
    path: ./ruleset/tld-not-cn.yaml
    interval: 86400

  telegramcidr:
    type: http
    behavior: ipcidr
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/telegramcidr.txt"
    path: ./ruleset/telegramcidr.yaml
    interval: 86400

  cncidr:
    type: http
    behavior: ipcidr
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/cncidr.txt"
    path: ./ruleset/cncidr.yaml
    interval: 86400

  lancidr:
    type: http
    behavior: ipcidr
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/lancidr.txt"
    path: ./ruleset/lancidr.yaml
    interval: 86400

  applications:
    type: http
    behavior: classical
    url: "https://cdn.jsdelivr.net/gh/Loyalsoldier/clash-rules@release/applications.txt"
    path: ./ruleset/applications.yaml
    interval: 86400

rules:
  - DOMAIN,clash.razord.top,DIRECT
  - DOMAIN,yacd.haishan.me,DIRECT
  - RULE-SET,private,DIRECT
  - RULE-SET,reject,REJECT
  - RULE-SET,icloud,DIRECT
  - RULE-SET,apple,DIRECT
  - RULE-SET,google,PROXY
  - RULE-SET,proxy,PROXY
  - RULE-SET,direct,DIRECT
  - RULE-SET,lancidr,DIRECT,no-resolve
  - RULE-SET,cncidr,DIRECT,no-resolve
  - RULE-SET,telegramcidr,PROXY,no-resolve
  - GEOIP,LAN,DIRECT,no-resolve
  - GEOIP,CN,DIRECT,no-resolve
  - MATCH,PROXY

帮顶

首先感谢 @xjp666 大佬的帮助,因为我是新人,无法一天内连续回帖,大佬很热心地在私聊频道帮我分析了包括分流和DNS在内的各种原因。

关于解决方案,其实很魔幻。昨晚和大佬分析了一通没解决,我打算去CMFA提个Issue,结果发现这个Repo的Issue区已经被关闭了。本以为这问题没办法解决了,突然发现有个刚刚新鲜出炉的Release,更新文档很长,主要是修复和适配Meta内核的一些特性。更新后,就用主楼提到的UDP规则,配置文件都没动,这次WebRTC稳稳的不泄露了。升级更新解君愁啊!

唯一遗憾的是CFMA还保留了一些Bug,比如同样配置的WireGuard在Clash Verge Rev能用,但在Clash Meta for Android上就不行。看CMFA讨论区,这个Bug已经存在很久了,希望能尽早修复。

1 Like

有没有具体方法让我学学

呃呃,主楼里已经说了解决方案啊。节点和节点组不支持udp的,请直接disable,同时在rule那里加上udp类型直接reject的规则

@xjp666 大佬给出了一个详细的分析和解决方案,比我直接reject的好,我请他过来发一下。

不是不是,我的问题,没看懂并不是你的问题。

这样说,webrtc是基于udp的,因此对于不支持UDP的节点,可以在proxy加udp: false,在proxy group加disable-udp: true,在rules加- NETWORK,udp,RECJET来实现。

真诚、友善,不懂的欢迎继续问。另外 @xjp666 大佬估计不在线,他的方案更完善,可以等他发帖,我就不班门弄斧啦。

1 Like

刚刚测试复现了这个问题,原因是有些节点不支持 udp,匹配不了所有规则,导致 clash 走直连,关键日志文件如下:

level=debug msg="PROXY UDP is not supported"
level=info msg="[UDP] 198.18.0.1:49681 --> stun.nextcloud.com:443 doesn't match any rule using DIRECT"
level=debug msg="[Rule] use default rules"
level=debug msg="PROXY UDP is not supported"
level=info msg="[UDP] 198.18.0.1:49759 --> jp1.stun.twilio.com:3478 doesn't match any rule using DIRECT"
level=debug msg="PROXY UDP is not supported"
level=info msg="[UDP] 198.18.0.1:49765 --> stun.syncthing.net:3478 doesn't match any rule using DIRECT"
level=debug msg="PROXY UDP is not supported"
level=info msg="[UDP] 198.18.0.1:49695 --> us1.stun.twilio.com:3478 doesn't match any rule using DIRECT"
level=debug msg="[Rule] use default rules"
level=info msg="[UDP] 198.18.0.1:49749 --> stun.nextcloud.com:443 doesn't match any rule using DIRECT"
level=debug msg="[Rule] use default rules"
level=info msg="[UDP] 198.18.0.1:49697 --> stun.syncthing.net:3478 doesn't match any rule using DIRECT"
level=debug msg="[Rule] use default rules"
level=info msg="[UDP] 198.18.0.1:49725 --> jp1.stun.twilio.com:3478 doesn't match any rule using DIRECT"
level=debug msg="PROXY UDP is not supported"
level=info msg="[UDP] 198.18.0.1:49685 --> stunserver.stunprotocol.org:3478 match GeoIP(lan) using DIRECT"
level=debug msg="PROXY UDP is not supported"

其中 PROXY 为代理节点分组,选中的节点不支持 udp:

PROXY UDP is not supported

结果是走直连:

doesn't match any rule using DIRECT

解决方法1:

出站代理 udp 设置为 true( 默认为 false),
https://wiki.metacubex.one/config/proxies/#udp
https://wiki.metacubex.one/config/rules/#_2
方法1只适用支持 udp 的代理,但是没有设置 udp 为 true 的情况

解决方法2:

在规则最后加上一条兜底:

NETWORK,udp,REJECT

代理不支持 udp 则拦截数据出站,以避免 WebRTC 泄露

参考:

https://github.com/MetaCubeX/mihomo/issues/945
https://github.com/MetaCubeX/mihomo/pull/178

2 Likes

可以换个思路,家里用paopaodns.然后配置远程dns直接走外面查询。 这样就肯定不漏了

感觉和DNS关系不大,完全交给远程查询能确保DNS不漏,但是对WebRTC,如果出口代理不支持UDP,仍会因为Clash默认Compatible的策略回退到Direct导致漏真实IP。这点也是Clash被诟病已久的地方。(另外Clash还会默认出口代理的UDP支持为True,所以特别容易漏:sweat:

学习了。

From 快问快答 to 开发调优