如何获取重定向UDP消息的原始目标端口? [英] How to get original destination port of redirected UDP message?

查看:16
本文介绍了如何获取重定向UDP消息的原始目标端口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用这个东西我可以获得原版socket(PF_INET, SOCK_DGRAM, 0) socket的目的IP地址.

Using this thing I can obtain original destination IP address of socket(PF_INET, SOCK_DGRAM, 0) socket.

如何获取原始目的端口?

How to get original destination port?

推荐答案

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

Depends on the redirection mechanism. If you are using REDIRECT (which is NAT under the hood), then you need to use SO_ORIGINAL_DST, or libnetfilter_conntrack to query the original destination of the connection before NAT was applied. However since you can serve several connections with the same listener socket, this lookup has to be done for every packet.

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

You can experiment with libnetfilter_conntrack and the services it provides using the conntrack command line tool.

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

An alterntive is to use TPROXY for the redirection, which was meant to be used in cases like this. There you can get the original destination of the packet using an ancillirary message using recvmsg(). The key to look for is the IP_RECVORIGDST setsockopt.

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

More information on TPROXY can be found in the kernel Documentation directory, in a file called tproxy.txt. It is a bit difficult to use, but works more reliably as it is implemented by the stack, rather than the packet filtering subsystem.

添加如何使用 TProxy 查询 UDP 目标地址.

Edited: to add how to query UDP destination addresses with TProxy.

  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

Edited: SO_ORIGINAL_DST vs. udp

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

SO_ORIGINAL_DST should work with udp sockets, however the kernel doesn't let you specify the connection endpoints, it'll use the socket that you call SO_ORIGINAL_DST on to get this address information.

这意味着它只有在 UDP 套接字正确绑定(到重定向到的地址/端口)并连接(到有问题的客户端)的情况下才能工作.您的侦听器套接字可能绑定到 0.0.0.0,并且不仅为单个客户端提供服务,而且还为多个客户端提供服务.

This means that it'll only work, if the UDP socket is properly bound (to the redirected-to address/port) and connected (to the client in question). Your listener socket is probably bound to 0.0.0.0 and is servicing not just a single, but mulitple clients.

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

However, you don't need to use your actual listener socket to query the destination address. Since since UDP doesn't transmit datagrams on connection establishment, you can create a new UDP socket, bind it to the redirect address and connect it to the client (whose address you know since it sent the first packet to your listener anyway). Then you could use this socket to run SO_ORIGINAL_DST on, however there are culprits:

  1. 一旦你打开了这样一个套接字,如果客户端在第一个数据包之后发送额外的数据包,内核会更喜欢,而不是你的监听套接字
  2. 这本质上是不合理的,因为当您的应用程序有机会调用 SO_ORIGINAL_DST 时,conntrack 条目可能已经超时.
  3. 速度很慢,开销很大

基于 TProxy 的方法显然更好.

The TProxy based method is clearly better.

这篇关于如何获取重定向UDP消息的原始目标端口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