tcp/ip 协议栈中,子网掩码是存哪的?

2021-07-07 12:40:12 +08:00
 lolcat
网络数据报文里好像没有保存子网掩码的部分。假设有如下场景:

路由器,A 口网段:192.168.128.0/24,B 口网段:192.168.128.0/23,如果有人给 192.168.128.0/24 网段的某个机器发了个数据报,路由器怎么知道是转发给 A 口还是 B 口?
3425 次点击
所在节点    Linux
34 条回复
ThirdFlame
2021-07-07 12:44:51 +08:00
路由器是根据路由表转发的。
路由表 路由条目根据生成方法可以分为 直连路由、静态路由、动态路由
路由器根据 A 口、B 口配置的 IP 地址 /掩码 自动生成相应的直连路由。
coolzjy
2021-07-07 12:45:01 +08:00
报文不需要子网掩码,IP 即唯一标识一个网络节点。子网掩码是用来划分网络的,只需要在网络节点上配置就好了。
lolcat
2021-07-07 12:50:28 +08:00
@ThirdFlame 请问在我说的上述场景中,静态路由表已经写好了,192.168.128.0/24 网段的报文就转发给 A 口,192.168.128.0/23 网段的报文就转发给 B 口,那么路由器收到一个目标地址是 192.168.128.7 的报文,他该转发给那个口呢?
lolcat
2021-07-07 12:50:34 +08:00
@coolzjy 请问在我说的上述场景中,静态路由表已经写好了,192.168.128.0/24 网段的报文就转发给 A 口,192.168.128.0/23 网段的报文就转发给 B 口,那么路由器收到一个目标地址是 192.168.128.7 的报文,他该转发给那个口呢?
mmtromsb456
2021-07-07 12:59:27 +08:00
路由表遵守最长前缀匹配,所以 A 接口与 B 接口交集部分走 A 接口,剩余部分走 B 接口
lolcat
2021-07-07 13:30:30 +08:00
@mmtromsb456 还是没看懂,请问在上述的例子中,A 接口和 B 接口在不同网段,怎么可能有交集呢?如果静态路由表已经写好了,192.168.128.0/24 网段的报文就转发给 A 口,192.168.128.0/23 网段的报文就转发给 B 口,那么路由器收到一个目标地址是 192.168.128.7 的报文,他该转发给那个口呢?
v2mm
2021-07-07 13:31:50 +08:00
192.168.128.7 取前 24bit == 192.168.128.0 走 A 口

但是比如 192.168.129.7,则
192.168.129.7 取前 24bit == 192.168.129.0 不走 A 口
192.168.129.7 取前 23bit == 192.168.128.0 走 B 口
qbqbqbqb
2021-07-07 13:43:53 +08:00
@lolcat 系统不会也无法知道你现实中的网段配置,一切按照路由表和规则来。如果路由表写成这样,按照路由表匹配规则(最长前缀),这个报文必然是走 A 口。如果实际上这台机器在 B 网段,那这个包就丢了。
Tianao
2021-07-07 13:45:07 +08:00
「路由器,A 口网段:192.168.128.0/24,B 口网段:192.168.128.0/23 」

路由器的以太网接口等广播型三层接口(还包括但不限于 dot1q 子接口、vlan 虚接口)不允许这么配,会提示网段冲突。

如果是 loopback 口、地址借用等情况确实配上了,此时适用最长匹配原则。
qbqbqbqb
2021-07-07 13:56:31 +08:00
“子网掩码”和“默认网关”你可以理解成一种简化的静态路由表配置,系统根据这两个参数将其展开成完整的静态路由表(即设置“IP/子网掩码”网段走接口直连路由,"0.0.0.0/0"走“默认网关”),是不会出现在具体的报文里的(当然 DHCP 这种除外)。

比如说 192.168.128.7/24 和 192.168.128.7/23,这就是一个 IP 地址,只能代表一台主机(绝对不能将其理解为两个网段中的两个不同主机,这是一种常见的误解,如果在相互连接的网络中这样配置两台主机的话会导致 IP 冲突),只是说配置前者的话系统会认为它的网段有最多 254 台主机这么大,配置后者的话系统会认为它的网段有最多 510 台主机那么大。
xiaooloong
2021-07-07 13:57:52 +08:00
掩码只做本地演算用,传输的数据中不体现。
Tianao
2021-07-07 14:02:55 +08:00
@lolcat 看了楼主楼上的回复,看来楼主根本没有这样用过路由器,也不理解网段、网络、子网、超网、网络地址、网络号、主机地址、最长匹配的概念和实际意义,建议楼主先去学习下这些基础知识,再来纠结这些以自己的水平在现实应用场景中根本不可能遇到的场景(最典型的 IP 以太网路由器在简单的局域网环境下不可能(不被允许)这样配置,如果遇到串行、帧中继等非广播型网络、loopback 口做路由通告或身份 ID 等有条件出现这样的配置场景的情况,这个问题自然就不会成为问题了)。

