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

时间:2011-04-11 00:02:23

标签: linux sockets udp redirect iptables

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

如何获得原始目的端口?

2 个答案:

答案 0 :(得分:10)

取决于重定向机制。如果您正在使用REDIRECT(它是引擎盖下的NAT),那么您需要使用SO_ORIGINAL_DST或libnetfilter_conntrack在应用NAT之前查询连接的原始目标。但是,由于您可以使用相同的侦听器套接字提供多个连接,因此必须对每个数据包执行此查找。

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

另一种方法是使用TPROXY进行重定向,这意味着要在这种情况下使用。在那里,您可以使用recvmsg()使用ancillirary消息获取数据包的原始目的地。要查找的关键是IP_RECVORIGDST setsockopt。

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

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

  1. 打开UDP套接字,将其绑定到0.0.0.0或更具体的IP
  2. 您通过setsockopt启用IP_RECVORIGDST(fd,SOL_IP,IP_RECVORIGDSTADDR,...)
  3. 使用recvmsg()而不是recvfrom()/ recv()来接收帧
  4. recvmsg()将返回数据包和一系列辅助消息,
  5. 迭代辅助消息,找到级别为SOL_IP的CMSG块,索引为IP_ORIGDSTADDR
  6. 此CMSG块将包含带有IP和端口信息的struct sockaddr_in。
  7. 已编辑: 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. 它很慢而且很多开销
    4. 基于TProxy的方法显然更好。

答案 1 :(得分:1)

尝试解析/proc/net/nf_conntrack