防止内核处理绑定到原始套接字的TCP段

拉吉·库玛(Raj Kumar)

根据http://linux.die.net/man/7/raw的介绍,这raw_socket = socket(AF_INET, SOCK_RAW, int protocol);是创建原始套接字的方法。

  1. 我假设raw-socket是在第3层上创建的,因此协议不应该IPPROTO_TCP/IPPROTO_UDP而是应该IPPROTO_IP这种理解正确吗?

  2. 但是,当我使用协议IPPROTO_IP*socketFd = socket(AF_INET, SOCK_RAW, IPPROTO_IP);创建原始套接字时,套接字创建失败,并显示错误协议不支持

  3. 当我使用协议IPPROTO_RAW*socketFd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);创建原始套接字时,我的应用程序未收到任何数据包

  4. 当我使用IPPROTO_TCPsocketFd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);协议创建原始套接字时,我的应用程序会接收TCP数据包,但内核也会响应这些数据包(在我的情况下,它会RST链接)。我认为这是因为内核认为没有人在听该数据包打算到达的端口。

我的意图只是使用伪造的IP和TCP标头发送对到达我的应用程序的消息的响应。由于上述任何尝试都不适合我,我应该如何创建原始套接字并使内核TCP层仅对该连接保持安静?

编辑:请跳过问题1-3。Filipe已经回答了他们。对于问题4,我们确实有一种解决方法。但是,如果有人在这里有答案并想回答,请不要提出任何疑问。

菲利普·贡萨尔维斯(FilipeGonçalves)

我假设原始套接字是在第3层上创建的,因此协议不应为IPPROTO_TCP / IPPROTO_UDP,而应为IPPROTO_IP。这种理解正确吗?

正确。原始套接字基本上是第3层数据包,但是协议不应该是IPPROTO_IP如果使用原始套接字,则协议参数指示您希望在该套接字上接收哪种类型的数据包。请记住,协议基本上执行传输层解复用,所以你需要指定什么类型的协议,你的原始套接字的兴趣在于这是在明确。man 7 raw

与原始套接字指定的协议号匹配的所有数据包或错误都将传递到此套接字。有关允许的协议的列表,请参阅RFC 1700分配的编号和getprotobyname(3)。

由于您有兴趣接收用于TCP连接的IP数据包,因此应使用IPPROTO_TCP

但是,当我使用协议将原始套接字创建为IPPROTO_IP(* socketFd =套接字(AF_INET,SOCK_RAW,IPPROTO_IP);)时,套接字创建失败,并显示错误协议不支持。

是的,这是可以预期的:IP协议不是第4层协议。就像我说的,协议字段用于传输层多路分解,因此使用几乎没有意义IPPROTO_IP

当我使用协议将原始套接字创建为IPPROTO_RAW(* socketFd =套接字(AF_INET,SOCK_RAW,IPPROTO_RAW);)时,我的应用程序未收到任何数据包

这是因为这IPPROTO_RAW意味着您对发送所有类型的协议数据包(TCP,UDP或任何其他协议)感兴趣。但是,IPPROTO_RAW您不能做相反的事情:IPPROTO_RAW这意味着您可以在此原始套接字中接收任何协议,但不支持该协议。这在以下内容中也很清楚man 7 raw

IPPROTO_RAW协议表示已启用IP_HDRINCL,并且能够发送在传递的标头中指定的任何IP协议。使用原始套接字无法通过IPPROTO_RAW接收所有IP协议。

换句话说,IPPROTO_RAW它使您能够发送与任何协议匹配的数据包,但这样做的代价是阻止您获得答复。您可以创建与协议绑定的其他特定原始套接字,以获取答复,这是一种解决方法,但这会使设计复杂化,因为您必须管理原始套接字池,并且绝对不是您想要在此处执行的操作。

当我创建协议为IPPROTO_TCP的原始套接字(socketFd =套接字(AF_INET,SOCK_RAW,IPPROTO_TCP);)时,我的应用程序会收到TCP数据包,但内核也会响应这些数据包(在我的情况下,它会RST链接)。我认为这是因为内核认为没有人在听该数据包打算到达的端口。

您不能阻止内核完成其工作。从原始套接字的联机帮助页:

接收到数据包后,它会先传递到已绑定到其协议的任何原始套接字,然后再传递给其他协议处理程序(例如,内核协议模块)。

因此,您是对的,因为内核RST不知道指定端口上的活动TCP套接字或连接,因此内核发送了一个数据包。就像我说的那样,您不能阻止内核完成其工作,但是一个相对较快(也许很丑陋)的破解方法是使用iptables丢弃RST数据包:

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

是的,不是很优雅,但是我认为我们在这里不能做太多事情。

如注释中所建议,您可能还会创建一个虚拟TCP套接字,该套接字绑定到您刚刚接收和丢弃消息的相同端口和地址。这样,内核将不会发送RST答复,并且您无需弄乱iptables。

还要记住,由于需要IPPROTO_TCP为原始套接字指定IP_HDRINCLsetsockopts(2)因此在套接字上设置with,以便可以构建自定义IP标头。

最后,确保运行此进程的进程的有效用户ID为0或具有该CAP_NET_RAW功能(实际上:以root身份运行)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章