首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止内核处理绑定到原始套接字的TCP段。

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

Stack Overflow用户
提问于 2015-08-01 13:20:54
回答 3查看 2.7K关注 0票数 7

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

  1. 我假设原始套接字是在第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_TCP (socketFd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);)协议创建原始套接字时,我的应用程序接收TCP数据包,但是内核也会响应这些数据包(在我的例子中,它是RSTs链接)。我认为这是因为内核认为没有人在监听该数据包的端口。

我的意图只是发送响应的消息来我的应用程序与一个假的IP和TCP报头。由于上述任何尝试都没有对我有效,我应该如何创建原始套接字并使内核TCP层只对该连接保持安静?

编辑:请跳过问题1-3.菲律宾已经回答了这些问题。对于问题4,我们确实有一个解决办法。但是,如果这里有人有答案,并且想要回答的话,那就让问题公开吧。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-01 13:54:00

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

不是的。原始套接字基本上是第三层数据包,这是正确的,但是协议不应该是IPPROTO_IP。对于原始套接字,协议参数指示您感兴趣在该套接字上接收哪种类型的数据包。请记住,协议本质上执行传输级解复用器,因此您需要指定您的原始套接字感兴趣的协议类型。这一点在man 7 raw中已经很清楚了。

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

由于您对接收TCP连接的IP数据包感兴趣,所以应该使用IPPROTO_TCP

但是,当我以IPPROTO_IP (*socketFd = socket(AF_INET,SOCK_RAW,IPPROTO_IP))的协议创建原始套接字时,如果错误协议不受支持,套接字创建就会失败。

是的,这是可以预料的: IP协议不是第四层协议。正如我所说,协议字段用于传输层解复用,所以使用IPPROTO_IP没有什么意义。

当我以IPPROTO_RAW (*socketFd = socket(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 = socket(AF_INET,SOCK_RAW,IPPROTO_TCP))创建原始套接字时,我的应用程序接收TCP数据包,但是内核也会响应这些数据包(在我的例子中,它是RSTs链接)。我认为这是因为内核认为没有人在监听该数据包的端口。

您不能阻止内核完成它的工作。从原始套接字手册页:

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

因此,内核发送RST数据包是正确的,因为它不知道指定端口上的活动TCP套接字或连接。正如我说过的,您不能阻止内核完成它的工作,但是一种相对快速(可能也很难看)的攻击是丢弃带有iptables的RST数据包:

代码语言:javascript
复制
iptables -A OUTPUT -p tcp --tcp-flags RST RST -j DROP

是的,不太优雅,但我认为我们在这里没什么可做的。

正如注释中所建议的那样,您还可以创建绑定到仅接收和丢弃消息的同一个端口和地址的虚拟TCP套接字。这样,内核就不会发送RST回复,您也不需要处理iptable。

还请记住,由于您需要为原始套接字指定IPPROTO_TCP,所以应该使用setsockopts(2)在套接字上设置IP_HDRINCL,以便可以构建自定义IP报头。

最后,确保运行该进程的有效用户ID为0或CAP_NET_RAW功能(在实践中:以根用户身份运行它)。

票数 8
EN

Stack Overflow用户

发布于 2015-08-01 17:07:11

这是对Jonathon的评论,但我没有足够的声誉

关于AF-数据包套接字

用AF_PACKET创建原始套接字在man packet中描述。“协议”变量的值应该是以网络字节顺序表示的以太类型的值。这些值是以<linux/if_ether.h> (按主机字节顺序)定义的。因此,若要打开原始套接字,请执行以下操作

socketFd = socket ( AF_PACKET , SOCK_RAW , htons ( ETH_P_IP ) );

如果AF_PACKET套接字是您所需要的,您也可以使用libpcap。它将允许您捕获以太网帧并发送原始以太网帧。为了捕获,您可以设置一个筛选器来确定您想要的帧(例如,TCP端口X)。(基本上,使用libpcap,您可以做与AF_PACKET套接字相同的事情,但更容易)

指向捕获指南发送手册页的链接

票数 0
EN

Stack Overflow用户

发布于 2015-08-01 13:48:06

这里的链接http://www.tenouk.com/Module43a.html是从回答这个问题的Linux上C/C++中简单的原始套接字服务器中检索的,它建议您必须是根用户或以setuid0的身份运行才能使用原始套接字。

代码语言:javascript
复制
/* Must be root or SUID 0 to open RAW socket */
...
 /* Create RAW socket */

   if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)

   {

    perror("socket() error");

    /* If something wrong, just exit */

    exit(1);

   }
票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31762305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档