You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Raw Socket无法捕获指定接口的DHCP数据包但Wireshark可捕获

问题原因

你创建Raw Socket时指定了IPPROTO_TCP作为第三个参数:

int sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);

Linux内核会根据这个参数过滤数据包,只将TCP协议的IP数据包交付给该socket,UDP、ICMP等其他协议的数据包会被内核直接忽略,不会传递到你的程序中——这就是DHCP(UDP协议)流量抓不到,但TCP流量能正常捕获的核心原因。

修复方案

将socket创建时的协议参数改为IPPROTO_IP,这样内核会把所有IP层的数据包(包括TCP、UDP、ICMP、IGMP等)都交付给你的socket:

int sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);

修改后的关键代码片段如下(同时补充了错误信息输出,方便排查问题):

int main()
{    
    unsigned char *buffer = (unsigned char *)malloc(65536); // 足够容纳最大IP数据包
    
    printf("Starting...\n");
    // 修改协议参数为IPPROTO_IP,接收所有IP层数据包
    int sock_raw = socket(AF_INET , SOCK_RAW , IPPROTO_IP);

    if(sock_raw < 0)
    {
        perror("socket creation failed");
        abort();
    }

    int r = setsockopt(sock_raw, SOL_SOCKET, SO_BINDTODEVICE, "wlp3s0", strlen("wlp3s0"));
    
    if (r == -1)
    {
        perror("bind to device failed");
        abort();
    }
   
    while(1)
    {
        int data_size = recv(sock_raw , buffer , 65536 , 0);
        
        if(data_size <0 )
        {
            perror("recv failed");
            abort();
        }

        ProcessPacket(buffer , data_size);
    }
    
    ::close(sock_raw);
    return 0;
}
补充说明
  1. Raw Socket协议参数的作用:

    • IPPROTO_TCP:仅接收TCP协议的IP数据包
    • IPPROTO_UDP:仅接收UDP协议的IP数据包
    • IPPROTO_IP:接收所有IP层数据包(需root权限)
    • 其他协议值对应各自的网络层/传输层协议
  2. 若仅需捕获特定几种协议(比如TCP+UDP),也可以分别创建两个Raw Socket,分别指定IPPROTO_TCP和IPPROTO_UDP,再用select()或epoll()实现多路复用,但这种方式比直接使用IPPROTO_IP更复杂,适合有严格过滤需求的场景。

  3. 始终以sudo权限运行程序,Linux下Raw Socket的创建需要root权限。

内容的提问来源于stack exchange,提问作者intrigued_66

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:22:50