为什么系统在发送 IP 数据包之前不进行 ARP 请求广播?

为什么系统在发送 IP 数据包之前不进行 ARP 请求广播?

首先,让我简单描述一下这个问题。我有两个程序,它们将 IP 数据包从一个主机(192.168.0.101)发送到另一个主机(192.168.0.106)。这两个程序分别用 C 和 C++ 编写,但功能相同。

如果我运行 C 程序,当原始套接字要发送目标 IP 为 192.168.0.106 的 IP 数据包(该程序使 IP 数据包不带 MAC/以太网头)时,从 tcpdump 捕获的数据包中,我注意到主机广播了针对 192.168.0.106 的 MAC 的 ARP 查询,因此它可以成功地将数据包传送到该主机。

如果我运行 C++ 程序,它不会广播 ARP 来查询 192.168.0.106 的 MAC,并且它会将错误的 MAC 标头添加到 IP 数据包中,从而将其发送到错误的主机(在 C 程序和 C++ 程序场景中,它也与主机 192.168.0.101 通信)

我真的很困惑,为什么第一种情况下会发生 ARP 广播,而第二种情况下不会发生,这种差异有什么潜在原因吗?为什么系统在第二种情况下不进行 ARP 请求广播,从而导致错误传递?


很长的故事:

我有三台笔记本电脑接入WLAN,A和C使用wlan0,但B通过有线连接到无线路由器,并使用eth0。

我写了一个C程序做TCP劫持实验,然后将其修改为C++程序。

  1. A与B建立TCP连接
  2. C 运行该程序并伪装成 B,因此它发送 src_ip = IP(B) 和 dst_ip = IP(A) 的数据包
  3. 我使用 tcpdump 在 A、B 和 C 上捕获数据包
  4. 本来以为 A 上的 tcpdump 可以抓到 IP 欺骗数据包,用原来的 C 程序确实可以,但是我运行 C++ 程序后,奇怪的是 B 上的 tcpdump 可以抓到数据包,而 A 上的 tcpdump 却抓不到。

经过一番调查,我发现这是由于 MAC 地址造成的。当 C++ 程序运行时,内核/系统将 B 的 MAC 地址作为目标 MAC 添加到 IP 欺骗数据包中(预计内核会添加 A 的 MAC 地址,因为目标 IP 地址是 A)。但是,我在 IP 级别编写了数据包,并且在 C 程序和 C++ 程序中使用了如下所示的原始套接字:

send_sd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW));
...
sendto(send_sd, packet, ip_len, 0, (struct sockaddr*)&client_addr, addr_len);

奇怪的是,当我运行这两个程序时,内核/系统添加了不同的目标 MAC 地址。可能的原因是什么?

相关内容