我想知道在linux中是否可以在用户空间接收具有127.0.0.0/8 dst地址但来自外部接口的UDP数据包。
我用 nc 测试了它,我可以看到虽然 nc 绑定到所有地址,但它没有收到数据包。
在设备 1上,我操纵本地路由表将此数据包路由到所需的接口,然后发送测试数据包。
设备1:
frr:~# ip route show table local
...
127.1.1.1 nhid 17 encap mpls 16 via 10.10.10.5 dev eth5
...
frr:~# echo "foo" | nc -w1 -u -v -s 3.3.3.3 127.1.1.1 3503
设备2:
frr:~# nc -l -u -p 3503
在设备 2 接口上的wireshark 中生成并捕获以下数据包:
我知道根据RFC 1812这永远不应该发生。另一方面,根据RFC4379,这是一个有效的用例。这里的技巧是,我发送的数据包实际上不是 IP 路由的,而是 MPLS 交换的,并且在最后一跳,由于 PHP(倒数第二跳弹出)而丢失了 MPLS 标签,并且使用 127.0.0.0/8 地址作为 dst 的目标是确保当标签堆栈耗尽或没有有效的下一跳时,路由器不会根据 IP 地址转发,而是处理数据包。这称为 MPLS OAM 或 LSP Ping。
默认情况下, Linux 内核在对具有此类源或目标的数据包执行路由验证时强制执行 RFC 1812。以下是一些示例: IPv4: 1 2 3 4 5 , ARP: 6。它们看起来都差不多:
如果地址的源或目标在 127.0.0.0/8 内,并且这不会发生在主机内,即通过环回接口,则数据包将被丢弃...除非专用sysctl切换
route_localnet
(由上面的宏检查)已启用,在这种情况下,该地址被视为正常的可路由地址:因此,要让接口接受或发出此类流量而不被路由堆栈丢弃,必须在其上启用切换。对于接口,
eth5
这可以通过以下方式完成:根据封装的完成方式和整体设置,可能会涉及其他接口,如果有疑问,请使用
all
而不是首先使用。eth5
这是我在 SU 上回答的关于网络上此类数据包的问题:
将发往 127.0.0.1/8 上的地址的数据包发送到 Ubuntu 上的网络
提示:调试时也禁用
rp_filter
所有地方(包括all
和),直到它开始工作。default
这就是导致某些问题的原因,RTNETLINK answers: Invalid argument
直到两个方向的所有路由都正确配置为止。除了这个 RFC 4379 用例之外,一种可能更常见的情况是,完成目标 NAT 将普通地址更改为环回地址,以廉价地克服仅将其服务绑定在环回地址上的应用程序。简化示例:
它只能在启用切换的情况下工作,因为路由堆栈本身会看到不在环回上且内部有环回地址的数据包(传入目的地,回复源)。线路上实际上没有出现这样的数据包(NAT 发生),但路由堆栈不知道这一点,因此必须忽略检查。
创建时
lo0
,它被分配为 127.0.0.1,网络掩码为 /8。这是由内核完成的(参见 参考资料net/ipv4/devinet.c
)。因此,如果您想尝试重用部分 127.0.0.0/8 空间,则必须在初始化后重新分配 IP 掩码。因此,在将以太网设置为 127.1.1.0/24 之前,您可能应该将lo0
网络设置为 127.0.0.0/24。请注意,有许多进程期望 127.0.0.0/8 位于 上
lo0
。因此,将网络设置lo0
为 /24 可能会起作用,但可能会破坏其他进程。您可能想使用无 systemd 的发行版。目前正在讨论回收 127.0.0.0/8 的至少一部分。例如,请参阅IETF 草案。
您将无法通过标准路由器。您还需要自定义它们。