raw socket需root权限:linux/macos下非特权进程调用socket(af_packet, sock_raw, …)或socket(af_inet, sock_raw, …)会报operation not permitted;windows需管理员身份运行,否则wsasocket返回invalid_socket。

Raw Socket需要root权限才能创建
Linux/macOS下用socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))或socket(AF_INET, SOCK_RAW, IPPROTO_IP)抓包时,内核会直接拒绝非特权进程的请求,报错Operation not permitted。Windows上虽然不强制要求管理员,但WinPcap/Npcap驱动实际仍需提升权限才能访问网卡底层数据。
实操建议:
- Linux:启动程序前加
sudo,或用setcap cap_net_raw+ep ./your_program授予权限(比sudo更安全) - macOS:必须用
sudo,且从 macOS 10.15 起还需关闭系统完整性保护(SIP)中对pfz和bpf设备的限制(不推荐关SIP,建议改用libpcap) - Windows:以管理员身份运行,否则
WSASocket返回INVALID_SOCKET,WSAGetLastError()为WSAEACCES
AF_PACKET比AF_INET更适合全链路抓包
AF_INET + SOCK_RAW只能拿到IP层及以上的数据(不含以太网帧头),且不同系统行为不一致:Linux默认过滤掉发往本机的数据包,Windows需额外调用WSAIoctl开启IP_HDRINCL并设置SOCK_RAW为IPPROTO_IP,但仍收不到ARP、ICMPv6邻居发现等非IP协议包。
实操建议:
- 抓完整二层帧(含MAC头、VLAN、LLC等),优先用
AF_PACKET(Linux独占) - 绑定接口时用
bind()配struct sockaddr_ll,sll_ifindex填if_nametoindex("eth0"),sll_protocol设为htons(ETH_P_ALL) - 注意
AF_PACKET返回的数据包含物理帧,首地址不是IP头——需手动跳过sizeof(struct ethhdr)再解析
recvfrom()返回长度可能小于MTU,别硬按65535读
即使分配了65535字节缓冲区,recvfrom()实际返回值常远小于此:Linux AF_PACKET默认使用TPACKET_V2,单次最多返回一个完整帧;而AF_INET下若未设置IP_HDRINCL,内核可能只返回IP载荷部分。
实操建议:
- 永远用返回值做边界判断,不要假设“一次必收完”
- 对
AF_PACKET,检查struct ethhdr->h_proto确认上层协议(如htons(ETH_P_IP)) - 对
AF_INET,记得用setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on))开启IP头透传,否则收不到IP头字段(TTL、ID、Flags等) - Windows下
WSARecvFrom()需配合WSAIoctl(... SIO_RCVALL ...)启用混杂模式,否则只收发给本机的包
没开混杂模式就抓不到其他主机流量
网卡默认只把目的MAC匹配本机、广播或组播地址的帧送入接收队列。Raw Socket本身不自动开启混杂(promiscuous)模式——这步必须显式控制。
实操建议:
- Linux
AF_PACKET:调用ioctl(sockfd, SIOCGIFINDEX, &ifr)获取接口索引后,再用ioctl(sockfd, SIOCETHTOOL, ðcmd)或直接写/sys/class/net/eth0/flags(不推荐) - 更可靠方式:用
system("ip link set eth0 promisc on")或依赖libpcap的pcap_set_promisc() - Windows下必须调用
WSAIoctl(sockfd, SIO_RCVALL, &buf, sizeof(buf), NULL, 0, &bytes, NULL, NULL),其中buf = RCVALL_ON - 注意:混杂模式会影响性能,且某些虚拟网卡(如Docker bridge、Hyper-V vSwitch)不支持
绕过权限、选错域、忽略帧边界、漏掉混杂开关——这四点踩中任意一个,recvfrom()就基本收不到有效数据。尤其AF_PACKET在不同内核版本对tpacket_auxdata的支持差异很大,生产环境建议先用tcpdump -i eth0 -dd生成BPF码验证路径是否通。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











