概要

网络层在每台主机和路由器中实现,上接传输层,下接接口层(数据链路层)

  • 发送端:将传输层数据单元封装在数据包中
  • 接收端:解析接收的数据包中,取出传输层数据单元,交付给传输层
  • 路由器:检查数据包首部,转发数据包。

网络层关键功能
分为控制面和数据面两方面内容。

  • 路由(控制面): 决定数据包从源主机到目的主机的路径核心:路由算法与路由协议
  • 转发(数据面): 将数据包从路由器的输入接口送到输出接口的过程

说人话就是,转发什么以及怎么转(往哪儿转)。而路由表就类似于高速公路上的指路牌,告诉数据包每到达一个地方后接下来怎么走。每个路由器都有n个接口,每个接口都有单独的MAC地址。

数据面/IP协议

IPv4

也是大爹,协议本身相对简单,但为了解决IPv4地址短缺的问题引入了很多复杂的玩意儿。

基本特点:

面向无连接的数据报服务。不需要提前建立连接,数据包基于目的主机地址进行转发,数据包独立转发,相同源-目的的数据包可能经过不同的路径。即先发送A包,后发送B包,每个数据报都是独立地进行路由选择,可能选择不同的路线,因此 B 可能在 A 之前先到达。

尽力而为(Best-effort)的不可靠服务。数据包可能会产生较长的时延,数据包可能会丢失、失序、重复。

在IP协议中会引入一个叫TTL(Time To Live)的东西,主要用来防止数据包在网络中无限循环。具体工作原理:在数据发出时,会设定一个初始TTL值。之后数据包每经过一个路由器,TTL值会减1,当TTL值为0后,该包将会被丢弃。

报文格式

IP数据包
IPv4数据包的头部为20字节+40字节的选项部分。版本号占用4比特,标识目前采用的IP协议的版本号,一般取值为 0100(IPv4)和 0110(IPv6)。选项部分可以包含源路由(给出转发IP数据包需要经过的IP地址列表)、记录路由(记录IP数据包从源主机到目的主机所经过的各个路由器的IP地址)以及时间戳(记录IP数据报经过的每一个路由器时的当地时间)信息。

IPv4地址

IPv4地址:唯一标识主机和路由器的接口(主机一个或多个接口,路由器多个接口,有多个IP地址)。32位01串,8位为一组以十进制数表示,每组用 . 间隔,地址分为网络号和主机号两部分。网络号相同的IP地址代表处在同一网络中,网络号唯一标识一个网络,同一网络中的每个主机用主机号来互相区分。
IPv4地址
总的来说就是,A类地址能分配的网络号很少,但同一网络中的主机号众多,自然而然适用于大型网络。相反,C类地址能分配的网络号很多,但主机号很少,适用于小型网络。说到这里,就需要提到路由器。路由器的作用是连接不同的网络。网络是异构的,网络号用来唯一标识
特殊IP地址
还有一些特殊的IP地址,见上图。NAT的时候会用到私有地址。单独为私有地址划出来了几个地址空间,所以在公网中不能出现这些IP地址。网络地址不能在数据包中使用,具有回环地址数据包不会离开本机。
地址分配:公有IP地址要求全球唯一。主要靠静态设定和动态获取两种方式获得IP地址。动态怎么获取?–>DHCP协议,用于主机动态获取IP地址。
DHCP协议
DHCP完整流程
通俗点说,DHCP协议就是主机没有地址,需要找DHCP服务器租一个来用,这自然就涉及到怎么租和租期。上面这张图给出了租地址的具体过程。简单点描述这个过程就是:主机说我要地址,服务器说好,给你一个(yiaddr),你要吗?主机说可以,就要这个。服务器说那行,就这么决定了。而lifetime即为地址租期。而主机发出请求的目的地址均为255.255.255.255,全1用于广播,之后会被DHCP服务器捕获。注意DHCP协议是建立在UDP协议之上的。租期也是必须的,这是因为主机不一定会用Release的过程(比如直接断电了)。

IP数据包转发

