Clash TUN模式下的UDP服务异常诊断与解决

Clash开启TUN模式后,本地UDP端口无法与外部访问正常建立连接,如何诊断问题?如何解决问题?

本文同时提供其他语言的版本: English.

问题背景 Background

在我的日常生活中,我已经习惯通过ClashX的TUN模式(增强模式)接管MacOS系统的所有流量,便于观察实时流量并配置规则。Clash作为Surge的平替,已经成为了我在MacOS系统中的出口流量管理中心和出口防火墙。

MacOS的入口流量管理还是推荐使用PF防火墙

最近随着幻兽帕鲁的爆火,我在本地建立专用服务器后,发现局域网可以正常登录,来自公网的客户端却显示无法连接(我拥有公网IP并已建立好公网映射)。

问题诊断 Troubleshooting

UDP&TCP 进出流量检查

首先,我对TCP和UDP的进出流量进行诊断

TCP出口流量,很容易测试,可以发现流量分流运行正常

image-20240229144359702

image-20240229144451892

TCP入口流量,可以发现也可以正常通过公网IP访问,也可以正常双向通信(Hello从客户端发到服务端,Back从服务端发回客户端)

image-20240229144918734

image-20240229144946166

UDP出口流量,这里我们尝试访问谷歌的NTP服务,可以发现正常建立连接

image-20240229145054536

UDP入口流量,我们先建立测试服务

image-20240229145229874

尝试发送一个UDP包,可以发现成功接收到数据包?似乎UDP监听目前也可以正常使用?事情真的如此吗?

image-20240229145313016

尝试发送响应包,我们发现客户端无法接收到。让客户端再次发送请求包,我们发现服务端也无法接收到。

image-20240229145830292

image-20240229145708448

此时在局域网中或不开启TUN进行测试,所有连接均正常,方法也一样,就跳过了

Wireshark分析

此时我们已经确认了问题,让我们用Wireshark深入诊断一下,在使用Wireshark监听的同时再次复现上文中出现问题的操作

你可能发现了此时我的公网IP和端口改变了,IP从218.79.x.x变为117.131.x.x,端口变为50011,不要在意这个

我们可以发现第一个成功发送的UDP数据包,目标端口是50011,这个数据包我们在服务端正常收到了

image-20240229150452204

第二个数据包是服务端返回发送的数据包,在客户端中我们并没能收到。图中可以看到Source Port为50131,这与服务开放的端口50011并不一致,此处我猜测是Clash在TUN NIC中对Source Port进行了重新映射,避免多个代理客户端发送了同样的Source Port产生冲突。那么因为Source Port和客户端发出的Destination Port不同,由于目前广泛采用的端口受限型NAT(在PlayStation中被称为NAT3),所以无法成功连接。此时如果客户端是地址受限型NAT(NAT2)或完全圆锥形NAT(NAT1),我推测是可以正常通信的。

问题解决 Solve it

此时我们已经确定了问题的原因——UDP服务出口流量经过TUN网卡导致Source Port不正确,无法与客户端构建连接。那么我们应该如何解决呢?

方案1 - 手动管理路由表

既然问题出在流量经过TUN网卡,那么我们可以为特定客户端IP指定路由表规则,让其直接使用物理网卡,忽略TUN网卡。

在MacOS中,我通过如下命令指定去往117.131.x.x的流量直接使用en20物理网卡,成功解决问题。

1
sudo route add 117.131.x.x -interface en20

更换ClashX客户端为ClashX.Meta,其允许对TUN功能进行更详细的配置,我们也可以编写配置文件以使其自动排除特定的网段

1
2
3
tun:
inet4-route-exclude-address:
- 117.131.x.x/32

缺陷

  • 此方法只能用于经常通信的几个客户端

方案2 - 使用端口转发工具

一些端口转发工具可以指定使用的监听地址,并且从对应的网卡发送响应数据包。如 gost

使用gost绑定物理网卡对应的地址,进行流量转发

1
gost -L=udp://192.168.x.x:50111/127.0.0.1:50112

客户端可以正常发送数据包,也可以正常收到响应数据包

image-20240229154654997

缺陷

  • 流量增加一层应用层转发,增大了服务器性能压力,也增加了网络延迟
  • 服务端应用无法正确判断客户端真实地址

方案3 - 网卡桥接

仅为猜想,并未测试

可以使用Vmware添加桥接网卡,直接接入物理网卡,即可忽略Clash TUN网卡

缺陷

  • 路由器的端口转发很可能不认桥接网卡,导致无法连接(我就遇到了这个情况,华为k662c路由器的端口转发无法绑定桥接设备的端口)
作者

4xpl0r3r

发布于

2024-02-29

更新于

2024-02-29

许可协议

评论