别人再问你路由表是啥,这篇文章摔它脸上

局域网内靠 ARP 广播能找到同网段设备,但是跨网段通信时,必须依赖路由器(网关),没有路由数据包根本不知道往哪里走。

最近在学习Docker 的网络,了解到docker网络的隔离基于 Network Namespace,每个容器拥有独立的网络栈(网卡、路由表、iptables 规则),所以想要对里面的路由进行一下系统的学习,后面会单独找一个章节对iptables进行学习。

路由表

理解下路由表的概念,通过route -n 命令可以查看宿主机的路由条目,

bash 复制代码
[root@iZ2ze4kh3gm5ijgppvs77sZ ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.207.253  0.0.0.0         UG    100    0        0 eth0
172.17.192.0    0.0.0.0         255.255.240.0   U     100    0        0 eth0

1.Gateway 列表示的就是"这个数据包发送时,是否需要递交给某个中间网关(路由器)来转发"

更精准地说,Gateway 列的值决定了数据包在离开你的网卡(eth0)时,封装的目标 MAC 地址到底填谁

  • Gateway 显示为 0.0.0.0(或 *): 表示直连,无需网关。也就是说目标IP和你的服务器在同一个局域网,数据包通过eth0网卡发出时,二层目标 MAC 地址直接填写目标主机自身的 MAC 地址(直接送达)

  • Gateway 显示为具体 IP(如 172.17.207.253)

目标 IP 不在本地局域网,服务器自己无法直接送达,必须找这个"中转站"帮忙。 数据包通过 eth0 发出时,三层目标 IP 保持为真正的终点(比如百度),但二层目标 MAC 地址填写的是网关 172.17.207.253 的 MAC 地址。

2.Iface (eth0): Iface (eth0)列表示数据包从网卡eth0发出去。

啥是下一跳啊?

"下一跳(Next Hop)"指的就是:数据包离开当前设备后,在网络中紧接着要交给的下一个路由器(网关)的 IP 地址。

  1. 同网段通信:目的地就在同一个局域网,0 跳(直接送达,没有下一跳,Gateway 显示为 0.0.0.0)。
  2. 跨网段通信:目的地在外面,必须经过至少 1 跳(下一跳就是 Gateway 指定的 IP)

同网段 vs 跨网段的区别

它们的终极区别就在于二层(数据链路层)的"目标 MAC 地址"是谁:

  • 同网段通信(比如发给同局域网的 172.17.194.200):

IP 目标:172.17.194.200(目标主机)

MAC 目标:172.17.194.200 的 MAC 地址(通过 ARP 广播问出来的)

逻辑:直接叫对方的名字,把数据包丢给对方。

  • 跨网段通信(比如发给百度 110.242.68.66):

IP 目标:110.242.68.66(百度,全程不变)

MAC 目标:网关 172.17.207.253 的 MAC 地址(变为了网关)

逻辑:包裹信封上写着"寄给百度",但我先把包裹亲手递给快递员(网关)。

网关必须是你在当前局域网内能直接用 MAC 地址连上的"邻居"。

路由条目的理解

我们先讲解下路由匹配的机制:将你要访问的目标IP和 路由表中的Genmask,逐位做"按位与(AND)"运算,算出的结果如果等于 Destination,就代表匹配上了这条路由。

第一条是默认路由

plaintext 复制代码
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.17.207.253  0.0.0.0         UG    100    0        0 eth0
  1. Destination (0.0.0.0) + Genmask (0.0.0.0):匹配任意/所有 IP 地址。

因为任何IP和0.0.0.0 做and运算,都会等于0.0.0.0 被清空

  1. Gateway (172.17.207.253):下一跳的网关地址。

  2. Flags (UG):U 代表路由有效(Up),G 代表需要经过网关(Gateway)。

  3. Iface (eth0):通过网卡 eth0 发送。

也就是说如果要访问的IP地址不属于本地网段,(比如访问百度 110.242.68.66,或者跨网段的其它私网 IP),路由表查到最后发现只有这条能匹配上,就会把数据包交给网关 172.17.207.253,由网关帮你转发出去。

再看看看第二条路由:

plaintext 复制代码
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
172.17.192.0    0.0.0.0         255.255.240.0   U     100    0        0 eth0

Gateway (0.0.0.0):网关是 0.0.0.0,意思是"不需要网关(直接发送)"。

说明这个是同网段的路由,不需要经过网关转发。

那我们看看到底是访问什么范围内的IP,可以匹配命中这条路由。

先看Genmask 255.255.240.0 ,整个掩码的二进制表示形式是:

plaintext 复制代码
255      . 255      . 240      . 0
11111111 . 11111111 . 11110000 . 00000000

连续为1的个数正好是 8+8+4 =20,这种掩码在CIDR记法里写作 /20.

剩下的12个0用来给主机分配IP。,共支持 212−2=40942^{12} - 2 = 4094 212−2=4094 个可用 IP 地址。

所以第二条路由表示的意思是:只要访问的ip是172.17.192.0/20,就不需要经过网关,直接发送到目标主机。

这里的区别在于:同网段VS跨网段

  • 同网段通信,数据包二层(数据链路层)的"目标 MAC 地址":直接是目标主机的mac地址,直接通过(ARP广播)问出来。
  • 跨网段通信,数据包二层(数据链路层)的"目标 MAC 地址":是网关172.17.207.253的mac地址。

172.17.192.0/20 到底表示的是多大范围的IP呢?

先说结论:

子网掩码 255.255.240.0(分成四段,点分十进制) 转成二进制是:

11111111.11111111.11110000.00000000

无论在这个范围里挑哪一个 IP,只要和 255.255.240.0 做按位与(AND)运算,得出的结果通通都是 172.17.192.0,这就是同一个网段。

二进制中AND运算有个规律就是:和1进行and原样保留,和0进行and运算结果都被清0。

所以如果一个ip要想和172.17.192.0/20是一个网段的。

1.那么这个ip的前两段必须是172.17 因为子网掩码的前两段全是1。和全是1的位进行与运算结果还是自己本身。所以ip必须是172.17.xx.xx

2.这个ip的最后一段可以是0-255,因为子网掩码最后一段全是0,和全是0的位进行与运算结果肯定会清0,所以这个ip的最后一段 肯定是 172.17.xx.1~172.17.xx.254(去掉首尾两个)

3.这里关键是掩码的第三段 240,把 IP 的第三段与 240(11110000)做"按位与"。因为240的后四位都是0,所以任何ip和240进行与运算后 后四位都是清零的 变成xxxx0000。因为是后四位变成0 ,后 4 位是 0(0000),表示这 4 个位置可以自由变化

24=2×2×2×2=162^4 = 2 \times 2 \times 2 \times 2 = \mathbf{16} 24=2×2×2×2=16

从0000~1111,每当满16就会向前进一位,所以网段一定都是16的倍数

  • 0(0 ~ 15)
  • 16(16 ~ 31)
  • 32(32 ~ 47)
  • ...\dots ...
  • 160(160 ~ 175)
  • 176(176 ~ 191)
  • 192(192 ~ 207) ←\leftarrow ← 你的网段正好落在这里!
  • 208(208 ~ 223)

从 192 到 207 这 16 个数字,它们在二进制世界里有一个共同的特征:前 4 位全都是 1100!

因为网络工程师在配置网络的时候选择了192(11000000)作为子网的起点,所以只有192~207 整个范围内的数和240进行与运算的时候才能得到前四位1100。

只要前 4 位是 1100,不管你后面 4 位怎么变(从 0000 变到 1111),这 8 个开关组合出来的十进制数值,数学上就只能在 192 到 207 之间。

  1. 最后得到的ip范围就是 172.17.192.0 ∼\sim ∼ 172.17.207.255

仔细分析

首先我们需要明白这个ip的范围,它要求所有属于这个网段的ip,它的前20位必须和172.17.192.0的前 20 位保持完全固定不变。

我们将 172.17.192.0 拆成 4 个字节,逐个翻译成 8 位二进制:

172 →\rightarrow → 10101100 ( 128+32+8+4128 + 32 + 8 + 4 128+32+8+4)

17 →\rightarrow → 00010001 ( 16+116 + 1 16+1)

192 →\rightarrow → 11000000 ( 128+64128 + 64 128+64)

0 →\rightarrow → 00000000

组合起来,完整的 32 位二进制 是: 10101100.00010001.11000000.00000000\mathbf{10101100.00010001.11000000.00000000} 10101100.00010001.11000000.00000000

也就是说,172.17.192.0/20 被 /20 锁死固定的 前 20 位 展开写出来就是: 10101100.00010001.1100\mathbf{10101100.00010001.1100} 10101100.00010001.1100

把这前 20 位(网络身份)和剩下的 12 位(主机自由变化区)画出界线看最直观:

plaintext 复制代码
【被 /20 锁定的前 20 位】      │ 【自由变化的后 12 位】
10101100 . 00010001 . 1100   │  0000 . 00000000   (最小值,即 172.17.192.0)
10101100 . 00010001 . 1100   │  1111 . 11111111   (最大值,即 172.17.207.255)

只要任何一个 IP 地址,把前 20 位抓出来一比对,只要是 10101100.00010001.1100\mathbf{10101100.00010001.1100} 10101100.00010001.1100,它就 100% 属于这个网段!

我们来分析下第三个字节的掩码240

掩码 240=11110000\text{掩码 } 240 = \mathbf{1111}0000 掩码 240=11110000

网络基准 192=11000000\text{网络基准 } 192 = \mathbf{1100}0000 网络基准 192=11000000

叠在一起看

plaintext 复制代码
掩码 (规则):   1 1 1 1  0 0 0 0  (前 4 位是 1,代表死死锁住前 4 位)
              │ │ │ │
基准IP (数值): 1 1 0 0  0 0 0 0  (前 4 位的内容是 1 1 0 0,即十进制的 192)
  • 掩码的 1111 规定了:"前 4 位必须和 192 的前 4 位(1100)一模一样!"

  • 只要前 4 位是 1100,后 4 位不管怎么变(从 0000 变到 1111),算出来的十进制数就必定落在 192 到 207 之间。

192 所在的那个字节(第 3 个字节)的前 4 位死死锁定 为 1100。

十进制 192= 1 1 0 0⏟ 前 4 位 0 0 0 0⏟ 后 4 位 \text{十进制 } 192 = \underbrace{\mathbf{1\ 1\ 0\ 0}}{\text{前 4 位}}\ \underbrace{0\ 0\ 0\ 0}{\text{后 4 位}} 十进制 192=前 4 位 1 1 0 0 后 4 位 0 0 0 0

在计算机里,192 这个数字拆成 8 个二进制开关(对应权重 128,64,32,16,8,4,2,1128, 64, 32, 16, 8, 4, 2, 1 128,64,32,16,8,4,2,1),必须用 128+64128 + 64 128+64 才能凑出来:

权重: 128 64 32 16 8 4 2 1 开关: 1 1 0 0 0 0 0 0 \begin{array}{rcccccccc} \text{权重:} & \mathbf{128} & \mathbf{64} & 32 & 16 & 8 & 4 & 2 & 1 \\ \text{开关:} & \mathbf{1} & \mathbf{1} & 0 & 0 & 0 & 0 & 0 & 0 \end{array} 权重:开关:128164132016080402010

它的前 4 位就是 1100

因为前 4 位被粘死成了 1100:

只要前 4 位是 1100,不管你后面 4 位怎么变(从 0000 变到 1111),这 8 个开关组合出来的十进制数值,数学上就只能在 192 到 207 之间

从 192 到 207 这 16 个数字,它们在二进制世界里有一个共同的特征:前 4 位全都是 1100!

网络工程师在配置网络时,选择了 192 作为这个子网的起点,所以系统通过 /20(锁定前 20 位,即第 3 字节的前 4 位 1100),自动就把范围给卡死在 192 到 207 了。

我们可以自己算一下,既然前 4 位被锁死为 1100,后 4 位可以自由变化,那么这个字节能变化的最小值和最大值是多少呢?

  • 最小值(后 4 位全为 0):

1100 0000‾2 =128+64+0=192 \mathbf{1100}\ \underline{0000}_2 = 128 + 64 + 0 = \mathbf{192} 1100 00002=128+64+0=192

这就是你看到的起始网段:192

  • 最大值(后 4 位全为 1):

1100 1111‾2 =128+64+8+4+2+1=207 \mathbf{1100}\ \underline{1111}_2 = 128 + 64 + 8 + 4 + 2 + 1 = \mathbf{207} 1100 11112=128+64+8+4+2+1=207

这就是你看到的结束网段:207!

结论

所以,只要第 3 个字节落在 192 到 207 之间,它的二进制前 4 位就永远是 1100! 一旦到了 208(二进制是 11010000),前 4 位变成了 1101,与掩码锁定的 1100 不符,就超出这个局域网了。

心算。

网络工程师最爱的"块大小(Block Size)心算法"

240那个块大小是16

  1. 为什么"块大小是 16"?

因为第 3 个字节的后 4 位没有被锁死(可以随便变)。后 4 位二进制从 0000 变到 1111,在十进制里一共可以产生 24=162^4 = 16 24=16 个连续的数字(也就是一个网段包下了 16 个不同的第 3 字节数字)。

  1. 为什么"网段的起点一定是 16 的倍数"?

因为网段的开头(网络地址)要求主机位全部清零。把第 3 字节的后 4 位全部清为 0(变成 xxxx0000),在二进制数学里,任何低 4 位是 0000 的二进制数,转成十进制必然能被 16(即 242^4 24)整除!192 的二进制:1100 0000(后 4 位是 0 →\rightarrow → 192÷16=12192 \div 16 = 12 192÷16=12,整除!)208 的二进制:1101 0000(后 4 位是 0 →\rightarrow → 208÷16=13208 \div 16 = 13 208÷16=13,整除!)

最后理解一下路由器

plaintext 复制代码
               ┌──────────────────────────────┐
               │          路 由 器            │
               │                              │
[你的电脑] ────┼──> LAN口 IP: 192.168.1.1     │
(192.168.1.100)│    (和你的电脑在同网段)        │
               │                              │
               │    WAN口 IP: 10.0.8.2        ┼──> [上级路由器]
               │    (和上级路由器在同网段)      │   (10.0.8.1)
               └──────────────────────────────┘

路由器在物理上至少有两个网口(接口):

LAN 口(内网口):插在你家/你机房内部,面对你的电脑。

WAN 口(外网口):插在上一级网络,面对运营商或上级路由器。

这两个口各自有一个独立的 IP 地址,并且属于完全不同的两个网段!

  • 网段 A(内网局域网:192.168.1.0/24)

你的电脑:192.168.1.100

路由器的 LAN 口:192.168.1.1

关系:电脑和路由器的 LAN 口在同一个网段。电脑把数据发给 192.168.1.1,直接用 MAC 地址传过去。

  • 网段 B(外网/上级局域网:10.0.8.0/24)

路由器的 WAN 口:10.0.8.2

上级路由器:10.0.8.1

关系:路由器的 WAN 口和上级路由器在另一个完全不同的网段。路由器的 WAN 口把数据发给 10.0.8.1,也是在它们自己的局域网里直接传过去。

相关推荐
羑悻2 小时前
穿越Docker内核迷雾:揭秘镜像分层存储的叠加态与卷挂载的多维空间穿梭技术
后端·docker·容器
运维开发王义杰2 小时前
ingress-nginx 退役后怎么选:Istio、Kong、Traefik 与 APISIX
云原生
吴声子夜歌3 小时前
Nginx应用与运维——Nginx在Kubernetes中的应用(一)
运维·nginx·kubernetes
筑梦之路3 小时前
docker-compose方式部署kafka集群(Kraft方式)——筑梦之路
docker·容器·kafka
JavaPub-rodert4 小时前
Docker 镜像地址总失效?基于 DockerHub 项目用 GitHub Actions 做一个自动检测状态页
docker·容器·github
天衍四九-4 小时前
Docker 进阶实战系列(一):容器镜像安全,最小镜像与非 Root 运行
安全·docker·eureka
天衍四九-4 小时前
Docker进阶实战系列(二):容器日志深度治理|驱动配置、自动切割、磁盘爆满彻底解决
docker·容器·eureka
吴声子夜歌4 小时前
Nginx应用与运维——Nginx在Kubernetes中的应用(三)
运维·nginx·kubernetes
sbjdhjd5 小时前
云安全 | Docker 容器逃逸复盘(一):从隔离边界到运行时链路,如何确认自己身处容器
网络安全·docker·云原生·容器·kubernetes·云计算·云安全