AF_PACKET 套接字在 Linux 中如何工作?

问题描述 投票:0回答:1

我正在尝试为 Linux 编写一个 C 嗅探器,并了解嗅探时内核中发生的操作。

我无法找到以下问题的答案: 如果我通过以下方式初始化套接字:

sock_raw = socket(AF_PACKET , SOCK_RAW , htons(ETH_P_ALL));

内核中发生了什么?我如何看到所有传入和传出的数据包,但不“劫持”它们?因为我到目前为止所理解的是,当内核收到数据包时,它将其发送到相关的协议处理函数。因此我无法理解 - 除了我打开的套接字之外,内核还会克隆数据包并发送它吗?

c linux sockets linux-kernel
1个回答
10
投票

内核中发生了什么?

内核一旦从物理层接收到数据包(对于传入数据包)或在将它们发送到物理层(对于传出数据包)之前,就会简单地复制数据包。每个数据包的一份副本将发送到您的套接字。如果您使用 ETH_P_ALL,那么您正在监听所有接口,但您也可以

bind(2)
监听特定接口。将副本发送到套接字后,另一个副本将像平常一样继续处理。例如,识别和解码协议、检查防火墙规则等

我如何看到所有传入和传出的数据包,而不是“劫持”它们?

为了发生

劫持
,您需要将数据

写入到注入新数据包的套接字(根据您想要劫持的协议准确制作)。如果您只读取传入的数据包,那么您只是嗅探,而没有劫持任何东西。 除了我打开的套接字之外,内核是否克隆数据包并发送它?

是的,基本上就是这样。

这张图片
可以帮助您直观地看到它(点击放大):

linux kernel packet flow

man 7 packet

也描述了这一点:


数据包套接字用于在设备驱动程序(OSI 第 2 层)级别接收或发送原始数据包。它们允许用户在物理层之上的用户空间中实现协议模块。

socket_type

是包含链路级标头的原始数据包的

SOCK_RAW

,或者是删除了链路级标头的熟数据包的 
SOCK_DGRAM
。链路级标头信息以 
sockaddr_ll
 结构中的通用格式提供。 
protocol
 是网络字节顺序中的 IEEE 802.3 协议号。请参阅 
<linux/if_ether.h>
 包含文件以获取允许的协议列表。当 
protocol
 设置为 
htons(ETH_P_ALL)
 时,则接收所有协议。 
该协议类型的所有传入数据包将先传递到数据包套接字,然后再传递到内核中实现的协议。


    

© www.soinside.com 2019 - 2024. All rights reserved.