假设我遇到这种情况,我编写了一个程序来毒害本地网络中的 2 个设备(假设 A 和 B)的 ARP 缓存,以便成功地从设备 M 进行 MITM。该程序在设备 M 上运行。当我启用使用设备 M 上的命令进行 IP 转发sysctl net.ipv4.ip_forward=1
,可以毫无问题地建立从设备 A 到 B 的 HTTP 连接,并且我能够看到设备 M 上的流量。
但是,同样的情况,在我使用设备 M 上的命令禁用 IP 转发后,ARP 缓存中毒,sysctl net.ipv4.ip_forward=0
无法建立从设备 A 到 B 的 HTTP 连接。我可以在设备 M 上看到来自设备 A 的 TCP SYN 数据包。在我的程序中,在设备M上收到SYN数据包后,我将数据包中的src MAC地址修改为M的MAC地址(来自A的MAC地址)和dst MAC地址为B的MAC地址(来自M的MAC地址)并将其注入网络。我不会从网络层开始修改任何内容。我可以使用 TCPdump 命令看到 B 处的数据包具有新的 src 和 dst MAC,这意味着数据包到达了 B。但是 B 没有响应该数据包,我无法理解为什么。
那么,问题是,ip_forward=1
这种 MITM 情况有什么特殊之处吗?澄清一下,所有的机器都是Linux的。在设备 M 上启用转发后,我不需要修改数据包中的 MAC 地址。我只是毒害了缓存,从那里一切正常。
答案1
M 的内核收到一个数据包,其目标 IP 地址表明该数据包不是发给 M 的。它会做什么?
当 时ip_forward=0
,它会想:“我不知道为什么会发给我这个,我也不在乎。它会被扔进垃圾桶!”
与ip_forward=1
,“嗯,这不适合我。但我知道收件人在哪里,所以我会使用正确的 MAC 地址重新发送它。”
换句话说,随着ip_forward=1
,你不必修改 MAC 地址,因为您的内核已为您完成此操作。
答案2
最小样本实验net.ipv4.ip_forward=1
至关重要
考虑以下拓扑:
Internet --- Wi-Fi --- Computer 1 --- Ethernet --- Computer 2
假设您希望计算机 2 能够通过计算机 1 访问 Internet,例如因为计算机 2 没有 Wi-Fi。我认为这基本上意味着将计算机 1 变成路由器。
在:https://askubuntu.com/questions/3063/share-wireless-connection-with-wired-ethernet-port/1502850#1502850我成功地使用两台 Ubuntu 笔记本电脑实现了此设置,并且:
sudo sysctl net.ipv4.ip_forward=1
是至关重要的一步,因为没有它,计算机 1 就不会将 IP 数据包从计算机 2 转发到 Internet。
通过net.ipv4.ip_forward=0
,我们可以从计算机 2 访问计算机 1,但我们无法超越计算机 1 访问 Internet 并返回。
您可以在计算机 1 上做的一件很酷的事情net.ipv4.ip_forward=1
是观察数据包流向:
sudo wireshark -k -f 'icmp' -i enp1s0f0 -i wlp2s0
如果您在计算机 2 上执行此操作:
ping example.com
那么每次 ping 都会产生 4 条 Wireshark 线路,您可以清楚地看到计算机 1 如何消费来自计算机 2 的请求数据包并将其转发到 Internet,然后从 Internet 取回响应并将其发送到计算机 2:
Time Source Dest Hw src Hw dst Protocol
1 0.000000000 10.42.0.70 93.184.216.34 54:e1:ad:b5:5b:08 fc:5c:ee:24:fb:b4 ICMP request id=0x79ee, seq=8/2048, ttl=64 (reply in 4)
2 0.000074761 192.168.1.123 93.184.216.34 04:7b:cb:cc:1b:10 9c:53:22:17:e2:0e ICMP request id=0x79ee, seq=8/2048, ttl=63 (reply in 3)
3 0.098882299 93.184.216.34 192.168.1.123 9c:53:22:17:e2:0e 04:7b:cb:cc:1b:10 ICMP reply id=0x79ee, seq=8/2048, ttl=51 (request in 2)
4 0.098952451 93.184.216.34 10.42.0.70 fc:5c:ee:24:fb:b4 54:e1:ad:b5:5b:08 ICMP reply id=0x79ee, seq=8/2048, ttl=50 (request in 1)
想到基本上任何运行 Linux 并具有多个网络接口的机器都可以充当路由器,这是一件很有趣的事情。
测试计算机 1 = Lenovo ThinkPad P14s,计算机 2 = Lenovo ThinkPad P51(关闭 Wi-Fi),均运行 Ubuntu 23.10。
答案3
当您毒害 ARP 缓存时,A 和 B 开始向 M 发送数据报,数据报的 MAC 地址为 M,但 IP 地址分别为 B 和 A。因此,这些数据报在第 2 层(以太网)中定向到 M,但在第 3 层(IP)中定向到其他设备。为了将这些数据报发送到第 3 层接收者(根据 IP 地址),M 必须进行 IP 转发。
您可以net.ipv4.ip_forward=0
禁用 IP 转发,也net.ipv4.ip_forward=1
可以启用它。
为什么需要IP转发?
看一眼开放系统互连模型。在那里你会发现
- HTTP 第 7 层
- TCP 第 4 层
- 第 3 层 IP
- 以太网二层
您的 ARP 中毒会影响第 2 层。
如果没有 ARP 中毒,从 A 到 B 的 HTTP 消息将被包装到 TCP 流(定向在端口 80)中,该流与 IP 一起发送到 B 的 IP 地址。B 的 IP 地址与 B 的以太网地址相关联数据报直接(通过集线器或交换机)从 A 传送到 B,反之亦然。没有必要转发IP。
当您毒害 A 和 B 的 ARP 缓存以指向 M 时,会发生以下情况。从 A 到 B 的 HTTP 消息被包装到 TCP 流(定向在端口 80)中,该流通过 IP 发送到 B 的 IP 地址。B 的 IP 地址与 M 的以太网地址关联,数据报发送到 M 。M 不是这些数据报的预期接收者。
为了使 HTTP 连接正常工作,M 必须转发 IP 数据报从 A 到 B,反之亦然。这可以通过具有上述设置的内核或通过侦听这些数据报并重新发送它们的特殊程序来发生。