为什么Linux Loopback接口上整个网段的地址都能通?_dog250 lo口

皮鞋湿,不会胖。下班本想找个地方思考,然而没有找到,直接回家吧,闭关,思考,自省,买皮鞋。


昨天写了一篇关于Loopback接口上配置IPv6地址的文章:
闲谈IPv6-Loopback网口上的IPv6地址: https://blog.csdn.net/dog250/article/details/89333045
随后有人咨询了一个比较有意思的问题:
我在lo上添加了10.0.1.1/24这个地址,为什么10.0.1.0/24整个段都可以在本机ping通呢?而且在本机telnet这个段任何地址的侦听0.0.0.0的端口也是通的,为什么?

答案似乎不难解释。 因为添加IPv4地址到lo口时,链路层路由就自动在Local表生成啊!

本文接着上面那篇继续写点儿细节。


比如,当我添加地址到lo口时:

[root@localhost ~]# ip addr add dev lo 10.0.1.1/24

按照IP路由规范,一条 链路层路由 将会自动生成,该路由项以添加地址前缀10.0.1.0/24为健值。由于地址是添加在lo口,而lo口的路由在IPv4关联了Local表,所以这条链路层路由被添加在了Local表中:

[root@localhost ~]# ip route show 10.0.1.0/24 dev lo tab local
local 10.0.1.0/24 proto kernel scope host src 10.0.1.1

现在我们知道,当我们在lo口添加一个非32位长度掩码的地址时:

  • 该前缀的链路层网段路由会被添加在Local表中。

看另一方面,当数据包进入IP路由逻辑时,会用目标地址为健值按照下面的顺序查询路由表(基于Linux实现):

[root@localhost ~]# cat /etc/iproute2/rt_tables
255 local
254 main
253 default
0   unspec

我们看得出来,Local表是最优先被查询的(注意:后面4.X高版本的内核,Local表只是默认最高优先级,即便是Local的优先级也是可以调到非最高优先级的!):

  • 只要在Local表命中路由的,数据包都会被导入到本机第四层去处理。

由此可见,如果在本机去ping或者telnet一个lo口上配置的地址段的其中一个地址,那么由于会命中Local表中链路层路由,所以数据自然而然会导入到本地四层。

在协议栈的实现中,导入到本地四层的数据包是 直接被处理的,不会再去check数据包的目标地址是不是真的被配置在本机的某个接口上!

所以说,按照上文中的10.0.1.1/24的配置,下面的telnet是成功的:

[root@localhost ~]# netstat -lntp
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1036/sshd
...
[root@localhost ~]# telnet 10.0.1.123
Trying 10.0.1.123...
telnet: connect to address 10.0.1.123: Connection refused
[root@localhost ~]# telnet 10.0.1.123 22
Trying 10.0.1.123...
Connected to 10.0.1.123.
Escape character is '^]'.
SSH-2.0-OpenSSH_7.4
^]q

telnet> q
Connection closed.

然而,在我个人看来,这样实现是不对的!至少是不直观的。我还是觉得IPv6的做法更加合理!


IPv6的协议栈标准和实现中,当你添加一个前缀地址到lo口时:
- 该前缀的链路层网段路由会被添加在Local表中

  • 该前缀的链路层网段路由不会被添加在Local表中而是添加在Main表中
  • 添加到Main表中的链路层路由是unreachable的!

这样, 如果不是明确配置在lo口上的地址,就不会通! 比如配置下面的IPv6地址:

[root@localhost ~]# ip -6 addr add dev lo 2222:2222::1234/64

下面的路由会生成:

[root@localhost ~]# ip -6 route show tab main
...
unreachable 2222:2222::/64 dev lo proto kernel metric 256 error -101
...

下面的telnet是不会成功的:

[root@localhost ~]# telnet 2222:2222::1111 22
Trying 2222:2222::1111...
telnet: connect to address 2222:2222::1111: No route to host

整个 2222:2222::/64 段,只有你配置的那个地址 2222:2222::1234 会通:

[root@localhost ~]# telnet 2222:2222::1234 22
Trying 2222:2222::1234...
Connected to 2222:2222::1234.
Escape character is '^]'.
SSH-2.0-OpenSSH_7.4

但是,我在昨天的文章里也说了,这个只是一个默认的配置,并不是不可改变的。我们完全可以把unreachable路由从main表删除,然后把链路层路由 依然 添加到local表中,实现和IPv4一样的效果!以表示怀念或者说维持一种惰性!

IPv6取消了IPv4很多Trick般的玩法,变得规范自然了很多,比如IPv6就没有下面的参数:

net.ipv4.conf.all.route_localnet
net.ipv4.conf.all.accept_local
net.ipv4.conf.all.arp_ignore
net.ipv4.conf.all.arp_filter
net.ipv4.conf.all.rp_filter
...

这些参数可以玩出很多中看不中用的炫技般的Trick,但是几乎没有什么实用性,实际的运维部署中,如果使用这些非规范的Trick,经理会哭的。

之所以IPv4会催生一系列的Trick而IPv6没有,除了IPv6目前使用并不广泛这种理由之外,我感觉还有很重要的一点,那就是IPv4年代很多东西真的就是模糊的,比如RFC826的ARP,IPv4横跨的时间轴太长了,30多年时间,很多技术进化的非常快,早就不是它们一开始被定义的时候的样子了。所以,当初未能考虑到的一些细节,到了最后就是 未定义 的,于是就可以随意去根据上下文来规范解释权了。于是也就有了很多把玩的空间…

原文链接: https://blog.csdn.net/dog250/article/details/89356912

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    为什么Linux Loopback接口上整个网段的地址都能通?_dog250 lo口

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/406599

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月26日 上午9:57
下一篇 2023年4月26日 上午9:57

相关推荐