文件名称:
9.2.3.1IP协议.md
所在目录:
2023旧版内容 / 9.计算机网络
文件大小:
9.68 KB
下载地址:
文本预览:
# IP 协议
> Author: 柏喵樱
>
> copyright reserved
## IP 协议数据包结构
IP 协议是网络层最主要的协议,几乎所有的上层数据包都需要 IP 协议的承载,我们网络层的第一块内容将从 IP 协议讲起。
下图展示了 IP 协议的报文头部格式,这张图每行代表 32 个 bit,也就是 4 个字节(byte)。如果不计算 Options 这种可选项的话,IP 协议的报头长度为 20 个字节。
在头部的后面,会携带负载(payload),这个词可能略显晦涩,但实际上就是我们需要发送的数据。
## 版本
第一个字段是 IP 协议版本号,用于标识 IPv4 和 IPv6 两个版本,这两个版本的报文格式是不同的。上图展示的是 IPv4 的报文格式
## IHL (Internet Header Length)
就是 IP 协议的头部部分的长度,单位是 4byte,由于 IP 头一般长度为 20byte,所以这个值一般为 5。如果存在 Options 字段,这个值会相应增加。
## Type of Service
服务类型,标记服务类型最初是为了对不同服务的数据包做不同的转发策略,比如说哪些数据包应该被优先转发,应该更注重转发延时还是更注重吞吐量一类的问题,除非到运营商层面一般接触不太到。
## 数据包总长度
Total Length 很好理解就是包括 IP 头在内的 IP 报文的总长度,报文长度上限就是 MTU。
## Identification & Flags & Fragment Offset
这三个字段放在一起讲,他们都是用于控制分片的。
我们的 MTU 他一般是 1500,去除 20 bytes 的头部他还能够携带 1480 bytes 的数据,但是现实中的负载很容易就能够超出这个大小,这时候就需要将内容切片分块发送。
切片时,会切出许多 1480 bytes 的切片,和剩下的不足 1480 bytes 的部分。对于以上的所有切片,都会给他们加一个自己的 IP 头。这些 IP 头有一个共同点,就是他们具有一个相同的 Identification 用于识别(identify)他们原先是一块的。
现在还存在两个问题,
1. 服务器接收到一个分片后,不知道要不要继续接收
2. 分片很有可能乱序抵达,服务器不知道分片的顺序
对于第二个问题,引入了 Fragment Offset(分片偏移量),他的单位是 byte,用于标识这一个分片的数据,是从原来超长负载的哪个位置开始的。比如对于一个长度为 5000 bytes 的负载,他的几个分片的 Fragment Offset 依次为 0,1480,2960,4440。在收到数据后,服务器只需要按照这个字段重新组装即可。
对于第一个问题,引入了 Flags(标志位), Flags 里有三个 Flag,其中最后一位的意义是“后面还有更多分片“,这就相当于告诉服务器,你要继续等待接收其他分片。而当最后的分片抵达时,服务器在知道这是最后的分片的同时,他也能从这个分片的 Fragment Offset 里得知前面应该有多少数据,如果缺失,服务器也能继续等待接收。
关于 Flags 的其他两位,最高位是目前保留不使用,永远为 0。后面那位的意义是不要分片,这一般是不设置的,他这句话是对传输过程中的路由设备讲的,因为如果途径 MTU 低于当前包长度的链路可能会进行二次分片。如果设置了这个 Flag,转发时再碰到 MTU 低的链路这种包会被直接丢弃同时返回一个 ICMP 包告诉源 IP 地址的设备发生了什么。
## TTL(Time To Live)
TTL 是一个 unsigned int,代表数据包的剩余生存时间,指的是数据包在互联网中还能转发多少时间,单位是秒。
虽然单位是秒,但是一般情况下转发耗时是远远低于一秒的,根据 IP 协议的规定,无论转发耗时多少,TTL 应当至少 -1,所以在实践中 TTL 往往指的是转发了几次。
一般发往互联网的数据包初始 TTL 为 64 或 128,你可以试试 ping 命令,他会显示一个 TTL,这是对面服务器回复的包到自己的设备的时候的 TTL。
```powershell
PS C:\Users\bs> ping baidu.com
正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据:
来自 39.156.66.10 的回复: 字节=32 时间=43ms TTL=47
来自 39.156.66.10 的回复: 字节=32 时间=144ms TTL=47
来自 39.156.66.10 的回复: 字节=32 时间=43ms TTL=47
来自 39.156.66.10 的回复: 字节=32 时间=42ms TTL=47
39.156.66.10 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 42ms,最长 = 144ms,平均 = 68ms
```
TTL 减少到 0 的时候,这个数据包会被丢弃,所以如果互联网中出现路由配置错误,以至于产生了一个环,TTL 能够帮助数据包及时停止转发,避免事故扩大最终导致网络设施瘫痪。
当路由设备由于 TTL 为 0,而丢弃这个数据包的时候,路由设备还会向源 IP 回复一个 `TTL超时`的 ICMP 报文
```powershell
PS C:\Users\bs> ping baidu.com -i 2
正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据:
来自 192.168.1.1 的回复: TTL 传输中过期。
来自 192.168.1.1 的回复: TTL 传输中过期。
来自 192.168.1.1 的回复: TTL 传输中过期。
来自 192.168.1.1 的回复: TTL 传输中过期。
39.156.66.10 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
```
traceroute 就是利用这个性质来实现的,通过从 0 开始遍历 TTL 的方式,可以拿到转发过程中的所有路由器的 ICMP 回复,从这些回复中可以读取到这些路由器的 IP。
当然 traceroute 不是万能的,真实互联网中广泛存在拦截,不响应,改写等等行为,会导致 traceroute 产生丢失或者藏跳等等比较迷惑的结果。
```powershell
PS C:\Users\bs> TRACERT.EXE bilibili.com
通过最多 30 个跃点跟踪
到 bilibili.com [8.134.50.24] 的路由:
1 8 ms 13 ms 2 ms 192.168.0.1 [192.168.0.1]
2 1 ms 1 ms 2 ms 192.168.1.1 [192.168.1.1]
3 8 ms 8 ms * 100.66.0.1
4 * * * 请求超时。
5 * * * 请求超时。
6 * * * 请求超时。
7 * * * 请求超时。
8 * * 8 ms 61.139.121.77
9 * * * 请求超时。
10 78 ms * * 113.96.5.134
11 * 83 ms 43 ms 121.14.50.241
12 45 ms 42 ms 41 ms 121.14.24.82
13 * * * 请求超时。
14 * * * 请求超时。
15 * * * 请求超时。
16 * * * 请求超时。
17 42 ms 50 ms 40 ms 8.134.50.24
跟踪完成。
```
上面就是一个真实案例,有很多路由设备在丢弃数据包时并没有给出 ICMP 回复。
## 协议
协议(Protocol)指的是负载中的数据所使用的协议。这就很广泛了,比如
- TCP
- UDP
- ICMP
- Telnet
- OSPF
具体可以参考 [List of IP protocol numbers - Wikipedia](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers)
## 头部校验和
头部校验和(Header Checksum)用于检验传输的数据是否出错,一旦出错直接丢弃。
在计算头部的校验和的时候,头部校验和这个字段会被置零,再使用特定算法计算得到校验和,填写到这个位置。
这个校验和算法比较简单,就是头部以 16 bits 为单位,取补码再求和
注意,由于 TTL 在每次转发中都会改变,所以实际上,每次转发都会重新计算校验和。
## IP 地址
正如上图的 `Source Address` 和 `Destination Address` 字段所展示的一样,一个 IP 地址占用 4 byte 的存储空间。在书面的写法上,我们用 `.` 将每一个 byte 分割开,例如 `1.1.1.1` 这样更便于人类处理和分类。
有一些 IP 地址被用作特殊用途,除了这些 IP 地址外的地址都是公网 IP,一个公网 IP 在整个互联网范围内按照规范来说,只能由一台网络设备占有(也有例外,anycast)。但互联网是复杂的,也有人占用这些地址作为自己的内网地址(例如 tr069),这个由网络运维人员自行分析情景把握。
网络地址的分类需要更多的前置知识,我们后续再介绍。
## 可选项
可选参数(Options)比较繁琐,一般没啥用,有兴趣的可以看看下面参考资料中 RFC 791 对此的描述。
## 参考资料
- [RFC 791 - Internet Protocol (ietf.org)](https://datatracker.ietf.org/doc/html/rfc791)
- [Reserved IP addresses - Wikipedia](https://en.wikipedia.org/wiki/Reserved_IP_addresses)
- [List of IP protocol numbers - Wikipedia](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers)
> Author: 柏喵樱
>
> copyright reserved
## IP 协议数据包结构
IP 协议是网络层最主要的协议,几乎所有的上层数据包都需要 IP 协议的承载,我们网络层的第一块内容将从 IP 协议讲起。
下图展示了 IP 协议的报文头部格式,这张图每行代表 32 个 bit,也就是 4 个字节(byte)。如果不计算 Options 这种可选项的话,IP 协议的报头长度为 20 个字节。
在头部的后面,会携带负载(payload),这个词可能略显晦涩,但实际上就是我们需要发送的数据。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|Version| IHL |Type of Service| Total Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identification |Flags| Fragment Offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Time to Live | Protocol | Header Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Example Internet Datagram Header
## 版本
第一个字段是 IP 协议版本号,用于标识 IPv4 和 IPv6 两个版本,这两个版本的报文格式是不同的。上图展示的是 IPv4 的报文格式
## IHL (Internet Header Length)
就是 IP 协议的头部部分的长度,单位是 4byte,由于 IP 头一般长度为 20byte,所以这个值一般为 5。如果存在 Options 字段,这个值会相应增加。
## Type of Service
服务类型,标记服务类型最初是为了对不同服务的数据包做不同的转发策略,比如说哪些数据包应该被优先转发,应该更注重转发延时还是更注重吞吐量一类的问题,除非到运营商层面一般接触不太到。
## 数据包总长度
Total Length 很好理解就是包括 IP 头在内的 IP 报文的总长度,报文长度上限就是 MTU。
## Identification & Flags & Fragment Offset
这三个字段放在一起讲,他们都是用于控制分片的。
我们的 MTU 他一般是 1500,去除 20 bytes 的头部他还能够携带 1480 bytes 的数据,但是现实中的负载很容易就能够超出这个大小,这时候就需要将内容切片分块发送。
切片时,会切出许多 1480 bytes 的切片,和剩下的不足 1480 bytes 的部分。对于以上的所有切片,都会给他们加一个自己的 IP 头。这些 IP 头有一个共同点,就是他们具有一个相同的 Identification 用于识别(identify)他们原先是一块的。
现在还存在两个问题,
1. 服务器接收到一个分片后,不知道要不要继续接收
2. 分片很有可能乱序抵达,服务器不知道分片的顺序
对于第二个问题,引入了 Fragment Offset(分片偏移量),他的单位是 byte,用于标识这一个分片的数据,是从原来超长负载的哪个位置开始的。比如对于一个长度为 5000 bytes 的负载,他的几个分片的 Fragment Offset 依次为 0,1480,2960,4440。在收到数据后,服务器只需要按照这个字段重新组装即可。
对于第一个问题,引入了 Flags(标志位), Flags 里有三个 Flag,其中最后一位的意义是“后面还有更多分片“,这就相当于告诉服务器,你要继续等待接收其他分片。而当最后的分片抵达时,服务器在知道这是最后的分片的同时,他也能从这个分片的 Fragment Offset 里得知前面应该有多少数据,如果缺失,服务器也能继续等待接收。
关于 Flags 的其他两位,最高位是目前保留不使用,永远为 0。后面那位的意义是不要分片,这一般是不设置的,他这句话是对传输过程中的路由设备讲的,因为如果途径 MTU 低于当前包长度的链路可能会进行二次分片。如果设置了这个 Flag,转发时再碰到 MTU 低的链路这种包会被直接丢弃同时返回一个 ICMP 包告诉源 IP 地址的设备发生了什么。
## TTL(Time To Live)
TTL 是一个 unsigned int,代表数据包的剩余生存时间,指的是数据包在互联网中还能转发多少时间,单位是秒。
虽然单位是秒,但是一般情况下转发耗时是远远低于一秒的,根据 IP 协议的规定,无论转发耗时多少,TTL 应当至少 -1,所以在实践中 TTL 往往指的是转发了几次。
一般发往互联网的数据包初始 TTL 为 64 或 128,你可以试试 ping 命令,他会显示一个 TTL,这是对面服务器回复的包到自己的设备的时候的 TTL。
```powershell
PS C:\Users\bs> ping baidu.com
正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据:
来自 39.156.66.10 的回复: 字节=32 时间=43ms TTL=47
来自 39.156.66.10 的回复: 字节=32 时间=144ms TTL=47
来自 39.156.66.10 的回复: 字节=32 时间=43ms TTL=47
来自 39.156.66.10 的回复: 字节=32 时间=42ms TTL=47
39.156.66.10 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 42ms,最长 = 144ms,平均 = 68ms
```
TTL 减少到 0 的时候,这个数据包会被丢弃,所以如果互联网中出现路由配置错误,以至于产生了一个环,TTL 能够帮助数据包及时停止转发,避免事故扩大最终导致网络设施瘫痪。
当路由设备由于 TTL 为 0,而丢弃这个数据包的时候,路由设备还会向源 IP 回复一个 `TTL超时`的 ICMP 报文
```powershell
PS C:\Users\bs> ping baidu.com -i 2
正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据:
来自 192.168.1.1 的回复: TTL 传输中过期。
来自 192.168.1.1 的回复: TTL 传输中过期。
来自 192.168.1.1 的回复: TTL 传输中过期。
来自 192.168.1.1 的回复: TTL 传输中过期。
39.156.66.10 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
```
traceroute 就是利用这个性质来实现的,通过从 0 开始遍历 TTL 的方式,可以拿到转发过程中的所有路由器的 ICMP 回复,从这些回复中可以读取到这些路由器的 IP。
当然 traceroute 不是万能的,真实互联网中广泛存在拦截,不响应,改写等等行为,会导致 traceroute 产生丢失或者藏跳等等比较迷惑的结果。
```powershell
PS C:\Users\bs> TRACERT.EXE bilibili.com
通过最多 30 个跃点跟踪
到 bilibili.com [8.134.50.24] 的路由:
1 8 ms 13 ms 2 ms 192.168.0.1 [192.168.0.1]
2 1 ms 1 ms 2 ms 192.168.1.1 [192.168.1.1]
3 8 ms 8 ms * 100.66.0.1
4 * * * 请求超时。
5 * * * 请求超时。
6 * * * 请求超时。
7 * * * 请求超时。
8 * * 8 ms 61.139.121.77
9 * * * 请求超时。
10 78 ms * * 113.96.5.134
11 * 83 ms 43 ms 121.14.50.241
12 45 ms 42 ms 41 ms 121.14.24.82
13 * * * 请求超时。
14 * * * 请求超时。
15 * * * 请求超时。
16 * * * 请求超时。
17 42 ms 50 ms 40 ms 8.134.50.24
跟踪完成。
```
上面就是一个真实案例,有很多路由设备在丢弃数据包时并没有给出 ICMP 回复。
## 协议
协议(Protocol)指的是负载中的数据所使用的协议。这就很广泛了,比如
- TCP
- UDP
- ICMP
- Telnet
- OSPF
具体可以参考 [List of IP protocol numbers - Wikipedia](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers)
## 头部校验和
头部校验和(Header Checksum)用于检验传输的数据是否出错,一旦出错直接丢弃。
在计算头部的校验和的时候,头部校验和这个字段会被置零,再使用特定算法计算得到校验和,填写到这个位置。
这个校验和算法比较简单,就是头部以 16 bits 为单位,取补码再求和
注意,由于 TTL 在每次转发中都会改变,所以实际上,每次转发都会重新计算校验和。
## IP 地址
正如上图的 `Source Address` 和 `Destination Address` 字段所展示的一样,一个 IP 地址占用 4 byte 的存储空间。在书面的写法上,我们用 `.` 将每一个 byte 分割开,例如 `1.1.1.1` 这样更便于人类处理和分类。
有一些 IP 地址被用作特殊用途,除了这些 IP 地址外的地址都是公网 IP,一个公网 IP 在整个互联网范围内按照规范来说,只能由一台网络设备占有(也有例外,anycast)。但互联网是复杂的,也有人占用这些地址作为自己的内网地址(例如 tr069),这个由网络运维人员自行分析情景把握。
网络地址的分类需要更多的前置知识,我们后续再介绍。
## 可选项
可选参数(Options)比较繁琐,一般没啥用,有兴趣的可以看看下面参考资料中 RFC 791 对此的描述。
## 参考资料
- [RFC 791 - Internet Protocol (ietf.org)](https://datatracker.ietf.org/doc/html/rfc791)
- [Reserved IP addresses - Wikipedia](https://en.wikipedia.org/wiki/Reserved_IP_addresses)
- [List of IP protocol numbers - Wikipedia](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers)
点赞
回复
X