计算机网络:网络层

IP地址的划分

IP地址的编址方法共经过了三个历史阶段:

1. 分类的 IP 地址

分类的 IP 地址就是将 IP 地址划分为若干个固定类,每一类地址都由两个固定长度的字段组成,第一个字段是网络号,它标志主机或路由器所连接到的网络,一个网络号在整个因特网范围内必须是唯一的。第二个字段是主机号,它标志该主机或路由器,一个主机号在它前面的网络号所指明的网络范围内必须是唯一的,所以一个 IP 地址在整个因特网中也是唯一的。

IP 地址 ::= { <网络号>, <主机号> }

A 类地址的网络号共有8位,第一位固定为 0
B 类地址的网络号共有16位,前两位固定为 10
C 类地址的网络号共有24位,前三位固定为 110
D 类地址前四位固定为 1110,主要用于多播
E 类地址前四位固定为 1111,保留以后使用。

特殊含义的IP:

  • 全 0 的 IP 地址是保留地址,意思为“本网络”。
  • 127.0.0.1 保留为本地软件环回测试进程间通信用。
  • 全 1 的 IP 地址表示该网络上的所有主机。

IP 地址有以下特点:

  1. IP 地址由两部分组成,从这个意义上来说,IP 地址是一种分等级的地址结构。好处有两点,一是 IP 地址管理机构在分配 IP 地址的时候只分配网络号,剩下的主机号由获得网络号的厂商自行分配。二是路由器仅根据目的主机所连接的网络号来转发分组而不用考虑主机号,可以使路由表中的项目大大减少,从而减少存储占用和查询路由表的时间。

  2. 实际上 IP 地址是标志一个主机和一条链路的接口,当一个主机同时连接到两个网络上时,该主机就要同时具有两个 IP 地址,其网络号必是不同的。

  3. 按照因特网的观点,一个网络是指具有相同网络号的主机的集合,因此用转发器或网桥连接起来的若干个局域网仍是一个网络,因为这些局域网都具有同样的网络号,具有不同网络号的局域网必须使用路由器进行互联。

  4. 在 IP 地址中,所有 IP 地址都是平等的,因特网不会区别对待。

互联网中的IP地址

2. 子网的划分

子网划分将两级 IP 地址变为了三级 IP 地址:

IP 地址 ::= { <网络号>, <子网号>, <主机号> }

从 IP 数据报的首部中也无法看出源主机和目的主机是否进行了子网划分,于是产生了子网掩码的概念。子网掩码同 IP 一样为 32 位。网络号和子网号部分为 1,主机号部分为 0。路由器只需要将 IP 地址和子网掩码进行与运算即可得出子网的网络的地址。

*注: 主机号全 0 表示子网的网路地址,全 1 表示子网的广播地址。

路由器转发分组的算法如下:

  1. 从数据报中提取目的 IP 地址 D。

  2. 判断是否可以直接交付,把所有直接相连的网络的子网掩码和 D 按位与,如果结果和相应的网络地址匹配,则直接交付。

  3. 若路由表中有目的地址为 D 的特定主机路由,则把数据报传送给路由表中所指明的下一跳路由器。

  4. 遍历路由表(目的网络地址,子网掩码,下一跳地址),如果某行的子网掩码和 D 按位与的结果同该行的目的网络地址相同,则把数据报传送给该行的下一跳路由器。

  5. 若有默认路由,则传送给默认路由,否则报错。

3. 构成超网

无分类编址(CIDR):

  1. 取消传统 A、B、C 类地址以及划分子网的概念,转而将 IP 地址划分为两部分 IP 地址 ::= { <网络前缀>, <主机号> },并且在 IP 地址后面加上斜线 “/”,然后写上网络前缀所占的位数。

  2. 把网络前缀相同的连续的 IP 地址组成一个 CIDR 地址块。

为了更方便地进行路由选择,CIDR 使用 32 位的地址掩码,例如 /20 的地址掩码是 11111111 11111111 11110000 00000000(20 个连续的 1),斜线记法中,斜线后面的数字就是地址掩码中 1 的个数。

在查找路由表时,可能会得到不止一个匹配结果,应该当从匹配结果中选择具有最长网络前缀的路由。为了加快查询速度,路由表还会建立二叉线索以及各种压缩技术。

地址解析协议 ARP

ARP 协议是为了从网络层使用的 IP 地址解析出在数据链路层使用的 MAC 地址。

