zhxie / pcap2socks

Redirect traffic to SOCKS proxy with pcap.
MIT License
631 stars 76 forks source link

无法获得NAT A #4

Closed feng92f closed 3 years ago

feng92f commented 3 years ago

0.4 版本 ,NS 测试联机的时候显示类型是 D。服务器直接是无验证的Socks5,服务器测试是 Full cone。

zhxie commented 3 years ago

According to your description, I guess you network topology is as follow:

Source ---> pcap2socks --[*]--> SOCKS5 Server

When connect to the remote SOCKS5 server using the SOCKS5 client of pcap2socks directly, there may be NAT at the location shown in the [*], and your source may not be able to obtain a NAT type A. You can use stunxy to check the NAT in the data link.

In fact, pcap2socks should work with other proxy backends, like Shadowsocks, the network topology is as follow:

Source ---> pcap2socks ----> [SOCKS5 Server --> Proxy Client] ----> Proxy Server

Other proxy's client is surrounded by [].

根据你的描述,我推测你的网络拓扑如下:

源 ---> pcap2socks --[*]--> SOCKS5 服务器

当使用 pcap2socks 直接连接远程 SOCKS5 服务器时,由于图示中 [*] 位置可能存在 NAT,你的源可能确实无法获得 NAT 类型 A。你可以使用 stunxy 确认链路中的 NAT。

事实上,pcap2socks 应当配合其它代理后端一起使用,如 Shadowsocks,其网络拓扑如下:

源 ----> pcap2socks ---> [SOCKS5 服务器 --> 代理客户端] ----> 代理服务器

被 [] 包住的即其它代理的客户端
feng92f commented 3 years ago

测试了本地使用V2ray 开 socks 的 inbound 和 outbound,inbound作为客户端,outbound连接外部socks,NAT类型没有变,仍然是D。v2ray 客户端这里看日志有部分 udp input 请求出错(read/write on closed pipe),是不是过早关掉了associate port的tcp请求?具体看不出来细节。

feng92f commented 3 years ago

即使是 Source ---> pcap2socks --[*]--> SOCKS5 Server 这种情况,也不影响NAT类型才对。我的理解是不管什么端口和IP来的UDP都被 SOCKS5 Server 接收了,不管中间怎么NAT都能返回给 pcap2socks,所以只要服务器是Fullcone,socks 代理都能获得fullcone。 我用pystun测试过服务器的NAT是对的。

zhxie commented 3 years ago

首先,你说的没错,理论上是不影响 NAT 类型的。唯一的区别在于,直接使用 pcap2socks 连接远程 SOCKS5 服务器时,对于每 1 个传入的 UDP 连接,将会创建 1 个 TCP 与 1 个 UDP 连接,而使用其他代理时,可能全程仅保持 1 个或数个共用的 TCP 或 UDP 连接。由于我在此前的测试中,无法通过 pcap2socks 直接连接 SOCKS5 服务器,因此怀疑是受到 ISP 防火墙、NAT 等的限制,因此更加推荐同时使用其他代理。具体的原因,我暂时也没有进行进一步的分析。

而关于 pcap2socks 的实现,pcap2socks 并不会过早地关闭用于 ASSOCIATE 的 TCP 连接,该连接仅会在 UDP 连接(UDP 是非连接的,此处的释放是由 LRU 控制的,最大连接数由 MAX_UDP_PORT 定义)被释放的情况下被动关闭,参考。但由于你提及 V2Ray 的日志显示 UDP read/write on closed pipe,我之后将会进一步调查这个问题。

zhxie commented 3 years ago

另外,pystun 等测试工具应当只能测试本机直接连接时的 NAT 类型,如你提到的在 SOCKS5 服务器所在主机上测试 NAT 类型为 Full-Cone。而我提到的 stunxy 可以通过 SOCKS5 代理测试 NAT,也就是说,你可以在你运行 pcap2socks 的主机上,测试你的客户端主机通过 SOCKS5 服务器的 NAT 类型。如果有兴趣,可以尝试一下。

[STUN client --> SOCKS5 client] ----> SOCKS5 server ----> STUN server

被 [] 包住的即 stunxy
feng92f commented 3 years ago

好的 ,我有在windows上编译的PTSD,我感觉是没问题的因为之前用tun2sock试过。

zhxie commented 3 years ago

这边跟进一下,我在我的腾讯云 VPS 上测试,发现 SOCKS5 ASSOCIATE 的响应报文中的 BND.ADDR 与 BND.PORT,也就是用于穿透的 UDP 连接对应的地址为内网地址。即使我的 VPS 拥有唯一的公网地址与 Full-Cone 的 NAT 类型,但是通信所使用的实际连接依然是经过腾讯云的防火墙或 NAT,并进行了地址转换的。

我的 VPS BIND 了 UDP InnerAddr:InnerPort,并将这一信息发给了 pcap2socks,但 pcap2socks 需要这个连接的 OuterAddr:OuterPort,因此无法进行通信。

我不清楚你的问题是否也是这种情况导致的。但如果确实是由于这一情况,我可能无法解决也不会去解决,因为这是 VPS 方面的问题。

zhxie commented 3 years ago

接上,我这边已在 commit e070dead 解决了这一问题。

假设你的 VPS 运营商有 OuterIP:Port 到 InnerIP:Port 的 NAT 的话,在启动时带上 --force-associate-destination 即可。pcap2socks 将会覆盖收到的 BND.ADDR 为你设置的 destination 的 IP 地址。

如果你在 macOS 或 Linux 下使用 pcap2socks,那么将可以在 Actions 获得最新编译的版本。如果你在 Windows 下使用 pcap2socks,我将在这两天发布 v0.4.1 并在 Releases 中附上编译完的二进制文件。