假设A发送数据包给B,分两种情况:

  1. 如果A和B在同一网络中(网络号相同),则直接封装成链路帧发出去。(这里就不需要路由器)
  2. 如果A和B不在同一网络中,则A把数据包封装成链路帧发给路由器,路由器根据路由表,选择将数据包从哪个接口传出去。
    路由表: 目的网络 || 下一跳的路由器IP || 跳数 || 接口

IP数据包分片与重组

问题引入:物理网络一次传送的数据是有最大长度的,因此网络层的下层(数据链路层)的传输单元(数据帧)也有一个最大长度,这个最大长度值称作 MTU(Max Transfer Unit),每一种物理网络都会规定链路层数据帧的最大长度,比如以太网的 MTU 为 1500 字节。

因此较大的IP数据包在路由器转发时可能会被分片,即将数据报分为若干分片(小数据报)后进行传输,并且只有在最终的目的主机才进行重组。(很好理解,走的路由可能都不一样,总不能半路上就重组)合久必分,分久必合协议首部的一些标志位被用来分片,直接看示意图。
IP包分片
这里也算补充协议头之前没说的那几个字段的作用。ID用来表示被分片的小数据包,ID相同则说明是同一个大包分出来的小包。偏移即是这个小包在大包中所处的位置(注意这里需要除以8,还需要减去协议头的20字节)。标志位为1则说明不是最后一个,为0则说明是最后一个包。最后组装的过程也就显而易见,拿到所有ID相同的数据包,依据偏移组装即可,然后以标志位0的包收尾。要是缺失了某个小包那所有小包都一起跟着寄了。

路由器转发IP数据包过程总结:

  1. 路由器确定IP数据包中目的地址的网络号
  2. 如果目的主机与路由器属于相同的IP网络,则直接转发到目的主机
  3. 如果目的主机与路由器不属于相同的IP网络,则查找路由表,确定下一跳路由器地址。如果存在相应的路由信息,则转发;如果没有相应的路由信息,则丢弃。
  4. 减小TTL值,修改首部的校验和
  5. 将数据包转发到相应的接口(网络号与下一跳IP网络号相同的接口)

至此IPv4协议的基本内容结束,但由于地址短缺,于是又背时地有了下面部分的内容。

问题1:组织内部的每一个物理网络都需要一个独立的net-id(可以是A类、B类、C类),而net-id和host-id两部分划分不灵活,IP地址不能充分利用。例如:一个B类网络地172.123.0.0,可以包含2^16-2个有效的IP地址(分配给路由器或主机接口,注意这里的-2分别是全0的网络地址和全1的广播地址),如果一个网络只需要256个IP地址,分配B类网络地址,则有2^16-2-256个地址被浪费,不能被其他网络使用。换句话说,A、B、C分类太少了,C类有2^8-2个地址,B类就有2^16-2个地址,如果某个网络中需要256个地址则C类不够用,B类能提供的又远远大于256,就会造成地址浪费。

问题2:A类(2^7)、B类(2^14)网络号有限,大量C类网络号使用使核心路由器路由表路由条数剧增。

无类地址划分 (CIDR)

CIDR: Classless Inter-Domain Routing
基本思路:IPv4地址还是32位01串,八位一组,以十进制表示。每个IP不再分网络号和主机号,分为前缀和后缀(一个前缀不一定标识一个物理网络)。前缀可以是任意长度,前缀和后缀长度用32位掩码标识,也可以表示成:a.b.c.d /x,x为前缀长度。具体来说,eg:

  • 方法一:200.23.16.0/20,表示地址前20位为前缀,剩余位数为后缀
  • 方法二:IP地址:200.23.16.0 子网掩码:255.255.240.0,将IP与子网掩码按位与即可得到前缀。

最长匹配原则(直接看例子吧),假设有以下路由条目:

  • 10.0.0.0/8
  • 10.1.0.0/16
  • 10.1.2.0/24

如果有一个目的地址为 10.1.2.3 的数据包,按照最长匹配原则,路由器会选择第三个路由条目(10.1.2.0/24),因为它与目的地址的匹配程度最高。
CIDR的转发流程:

  1. 检查数据包的目的 IP 地址

  2. 查找路由表,注意匹配最长前缀

  3. 转发或丢弃
    一旦找到匹配的路由,路由器就会将数据包转发到对应的下一跳地址;如果没有找到匹配的路由,路由器通常会丢弃该数据包,并可能发送一个ICMP目的地不可达消息到数据包的源地址。

  4. 特殊情况:默认路由
    如果路由表中包含一个“默认路由”(通常标记为 0.0.0.0/0),当没有找到其他匹配的路由时,数据包会被发送到默认路由指定的下一跳。

