10

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

如何获得原始目的港?

4

2 回答 2

13

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

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

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

有关 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 块将包含一个 struct 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 的方法显然更好。

于 2011-04-28T06:39:35.160 回答
1

尝试解析/proc/net/nf_conntrack

于 2011-04-11T06:26:52.770 回答