feng92f commented 3 years ago

@zhxie 这个 BND.ADDR 与 BND.PORT 是 socks 服务器指定的,v2ray里是可以配置的。我测试的时候是写的公网的IP,socks 服务器返回是公网的 ,NAT不会去改报文的。 还有就是这个 UDP 的IP 不一定是和 destination 一样的IP,协议有IP这个变量,就是说可以有不同的IP。

zhxie commented 3 years ago

是的,并且我这里直接拿 SOCKS5 服务器测试之后已经没问题了。现在你用 v0.4.1,依然会出现你所描述的这一问题吗,无法 ASSOCIATE 吗?

feng92f commented 3 years ago

https://www.v2ray.com/chapter_02/protocols/socks.html ”当开启 UDP 时,V2Ray 需要知道本机的 IP 地址。默认值为"127.0.0.1"。“ 这里的本机IP就是公网IP,就是 BND.ADDR 。

feng92f commented 3 years ago

刚测试了一下,还是D。如果是你说的返回的IP是内网的话,那么DNS查询也会出错的。

zhxie commented 3 years ago

由于不是所有的代理都具有可配置的 BND.ADDR,所以 --force-associate-destination 这一标签在某些情况下还是有必要的,既然 V2Ray 可以配置 BND.ADDR,那也就没问题。

但问题在用你的 NAT Type 依然为 D,而事实上 pcap2socks 和 SOCKS5 服务器的连接没有问题,那么问题可能会在 V2Ray 侧,或是在启动 pcap2socks 的方式上。如使用 macOS 或 Linux 时,是否配置了 IP Forwarding;使用 Windows 时,是否存在冲突软件(VMWare 等)。同时一般情况下,使用 -p <ADDRESS> 配置 ARP 代理的兼容性会更强。

就现有的数据,我可能无法解决这一问题,因为无法定位到问题存在的原因。

zhxie commented 3 years ago

我这边复现了使用 V2Ray 的 SOCKS5 作为入栈协议时,NAT Type 为 D 的情况。同时,在使用 Shadowsocks、GOST 等代理软件时,NAT Type 为 A。

推测是 V2Ray 的 SOCKS5 的实现存在问题。

feng92f commented 3 years ago

你试试 stunxy ?

zhxie commented 3 years ago

stunxy 测试 V2Ray 的结果是正常的 Full-Cone。

zhxie commented 3 years ago

这个现象确实很有趣,我这里通过 debug 日志截了一段 Switch 用于获得自身 NAT 类型的报文。

// GOST, NAT Type A
send to SOCKS UDP: 63513 -> 52.199.66.160:33334 (16 Bytes)
send to SOCKS UDP: 63513 -> 52.199.66.160:10025 (16 Bytes)
send to SOCKS UDP: 63513 -> 52.193.120.207:10025 (16 Bytes)
receive from SOCKS: UDP: 52.193.120.207:10025 -> 63513 (16 Bytes)
receive from SOCKS: UDP: 52.199.66.160:50920 -> 63513 (16 Bytes)
receive from SOCKS: UDP: 52.199.66.160:10025 -> 63513 (16 Bytes)
send to SOCKS UDP: 63514 -> 52.199.66.160:33334 (16 Bytes)
send to SOCKS UDP: 63514 -> 52.199.66.160:10025 (16 Bytes)
send to SOCKS UDP: 63514 -> 52.193.120.207:10025 (16 Bytes)
receive from SOCKS: UDP: 52.193.120.207:10025 -> 63514 (16 Bytes)
receive from SOCKS: UDP: 52.199.66.160:10025 -> 63514 (16 Bytes)
receive from SOCKS: UDP: 52.199.66.160:50920 -> 63514 (16 Bytes)
// V2Ray, NAT Type D
send to SOCKS UDP: 55287 -> 52.199.66.160:33334 (16 Bytes)
send to SOCKS UDP: 55287 -> 52.199.66.160:10025 (16 Bytes)
send to SOCKS UDP: 55287 -> 54.64.157.221:10025 (16 Bytes)
receive from SOCKS: UDP: 52.199.66.160:10025 -> 55287 (16 Bytes)
receive from SOCKS: UDP: 54.64.157.221:10025 -> 55287 (16 Bytes)
// Seems like a retry
send to SOCKS UDP: 55287 -> 52.199.66.160:33334 (16 Bytes)
send to SOCKS UDP: 55287 -> 52.199.66.160:10025 (16 Bytes)
send to SOCKS UDP: 55287 -> 54.64.157.221:10025 (16 Bytes)
receive from SOCKS: UDP: 52.199.66.160:10025 -> 55287 (16 Bytes)
receive from SOCKS: UDP: 54.64.157.221:10025 -> 55287 (16 Bytes)

从中可以看出,使用 V2Ray 时,Switch 进行的 2 次测试都少了一条响应,也就是从同地址,不同端口的响应。由于 pcap2socks 的 debug 日志会忠实的将自己从 SOCKS5 收到的报文打印出来,因此我依然更倾向于是 V2Ray 侧的问题。

feng92f commented 3 years ago

确实有可能 我记得是 如果 V2ray 收到的包是两个IP来的(不同的内容) ,但是他只会告诉 client 一个IP来了两个包 (不同的内容,一个IP),然后检测居然都是NAT A 我就以为是那个STUN RFC没要求这个,没细看。 可能是这里的问题 。

zhxie commented 3 years ago

顺便,V2Ray 那边是有相关的 issue 讨论 NAT 问题的。那看来应该是 V2Ray 侧的问题,我就关闭 issue 了,感谢反馈。