繁体   English   中英

使用套接字 AF_PACKET / SOCK_RAW 但告诉内核不要发送 RST

[英]Using socket AF_PACKET / SOCK_RAW but tell kernel to not send RST

我的问题在这里已经大致讨论过

而 tl;dr 解决方案是:

iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

您可以修改它以仅阻止您正在积极侦听的端口。
但是正如上面的问题和这里提到的,这些都不是优雅的解决方案。

现在,我真的不在乎事物的优雅。
但我确实在乎学习。 因此,我深入研究了 Linux 源代码(目前主要对基于 Linux 的机器感兴趣)并整理了我认为的socket.bind方法,以便找到与指示“我们”正在积极监视的内核相关的任何内容一个 TCP 端口。

我假设套接字库通知内核一些特定端口绑定到应用程序的情况,这样内核就不会自动使用RST数据包响应客户端连接,提示“连接被拒绝”

但是,我在源代码中找不到这样的代码。
数据包手册页也没有告诉我如何通知内核忽略/接受来自特定端口的数据包。

我有一个非常基本的套接字设置来以混杂模式收听(这是它自己的故事)

但是,我的问题是,一旦客户端在任何给定端口上连接 - 内核按预期的方式发送传入的Ethernet+IP+TCP数据帧 - 但它也会立即发送具有“反向”源和目标的响应端口和RST标志集。 它应该,但不是在我告诉它的特定端口上。 问题是,我如何告诉内核我正在监视特定端口?

一种选择是(如在其他一些论坛和其他各种 SO 线程中讨论的那样) - 在该端口上创建一个虚拟套接字。

s = socket()
s.bind(('', <port>))

然而,这会导致一系列其他问题(其中一个是这将有一个很快就会被填满的缓冲区) ,最重要的是,仍然没有告诉我所有这些魔法是如何发生的。 如果没有其他方法,上述两种解决方案是最后的手段,但我觉得我比以往任何时候都更接近,但也比以往任何时候都更难找到解决这个问题的适当方法。

解决方案或提示也可以在C 中,和/或内核模块,只是为了指示内核所需的信息。 我知道这一切都在内核中发生了,在下面的评论和一个非常感谢的解决方案想法之后,我现在知道没有用户空间功能可以解决这个问题。 我可能/轻松地将它移植到 cPython 模块,或者使用内核模块/扩展轻松地将它转换为 Python 代码。 但是我真的不知道设置这些东西的内核函数在哪里,或者它们叫什么。

我挖得很深,很远很浅。但似乎没有其他人需要这样做。 主要是因为混杂的套接字旨在获取流量并对其进行分析。 .bind((interface, protocol))也在那里,它面临着同样的问题,一种不进入混杂模式而是只接收 TCP 数据包的方法,例如通过执行.bind((interface, 0x0800))

我可能在这里man 7 netdevice了,但也许man 7 netdevice只是给了我一个想法。 我正在尝试设置SystemTap以检查调用ioctl()作用以及socket()对象如何请求文件描述符。 可能是关于这一切如何发生的线索。 让 SystemTap 工作很棘手。

任何人都有任何其他线索如何解决这个问题或以前遇到过这个问题?

附言。 对不起,我问了一个模糊的问题,我不知道这些低级事物的正确术语是什么。 因为他们对我来说很新。

编辑:我可能一直在寻找错误的地方bind() ,根据ipv4.af_inet实现,它将尝试调用套接字bind()函数,但如果没有,它将尝试在这里设置很多魔法. 在这里,他们在af_inetaf_inet ,做了很多表垃圾..我仍然没有找到解决方案,但也许已经迈出了一步......或者最坏的情况是,又一次鹅狩猎。

更进一步, selinux/hooks.c 也包含一些绑定功能。 也许更多的安全相关,但仍然值得我调查。 仍然无法解决这个该死的谜语。

这里的问题是,您正在寻求一种方法来告诉内核实际上“为我做这 100 件事,但忽略这个特定的细节”。 坦率地说,我认为 iptables 的解决方案是最简单和最干净的。

但是,另一种选择是要求内核完成所有其他工作,而是自己承担更多工作。 具体来说,自己编一个IP地址,然后开始使用。 唯一的缺点是你必须接管内核一直在为你做的另一件重要的事情:响应 ARP(ARP 用于发现拥有给定 IP 地址的站的 MAC [以太网] 地址)。 简而言之,我建议你:

  1. 在本地子网上选择一个未使用的 IP 地址。
  2. 组成一个 MAC 地址供您使用。 (并非绝对必要,但可以更轻松地区分“您的”流量。)
  3. 打开原始数据包套接字而不是原始 IP 套接字 ( https://linux.die.net/man/7/packet )。
  4. 编写并发送 ARP 请求以发现您要发送到的站的 MAC 地址(如果在本地 LAN 上,否则为下一跳 [路由器] IP 地址的 MAC)。
  5. 收到ARP回复,记录对方的MAC。
  6. 构建您的 SYN 数据包并将其从您自己的 MAC 地址发送到目标站的 MAC。 (使用您选择的源和目标 IP、端口等)
  7. 侦听您的 IP 的返回 ARP 并根据需要进行回复。
  8. 接收 SYN+ACK 响应。 由于内核不知道目标 IP 地址(您创建的 IP 地址)属于您的系统,因此内核不会使用 RST(或其他任何内容)响应 SYN+ACK。
  9. 做你接下来想做的事……

如果您使用的 MAC 地址不是分配给接口的 MAC 地址,则您当然必须进行混杂的捕获。 这对于原始数据包套接字来说非常典型。 此外,您将为所有流量构建以太网标头、IP 标头和 TCP 标头(嗯,用于 ARP 请求的以太网 + ARP),因此您将学到很多东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM