必须以root权限或cap_net_raw能力使用af_packet(linux)/af_link(macos)原始套接字,手动构造含目的mac、源mac、ethertype及载荷的完整以太网帧,长度不足64字节需自行填充,网卡硬件生成crc。

需要 root 权限和原始套接字支持
直接构造并发送以太网帧在用户态无法绕过内核协议栈,必须用 AF_PACKET 套接字(Linux)或 AF_LINK(macOS),且进程需有 CAP_NET_RAW 能力或以 root 运行。普通 AF_INET 套接字只能到 IP 层,发不出带自定义 MAC 头的帧。
常见错误现象:socket(): Operation not permitted(没权限)、sendto(): Invalid argument(地址结构填错)、发出去但对方收不到(目标 MAC 不对或网卡没混杂模式)。
- Linux 下优先用
SOCK_RAW+AF_PACKET,绑定到具体接口(如"eth0") - 不要用
SOCK_DGRAM——它会自动补 MAC 头,你没法控制源/目的 MAC - 确保目标 MAC 地址真实可达(可用
arp -n或ip neigh查)
构造帧时必须手动填充 MAC 头和载荷
以太网帧格式是:6 字节目的 MAC + 6 字节源 MAC + 2 字节 EtherType + 载荷(最小 46 字节)。内核不校验、不补零——长度不足要自己填充;CRC 也不用算,网卡硬件自动生成。
示例关键片段(Linux):
uint8_t frame[1024]; // 目的 MAC memcpy(frame, dst_mac, 6); // 源 MAC(需从接口获取,不能硬写) memcpy(frame + 6, src_mac, 6); // EtherType:0x0800 = IPv4, 0x0806 = ARP frame[12] = 0x08; frame[13] = 0x00; // 然后接你的载荷(比如一个 ICMP 包) memcpy(frame + 14, payload, payload_len); // 补齐到最小长度(64 字节帧,含 14 字节 MAC 头 → 载荷至少 46 字节) size_t total_len = 14 + payload_len; if (total_len
-
src_mac必须从实际网卡读取(ioctl(SIOCGIFHWADDR)),写错会导致交换机丢包 - EtherType 不能为 0x0000–0x05DC(这些是 IEEE 802.3 长度字段,会被内核当 legacy 帧处理)
- 别忘了
struct sockaddr_ll的sll_addr字段要设成全 0,否则sendto()可能覆盖你填的 MAC
sendto() 的地址结构容易填错
用 AF_PACKET 发原始帧,sendto() 的 addr 参数不是 IP 地址,而是 struct sockaddr_ll,其中关键字段是:sll_ifindex(接口索引)、sll_halen(MAC 长度,填 6)、sll_addr(这里**必须清零**)。
常见错误:sll_addr 里填了 MAC,结果内核把帧头又覆盖一遍,发出双份 MAC 头;或者 sll_ifindex 为 0,帧被发到“any”接口,行为未定义。
- 用
if_nametoindex("eth0")获取sll_ifindex -
sll_halen = 6,sll_addr[8] = {0}(显式清零,别依赖栈初始化) -
sll_protocol填htons(ETH_P_ALL)或对应 EtherType,不影响发送,但建议保持一致
跨平台差异大,Windows 上基本不可行
Windows 默认禁用原始二层发送,需要 NDIS 驱动或 WinPcap / Npcap 库(本质是绕过 TCP/IP 栈的第三方内核模块)。标准 Win32 API 中 AF_PACKET 不存在,SOCK_RAW 只支持 IP 层以上。
如果你的目标环境不确定是 Linux 还是 macOS,别试图封装统一接口——二者 AF_PACKET 和 AF_LINK 的结构、标志、错误码完全不同。先明确部署平台再写。
- macOS 用
BPF(/dev/bpf*)更底层,需ioctl(BIOCSETIF)绑定接口,比 LinuxAF_PACKET更繁琐 - 即使在 Linux,不同发行版内核版本可能影响
PACKET_TX_RING等高级特性,简单sendto()最稳妥 - 注意网卡 offload 功能(如 TSO/GSO)可能干扰自定义帧,必要时用
ethtool -K eth0 tx off关闭
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