私有地址和NAT

  • 私有IP地址(见特殊地址部分),可以在私有网络(本地网络)中自由使用,但不能出现在公网上
  • 如果数据包要进入公网,需要进行私有地址到公有地址的转换
  • 承担地址转换的设备称为NAT(Network Address Translation)

也是为了解决地址短缺问题,本来需要使用多个IP的主机或路由器接口,现在统一使用一个公有地址即可。
下一个问题:NAT怎么转换?这里挺像复用分用的机制,即大家都使用一个公有网络接口,那么收发数据的时候怎么分清彼此?
NAT功能

  • 离开本地网络的数据包:用(NAT的IP地址+新端口号)代替(源IP地址+端口号),远端的主机返回的数据包将使用(NAT的IP地址+新端口号)作为目的IP地址和目的端口。NAT在转换表中记录(NAT的IP地址+新端口号)到(源IP地址+端口号)的映射
  • 进入本地网络的数据包:用转换表中的(源IP地址+端口号)替换数据包中的目的IP地址和端口号(NAT的IP地址+新端口号)

简单来说就是离开的时候写一条记录在NAT设备中,并且更改源IP地址和端口,对方看到的就是NAT的IP和端口,之后发回来再依据写好的记录转换,NAT有点像一个托管设备。

问题:破环端到端原则,应用部署困难,安全溯源困难(很好理解,都用一个公有IP,最后不好查谁干的坏事)

终极解决方案:不够,那就继续加地址空间。

IPv6

32位→128位

简介

无需使用NAT设备,路由表项也更少。128位地址:由冒号分开的8组十六进制字段组成。

  • 完全形式:1080:0000:0000:0000:0008:0800:200C:417A
  • 圧缩形式:1080:0:0:0:8:800:200C:417A / 1080::8:800:200C:417A

地址段中有时会出现连续的几组0,这时这些0可以用“::”代替,但一个地址中只能出现一次“::”,例如:FF01:0:0:0:0:0:0:101=FF01::101,0:0:0:0:0:0:0:1=::1

地址类型

  • 单播地址:标识一个网络接口
  • 组播地址:标识一组网络接口,发送到组播地址的数据包将被组播地址标识的所有接口接收
  • 任播地址:标识一个任播组,发送到任播地址的数据包将发送到任播组中最近的节点(实现方法之一:共享单播地址,实现冗余及负载均衡等)

ICMP协议

ICMP主要负责在主机、路由器之间传递差错报文与控制报文
ICMP的功能是检错而不是纠错,它将出错的报文返回给发送方的设备,发送方根据ICMP报文确定「错误类型」,从而更好的重发错误的数据包。用来测试网络连通性的 ping 命令,就是ICMP的工作示例。
ICMP
ICMP类型
例子:ping 命令(测试网络连通性)和 traceroute 命令(用于跟踪数据包从源计算机到目的地计算机经过的路径)。ping命令没什么好说,就是将ICMP报文封装到IP包的数据部分,然后发就行了。traceroute的工作原理如下:

  • traceroute开始时,发送一个TTL为1的数据包。当第一个路由器接收到这个数据包时,它将TTL减到0,丢弃数据包,并向源地址发送一个ICMP超时响应。
  • 接着traceroute发送一个TTL为2的数据包,这个数据包会通过第一个路由器,然后在第二个路由器处被丢弃,同样发送ICMP响应。
  • 这个过程一直持续,每次都将TTL值增加1,直到数据包到达目的地或达到预设的最大TTL值。

简单说就是让TTL=0,1,2,3……,实现一个跟踪的效果。怎么说,感觉跟C艹的断点调试有点像(雾)。路由器在遇到网络拥塞(基于存储转发,而缓存队列没位置了),或者TTL到0后,会依据IP包的源IP给源主机发送ICMP报文,用不同类型指代不同的错误。