IP协议提供的是一种尽力而为的服务,不提供可靠传输。这是因为让路由器提供差错控制会大大提高路由器的复杂度。况且即使IP协议自身是可靠的,并不能替代端到端的检查。因为可能在传到上层的情况出错。
IP协议是一种采用数据报的网络协议,而它最终成为了网络层唯一主流协议的原因也恰恰是这种简单性。
IP地址诞生于1980年的RFC760,它当时主要是为了把几个已有的链路层交换网络连接起来。
4.3.1 IPv4分组
有时我们也说IP数据报,分组和数据报是一样的。分组是网络传输的数据单位,而数据报通常用于无连接的,独立寻址和转发的。而IPv4就是无连接的,我们在之后的传输层会提到。
IPv4分组的布局和MAC地址的布局一样,同样不需要硬性记忆,只需要知道每一块的实际意义即可
选项与填充、数据部分均为长度示意,不固定占一行;无选项时首部为 20 字节。
首部,其中前20位是固定的,剩下的是可选的:
- 版本4位: 决定IP版本号,IPv4值就为4,IPv6值就为6, 首部长度4位: 前面已经提到IP地址的首部长度是可变的,此处的单位是4字节,那么4位最大能表示的是15,也就对应着60字节。
- 区分服务1字节: 通常不用
- 总长度2字节,也就是16位,单位是字节,也就是说整个数据报最长可以是65535字节,减去我们的20位首部长度,最多可以封装65515字节的数据
- 标识2字节: 通过计数器机制产生,每发一个标识+1,作为每个数据报的标识
- 标志3位:最高位保留,剩下两位分别是DF和MF,DF是禁止分片标志,Don't Fragment,MF是More Fragments 标志。DF=0标识路由器允许把数据报分片,DF=1代表不允许,MF=0代表未被分片或者已分片数据的最后一篇,MF=1表示后面还有分片
4.3.1.1 IP数据报的分片
你或许会好奇,什么是分片?我们都知道IP协议运行在链路层协议上方,但链路层能承担的数据最大长度是有限的,链路层协议所能承载的最大数据量是MTU,Maximum Transimission Unit有时没法完整的承担整个IP数据报,我们就必须把IP数据报切割再拼凑起来。
如果路由器不允许分片,也就是DF=1,那么就只能把它丢弃了。
- 片偏移13位
- 生存时间1字节
- 协议:值为6表示ICP,值为17表示UDP,值为1表示ICMP
4.3.2 IPv4地址与NAT
4.3.2.1 特殊IP地址
IP地址有以下特殊地址:
0.0.0.0: 仅仅用于本机尚未获得IP地址时的源地址。 255.255.255.255 也就是全1,有限广播地址,路由器接受到这个地址会把它发送给整个能直接连接到的局域网。换言之,有限广播就是在链路层广播,即使这个链路层包含多个IP子网。
一个IP地址由32位二进制构成,
一个主机不是只有一个IP地址,IP地址是与网络接口关联的,而不是和主机关联的。
IP地址除了表示一个物理连接的单播地址外,还有:
- 组播地址:于第6节介绍
- 网络地址:
4.3.2.2 NAT的原理
在目前IPv4紧张的情况下。我们没法为连接到互联网的主机分配到一个IP,于是我们的想法是能否让多个同一出口的设备共享一个公网IP。我们规定让家里多个设备用可能重复的IP,这些IP是针对内网设备和路由器而言的,外网不认识。路由器出口最终会把修改包变成共同的地址。这个概念就是NAT
外网把包回传的时候其实是往你的路由器的公网IP传的。那么问题来了,路由器怎么知道哪个包给发给内网的哪台机器呢,毕竟这些包的目的IP都是同一个公网IP。
其实仅就网络层而言,这个问题实质上是无解的。但是我们在更高层的传输层。在更高的传输层我们通过不同应用的端口来区分,这被称为NAPT或者PAT,其中的P就是Port。
假设两台主机分别通过50000端口通信。路由器通过修改传输层的包,把端口号分别改成40000和40001,IP地址还是改成路由器的地址。
但显然端口映射是有问题的,一句话,其根本总结就是把内网的多个主机在外部看来逻辑上变成了一个主机。但是真正的主机来源信息留存在内网里,那么路由器永远只能通过内网主动发出去的消息建立映射。假如外网想要访问内网主机就没办法了。
反过来的问题,如果不是我们的电脑主动访问服务器,而是外面的电脑要访问内网的主机。
4.3.3 子网划分、路由聚集、子网掩码与CIDR
给网络中主机的分配地址时,你当然可以随机分配,但是这样任何一个路由器路由器就要记住每一个主机的分配。这很没必要。
最早的网络层协议不就是为了把多个协议不同的异构网络连接起来么,那么每一个链路层网络只需要配备一个路由器。
在1981年的RFC791中,我们提出了ABC三类地址,想到了利用前缀划分网络。
子网划分的本质是通过IP前缀来划定逻辑分组。每个地址都被分为网络号和主机号这两部分。网络号指代一个IP地址的前缀部分,满足这个前缀就属于这个网络。剩下的部分就是主机号。
好处在于划定路由边界,从而使得一个路由器不用记住每一个IP地址所属的端口,而只要发往对应的网络,让对应的路由器来处理。
有的网络需要的主机数量多,有的需要的主机数量少。分配一样长度的前缀就会占用一样的地址空间。显然没必要。所以最早互联网的想法是分为ABC三类,前缀分别是8位16位24位。
为了避免一个IP地址有多种前缀方式,我们采用哈夫曼编码。A类前缀是0,B类是10,C类是110.
IP协议诞生于1981年,当时全球只有两百台登记IP的主机。
你看这个设计可能会觉得很奇怪,
4.3.3.1 子网划分
子网划分机制诞生于RFC 950,它发现我们一个大的组织里面可能有多个小的组织,
对于像大学一样的场景,你当然可以用一个局域网,但这样会存在一些问题。
- 它们之间可能是异构链路:有的使用以太网,有的使用无线网。
- 广播域太大:我们在数据链路层设备那一节层级提到过广播风暴的问题
所以我们希望能在网络层简历分层的子网概念。一个组织网络内可以有多个子网。
你当然可以给每一个子网一个独立的网络号,这看上去似乎没啥问题。不过会增大路由表规模。
这时,你或许回想到,为啥不干脆分层呢。
不过在我们今天来看
因此一个网络可以是另一个网络的子网。
把大的网络划分成小的网络被称为子网化.
但是这样A类B类C类很僵死,我们于是相到了一个办法,那就是子网化。
而逆向的,把多个统一前缀小的网络作为整体利用起来,被称为超网化
子网掩码当然可以用一个长度来替代。
你可能会觉得这样是不是太死了,为啥偏偏是8 16 和24呢,你说的对,所以我们有了CIDR
127.xxx.xxx.xxx 是一个特殊的子网,它被保留用作网络软件测试和本地机器的进程间通信,实际的网络上绝不允许出现这个网络中的地址。被称为回送地址。
10.xxx.xxx.xxx 和 192.168.xxx.xxx 则是专门用于内网的本地地址或者私有地址,也就是不和Internet相连的网络,一旦相连就要靠NAT或者重新获取IP.
IP协议中除了发送到单个主机的单播,还有广播和组播,在第6节中我们会介绍组播。
广播是好理解的,我们已经知道了有限广播就是在链路层广播。除了有限广播,我们还想介绍直接广播.
如果目的地址的主机号是全1的,那么这个包将被直接广播。路由器会向网络上的所有主机转播它。
划分好子网知乎。子网划分之后,我们要介绍一些特殊的IP地址,这些地址不能被直接用来代表单个的物理连接。
4.3.3.2 路由聚合
4.3.4 ARP协议、DHCP协议与ICMP协议
4.3.4.1 ARP协议
ARP协议用来勾连以太网和IP网:当我们已经知道下一跳在本地以太网上,知道了对方的IP地址之后,我们需要知道对方的MAC地址。严格来讲,ARP更像一个链路层协议。
每台主机上会有一个专用的内存区域称为ARP缓存,或者ARP表。它会存储所在的局域网内其他主机和路由器的IP地址和MAC的映射关系。这个映射表会经常更新。
如果这个表中有,直接就能查到。如果这个表中没有,会发布一个链路层广播,其中包含了我们想要找的IP。然后持有这个IP的主机会回应。
4.3.4.2 DHCP 协议
当一个组织获得一块地址块后,就需要为每台主机决定一个IP地址,当然,我们总是可以让管理员给每个主机和路由器手动指定IP地址,但DHCP协议提供了一种自动的方式:我们会在子网内运行DHCP服务器,用户在电脑上通过运行DHCP客户端获得IP地址。
后续RFC3074通过MAC地址划分避免多重响应啥的,我在这里只是提一下,考研显然不涉及RFC3074啥的。
通常来说我们买的路由器里面就包含了DHCP服务器的功能。
DHCP是应用层协议,使用UDP,服务器的端口是67,客户端的端口是68
DHCP的过程分为四步,可以记忆为DORA: Dicover,Offer ,Requset,ACK
Discover:一台计算机刚连接到网络时,首先需要知道 DHCP 服务器在哪里。虽然这个时候主机还没获得IP地址,所以我们发送一个特殊的广播数据报,源地址是0.0.0.0。
Offer: DHCP服务器会报告自己有哪些地址池可分配。
Request:主机通过Request决定接受某个DHCP服务器的offer
ACK:服务器确认
DHCP分配的每个地址都是有租期的,同时还会把分配子网掩码和默认网关等信息,本地DNS的IP等信息。
在DHCP的标准中,设计者决定要求应当允许子网内有多台DHCP服务器,并且还允许这些服务器使用重叠的地址尺。这一决定或许一定程度上是由于DHCP衍生于古老的BOOTP协议。Anyway,IPv6 通过自带地址分配,终极地解决了这个问题。
4.3.4.3 ICMP 协议
IP协议被设计的特别简单,尽力而为,可是这也意味着如果IP协议无法送达,IP协议本身是不能帮助我们知道出现了什么问题了,因此我们需要ICMP协议。
不过 ICMP 与其说是独立协议,ICMP是一种特殊的IP数据报。
举一个例子,主机 A 向主机 B 发送一个 IP 数据报。路由器 R 收到这个数据报,查找路由表,发现自己根本不知道如何到达 B 所在的网络。按照 IP 的尽力而为原则,R 完全可以直接丢弃这个数据报。但问题来了:A 根本不知道这个数据报为什么没有到达 B。
所有符合IPv4标准的路由器的必须支持ICMP。它希望能报告一些特定的信息:其中包括五种:
- 终点不可达
- 源点抑制
- 时间超时
- 参数问题
- 路由重定向