每一个主机设有一个 ARP 高速缓存,里面有本局域网上的各主机和路由器的 IP 地址到硬件地址的映射表,这些都是该主机目前知道的一些地址。

通过命令 arp -a 可以查看当前主机的 arp 缓存表。

当 A 要向本局域网上的 B 发送 IP 数据报时,就先在其 ARP 高速缓存中查看有无主机 B 的 IP 地址。如有,就在 ARP 高速缓存中查出其对应的硬件地址,再把这个硬件地址写入 MAC 帧,然后通过局域网把该 MAC 帧发往此硬件地址。

也有可能查不到 B 的硬件地址,这种情况下 A 就自动运行 ARP:

Wireshark 抓包

  1. ARP 进程在本局域网上广播发送一个 ARP 请求分组,Wrieshark 中对应的 Info 为 “who has 209.0.0.6? Tell 209.0.0.5”,ARP 的请求分组是广播发送的

  2. 在本局域网上的所有主机上运行的 ARP 进程都收到此 ARP 请求分组。

  3. B 的 IP 地址与 ARP 请求分组中要查询的 IP 地址一致,就收下这个 ARP 请求分组,并向 A 发送 ARP 相应分组,该分组中包含自己的硬件地址。Wrieshark 中对应的 Info 为 “209.0.0.6 is at 08-00-2B-EE-0A”。由于其余主机的 IP 地址都与 ARP 请求的 IP 地址不一致,因此都不予理睬。ARP 的响应分组是单播发送的

  4. 当 A 收到 B 的 ARP 响应分组后,就在本机的 ARP 高速缓存中写入主机 B 的 IP 地址到硬件地址的映射。为了减少网络通信,A 运行 ARP 时会将自己的 IP 地址到硬件地址的映射写入请求分组中,这样 B 接收到请求分组后,就将 A 的映射关系写入本机缓存中,之后再与 A 通信就不再发送 ARP 请求分组了。

ARP 写入缓存时还会为缓存设置生存时间,超过生存时间的都会被删除,这样网络拓扑变化时能够及时响应。此外如果数据链路层无法连通,则会直接在缓存中删除该项。

请注意,ARP 是解决同一个局域网上的主机或路由器的 IP 地址和硬件地址的映射问题,如果目标主机和源主机不在同一个局域网内,发送流程如下:

跨局域网发送 IP 数据报

IP 数据报的格式

跨局域网发送 IP 数据报

1. 版本

指 IP 协议的版本,通信双方使用的协议版本必须一致,目前主要是 IPv4。

2. 首部长度

首部长度字段的单位为 32 位(4 字节)。首部字段最小值是 5,最大值是 15,所以首部的长度为 20 字节到 60 字节。当首部长度不是 4 字节的整数倍时,必须利用最后的填充字段填充。最常用的首部长度为 20 字节,即首部长度为 0101,这时不使用任何选项。

3. 区分服务

一般不使用。

4. 总长度

总长度指首部和数据之和的长度,单位为字节。总长度字段为 16 位,因此数据报的最大长度为 216 - 1 = 65535 字节,然而实际上传送这样长的数据报很少见。

在 IP 层下面的每一种数据链路层协议都规定了一个数据帧中的数据字段的最大长度,称为最大传送单元 MTU,所以一个 IP 数据报的长度一定不能超过 MTU 值。

虽然使用尽可能长的 IP 数据报会使传输效率提高,但路由器的转发速度会随之下降。为此 IP 协议规定,因特网中的主机必须能接受长度不超过 576 字节的数据报。这是假定上层交下来的数据长度为 512 字节(合理长度),加上最长首部的60字节,再加上 4 字节的富余量,接得到 576 字节。当主机要发送长度超过 576 字节的数据报时,需要确认目的主机能否接收所要发送数据报长度,否则就要分片。

在进行分片时,数据报首部中的“总长度”字段是指分片后的每一个分片的首部长度与该根片的数据长度长度之和。

5.标识

IP 软件在存储器中维持一个计数器,每产生一个数据报计数器就加一,并将此值赋给标识字段。但这个标识并不是序号,因为 IP 是无连接服务,不存在按序接收的问题。当数据包由于长度超过 MTU 而必须分片时,这个标识字段的值使分片后的各数据报片最后能正确地重装成原来的数据报。

6. 标志

