蛮荆

网络基础: 网络层和路由器 (拾遗补缺)

2017-11-21

两种设备

所有的通信设备 (主机、笔记本电脑、手机、交换机、路由器、服务器) 在网络层面可以分为两种设备:

  1. 主机 (End System) : 不会转发 [目标 IP 地址 不等于 自身 IP 地址] 的数据包
  2. 路由器 (Intermediate System): 会转发 [目标 IP 地址 不等于 自身 IP 地址] 的数据包

主机

主机上的多个接口可以位于同一网段,但是不能使用相同的 IP 地址。

例如电脑上有一块网卡、有一个无线网卡,这两个网卡都可以从同一个 DHCP 服务器获取同一网段的 IP 地址,但是不能获得相同的 IP 地址。

路由器

路由器的每个接口都需要使用不同的网段和不同的 IP 地址。

对于路由器上面的网卡来说,每块网卡除了可以表示不同的 IP 地址外,还可以区分内网网卡 (专门收发内网的流量) 和公网网卡 (专门收发公网的流量)。

三种通信

1. 主机和自己通信

最常见的如本地环回网络 127.0.0.1

此外,当数据包的目标 IP 地址等于主机自己的 IP 地址时,数据包只是在 TCP/IP 协议内部过了一遍,没有到达硬件网卡。

例如本机 IP 地址为 192.168.1.200, 启动一个 Nginx 绑定并监听 192.168.1.200:8080, 那么请求 192.168.1.200 时,会返回 Nginx 的响应内容,数据包在本机内部过了一遍。

2. 主机和广播域内其他主机通信

如果目标 IP 地址既不是本地环回网络 IP,也不是主机自身的 IP, 那么就需要通过硬件网卡发送到目标地址了。

如何通过目标 IP 地址得出目标 Mac 地址呢?发送数据前,先使用 ARP 协议广播获取到目标 Mac 地址,详情过程可以参考 这篇文章

3. 主机和广播域外其他主机通信

如果主机和目标主机不在同一个广播域内,使用 ARP 协议获取目标 Mac 地址时,目标 Mac 地址应该填写什么了?当然是网关的 Mac 地址,详情过程可以参考 这篇文章


路由表

路由器根据 “IP地址” 判断转发目标,IP 报文依据的是 “路由表”,路由表的构建依赖路由协议 (互联网主要依赖 BGP 协议)。

路由器中有一张存储 IP 的表,根据这张表加数据包中的目标 IP 地址,可以查出数据包接下来应该发往哪个路由器。

图片来源: 网络是怎样连接的(户根勤)

为了将数据包发送到下一个路由器,还需要查出下一个路由器的 Mac 地址,并记录到数据包的 Mac 头部中 (修改 Mac 头部)。

表项

图片来源: 网络是怎样连接的(户根勤)

路由表包含了路由选择的必备信息,主要由以下 5 个表项组成:

  1. 目标 IP: 可以是一个完整的主机 IP 地址,也可以是一个网络地址
  2. 子网掩码: 表示目标 IP 地址中有多少为表示网络部分,目标 IP + 子网掩码 可以表示目标子网络信息,路由表的子网掩码列只表示在匹配网络包目标地址时需要对比的位数量
  3. 网关: 下一步需要转发的 IP 地址,包含转发接口的子网 IP 地址,通常是相邻路由器的网络接口IP地址,网关也可称为 “下一跳”
  4. 接口: 路由器上面对应的接口 (可以理解为一个 “网卡”)
  5. 指标: 当有多条路径可以到达相同目标地址(目标 IP 地址与子网掩码值相同)时不同路径的优先级。这个数字越小,表示距离目标地越近 (优先级越高);数字越大,表示距离目标地越远 (优先级越低)。如果任意一个路由条目只有一个表项,那么其对应的 metric 值没有意义,因为无论 metric 是多少,这都是唯一的选择

查看路由表

Linux 中可以使用如下命令查看路由表。

$ route -v

# 输出如下 (WSL2 环境)
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         DESKTOP-IUAK47Q 0.0.0.0         UG    0      0        0 eth0
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-b1b866c7f37c
172.20.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-e7543e50246b
172.21.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-b0601dad2b86
172.26.208.0    0.0.0.0         255.255.240.0   U     0      0        0 eth0
192.168.49.0    0.0.0.0         255.255.255.0   U     0      0        0 br-cbbb1e89822d

Flags 字段中部分标志解释:

  • U : 这条路由已经启用
  • H : 这是一个主机的路由。如果没有这个标志,那么这条路由就是到同一个网络的,如果没有使用 CIDR 的话,也可能是同一个子网
  • G : 这条路由是间接的,目标地没有直接相连,而必须通过中间路由器或网关 (Gateway,G) 相连
  • D : 这条路由由重定向报文创建
  • M : 这条路由已经被重定向报文修改了

Refs 字段说明了路由的引用计数,也就是当前有多少个仍处于活动状态的使用者。

Use 字段说明已经用该路由发送了多少分组。

Netif 字段是相关网络接口的名称。

Mac OS 中可以使用如下命令查看路由表。

$ netstat -rn
Routing tables

# 输出如下
Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            192.168.20.1       UGSc           39        0     en0
127.0.0.1          127.0.0.1          UH              3    11132     lo0
192.168.20/24      link#4             UCS             8        0     en0
192.168.20.1       0:1f:ca:88:96:8c   UHLWIir        40       22     en0   1025
192.168.20.255     ff:ff:ff:ff:ff:ff  UHLWbI          0        8     en0

路由选择

路由器根据接收到的数据包中的目标 IP 地址,从路由表中选择最适合的路径,并选择从哪个网路接口转发,这一系列过程称为路由选择。

路由选择可以分为针对单播通信的单播 IP 路由选择和针对多播通信的多播 IP 路由选择。


最长缀匹配

当数据包到达路由器时,路由器会根据目标 IP 地址中的 (网络部分) 信息,从路由表中查找对应的路由表表项。

如果路由表中存在该表项,则根据该表项记载的网络接口信息,转发数据包到对应的网关(下一跳路由器的 IP 地址)。

如果路由表中出现多条表示同一个目标网络地址的表项时,则选择子网掩码最长、metric 指标值最小的表项,这种方式也称为最长缀匹配。

也就是说,主机表项比网络表项优先级高,网络表项比默认表项优先级高。

图片来源: 图解网络硬件(三轮贤一)

送快递示例

其实最长缀匹配和送快递的收货地址类似,例如一个快递包裹收件人地址为: 北京市海淀区知春路 ???

路由表中现在有三条路径:

  1. 北京市
  2. 北京市海淀区
  3. 北京海淀区知春路

虽然 3 条路径都可以匹配到收货地址,但是显然快递小哥 (网关) 会选择第 3 条路径,因为它更具体,更可信。


数据转发

路由器会忽略主机号,只匹配网络号。

接收包

路由器的网卡接口都具有 Mac 地址,只接收目标 Mac 地址与自身地址匹配的包,遇到不匹配的包直接丢弃。

完成包接收操作之后,路由器就会丢弃包中的 Mac 头部,Mac 头部的作用就是将包送达路由器,其中的接收方 Mac 地址就是路由器网卡接口的 Mac 地址。因此当数据包到达路由器之后,Mac 头部的任务就完成了。

转发过程

1. 查询路由表判断转发目标

图片来源: 网络是怎样连接的(户根勤)

假设地址为 10.10.1.101 的计算机要向地址为 192.168.1.10 的服务器发送一个包,这个包先到达图中的路由器。

判断转发目标的第一步,就是根据包的接收方 IP 地址查询路由表中的目标地址栏,以找到相匹配的记录。就像前文提到的一样,这个匹配并不是匹配全部 32 个比特,而是根据子网掩码列中的值判断网络号的比特数,并匹配相应数量的比特。

例如,图中的第 3 行,子网掩码列为 255.255.255.0,就表示需要匹配从左起 24 个比特,网络包的接收方 IP 地址和路由表中的目标地址左起 24 个比特的内容都是 192.168.1,因此两者是匹配的,该行记录就是候选转发目标之一。

按照这样的规则,可能会匹配到多条候选记录。在这个例子中,第 3、4、5 行都可以匹配。

路由器首先寻找网络号最长的一条记录 (最长缀匹配)。网络号越长,说明主机号比特数越短,也就意味着该子网内可分配的主机数量越少 (子网中可能存在的主机数量越少),这一规则的目标是尽量缩小范围,所以根据这条 (最长缀匹配) 记录判断的转发目标就会更加准确

  • 第 3 行 192.168.1.0/255.255.255.0 表示一个子网
  • 第 4 行 192.168.1.10/255.255.255.255 表示一台服务器

相比服务器所属的子网来说,直接指定服务器本身的地址时范围更小,因此这里应该选择第 4 行作为转发目标。根据最长缀匹配原则筛选后,如果只剩一条候选记录,则按照这条记录的内容进行转发。

有时候路由表中会存在网络号长度相同的多条记录,例如考虑到路由器或网线的故障而设置的备用路由就属于这种情况。这时需要根据 metric 指标计数的值来进行判断,指标计数越小说明该路由越近,因此应选择指标计数较小的记录。

如果在路由表中无法找到匹配的记录,路由器会丢弃这个包,并通过 ICMP 消息 (Destination Unreachable) 告知发送方。

2. 找不到匹配路由时选择默认路由

路由表中子网掩码为 0.0.0.0 的记录表示 “默认路由 (网关)”。

子网掩码 0.0.0.0 表示: 数据包目标 IP 地址和路由表目标地址的匹配中,需要匹配的比特数为 0。换句话说,就是根本不需要匹配。只要将子网掩码设置为 0.0.0.0,那么无论任何地址都能匹配到这一条记录 (默认记录)。

当匹配不到其他路由时,数据包就会被转发到网关路由器,因此这条记录也被称为默认网关。

图片来源: 图解网络硬件(三轮贤一)

如图所示,A 向 C 发送数据,路由器根据目标地址 192.168.3.0/24 查询路由表,结果没有查到对应的表项,因此使用 0.0.0.0/0 表项,将数据从端口 3 转发出去。

由于匹配的比特数越长,优先级越高,因此子网掩码 0.0.0.0 的记录优先级是最低的,只有找不到其他匹配的记录时,才会选择该 (默认) 记录。

3. 报错 && 丢弃包

如果根据数据包中的目标 IP 地址无法查询到有效的路由表项,并且路由表中也不存在默认网关,路由器会返回转发错误,并丢弃该数据包。


路由聚合

路由聚合会将几个子网合并成一个子网,并在路由表中只产生一条记录。

图片来源: 网络是怎样连接的(户根勤)

如图所示,现在有 3 个子网,分别为10.10.1.0/24、10.10.2.0/24、10.10.3.0/24,路由器 B 需要将包发往这 3 个子网。

在这种情况下,路由器 B 的路由表中原本应该有对应这 3 个子网的 3 条记录,但在这个例子中,无论发往任何一个子网,都是通过路由器 A 来进行转发,因此我们可以在路由表中将这 3 个子网合并成 10.10.0.0/16,这样也可以正确地进行转发,但我们减少了路由表中的记录数量,这就是路由聚合。

经过路由聚合,多个子网会被合并成一个子网,子网掩码会发生变化,同时,目标地址列也会改成聚合后的地址。

从结果上看,路由表的子网掩码列只是用来在匹配目标地址时告诉路由器应该匹配多少个比特。而且,目标地址中的地址和实际子网的网络号可能并不完全相同,但即便如此,路由器依然可以正常工作。


数据包的有效期

从路由表中查找到转发目标之后,数据包就会被转发给输出端口,并最终发送出去,但在此之前,路由器还会对数据包进行一些处理。

路由器在对数据包进行转发之前,会先更新 IP 报文头部的 TTL(Time to Live)字段,TTL 字段表示数据包的有效期,数据包每经过一个路由器的转发,这个值就会减 1,当这个值变成 0 时,就表示超过了有效期,路由器会将这个包直接丢弃。

这个机制是为了防止数据包在一个地方陷入死循环,如果路由表中的转发目标都配置正确,应该不会出现这样的情况,但如果其中某些路由器的路由表的配置有问题,或者由于路由设备故障等原因导致的临时性路由混乱,就会出现这样的情况。

