如果服务器从不同的端口响应,客户端不会从服务器接收 UDP 数据报
Client does not receive UDP datagram from server if the server responds from a different port
环境:
客户端 - Windows NAT 后面的桌面,运行 UDP 客户端应用程序。
Server - Ubuntu IP 地址为 public 的服务器,运行一个 UDP 服务器应用程序,需要端口 6000 上的数据包。
ClientPrivate/Public - private/public 客户端 IP
ServerPrivate/Public - private/public 服务器的 IPs
案例一:
- 客户端在 ClientPrivate:777 上打开一个 UDP 套接字并发送一个数据报到 ServerPublic :6000
- 服务器从ClientPublic:777接收数据报并向ClientPublic发送响应: 777 来自 ServerPrivate:6000
- 客户端收到响应,一切正常
服务器上的 WireShark 输出:
475 88.xxx.xxx.90 -> 10.0.0.5 UDP 777 → 6000
476 10.0.0.5 -> 88.xxx.xxx.90 UDP 6000 → 777
客户端的 WireShark 输出:
152 192.168.2.85 104.40.xxx.250 UDP 777 → 6000
153 104.40.xxx.250 192.168.2.85 UDP 6000 → 777
案例二:
- 客户端在 ClientPrivate:777 上打开一个 UDP 套接字并发送一个数据报到 ServerPublic :6000
- 服务器从ClientPublic:777
接收数据报
- 服务器在 ServerPrivate:46666 上打开一个新套接字,并向 ClientPublic 发送一个数据报:777
- 客户端没有收到数据报
服务器上的 WireShark 输出:
475 88.xxx.xxx.90 -> 10.0.0.5 UDP 777 → 6000
476 10.0.0.5 -> 88.xxx.xxx.90 UDP 46666 → 777
客户端的 WireShark 输出:
152 192.168.2.85 104.40.xxx.250 UDP 777 → 6000
问题:
为什么在案例 1 中 客户端收到数据报而在案例 2 中没有?
我认为这是由于 client-side NAT。当您的客户端向服务器发送 public IP 时,NAT 路由器会在其内部 table 连接中创建一个条目(类似于“192.168.2.85[777] => 104.40.xxx .250[6000]).
因此当响应从 104.40.xxx.250[6000] 返回时,NAT 将找到匹配的条目和 return 对客户端计算机的响应。该条目是它如何知道将数据包发送到客户端网络中的哪台机器的方式。但是,当从 104.40.xx.250[46666] 返回响应时,它不匹配其 table 中的任何条目,因此它丢弃了该数据包。
这就是 NAT 的工作方式。考虑一下你的 NAT 后面是否有另一台机器 also 与同一台服务器通信,比如说,“192.168.2.86[777] => 104 .40.xxx.250[6000]”。我认为您会发现您的 NAT 路由器实际上将源端口更改为 777 以外的端口。否则它如何正确地将响应路由回正确的机器。通常对于 NAT,如果来自路由器的传入数据包与其 table 中的条目不匹配( 或 您已经配置了 port-forwarding 规则)数据包将被丢弃。
Port-forwarding 允许您打开内部机器以供外部世界进行一般访问。但是缺少它,您真的不希望任何随机 IP 地址/端口对能够将数据报发送到您的客户端计算机。
环境:
客户端 - Windows NAT 后面的桌面,运行 UDP 客户端应用程序。
Server - Ubuntu IP 地址为 public 的服务器,运行一个 UDP 服务器应用程序,需要端口 6000 上的数据包。
ClientPrivate/Public - private/public 客户端 IP
ServerPrivate/Public - private/public 服务器的 IPs
案例一:
- 客户端在 ClientPrivate:777 上打开一个 UDP 套接字并发送一个数据报到 ServerPublic :6000
- 服务器从ClientPublic:777接收数据报并向ClientPublic发送响应: 777 来自 ServerPrivate:6000
- 客户端收到响应,一切正常
服务器上的 WireShark 输出:
475 88.xxx.xxx.90 -> 10.0.0.5 UDP 777 → 6000
476 10.0.0.5 -> 88.xxx.xxx.90 UDP 6000 → 777
客户端的 WireShark 输出:
152 192.168.2.85 104.40.xxx.250 UDP 777 → 6000
153 104.40.xxx.250 192.168.2.85 UDP 6000 → 777
案例二:
- 客户端在 ClientPrivate:777 上打开一个 UDP 套接字并发送一个数据报到 ServerPublic :6000
- 服务器从ClientPublic:777 接收数据报
- 服务器在 ServerPrivate:46666 上打开一个新套接字,并向 ClientPublic 发送一个数据报:777
- 客户端没有收到数据报
服务器上的 WireShark 输出:
475 88.xxx.xxx.90 -> 10.0.0.5 UDP 777 → 6000
476 10.0.0.5 -> 88.xxx.xxx.90 UDP 46666 → 777
客户端的 WireShark 输出:
152 192.168.2.85 104.40.xxx.250 UDP 777 → 6000
问题:
为什么在案例 1 中 客户端收到数据报而在案例 2 中没有?
我认为这是由于 client-side NAT。当您的客户端向服务器发送 public IP 时,NAT 路由器会在其内部 table 连接中创建一个条目(类似于“192.168.2.85[777] => 104.40.xxx .250[6000]).
因此当响应从 104.40.xxx.250[6000] 返回时,NAT 将找到匹配的条目和 return 对客户端计算机的响应。该条目是它如何知道将数据包发送到客户端网络中的哪台机器的方式。但是,当从 104.40.xx.250[46666] 返回响应时,它不匹配其 table 中的任何条目,因此它丢弃了该数据包。
这就是 NAT 的工作方式。考虑一下你的 NAT 后面是否有另一台机器 also 与同一台服务器通信,比如说,“192.168.2.86[777] => 104 .40.xxx.250[6000]”。我认为您会发现您的 NAT 路由器实际上将源端口更改为 777 以外的端口。否则它如何正确地将响应路由回正确的机器。通常对于 NAT,如果来自路由器的传入数据包与其 table 中的条目不匹配( 或 您已经配置了 port-forwarding 规则)数据包将被丢弃。
Port-forwarding 允许您打开内部机器以供外部世界进行一般访问。但是缺少它,您真的不希望任何随机 IP 地址/端口对能够将数据报发送到您的客户端计算机。