一尘不染

如何获取重定向的UDP消息的原始目标端口?

linux

使用这个东西,我可以获得socket(PF_INET, SOCK_DGRAM,0)套接字的原始目标IP地址。

如何获得原始目标端口?


阅读 733

收藏
2020-06-07

共1个答案

一尘不染

取决于重定向机制。如果使用的是REDIRECT(实际上是NAT),则需要在应用NAT之前使用SO_ORIGINAL_DST或libnetfilter_conntrack来查询连接的原始目标。但是,由于可以使用同一个侦听器套接字为多个连接提供服务,因此必须对每个数据包执行此查找。

您可以使用conntrack命令行工具尝试libnetfilter_conntrack及其提供的服务。

一种替代方法是使用TPROXY进行重定向,这是在这种情况下使用的。在那里,您可以使用recvmsg()使用辅助消息获得数据包的原始目标。查找的关键是IP_RECVORIGDSTsetsockopt。

关于TPROXY的更多信息可以在内核文档目录的tproxy.txt文件中找到。它有点难用,但是由于它是由堆栈而不是数据包过滤子系统实现的,因此工作更可靠。

编辑: 添加如何使用TProxy查询UDP目标地址。

  1. 打开UDP套接字,将其绑定到0.0.0.0或更特定的IP
  2. 您可以通过setsockopt(fd,SOL_IP,IP_RECVORIGDSTADDR,…)启用IP_RECVORIGDST
  3. 您使用recvmsg()代替recvfrom()/ recv()接收帧
  4. recvmsg()将返回数据包和一系列辅助消息,
  5. 迭代辅助消息,并找到级别为SOL_IP,索引为IP_ORIGDSTADDR的CMSG块
  6. 此CMSG块将包含结构sockaddr_in,其中包含IP和端口信息。

编辑: SO_ORIGINAL_DST与udp

SO_ORIGINAL_DST应该与udp套接字一起使用,但是内核不允许您指定连接端点,它将使用您调用SO_ORIGINAL_DST的套接字来获取此地址信息。

这意味着只有将UDP套接字正确绑定(绑定到重定向到的地址/端口)并连接(绑定到有关的客户端),它才会起作用。您的侦听器套接字可能绑定到0.0.0.0,并且不仅为单个客户端提供服务,而且还为多个客户端提供服务。

但是,您不需要使用实际的侦听器套接字来查询目标地址。由于UDP在建立连接时不会传输数据报,因此您可以创建一个新的UDP套接字,将其绑定到重定向地址,然后将其连接到客户端(您知道的地址,因为它无论如何都会将第一个数据包发送给侦听器)。然后,您可以使用此套接字在其上运行SO_ORIGINAL_DST,但是有罪魁祸首:

  1. 一旦打开了这样的套接字,内核将更喜欢客户端在第一个套接字之后发送其他数据包,而不是侦听器套接字
  2. 这是固有的习惯,因为到您的应用程序有机会调用SO_ORIGINAL_DST时,conntrack条目可能已超时。
  3. 它很慢而且开销很大

基于TProxy的方法显然更好。

2020-06-07