总而言之,楼主现在的基础知识决定了这样纠结这个问题没有意义,只会成为“思而不学则殆”的典型。
cpstar
2021-07-07 14:26:17 +08:00
A 口 B 口冲突了吧
按道理,掩码只负责子网判定,跟 IP 无关,所以按照 LZ 描述,A 口 B 口可以同时设置 192.168.128.5,那显然这是不允许的。
msaionyc
2021-07-07 14:30:18 +08:00
@lolcat A 和 B 为什么没交集?
raaaaaar
2021-07-07 14:31:34 +08:00
建议看下《计算机网络》,谢的那本,网络那章,写得很清楚
dier
2021-07-07 15:24:29 +08:00
在路由器上如果你先配置了条件中 A 口的网段,B 口的网段就配置不成功,所以你这个问题不存在
lolcat
2021-07-07 15:43:43 +08:00
@raaaaaar 谢的那本书我不记得讲了这方面的知识啊
CRVV
2021-07-07 16:45:48 +08:00
路由表当然可以这么配置
ip route add 192.168.128.0/24 dev eth0
ip route add 192.168.128.0/23 dev eth1
这么配置完,走 eth0

如果是给 interface 这么设置,Linux 上也可以配置出来,但这是很奇怪的配置,没人这么用。
网络里面通常认为一个 IP 地址对应唯一一台机器,如果设置成这样
eth0 192.168.128.1/24
eth1 192.168.128.2/23
那么 192.168.128.3 同时属于这两个网络,那么当然会认为这是一台机器而不是两个子网里的两台机器,这个数据包要怎么发给这一台机器是无所谓的事情,总能到。

子网掩码不是一个网络的属性,也不是一个地址的属性。它本身唯一的作用就是表示一组连续的 IP 地址,然后这一组 IP 地址叫做一个子网。
比如 ip route add 192.168.1.0/24 via 10.2.3.4 一次设置了 256 个 IP 地址的路由,不用一个一个加路由。
给 interface 设置的子网掩码是告诉电脑哪些 IP 地址和本机是直连的,这些直连的 IP 可以直接走数据链路层通信( ARP 协议),不用经过路由器。和本机直连的 IP 地址也不一定是连续的,你可以在一个 interface 上设置多个 IP 地址和子网掩码。和设置路由一样,一次设置一组,不用一个一个加,仅些而已。

这种事情找几台机器,至少要有一台带两个网卡的,连起来玩一下就知道了。
Tianao
2021-07-07 16:57:25 +08:00
回复楼主附言 1
「看了大家回复,
1. 有人说路由器的静态路由表不允许这么配置。
2. 有人说根据最长匹配原则,192.168.128.7 这个地址可以匹配 A 口 192.168.128.0/24 这个网段的 24 位,而只能匹配 B 口 192.168.128.0/23 这个网段的 23 位,根据最长匹配规则应该会把这个数据包转发到 A 口。

到底哪个答案是正确的呢?」

首先,192.168.128.0/24 192.168.128.0/23 是两个网络地址而不是主机地址,因此不能配置到普通接口上。如果 A B 两个口都是工作在三层模式的以太网接口,那么路由器不允许配置为两个接口分别配置 192.168.128.1/24 192.168.128.1/23 这样两个地址,在配置好一个之后,再配置另一个时会被拒绝并报错。

其次,假设两个地址配置成功后,路由器会自动生成去往这两个网络的直连路由。

然后,现代路由器路由器在实际执行路由转发时的直接参照是 FIB (转发信息表)而不是路由表(路由表不一定包含物理出接口,也没有下一跳的目的 MAC 地址),而 FIB 是根据全局路由表(有时候被称为系统路由表或者优选路由表)及其他表项生成的。

再然后,全局路由表是通过参照各协议路由表经路由优选后得出的。路由优选的一个原则是路由协议的管理距离优,比如,直连路由的管理距离优于手工静态路由,也就是说对于去往同一目的网络(即网络地址和掩码均完全相同)的路由,直连路由永远会在优选中胜出(除非手动干预路由协议的管理距离),也就是说,在楼主假想的这种情况下,手工配置的静态路由永远不会「成为活跃路由生效而参与 FIB 的构建进而影响最终路由选路和转发执行」。

最后,路由器在针对特定目的主机地址( 192.168.128.7 )在存储 FIB 的 TCAM (三元内容可寻址寄存器)中执行硬件查表时,才会用到并遵循最长匹配原则,此时路由器为目的主机地址 192.168.128.7 匹配到了具有最长匹配位数的 192.168.128.0/24 表项,并从此直连路由出接口送出。全程和静态路由没有半毛钱关系。

而且,以上的前提是,这两个重叠的接口地址可以被配置上去并生效。
Tianao
2021-07-07 17:09:22 +08:00
再明确回复一下楼主附言 1 的「 1. 有人说路由器的静态路由表不允许这么配置。」

不是静态路由不允许这么配,是接口地址不允许这么配。静态路由可以这么配,但是配了也不会生效(成为在优选中胜出的活跃路由并被显示在全局路由表)。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/788054

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX