title: 《计算机网络》笔记-第4/5章网络层
date: 2020-06-18 20:58:25
综合第4章与第5章的网络层,以及课上老师所讲内容,与书本有较大不同。
在上一章中,曾提到运输层解决了进程间的通信问题。那么,网络层则解决了主机间的通信问题。
在偌大的互联网上,网络层会选择一条最短路径,将源主机的数据,经过一步步的转发,交付给目的主机。
而这个过程,就像现在的物流寄件,我们要如何将一份邮件或物品从发件地址邮寄到收件地址。
网络层的主要协议为:IP协议。
网络层传输单元为:数据报。
网络层主要有两种功能:
在进行转发和路由选择之前,我们必须解决一个重要问题:如何标识一台主机?
主机的标识就像邮寄单上的收件地址一样。只有当每个主机的标识唯一时,才能将数据准确地交付到目的地。
而这,就是IP协议中IP地址的作用。
主机与物理链路之间的边界叫做网络接口(Interface,也叫网卡)。
主机通常只有一个网络接口(也可能是两个:有线网接口和无线网接口);而路由器由于是不同网络间的交接中心,所以路由器至少需要与两条网络链路相连,因此路由器拥有多个网络接口。
从技术上讲,一个IP地址与一个网络接口(网卡)相关联,而不是主机或路由器(可能是方便网络管理)。比如:路由器通常有内网接口和公网接口,而内网接口和公网接口的IP地址是不相同的。
为了方便IP地址分类管理,我们通常将一定数量的主机组成一个子网 / 网络。
其好处是:
方便子网内部管理。每个子网可以自由决定所使用的链路层网络、路由算法等。
网络一般通过一个路由器与其它网络相连,当路由器要转发IP数据报时,只要将数据报转发到所属的网络即可,再由所属的网络进行分发,使得路由器的转发工作更加简单。我们可以类比 邮编地址:南京市每个区都有特定的邮编地址,组成起来,就是南京市邮编地址的“网络”。若要转发 目的地为南京市江宁区 的邮件,我们可以先将它转发给南京市,再由南京市内部进行分发。
那么如何来划分网络呢?从古至今,经过了三步发展:
将IP地址划分为网络号和主机号。网络号用于标识网络,主机号用于标识网络中的主机。
如果两个IP地址的网络号部分相同,则说明它们都属于同一个网络。
总共有 A、B、C、D、E 五种分类方法。A 类常用于大型网络,B 类常用于中型,C 类则用于小型,D、E 类特殊用途。
注:网络号不能全为0,所以A类网络的网络数需要减多一个 1 ;主机号不能全为0,也不能全为1,所以C类网络中主机数为 2 8 − 2 = 254 2^8-2 = 254 28−2=254。
以下是分类 IP 地址的一些示例:
由于分类的 IP 地址中,某类网络所拥有的主机数是固定的,所以有时候会觉得C类地址中主机数太少,有时候又会觉得B类地址中主机数太多。
为此,又提出从主机号中划分出子网号,使得两级 IP 地址变成了三级 IP 地址。而且,子网号的长度是可变的:
但新的问题出现了,由于子网号可变,那如何从一个IP地址中区分出子网号呢?
子网掩码!子网掩码长度为32位,左边连续且全为 1 的部分对应网络号和子网号,右边连续且全为 0 的部分对应主机号。当用子网掩码与 IP 地址进行 与运算 后,便可以得到子网号。
另外,子网掩码是由子网提供的,并会记录在路由器的路由表中:
随着时代的发展,人们发现了更好的 无分类域间路由选择 CIDR 方法。
补充说明:
/
之后的 x
表示子网掩码中 1 的个数,用来指明网络前缀的长度。CIDR 实践:
Fly-By-Night-ISP
内部有 8 个自组织,每个组织都有自己的子网。通过 CIDR 编址,外界只需要将所有 IP 地址前 20 比特与 200.23.16.0/20
相符的数据报,发送到该 ISP 即可,而不需要知道该 ISP 内还存在 8 个其它组织。受限于 链路层最大帧长度 MTU 影响(以太网帧不能超过1500字节、某些广域网链路不能超过576字节),IP 数据报过大时,需要对 IP 数据报进行分片:将原数据报中的数据部分分成恰好的几部分,对每一部分数据都加上 IP 首部,组成几个新的 IP 数据报。
IP 数据报分片依托于首部的标识、标志、片偏移字段:
MF = 1
表示后面还有分片,MF = 0
表示最后一个分片,DF = 0
表示允许分片。示例:
注意:在第3章中提到,TCP为了防止IP分片,会先一步进行分段。
我们知道,划分网络是为了各种各样的组织更好地管理网络。当某个组织(比如学校、公司等)申请入网后,相关机构会给组织分配一个子网络(也就是一系列IP地址),组织可以自由地分配这一些列IP地址。
从前,这项工作通常由组织的管理员手动为每台主机和路由器配置。但如今,更多的是使用 动态主机配置协议(Dynamic Host Configuration Protocol,DHCP) 来完成:
它也常常被称为即插即用协议或零配置协议。
DHCP 为联网主机分配IP地址的过程为:
DHCP 服务器发现:一台刚联网的主机,会向网络中发送一个 DHCP 发现报文(DHCP discover message),这是一个由 67 号端口发送的 UDP 报文。该报文的 目的地址 为 255.255.255.255(IP 地址全 1 表示广播地址,会发送给当前子网络中的所有主机),源地址 为 0.0.0.0(主机还不知道它的地址) 。
DHCP 服务器提供:网络中的 DHCP 服务器收到一个 DHCP 发现报文后,会用 DHCP 提供报文(DHCP offer message) 进行响应。报文的目的地址依然是 255.255.255.255,但同时报文中包含对应 DHCP 发现报文的事务ID、向用户推荐的IP地址、网络掩码和IP地址有效期等。
DHCP 请求:由于一个网络中可能存在多个 DHCP 服务器,用户会从多个 DHCP 提供报文中选择一个,并发送 DHCP 请求报文(DHCP request message) 响应对应的 DHCP 服务器(你就天选之子>.<)。
DHCP ACK:DHCP 服务会对 DHCP 请求报文进行响应。
从前面的介绍中,我们知道:每个联网设备都会分配一个唯一的IP地址。但是,随着互联网的爆发,入网设备激增,剩余 IP 地址越来越少。
同时,越来越多的小型子网(家庭网络、小型办公室)涌现。如果这些子网想要联网,ISP 则需要分配一组地址给该子网的所有联网设备。如果某天这个子网变大了,ISP 可能得分配一块较大的连续地址,但这组地址后的连续地址都被占有了,这该怎么办呢?ISP 管理这些子网显得十分繁琐。而且,家庭的主人还需要知道 IP 地址管理经典方法。
幸运的是,一个简单的方法被用来解决这个问题,那就是 网络地址转换(Network Address Translation, NAT) ——它将这些子网指定为专用网络,专用网络中可以自主分配专用地址。
在介绍 NAT 之前,不知道细心的同学们有没有发现一个现象:不管你电脑连接的是家庭网络、学校网络、还是手机热点,电脑的 IP 地址经常都是 192.168.x.x
,甚至有时候还是相同的。
为什么会这么巧呢?这就是 NAT 在背后作祟。
以家庭网络为例:
在外界看来,NAT 路由器就像一个具有单一 IP 地址的单一设备,它隐藏了家庭网络的细节。所有离开家庭网络流向公网的报文都拥有同一个源 IP 地址,而所有进入家庭网络的报文都拥有同一个目的 IP 地址。
凭借着 NAT 协议,N 个主机可以拥有任意内网 IP ,而在外界看来就只有一个公网 IP 地址(由于端口号字段为 16 比特,所以 NAT 路由器可支持超过 60000 个的连接)。如此往后,ISP 再也不用操心子网 IP 地址分配的问题,家庭子网的主人也不需要掌握管理子网的方法了,这都可以由家庭路由器统一自动分配管理。
虽然 NAT 既简单又好用,但也存在着几个问题:
由于内网中所有的 IP 地址经过 NAT 路由器后,都会变成 NAT 路由器的公网 IP 地址,所以内网中的 IP 地址可以任意分配。但是,如果一个 IP 地址即存在于内网又存在于公网,NAT 路由器要如何转发呢?
为了避免这个矛盾的出现,互联网规定三类 IP 地址块(地址范围)为专用地址,只能用于专用网络(也就是内网)不能出现在公网上,分别是:10.0.0.0 ~ 10.255.255.255
、172.16.0.0 ~ 172.31.255.255
、192.168.0.0 ~ 192.168.255.255
(所以,我们经常见到电脑的 IP 地址为 192.168.x.x
,其实这就是一个内网 IP )。
由于 NAT 路由器把内网隐藏了,而且内网 IP 也不会出现在公网上。如果一台主机想要被外部主机访问,则需要申请公网 IP,而这只能向相关运营商购买。如果实在想访问内网主机,可以采用内网穿透等方法。
但随着 NAT 的流行,这种反对的声音也渐渐变小。
上文提到,NAT 协议能够方便地管理专用网络,但其中一个问题就是专用网络(内网)中的主机是不可访问的。有些机构在使用 NAT 的同时,又想从外部访问内网的主机,那要怎么办呢?
申请公网 IP ?但问题是,机构申请到的公网 IP 数量往往是有限;而且由于互联网的不安全性,一个机构也不想把部分主机接入互联网。
为了解决从外部网络访问内网主机的问题,虚拟专用网络(Virtual Private Network,VPN) 被提出来了。说到 VPN ,很多老司机们应该再清楚不过了:) 科学上网的必备工具,此刻我们就来见识一下 VPN 奥妙。
VPN 可以将相隔着公网的两个专用网络连接起来,就好像一个专用网络一样(实际上并不是),所以称为虚拟专用网络。那它是如何实现的呢?
首先,购买 VPN 的机构,必须在通信的两端进行相关配置,相互之间必须知道对方的地址。
其次,专用网络之间的通信必须经过公网,为了保密要求,VPN 还必须对所有传输的数据进行加密。
最后,利用 隧道 技术进行传输。隧道技术其实就一个包装、拆包的过程:内网 A 中主机 X 发送给内网 B 中主机 Y 的数据报,到达出口路由器后,会将数据报进行加密,并再套上一个 IP 首部,以内网 B 中入口路由器的公网 IP 地址为目的地址;到达内网 B 的入口路由器后,会取出数据部分进行解密,并转发到内网,最终到达主机 Y 。
虽然 NAT 一定程度上也扩充了互联网中联网设备的容量,但公网 IP 的数量还是受 IPv4 地址的限制,IPv4 地址只有 32 位,总共才 4 , 294 , 967 , 295 ≈ 4.2 × 1 0 9 ≈ 42 亿 4,294,967,295 \approx 4.2 \times 10^9 \approx 42亿 4,294,967,295≈4.2×109≈42亿 个。随着互联网惊人的增长,公网 IP 也即将耗尽。
为了避免耗尽情况的出现,一种新的 IP 协议被提出——IPv6。
IPv6 将 IP 地址长度从 32 比特增加到了 128 比特。现在,地球上的每个沙砾都可以用 IP 地址寻址了。
IPv6 数据报格式如下:
其最重要的几大新增改变如下:
但几个 IPv4 中的字段和功能在 IPv6 数据报中也不复存在了:
虽然 IPv6 被设计出来,但已部署 IPv4 的系统却不能够处理 IPv6 数据报,如何从 IPv4 迁移到 IPv6 是当下的大问题。
其中一个迁移方法便是 建隧道(tunneling):
假设两个 IPv6 节点使用 IPv6 数据报进行交互,中间经过 IPv4 路由器,那么我们可以把中间 IPv4 路由器的集合称为一个 隧道。当 IPv6 数据报要进入隧道时,可以用 IPv4 数据报包裹起来,出隧道时,再取出。其过程如下:
在上文中提到,ICMP 报文可以被 IPv6 用来告知发送方数据报过大,但ICMP的作用不止于此。
因特网控制报文协议 ICMP [RFC 792],被主机和路由器用来彼此沟通网络层信息的协议。
其报文格式如下:
由图可知,ICMP 报文类似于 TCP、UDP ,它也是被 IP 数据报所包裹的。
根据首部类型字段和代码字段的不同,ICMP 报文有着不同的功能,常见的如下:
ICMP 最贴近我们的应用,便是 ping 程序和 Traceroute 程序了。众所周知的 ping 程序便是发送一个类型 8 编码 0 的 ICMP 报文,目的主机返回一个类型 0 编码 0 的 ICMP 响应报文。
Windows 下实验 traceroute,打开 cmd ,输入指令:
> tracert baidu.com
路由器是网络层中重要的设备。它用于连接不同的网络,并在不同网络间转发分组,同时也具备路由选择的功能。
路由器结构如下:
输入端口。输入端口包含物理层、链路层、网络层处理模块。物理层模块负责接收处理物理信号;链路层模块负责去掉帧首部和尾部;网络层模块负责进行查表、转发、排队进入交换结构。
其中,查表和转发是输入端口的核心功能。
交换结构。经过交换结构,分组才能从一个输入端口交换到一个输出端口。交换结构可以用多种形式,分别是 经内存交换、经总线交换、经互联网络交换(纵横式),如下:
输出端口。将队列中的分组发送到输出链路上。
路由选择器。路由选择算法运行之处(后面会详细讲解路由选择算法)。
路由选择算法,其目的是从发送方到接收方的网络中,选择一条最短路径(即网络最好最快的一条路)。
究其本质,就是图的最短路径问题。而解决该问题的经典算法,想必读者在数据结构或算法课上都学过,即Dijkstra、Bellman-Ford和Floyd等。
根据路由选择算法的差异,有不同的分类。接下来将介绍几种分类,第一种常用分类:
第二种广义分类:静态路由选择算法;动态路由选择算法。第三种分类:负载敏感算法;负载迟钝算法。
链路状态路由选择算法中,网络拓扑和所有链路开销情况都是已知的,都作为 LS 算法的输入。实践中,这些信息是让每个节点向网络中其它节点广播链路状态分组来完成的,分组中包含它所连接链路的标识和开销等信息。
LS 算法的本质其实是大名鼎鼎的 Dijkstra 算法。在我另一篇文章 图的最短路径算法 中,我已经详细介绍了 Dijkstra 算法的过程,在此就不再赘述了。
LS 算法运行过程示例如下。其中, D ( v ) D(v) D(v) 表示到本次迭代,从源节点到 v v v 节点的最短路径的开销; p ( v ) p(v) p(v) 表示最短路径中 v v v 的前一个节点:
Dijkstra 算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),相对较优,但也存在着一些问题:实践中,链路开销是非对称的,也就是 u 点到 v 点的开销与 v 点 u 点的开销是不相同的。同时,链路开销也是会变化的。当多个路由选择同一个时针方向时,该方向上的开销就会非常大,但反方向的开销相对较小;此时,多个路由可能同时改成反方向,而如此反方向开销剧增,正方向剧降;并进入反复横跳的循环中。
这种现象被称为振荡。有一种解决方法是:确保所有路由器不同时运行 LS 算法。
DV 算法是一种迭代、分布式的算法。它的本质是 Bellman-Ford 算法,即:
d ( x , y ) = m i n { c ( x , v ) + d ( v , y ) } d(x,y) = min\{c(x,v) + d(v,y)\} d(x,y)=min{c(x,v)+d(v,y)}
v ∈ x 所 有 的 邻 接 点 , c ( x , v ) 是 x 到 v 边 的 开 销 v \in x所有的邻接点,c(x,v) 是 x 到 v 边的开销 v∈x所有的邻接点,c(x,v)是x到v边的开销
DV 算法实际运行过程如下:
每个节点(节点=路由器) x x x 需要维护一些路由信息:
每个节点还需不时地向它的每个邻居发送它的距离向量。当节点 x x x 从它的任何一个邻居 v v v 接收到新的距离向量时,它将保持 v v v 的距离向量,然后使用 d ( x , y ) = m i n { c ( x , v ) + d ( v , y ) } d(x,y) = min\{c(x,v) + d(v,y)\} d(x,y)=min{c(x,v)+d(v,y)} 方程更新自己的距离向量。
如果节点 x x x 的距离向量因步骤2而更新,那么它会向所有邻居发送它更新后的距离向量。
示例如下:
注意在第2列中, y y y 节点的距离向量没有更新,因此节点 y y y 没有发送更新。
现在,我们需要考虑一些特殊情况:链路开销改变与链路故障。
当链路开销减小时:
当链路开销增加时:
从上述过程,我们可以看出:该循环将持续44次迭代(在 y y y 与 z z z 之间),直到 z z z 算出它经由 y y y 的路径开销大于50。这个问题被称为无穷计数问题。
一种毒性逆转的方法可用于解决该问题,但并不具有一般性。
设 N N N 是节点集, E E E 是链路集。比较:
传播开销。当链路开销改变时,LS 必须向所有节点广播新的链路开销,需要发送 O ( ∣ N ∣ ∣ E ∣ ) O(|N||E|) O(∣N∣∣E∣);而 DV 只需向邻近节点传播。
收敛(得到正确结果)速度。LS 算法为 O ( n 2 ) O(n^2) O(n2) ;而 DV 算法收敛较慢,且会遇到路由选择环路等问题。
健壮性。如果遇到出现故障的链路,LS 能够向所有节点广播不正常的开销;而 DV 可能把不正常的计算值扩散到整个网络。
LS 算法的应用:OSPF等。
DV 算法的应用:RIP、BGP等。
到目前为止的路由选择算法中,我们都将网络看作一个互联网路由器的集合,从所有路由器上执行相同的路由选择算法以计算穿过整个网络的最短路径。但是,实践中却并非如此简单,有如下原因:
于是乎,出现了 自治系统(autonomous system, AS)。每个 AS 是一个路由器集合,并对所属路由器使用相同的方法进行管理控制。ISP 通常将他们的网络划分成一到多个 AS。而在一个 AS 中运行的路由选择算法叫作自治系统内部路由选择协议(intra-autonomous system routing protocol)。
自治系统内部路由选择协议有很多,如:基于 LS 算法的 OSPF 协议、基于 DV 算法的 RIP 协议等。其中,开放最短路优先 OSPF [RFC 2328] 更为常用。
除了拥有 LS 算法的特性,OSPF 协议还有以下优点:
OSPF 可以解决自治系统内部的路由问题,但当一个分组需要跨越多个 AS 时,我们则需要 自治系统间路由选择协议(inter-autonomous system routing protocol)。
由于 AS 间路由选择协议涉及多个 AS 之间的协调,所以 AS 间必须运行相同的协议,即 边界网关协议 BGP [RFC 4271]。
BGP 协议有如下特性:
在 BGP 中,分组并不是路由到一个特定 IP 地址,而是路由到 CIDR 的前缀,也就是一个子网或子网的集合。所以,路由器的 BGP 路由表表项通常为 (x, l)
的形式,其中 x
是一个前缀(如138.16.68/22),l
是该路由器的输出接口之一。
与 DV 算法类似,在 BGP 中,路由器会向临近路由器传递路由信息。但不同的是,BGP 路由算法并不一定选择开销最小的路径,而是会选择“最佳”的路径。
在介绍 BGP 独特的路由选择算法之前,我们还需要了解一些 BGP 相关内容:
网关路由器。位于 AS 边缘,并连接到其它 AS 的路由器,被称为网关路由器。反之,则被称为内部路由器。如下图的 AS1 中,1c、1d 是网关路由器,1a、1b 则是内部路由器。
BGP 属性。在 BGP 中,当路由器向临近路由器传递信息时,除了包含前缀,还包括一些 BGP 属性。其中,两个比较重要的属性是 AS-PATH(表示到达目的前缀/子网所经过的 AS 路径,如下图中,从 AS1
到子网 x
有两条路,AS-PATH 分别是 “AS2 AS3”、“AS3”)和 NEXT-HOP(表示 AS-PATH 中第一个路由器的输入接口 IP 地址,如下图中,对于从 AS1
到子网 x
的路径 “AS2 AS3”,其 NEXT-HOP 值为路由器 2a 左边接口的 IP 地址)。
BGP 路由。包含前缀及其属性的路由信息,被称为 BGP 路由。实践中,一条 BGP 路由还包括其他属性,此处我们暂时忽略。
接下来,将介绍 BGP 的路由选择算法。考虑的情况是:从路由器 1b
路由到子网 x
,显然有两条路径:经过网关路由器 1c 到达 AS2 再到达 AS3、经过网关路由器 1d 直接到达 AS3。
热土豆路由选择算法。假设开销为经过的链路数,第一条路径的总开销肯定大于第二条路径。但根据热土豆算法,由于 1b 到 1c 的开销小于 1b 到 1d 的开销,算法会选择第一条路径。热土豆算法的思想是:尽可能地将分组送出其 AS ,而不担心送出来后的剩余开销。可以说,这是一个自私的算法。
真实的 BGP 路由选择算法。如果有多条路径,则按照如下规则顺序进行筛选,直到选出最好的路径:
由于第二条规则在第三条规则之前,所以 BGP 路由选择算法并不是一个自私的算法。
有关第一条规则中的 BGP 策略问题,书中也未作详细讲解,可以自行了解。
除了用于 AS 间的路由选择,BGP 还常用于实现 IP 任播 [RFC 1546, RFC 7094]。从 BGP 路由选择算法中,我们得知:当目的地相同时,算法会从多条路径中选择“最佳”的(比如 AS-PATH 最短)。
BGP 任播应用:
CDN 内容分发网络。CDN 公司会为它的多台服务器配置相同的 IP 地址,当客户访问视频等内容时,利用 BGP 路由选择算法的特点,算法会向“最近的”服务器转发请求,从而让用户得到更好的体验。但实践中 CDN 通常不使用 IP 任播,因为 BGP 路由选择算法可能会导致同一个 TCP 连接的不同分组到达不同的服务器。
DNS 系统。IP 任播被广泛地用于 DNS 系统,它会将 DNS 请求指向最近的 DNS 服务器(比如13个根服务器中的一个)。
BGP 在因特网中起着重要作用,以上只是 BGP 的简要介绍。
AS 间路由选择是面向策略的。不同 AS 可能是由不同的 ISP 管理的,而它们之间可能是竞争关系,或者说 ISP 都是自私的,比如:一个 AS 产生的流量不能经过另一个特定的 AS 、一个 AS 并不想承载其它 AS 的流量。
而,AS 内部路由选择是面向性能。AS 内部是由同一个 ISP 统一管理的,所以上述策略相对不重要,而性能才是关键。
软件定义网络(Software Defined Network,SDN),是近年来(201x)兴起的一种网络管理方法。它的提出类似于操作系统的思想,将底层网络设备进行抽象,屏蔽其具体细节,同时为上层提供相关接口。用户通过这些接口,可以开发各种软件,对网络进行集中式管理、灵活配置、自动化监控、访问控制、负载均衡等等操作。
书上提到,SDN 体系具有4个特征:
基于流的转发。SDN 控制的分组转发,能够基于运输层、网络层、链路层首部中的任意字段;而传统转发仅依据数据报的目的 IP 地址进行。
数据平面与控制平面分离。数据平面由路由器等网络设备组成,它们会根据流表执行“匹配加动作”的规则;控制平面由服务器、以及决定和管理流表的软件组成。
网络控制功能。与传统的路由器不同,算法软件在服务器上执行,服务器与网络设备截然分开并与之远离。如下图所示,控制平面由两部分组成:SDN 控制器 和 若干网络控制程序。SDN 控制器负责维护获取网络状态信息,并向上层提供;网络控制程序则以此监视、控制网络设备。
可编程网络。通过控制平面中的网络控制应用程序,SDN 控制平面即拥有了“智力”,例如:它可以决定源与目的间的路径、可以对特定分组进行阻挡、可以根据负载均衡对分组进行转发、甚至可以运行 AI 算法。
SDN 是当下的一股热潮。其中,相对突出的是 OpenFlow 协议,它运行在 SDN 控制器和网络设备上。但在此不做详细介绍。