目前只有前两位有意义。

  • 标志字段中的最低位记为 MF,MF = 1 标识后面还有分片数据报,MF = 0 标识这已是若干数据报片的最后一个。

  • 标志字段中间的一位记为 DF,意思是不能分片,只有当 DF = 0 时才允许分片。

7. 片偏移

片偏移指出较长的分组在分片后,某片在原分组中的相对位置。也就是说相对于用户数据字段的起点,该片从何处开始,片偏移以 8 个字节为偏移单位。

8. 生存时间

由源站设置这个字段,每经过一个路由器,就从 TTL 中减去在本路由器上的消耗时间,当 TTL 减为 0 时,该保文会被丢弃,这样可以避免数据报无限制的兜圈子。

但是随着技术的进步,它的单位已经是不是秒了,而是跳数,每经过一个路由器这个数值就减一,减为 0 时就丢弃该报文。因为生存时间有 8 位,所以最大只允许经过 255 个路由器。

9. 协议

协议字段指出此数据报携带的数据是使用何种协议,以便使目的主机的 IP 层知道应将数据部分上交给哪个处理过程。

协议名 ICMP IGMP IP TCP EGP IGP UDP IPv6 ESP OSPF
协议字段值 1 2 4 6 8 9 17 41 50 89

10. 首部校验和

该字段只校验数据报的首部,但不包括数据部分。

网际控制报文协议 ICMP

ICMP 报文是封装在 IP 数据报中的,作为其中的数据部分,仍属于 IP 层的协议。ICMP 的报文分为差错报文询问报文

询问报文共有五种:

  1. 终点不可达: 当路由器或主机不能交付数据报时就向源点发送终点不可达报文。

  2. 源点抑制: 当路由器或主机由于拥塞而丢弃数据报时,就像源点发送源点抑制报文,使源点知道应道把数据报的发送速率变慢。

  3. 时间超过: 当路由器收到生存时间为零的数据报时,除丢弃该报文外,还要向源点发送时间超过报文。当终点在预先规定的时间内不能收到一个数据报的全部数据报片时,就把已收到的数据报片丢弃,并向源点发送时间超过报文。

  4. 参数问题: 当路由器或目的主机收到的数据报的首部中有的字段的值不正确时,就丢弃该报文,并向源点发送参数问题报文。

  5. 改变路由(重定向): 路由器把改变路由报文发送给主机,让主机知道下次应将数据报发送给另外的路由器(可通过更好的路由)。在主机刚开始工作时,一般都在路由表中设置一个默认路由器的 IP 地址。不管数据报要发送到哪个目的地址,都一律先将数据报传送给这个默认路由,而默认路由知道每一个目的网络的最佳路由(通过和其它路由器交换路由信息得知)。如果默认路由发现主机发往目的地址的最佳路由不应该经过默认路由而应该通过另外一个路由 R 时,默认路由就会用改变路由报文告知主机,于是主机端的路由表中就增加了一个项目:到某某某地址的的报文应该经过路由 R。

常用的询问报文有两种:

  1. 回送请求和回答: 由主机或路由器向一个特定的目的主机发出询问,收到此报文的主机必须回送回答报文,用来测试目的站是否可达以及了解其有关状态。

  2. 时间戳请求和回答: 请某个主机或路由器回答当前的日期和时间,回答报文中有一个 32 位的字段,其中写入的整数代表从 1900 年 1 月 1 日到现在一共有多少秒。时间戳请求和回答可以用来进行时钟同步和测量时间。

ICMP 的一个重要应用就是分组网间探测 PING,用来探测两个主机之间的连通性。

另一个非常有用的的是 traceroute,linux 中对应命令为 tracepath,windows 中对应为 tracert:

code shell
tracepath 49.232.15.194

Traceroute 从源主机想目的主机发送一连串的 IP 数据报,数据报中封装的是无法交付的 UDP 数据报(使用了非法端口)。第一个数据报 P1 的生存时间 TTL 设置为 1,当 P1 到达第一个路由器时,路由器将 TTL 减一,由于 TTL 等于零所以该报文被丢弃,并向源主机发送一个 ICMP 时间超过的差错报文。发送第二个报文时 TTL 设置为 2, 以此类推。当最后一个数据报刚刚到达目的主机时,数据报的 TTL 为 1,主机不转发数据报,所以不会把 TTL 减一,但因 IP 数据报中的数据无法交付到的数据,因此目的主机要向源主机发送 ICMP 终点不可达差错报文。这样路由器就得到了所经过路由器的 IP 地址,以及往返时间。