有了这个 “兜底” 机制后,发送方在发送数据包时将 TTL 设为 64 或 128,数据包最多经过这么多路由器后就会 “寿终正寝”。现代的互联网即使访问一台位于地球另一侧的服务器,最多也只需要经过几十个路由器,因此只要数据包被正确转发,就可以在 TTL 过期之前到达目标地。


数据包的分片

一旦转发的数据包长度超过了输出端口能传输的最大长度,就无法直接发送这个包了,可以使用 IP 协议中定义的分片功能对包进行拆分,缩短每个包的长度。

IP 数据分片和 TCP 数据拆分机制是不同的。

TCP 拆分数据是在将数据封装到包里之前进行的,换句话说,拆分好的一个数据块正好装进一个包里。但是从 IP 分片的角度来看,这样一个包其实是一个未拆分的整体,也就是说,分片是对一个完整的包进行再拆分的过程。

分片过程

图片来源: 网络是怎样连接的(户根勤)

首先,我们需要知道输出端口的 MTU,看看这个包能不能不分片直接发送。最大包长度是由端口类型决定的,用这个最大长度减掉头部的长度就是 MTU,将 MTU 与要转发的包长度进行比较。

  • 如果输出端口的 MTU 足够大,那么就可以不分片直接发送
  • 如果输出端口的 MTU 太小,那么就需要将包按照这个 MTU 进行分片,但在此之前还需要看一下 IP 头部中的标志字段(Don’t fragment),确认是否可以分片。如果查询标志字段发现不能分片(带有 Don’t fragment 标志),那么就只能丢弃这个包,并通过 ICMP 消息通知发送方。否则,就可以按照输出端口 MTU 对数据进行依次拆分了

IP 分片示例

在分片中,TCP 头部及其后面的部分都是可分片的数据,尽管 TCP 头部不属于用户数据,但从 IP 来看也是 TCP 请求传输的数据的一部分。数据被拆分后,每一份数据前面会加上 IP 头部,其大部分内容都和原本的 IP 头部一模一样,但其中有部分字段需要更新,这些字段用于记录分片相关的信息。

分片重组

分片重组根据 = (IP 数据报) ID + Offset + More fragments

如果接收到的数据包是经过分片的,IP 协议栈会将它们还原成原始的包。

分片的数据包会在 IP 头部的标志字段中进行标记,当收到分片的包时,IP 协议栈会将其暂存在内部的内存空间中,然后等待 IP 头部中具有相同 ID 的包全部到达,这是因为 同一个包的所有分片都具有相同的 ID

此外,IP 头部还有一个分片偏移量 (fragment offset) 字段,表示当前分片在整个包中所处的位置

除了最后一个分片,其他分片包含了一个 More fragments = 1 的 Flag,接收方就可以判断出后续还有更多的分片。

最后一个分片,包含了一个 More fragments = 0 的 Flag,表示它是最后一个分片,因此接收方就可以开始重组了。

根据这些信息 (ID + offset),在所有分片全部收到之后,就可以将它们还原成原始的包,这个操作叫作分片重组。


控制平面和数据平面

高端路由器由控制平面(control plane)和数据平面(data plane,也可称为转发平面)组成,每个平面都有自己的 CPU 和内存。

路由器结构

控制平面负责执行路由选择协议,管理路由选择处理必备的数据库信息并生成 FIB(Forward Information Base,转发表), FIB 会被转发到用于接收传输数据包的数据平面中。

控制平面和数据平面分离的优点: 当需要转发的通信量剧增导致数据平面资源枯竭时,虽然无法继续进行分组转发,但对控制平面上路由选择处理所涉及的资源没有任何影响。同样,当路由选择处理负载剧增导致控制平面资源枯竭时,也不会给数据平面的资源以及分组转发处理带来任何影响。

低端路由器的控制平面与数据平面一般不分离,使用唯一的 CPU 和内存进行处理。当处理的通信量达到极限时,会出现无法完成分组转发,同时路由选择处理也会停止的情况。


路由选择协议

路由选择协议都是自适应的,能随着网络通信量和拓扑结构的变化而自适应地进行调整。

互联网可以划分为许多较小的自治系统 (AS),一个 AS 可以使用和别的 AS 不同的路由选择协议。

