为什么 linux 会重新发送数据包并更改 RAW 套接字 unix 的标头

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

我在下面有这段代码,我用

sendto
函数在 unix 上发送原始套接字。效果很好。如果数据包是 802.11 帧,当我发送数据包时,操作系统会重新发送数据包并进行一些修改。

我的802.11 Radiotap标头通常是26字节,数据包末尾有一个4字节的FCS(帧校验序列)。

重发数据包的标头减少到 13,并且 FCS 被删除。所以每帧都缺少 17 个字节。不仅丢失了,而且标题被完全修改了。

这是一个来自wireshark的例子。我发送 802.11 帧、ack 数据包(40 字节)和身份验证数据包(60 字节),它们会被操作系统修改并重新发送。(我在 ubuntu 和 kali linux 上尝试过。相同的行为)。您将看到

40
60
是我发送的数据包,其余数据包如所解释的那样被删除了 17 个字节。

这里是有关数据包的更多信息,这是我发送的原始数据包的标头标志..(如所述 26 个字节)

这是修改后的标头,也是操作系统发送的标头。

注意一些标记,如

Channel
dbm Antenna signal
等已被删除,并且
data retries
TX
已被标记。

我使用支持监控模式的自定义网络适配器来发送原始数据包。我知道,由于我从另一个程序硬复制粘贴身份验证数据包以使用我的适配器发送,因此 MACTIMESTAMP 可能是错误的,或者 dbm 和通道可能被修改。 (即使 802.11 帧上不存在通道/dbm 信息)

为什么linux和ubuntu要这样做?因为 ack 帧是从内置适配器硬拷贝的,我知道信号 dbm/channel 可能会被修改,但为什么操作系统会重新发送?

我也在 ubuntu 20.04 和 kali linux 上尝试过这个。他们的行为都是一样的。因此,这是 Linux 的一个基本行为,即重新发送使用

sendto()
发送的原始 802.11 帧。

这是我用 C 创建的 ack 数据包,

unsigned char acknowledgePacketToIphone7PlusFromTPLINK[] = {
        0x00, 0x00, 0x1a, 0x00, 0x2f, 0x48, 0x00, 0x00, 0x49, 0x42, 0xb7, 0x63, 0x00, 0x00, 0x00, 0x00,
        0x10, 0x02, 0x99, 0x09, 0xa0, 0x00, 0xd2, 0x01, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x82, 0xd6,
        0xb0, 0x18, 0x38, 0x7f, 0x6b, 0x14, 0xdf, 0x38
};

这是我的代码,与此无关。此外,例如,当我将每个字节切换为

0x01
(因此禁用 802.11 形成)时,不会发生这种重新发送行为

#include <net/ethernet.h> 

//initialize data
struct sockaddr_ll ll; // => link layer
struct ifreq ifreq_i;

int sock_raw = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); // => socket is layer 2


//Network Interface Name
memset(&ifreq_i,0,sizeof(ifreq_i)); memset(&ll,0,sizeof(ll));
strncpy(ifreq_i.ifr_name,"wlan1",IFNAMSIZ-1); 
 
if((ioctl(sock_raw,SIOCGIFINDEX,&ifreq_i))<0) printf("index failed");
 
printf("indeks=%d\n",ifreq_i.ifr_ifindex);

ll.sll_ifindex = ifreq_i.ifr_ifindex; ll.sll_protocol = htons(ETH_P_ALL); ll.sll_family = PF_PACKET;

//binding socket to the interface
if(bind(sock_raw, (struct sockaddr *)&ll, sizeof(ll)) == -1){ printf("Err: bind failed %d\n", errno); }

unsigned char *buffer = (unsigned char *)malloc(65526); //memset(&buffer, '\0', 65511);


int sendlen = sendto(sock_raw, &auth, sizeof(auth), 0, 0, 0);

我怎样才能在Linux上阻止这种情况,或者确切地了解为什么会发生这种情况?非常感谢。

c sockets networking ieee 802.11p
1个回答
0
投票

这里是有关数据包的更多信息,这是我发送的原始数据包的标头标志..(如所述 26 个字节)

您将“radiotap”标头与 802.11 标头混淆了。不存在“802.11 Radiotap”这样的东西。

“Radiotap”不是真正的标头;它不是发送或接收的 802.11 数据包的一部分。这是一个“仅捕获”伪标头,描述了在捕获过程中记录了除实际数据包之外的“环境”信息,但实际的 802.11 帧没有这些信息,因此没有任何意义尝试通过套接字发送它。 由于 Radiotap 伪标头描述的是捕获“环境”而不是捕获的数据,因此本地发送的帧具有与通过物理天线接收的帧不同的参数是完全正常的。这本身并不会改变发送的数据包数据。

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