traceroute 抓包

虚拟专用网 VPN

为避免本地地址和全球地址发生冲突,RFC 专门指定了一组专用地址。这些地址只能用在单位内部通信,而不能用于和网络上的主机通信,在公网的所有路由器中,对目的地址是专用地址的数据报一律不进行转发:

  • 10.0.0.0 - 10.255.255.255 或记为 10.0.0.0/8
  • 172.16.0.0 - 172.31.255.255 或记为 172.16.0.0/12
  • 192.168.0.0 - 192.168.255.255 或记为 192.168.0.0/16

如果同一机构的许多部门分布在不同的地域上,而在每个地域都有自己独立的专用网,假设它们之间需要通信,则有两种解决方案:一种是搭建专线,缺点是价格昂贵,另一种是利用公网作为通信载体,这样专用的网络又被称为虚拟专用网 VPN,如下图示意:

构成虚拟专用网

显然每个场所至少有一个路由器具有合法的全球 IP 地址,例如图中的 R1 和 R2。在场所内部的通信都不经过公网,但是如果 X 要和 Y 通信,则必须经过路由器 R1 和 R2

X 向 Y 发送的 IP 数据报的源地址是 10.1.0.1,而目的地址是 10.2.0.3,这个数据报首先会作为场所 A 的内部数据报发送到 R1,R1 发现目的地址必须通过公网才能到达,于是将整个内部数据报加密,然后重新封装成在公网上发送的外部数据报,其源地址是 R1 的公网地址,目的地址是 R2 的公网地址。R2 接收到数据报后进行解密恢复出原来的数据报,交付给 Y。

网络地址转换 NAT

当专网内的主机需要访问公网主机时,最简单的办法是新申请一个公网 IP 使用。但是随着 IP 资源枯竭的问题越来越严重,目前用的最多的办法就是网路地址转换。

NAT 路由器工作原理

例如 A 要发送给 B 的数据报,路由器收到相应 IP 数据报后,将其中的源 IP 地址 192.168.0.3 转换为公网 IP 地址 172.38.1.5,然后转发出去。当 B 收到这个 IP 数据报时,以为 A 的 IP 地址是 172.38.1.5,所以 B 并不知道 A 的内网地址,即使知道了也无法使用。当 NAT 路由器收到 B 发来的 IP 数据报时,通过查询 NAT 地址转换表将目的地址 172.38.1.5 转换为 A 的内部地址 192.168.0.3

假设有两台主机 192.168.0.3192.168.0.7 需要通过路由器与外网通信,路由器有两个公网 IP : 172.28.1.3172.38.1.6,NAT 地址转换表示例如下:

方向 字段 旧的 IP 地址 新的 IP 地址
源 IP 地址 192.168.0.3 172.38.1.5
目的 IP 地址 172.38.1.5 192.168.0.3
源 IP 地址 192.168.0.7 172.38.1.6
目的 IP 地址 172.38.1.6 192.168.0.7

由此可见,当 NAT 路由器具有 N 个公网地址时,专用网内最多可以同时有 N 个主机接入公网。这样就可以使专用网内较多数量的主机,轮流使用有限的公网 IP 地址。

通过 NAT 路由器的通信必须由专用网内的主机发起,否则 NAT 路由器不知道将目的 IP 地址转换为内部哪个 IP 地址,所以专用网内部的主机无法充当服务器为外部提供服务。

为了更加有效的利用 NAT 路由器上的公网 IP 地址,现在常用的 NAT 转换表把传输层的端口号也利用上。这样就可以使多个拥有本地地址的主机,共用一个 NAT 路由器上的公网 IP 地址。使用端口号的 NAT 也叫 NAPT,一些人认为它破坏了 OSI 的层次关系,但它仍成为了因特网的一个重要构件。

方向 字段 旧的 IP 地址和端口号 新的 IP 地址和端口号
源 IP 地址:TCP 源端口号 192.168.0.3:30000 172.38.1.5:40001
源 IP 地址:TCP 源端口号 192.168.0.7:30000 172.38.1.6:40002
目的 IP 地址:TCP 目的端口号 172.38.1.5:40001 192.168.0.3:30000
目的 IP 地址:TCP 目的端口号 172.38.1.6:40002 192.168.0.7:30000

正是因为 NAPT 的存在,才让内网的机器与外网的通信成为可能。