可以把路由选择协议划分为两大类:

  • 自治系统内部的路由选择:RIP 和 OSPF
  • 自治系统间的路由选择:BGP

1. 内部网关协议 RIP

RIP 是一种基于距离向量的路由选择协议。距离是指跳数,直接相连的路由器跳数为 1。跳数最多为 15,超过 15 表示不可达。

RIP 按固定的时间间隔仅和相邻路由器交换自己的路由表,经过若干次交换之后,所有路由器最终会知道到达本自治系统中任何一个网络的最短距离和下一跳路由器地址。

每个 RIP 路由器维护一张路由表,表中包含以下信息:

  • 目标网络(Destination Network)
  • 下一跳地址(Next Hop)
  • 路由距离(Metric)
  • 路由条目更新时间(Timer)

RIP 路由器周期性地(每30秒)向直接相连的所有邻居发送其完整的路由表,以便进行路由信息交换,这些路由更新报文使用 UDP 协议,端口号为 520。

收敛过程

当一个RIP路由器收到邻居路由器的路由更新信息时,它会执行以下步骤:

  • 更新路由表:如果收到的路由信息中的目标网络不在自己的路由表中,则将该目标网络添加到路由表中。如果该目标网络已经存在,且新的路径跳数更少,则更新路由表中的条目
  • 路由老化:RIP使用计时器机制老化路由表条目。如果一个路由条目在180秒内没有更新,则认为该路由条目过期,并将跳数设置为16,表示不可达

RIP 协议实现简单,开销小。但是 RIP 能使用的最大距离为 15,限制了网络的规模,并且当网络出现故障时,要经过比较长的时间才能将此消息传送到所有路由器,所以 RIP 收敛速度慢,仅适用于稳定的网络环境。

2. 内部网关协议 OSPF

开放最短路径优先 OSPF,是为了克服 RIP 的缺点而开发出来的。

开放表示 OSPF 不受某一家厂商控制,而是公开发表的;最短路径优先表示使用了 Dijkstra 提出的最短路径算法 SPF。

OSPF 具有以下特点:

  • 向本自治系统中的所有路由器 (广播) 发送信息
  • 发送的信息就是与相邻路由器的链路状态,链路状态包括与哪些路由器相连以及链路的 metric 指标 (metric 可以表示费用、距离、时延、带宽等)
  • 只有当链路状态发生变化时,路由器才会发送信息

所有路由器都具有全网的拓扑结构图,并且是一致的。相比于 RIP,OSPF 的更新过程收敛的很快。

3. 外部网关协议 BGP

BGP(Border Gateway Protocol,边界网关协议)

AS 之间的路由选择很困难,主要是由于:

  • 互联网规模很大
  • 各个 AS 内部使用不同的路由选择协议,无法准确定义路径的度量
  • AS 之间的路由选择必须考虑有关的策略,比如有些 AS 不愿意让其它 AS 经过

BGP 只能寻找一条比较好的路由,而不是最佳路由。

每个 AS 都必须配置 BGP 发言人,通过在两个相邻 BGP 发言人之间建立 TCP 连接来交换路由信息。


附录

路由器和光猫有什么区别

光猫的主要功能是将光纤信号转换为电信号。光纤传输使用光信号,而大多数家庭和办公设备使用电信号,光猫负责在这两者之间进行转换。光猫将数字信号调制成适合光纤传输的信号,同时将接收到的光信号解调成数字信号。光猫连接到互联网服务提供商(ISP)的光纤网络,提供互联网接入服务。

一般情况下,光猫设备上有 3 个接口

  • 光纤接口:用于连接ISP提供的光纤线路
  • 以太网接口(LAN):用于连接路由器或直接连接计算机。
  • 电话接口(可选):一些光猫还提供电话接口,用于 IP 电话服务

路由器通过 WAN 接口连接到光猫,以获取互联网接入,然后通过 LAN 接口和 Wi-Fi 接口将互联网接入分享到内部网络中的各个设备。

图片来源: 网络是怎样连接的(户根勤)


扩展阅读

转载申请

本作品采用 知识共享署名 4.0 国际许可协议 进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,商业转载请联系作者获得授权。