我有一台 Linux 主机 X,它有两个网络接口:
- eth0位于 10.0.1.0/24,IP 地址为 10.0.1.1
- eth1位于 10.0.2.0/24,IP 地址为 10.0.2.1
我在 10.0.1.0/24 网络上有另一个 Linux 主机 Y,其 IP 为 10.0.1.2。
我在 10.0.2.0/24 网络还有另一个 Linux 主机 Z,其 IP 为 10.0.2.2。
它们都是在 VirtualBox 上运行的 Alpine Linux。
主机 X 启动时启用 IP 转发,在 /etc/sysctl.conf 中设置 net.ipv4.ip_forward=1。
如果 Z (10.0.2.2) 尝试 ping Y(10.0.1.2),它会得到预期的答复。如果 Z (10.0.2.2) 尝试 ping IP 为 10.0.1.1 的主机 X,它也会得到预期的答复。
当我使用以下命令禁用 X 上的 IP 转发时:
# echo 0 > /proc/sys/net/ipv4/ip_forward
Z(10.0.2.2) 不再收到来自 Y (10.0.1.2) 的 ping 回复,但它仍收到来自 10.0.1.1 的 X 的回复。我预计它不会收到任何回复,因为它是来自不同网络的地址,并且 IP 转发已禁用。
这是预期的行为吗?Linux 内核中的配置参数?我在 RFC 792 和内核文档中都找不到关于它的任何提及。
PS:特别奇怪的是,无论是否启用 IP 转发,当从 Z (10.0.2.2) 向 X 10.0.1.1 发送回显请求时,tcpdump 均无输出。然而,如果启用了 IP 转发,它将显示从 Z (10.0.2.2) 发送到 Y (10.0.1.1) 的回显请求及其相应的回复。
答案1
这是预期的行为吗?
默认情况下,是的。Linux 实现了“弱宿主模型“——这意味着到达本地系统的数据包都会被接受,无论它们到达哪个接口。
这与“强宿主模型“,这要求到达的数据包发往传入接口上配置的地址。
可以使用 iptables / nftables 模拟强主机模型,通过将数据包匹配到接口和关联地址才可以被接受。
特别奇怪的是,当从 Z(10.0.2.2)向 X 10.0.1.1 发送回显请求时,tcpdump 没有输出
10.0.1.0/24 子网或接口上的这些 ping 没有关联任何流量,这一切都在内核中处理...同样,这表面上有点令人费解,但根据上述弱主机模型,这是有道理的。
尝试重新配置 Z,并删除 X 作为 10.0.1.0/24 的默认路由,这种行为将会停止 - 无论是否启用转发。
答案2
接口ip_forward
和forwarding
设置只关心发送数据包。由于您的 ping 不需要离开主机即可生成回复,因此它会成功。
Linux 的默认设置是让所有接口都回复同一主机上任何 IP 的 ARP 请求,因此即使没有路由,您也可以获得其他接口的一些流量/回复。这由/proc/sys/net/ipv4/conf/interface/arp_filter
=定义0
。
有关更多详细信息,请参阅:https://sysctl-explorer.net/net/ipv4/arp_filter/