【问题标题】:Raw socket bound to device not receiving all packets绑定到设备的原始套接字未接收到所有数据包
【发布时间】:2019-11-28 21:03:05
【问题描述】:

我有一个绑定到已经处于混杂模式的设备的原始套接字:

int sock = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
if(sock == -1)
{
   return -1;
}

struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_ifrn.ifrn_name, "eth0", IFNAMSIZ);
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
{
    close(sock);
    return -2;
}

while(1) {
  packet_size = recvfrom(sock , buffer , 65536 , 0 , NULL, NULL);
  // packet processing...
}

我的问题是我只在我的套接字上接收 IP 目标与我绑定的设备 (eth0) 的 IP 匹配的数据包。如何接收设备正在接收的所有 TCP 数据包?我可以在 Wireshark 中看到设备上的所有 TCP 数据包,但我在原始套接字中看到的唯一数据包是那些发往设备 IP 的数据包。

【问题讨论】:

  • 此代码块:if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &amp;ifr, sizeof(ifr)) &lt; 0) { close(sock); return -2; } 需要从您的代码中删除,因为 ifr 结构尚未初始化
  • @user3629249 更新了代码块,很抱歉在复制简化版本的代码时出现错误
  • 你不应该也设置数据包掩码吗?看到这个stackoverflow.com/questions/12177708/…stackoverflow.com/questions/114804/…
  • @TarunLalwani 谢谢,我已经为我感兴趣的特定接口添加了数据包掩码

标签: c linux sockets linux-kernel raw-sockets


【解决方案1】:

接收仅指向您设备 IP 的数据包的原因是您使用的是PF_INET 原始套接字。当使用 PF_INET 原始套接字时 - skb 在穿过堆栈时面临不同的健全性检查(见下文)。

F.e. :

int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
{
    /*...*/

    /* When the interface is in promisc. mode, drop all the crap
     * that it receives, do not try to analyse it.
     */
    if (skb->pkt_type == PACKET_OTHERHOST)
        goto drop;

所以呼叫跟踪类似于:__netif_receive_skb_core()->ip_rcv()->...->ip_local_deliver()->...->raw_local_deliver()->raw_rcv()->...- >tcp_rcv()(可以通过trace-cmd查看trace)。

但是 tcpdump/Wireshark 在__netif_receive_skb_core() 附近获取数据包,即在一些健全性检查之前。因此,差异让您感到困惑。

因此,如果您希望 skb 绕过大部分 Linux 内核网络堆栈 - 您应该使用 PF_PACKET 原始套接字。

Useful link

【讨论】:

猜你喜欢
  • 2017-04-09
  • 1970-01-01
  • 2016-09-14
  • 2022-01-01
  • 2014-07-06
  • 2018-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多