Python中使用UDP套接字进行GSM网络卡端口映射

7
我有一个Python服务器监听UDP数据包并回复发送者。在客户端中,我使用相同的端口连接回服务器。客户端通过GSM网络工作,它们的IP地址不是公共的,因此网络进行了一些端口映射,以便服务器可以联系它们,我认为是这样。
有时候端口映射可能会出现问题,因为打开的套接字仍然能够在客户端->服务器之间通信,但反向通信不能正常工作。
情况恶化到两个客户端具有相同的( IP、地址)对。在服务器上,当我使用sock.recvfrom接收来自它们的消息时,根据它们的内容,我清楚地知道这些消息来自于两个不同的客户端,但地址是相同的。
我在服务器上放置了nc -l,并在每个客户端上运行nc,很明显两张GSM卡共享相同的外部IP,所以最后一个打开端口的客户端会得到其映射,而旧的客户端则会根据假定它仍然拥有映射(实际上已经没有映射)而无法工作。
我没有编写原始代码,因此无法解释为什么客户端要使用特定的给定端口连接服务器,但我认为即使使用随机端口,该问题也将持续存在,因为网络在一段时间后(我想它应该是在某些事件之后,例如GSM信号丢失)重新映射端口。
有没有人有任何想法可以避免这种情况?
1个回答

2
动态NAT(名称地址转换)
在动态NAT中,内部侧必须发起连接,并且NAT设备从内部数据包的五元组中分配一个状态。
{protocol, internal_ip, internal_port, foreign_ip, foreign_port}

建立一个状态条目,该条目(假设只有一个外部IP)必须使用剩下的五元组中的四个来匹配更少歧视性的外部流量:
 {protocol, _, internal_port, foreign_ip, foreign_port}

看外部的4元组和您的协议/配置,您可能会发现每个外部NAT设备上此服务的状态条目不能超过一个,否则就会发生冲突。
此外,由于UDP没有握手,来自客户端的每个新数据包都可以启动一个新状态。因此,像您所描述的问题实际上是由于现有状态之间的冲突而不是状态缺失,就像TCP连接过期后仍然保持其动态NAT条目一样。
诸如NAT设备是否对所有可能的外部流量四元组进行区分以及状态条目的持续时间等细节通常是可配置的。它如何处理重叠状态可能会有所不同(最近创建的、最近使用的、阻止新的冲突状态),但通常不可配置。尽管如此,假设有各种各样的NAT设备(即没有一个主导电信公司拥有单一配置),如果确保您的客户端在良好配置的NAT设备后面至少有多个非冲突的外部4元组可用,则会获得良好的平均结果。
  • 如果客户端使用DNS获取服务器,则在尽可能多的IP上进行轮询。每次将服务器可以拥有的IP数加倍,您在每个NAT设备上都有两倍数量的非冲突状态。

  • 在每个可以更改一半客户端发送到不同服务器端口或选择不同客户端端口的机会上,您也会增加非冲突状态的数量,除了配置不良的NAT设备。由于端口并不稀缺,这比获得IP块(或区域块)要实际得多。

  • 最后一种可能性是向应用程序级协议添加复杂性。例如,在默认端口上,仅让服务器发送一个新的端口号。我会小心,以免慢慢重新实现现有服务,如STUN

随机端口的注意事项

如果客户端的端口设置与服务器不同,那么先前可能会遇到显著的过滤(无论何时有动态NAT,都有所有状态过滤的先决条件,因此没有过滤的NAT很少见)。在这种情况下,最好不要使用随机端口,而是选择地址空间中较高的一千个左右的块。如果客户端具有与服务器相同的端口,则先前选择“匹配端口”的人可能同样混乱或懒惰,此时最好从随机高端口绑定开始以最小化冲突,然后当客户端无法连接时回退到最佳测试。在任一情况下,您都必须寻找已经依赖于固定客户端端口的地方。

较不可能的可能性

如果您的服务器支持多个客户端应用程序或客户端应用程序是线程化、分叉等,那么这些可能实际上是来自同一设备上不同上下文的两个sendmsgs。在UDP中,4元组不一定是独占的,就像在TCP中一样,但是您很可能已经了解足够多关于您的系统和协议,以排除这种可能性。
如果您的客户端被直接分配真实地址并继续使用它们进行重新分配,我会说要么操作系统不知道这一点,这些客户端除了您的服务之外还应该有很多问题,要么操作系统知道但做得不够充分,例如将它们标记为过时但对于客户端仍然可访问,如果它们坚持绑定端口。我对此有些怀疑,因为这需要在客户端的网络管理中进行重大超工程,并且在电信网络方面进行不足的工程,因此我认为只有少数客户端会以这种方式出现,而您可能会由于丢失流量等其他难以描述的错误而遇到其他更难以解决的错误。尽管如此,我仍然建议:
- 鼓励客户端不要重用配置的套接字或任何依赖于本地地址的get*查找中使用的内容。

请告诉我您是否知道NAT部分在ISP端。假设我有100张GSM卡,每张卡都有一个ICCID,为什么内部IP会是相同的呢?我问这个问题是因为我不知道我是否已经清楚地表达了这个信息。我会多次阅读您的答案以充分理解。 - user246100
@user246100,使用DNAT时,您的客户端每个都有一个不同的内部IP地址,但只有一个外部IP地址的NAT设备一次只能将其中一个IP与服务器连接关联在一起,给定固定端口,因此另一个客户端什么也得不到。使用随机客户端端口,状态引擎可以具有许多关联,因为客户端端口是正确的内部IP状态条目的唯一索引。虽然您的客户端可能会遇到其他重新分配等问题,但我所描述的情况是有状态共享IP网络可以做到的最理论化的情况。>1:10k的理论碰撞率很高。 - lossleader

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接