vernesong / OpenClash

A Clash Client For OpenWrt
MIT License
15.69k stars 2.93k forks source link

[Feature] ChatGPT 语音请求 UDP 3478 TCP 7881 #3900

Open gemnioo opened 1 month ago

gemnioo commented 1 month ago

Verify Steps

Describe the Feature

上游删了, Surge Testflight 上周正在讨论, 尝试发这里

目前 OpenClash v0.46.011-beta 不再添加UTUN接口, 增强模式下 TCP 走 7892 UDP 走 7895 TProxy 端口

遇到 ChatGPT 语音模式在 TCP 请求 +.turn.livekit.cloud 后会直接 UDP 走 3478 尝试连接 (如图 138.3.210.144 是 livekit 甲骨文日本托管服务器

而 UDP 3478 是 Apple FaceTime Microsoft Team Tailscale Derp 等语音 打洞 STUN 等服务的默认 UDP 端口.

如果用 Script 规则控制可以做到强制回退, 用 TCP 7881 连接, 避免 TCP/UDP 请求不一致 (默认也会回退 TCP 因为 UDP relay 不佳.

`script: shortcuts:

4483 与 9305 为 BiliBili 的 QUIC CDN; 禁止 3478 会影响语音打洞服务

quic: network == 'udp' and (dst_port == 443 or dst_port == 4483 or dst_port == 9305)
derp: network == 'udp' and dst_port == 3478 
livekit: network == 'tcp' and dst_port == 7881

rules:

OpenClash 默认禁用QUIC 禁用 443 端口 UDP 流量(不包括国内) 是否需要增加调试 3478 端口的 UDP 流量?

截圖 2024-05-27 09 32 01

Describe Alternatives

No response

gemnioo commented 1 month ago

测试后觉得间歇性手动选择 UDP 3478 会产生很多问题 所以放弃 script shortcut

还是写明` 会请求 livekit 的甲骨文服务器地址

`script: shortcuts:

4483 与 9305 为 BiliBili 的 QUIC CDN, livekit 3478 强制走 TCP 7781

quic: network == 'udp' and (dst_port == 443 or dst_port == 4483 or dst_port == 9305)

rules:

观察到 ChatGPT 的语音服务会按如下顺序请求 webrtc.chatgpt.com TCP 443
1, .turn.livekit.cloud TCP 443 2, livekit 对应 IP 地址 UDP 3478 3, .,host.livekit.cloud UDP 3478 4, 回退到 2 中的域名 TCP 7881 或者 2 中的域名 UDP >=50000 (前者居多 类似打洞成功

gemnioo commented 1 month ago

还是要看 节点线路对于 UDP 转发的质量 reject 掉 livekit UDP 3478 或者 >= 50000 首次能稳定连接上 但是中途聊到一般会断 还是走 UDP 代理吧

script: shortcuts: #4483 与 9305 为 BiliBili 的 QUIC CDN, livekit 3478 强制走 TCP 7781 quic: network == 'udp' and (dst_port == 443 or dst_port == 4483 or dst_port == 9305) rules: - SCRIPT,quic,REJECT,no-resolve - IP-CIDR,138.3.210.144/32, Open AI,no-resolve - IP-CIDR,168.138.215.123/32, Open AI,no-resolve - IP-CIDR,140.238.51.65/32, Open AI,no-resolve

首次测试后 代理 livekit UDP 3478 或者 >= 50000 请求还是会间歇性连不上 最后 reject 掉 还是退回 TCP 7881 能够稳定连接 (就是后台 瞬间日志 reject 太多了

~~script:~~ ~~shortcuts:~~ ~~# 4483 与 9305 为 BiliBili 的 QUIC CDN, livekit 3478 强制走 TCP 7781~~ ~~quic: network == 'udp' and (dst_port == 443 or dst_port == 4483 or dst_port == 9305)~~ ~~livekit: network == 'udp' and (dst_ip == "138.3.210.144" or dst_ip == "168.138.215.123" or dst_ip == "140.238.51.65")~~ rules: ~~- SCRIPT,quic,REJECT,no-resolve~~ ~~- SCRIPT,livekit,REJECT,no-resolve~~ ~~- IP-CIDR,138.3.210.144/32, Open AI,no-resolve~~ ~~- IP-CIDR,168.138.215.123/32, Open AI,no-resolve~~ ~~- IP-CIDR,140.238.51.65/32, Open AI,no-resolve~~

gemnioo commented 3 weeks ago

周一为了解决以上 UDP 分流, 同时不影响 UDP 3478 stun 打洞 语音等服务, 使用了对应的地址规则走代理 如 IP-CIDR,168.138.215.123/32, Open AI,no-resolve 解决了兼容问题.

目前家庭网络拓扑是 旁路由开启 openclash fake-ip 增强模式(tcp rediect; udp tproxy. 使用防火墙转发黑白名单绕过终端电脑有线地址 .10.100 , 无线地址 .10.101还是走openclash内核 (方便排查

刚刚查看 openclash logs 同时对比 clash for windows logs 发现会有 UDP 流量通过 *.10.101漏到 openclash

_

2024-06-02 08:43:05 INF [TCP] connected lAddr=.10.101:53007 rAddr=138.3.210.144:7881 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI 2024-06-02 08:43:05 INF [TCP] connected lAddr=.10.101:52999 rAddr=138.3.210.144:7881 mode=rule rule=IPCIDR(138.3.210.144/32) proxy= Open AI 2024-06-02 08:43:05 INF [TCP] connected lAddr=.10.101:52991 rAddr=138.3.210.144:7881 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI 2024-06-02 08:43:05 INF [UDP] connected lAddr=.10.101:64592 rAddr=138.3.210.144:3478 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI 2024-06-02 08:43:05 INF [UDP] connected lAddr=.10.101:60422 rAddr=138.3.210.144:3478 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI 2024-06-02 08:43:05 INF [UDP] connected lAddr=.10.101:52091 rAddr=138.3.210.144:3478 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI 2024-06-02 08:43:05 INF [UDP] connected lAddr=.10.101:52317 rAddr=138.3.210.144:3478 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI 2024-06-02 08:43:05 INF [UDP] tunnel connected lAddr=127.0.0.1:36447 rAddr=engage.cloudflareclient.com:2408 proxy= Japan 2024-06-02 08:43:05 INF [UDP] connected lAddr=.10.101:61705 rAddr=138.3.210.144:3478 mode=rule rule=IPCIDR(138.3.210.144/32) proxy=Open AI

_

看上去并没有走终端电脑的默认网络顺序(有线优先于无线 所以 UDP 数据还是通过 .10.101 流向 openclash (检查logs发现也会有 apple 规则的tcp udp数据 10.100 漏到 openclash 所以请问为了避免 UDP 规则不走 *.10.101

是否需要电脑添加如下规则 ?(不同客户端写法不同 同时电脑还有 tailscale derp 打洞需要指定网卡出口

  • name: tailscale type: select interface-name: utun0 routing-mark: 6667 proxies:
    • DIRECT
  • name: OpenAI type: select interface-name: utun5 routing-mark: 1234 proxies:
    • Japan
    • USA
  • SCRIPT,quic,REJECT,no-resolve
  • IP-CIDR,138.3.210.144/32, OpenAI,no-resolve
  • IP-CIDR,168.138.215.123/32, OpenAI,no-resolve
  • IP-CIDR,140.238.51.65/32, OpenAI,no-resolve

再次阅读 clash.wiki 文档 规则集注明 interface-name 与 TUN 模式 interface-name 冲突; routing-mark 又仅在 Linux 上有效, 为了避免以上我遇到的情况 是否需要终端电脑配置文件 auto-detect-interface: false 同时每个规则集注明 interface-name ?

出站接口名称 interface-name: en0

fwmark (仅在 Linux 上有效) routing-mark: 6666

tun: enable: true stack: gvisor # or system dns-hijack:

  • 198.18.0.2:53 # 当 fake-ip-range 是 198.18.0.1/16, 应该劫持 198.18.0.2:53 auto-route: true # 为 Windows 自动设置全局路由 推荐使用 interface-name auto-detect-interface: true # 自动检测接口, 与 interface-name 冲突
gemnioo commented 3 weeks ago

看到 Surge TestFlight Feed telegram channel 昨天提到了这个问题

在之前的版本中,若开启了增强模式,由于系统的路由表已被 Surge 覆盖,所以所有向外发出的数据包,会被强制使用主 interface 发出,而不经由路由表,以避免产生死循环。

但这也导致在存在多网卡或其他 VPN 的情况下,数据包无法被从正确的 interface 上发出

阅读 clash wiki 文档

auto-route: true # 为 Windows 自动设置全局路由 推荐使用 interface-name auto-detect-interface: true # 自动检测接口, 与 interface-name 冲突

因为 proxy 节点信息是可以指定网口的

  • name: "ss1" type: ss interface-name: eth0 routing-mark: 1234 server: server port: 443 cipher: chacha20-ietf-poly1305 password: "password" udp: true

想请问 clash TUN 模式指定网卡出口 日常 direct 走 utun0 tailscale direct 走 utun5 该如何修改 interface 字段呢?

ps 虽然结论是和 openclash 防火墙转发黑白名单无关 (漏到 100.64.* 才走openclash 核心的 pps 是不是上游弃更只能等 surge stash 等其他客户端实现了?

gemnioo commented 3 weeks ago

经过ab测试, 以上问题和 openclash 绕过防火墙 黑白名单无关.

大概率会出现在 macOS 同时安装 ChatGPT 客户端和 Tailscale/xEgde 客户端,请求语音时候出现

因为都是走 UDP 3478 端口, 而UDP包没有校验连接确立的机制, 所以请求瞬间会有UDP流量 走100.64.*/16 utun0虚拟网卡 (类似 stun apple 的 UDP 请求存在连接的话也会走该网卡

Tailscale/xEgde 客户端会校验路由 同时会有 Wi-Fi & Ethernet UDP 连接 所以最终该 UDP 请求会二选一

至于 livekit UDP包走 final 香港( TCP/UDP 不一致 还是走规则 OpenAI 目前暂未看到连接差别(墙内不行

100.64.*/16 等于黑洞 走utun0变成直连必然会重新请求回退到 UDP 3478代理/TCP 7881 (大多数后者

这也是 ChatGPT 语音模式 有时连得上有时候不行的原因 选择 interface name 解决不了 UDP 的问题

gemnioo commented 3 weeks ago

这个锅大概是 macOS 的

因为终端电脑即使设置为系统代理 语音请求时也会有 UDP 流量走 Wi-Fi 而不是默认的有线网络, macOS 对于该 UDP 的包是 en0 en1 并发的

当终端电脑开启 TUN fake-ip 模式/增强模式的时候. 该 UDP 3478 请求会干扰到默认虚拟网卡出口, 使得同期建立连接在 UDP 3478 的流量不正常(不按rules规则连接 进而导致 TCP 也不正常 会重新建立握手

starsea commented 2 weeks ago

我抓包看到有时候仅仅会请求 udp 3478, 有时候 udp3478 和tcp 7881 都走。 搞不清为啥

gemnioo commented 2 weeks ago

我抓包看到有时候仅仅会请求 udp 3478, 有时候 udp3478 和tcp 7881 都走。 搞不清为啥

我观察到 ChatGPT 的语音服务请求会按如下顺序请求 webrtc.chatgpt.com TCP 443 1, .turn.livekit.cloud TCP 443 2, livekit 对应 IP 地址 UDP 3478 3, .,host.livekit.cloud UDP 3478 4, 回退到 2 中的域名 TCP 7881

但是我搞不明白为什么 OpenClash 里能看到防火墙转发并排除的黑名单不走代理本机地址的请求, 只能说 TProxy 对于相同端口的 UDP 3478 请求会和局域网内其他已连接的 UDP 3478 混淆.

至于为什么 macOS 会不走路由顺序从 en0 以太网发出,而是 en0 en1 同时都有请求,我只能选择关闭Wi-Fi

以上仅测试 Clash For Windows. 此请求走 Wireguard Tunnel 代理链套Warp 还是走 UDP 节点都能复现以上情况.

Stash 或者 Surge for Mac 还未测试