IP协议
IP协议为上层协议提供无状态、无连接、不可靠的服务。
- 无状态:内核中不需要维护状态信息
- 无连接:每次发包都要指定对方IP地址
- 不可靠:不能保证数据送达不会试图重发
总结:简单高效, 需要上层协议处理乱序、重复、丢包重传等问题。
IP头部结构
IP 头通常20个字节结构如下
- 4位版本号指定IP协议版本,IPv4来说就是4
- 4位头部长度,标记IP头有多少个32bit字(4字节)。所以ip头部最长是15*4=60字节
- 8位服务器类型,其中3位优先权字段现已忽略,4位TOS(Type of service)字段,和1位保留字段。TOS包括最小延时,最大吞吐量,最高可靠性,最小费用。根据业务设置,最多只能开启一个。
- 16位总长度指整个IP报文长度,字节为单位,最大长度为65535(2^16 - 1)
- 16位标识,发送端发送一个数据包时随机生成,没发送一次加一。如果一个数据包复制到多个分片中,所有分片的标识相同,表示属于同一数据包。
- 3位标志,第一位保留,第二位表示禁止分片。第三位表示更多分片,数据包被分片后,除了最后一个都为1
- 13位分片偏移,表示当前分片是数据包的哪一部分
- 8位生存时间,TTL(time of live) 数据包允许经过路由器跳数,防止进入路由环路
- 8位协议,用来区分上层协议,比如ICMP是1, TCP为6, UDP为17
- 16位头部校验和,使用CRC算法校验头部是否传输中损坏
- 32位源IP与目的IP地址
- 可选字段,IP头最大60字节,前20字节固定,所以可选字段最多40字节。
使用tcpdump观察IPv4头部结构
IP 127.0.0.1.17050 > 127.0.0.1.53542: Flags [P.], seq 1:47, ack 46, win 512, options [nop,nop,TS val 4050937092 ecr 4050937092], length 46
0x0000: 4500 0062 1368 4000 4006 292c 7f00 0001
0x0010: 7f00 0001 429a d126 f242 6472 2a7e 9718
// 后续省略
16进制 | 头部信息 |
---|---|
0x4 | IPv4版本 |
0x5 | 5*4字节,头部20字节 |
0x00 | 没有服务开启 |
0x0062 | 数据包总长度为98 |
0x1368 | 数据包标识 |
0x4 | 进制分片标志 |
0x000 | 分片偏移 |
0x40 | TTL为64 |
0x06 | 上层为TCP协议 |
0x292c | IP头部校验和 |
0x7f000001 | 源端口地址127.0.0.1 |
0x7f000001 | 目的端口地址127.0.0.1 |
MTU与IP的分片
MTU(Maximum Transmission Unit)最大传输单元,是一种通信协议的某一层上所能通过的最大数据包大小(字节位单位)。通常与通信接口有关。
IP数据报的长度超过MTU时会分片传输,这个可能发生在发送端也可能是中转路由器上,且可能在传输过程中多次分片。最后在目标机器上内核中吧的IP模块中重组。
可以使用ifconfig或netstat -i 产看MTU设置,以太网帧的MTU一般为1500。ip头部占用20字节, 所以IP数据报数据部分最多1480字节,超过部分在使用以太网帧传输时需要被分片。
通过ICMP协议测试IP数据分片
ping命令用于测试网络是否畅通,通过ICMP协议实现。测试中使用 ping -s 1551 定发送大小为1551字节的ICMP协议。并在目标机器监控ICMP协议查看IP分包状况。
其中前分片标识 id 37235 表示前两条记录属于同一个IP包。
对于第一个分片
- offset 0 flags[+] 表示当前数据偏移为0开始后续还有分片
- proto ICMP (1), length 1500 表示层协议是ICMP, 当前分片长度1500。其中IP头20字节,剩余1480字节给IP协议数据部分,IP协议数据部分是ICMP协议,其中ICMP协议头部分8字节,剩余1472字节可以传输ICMP协议数据部分。剩余79字节在下一个IP包中发送。
对于第二个分片 - offset 1480, flags [none] 当前IP包的数据偏移是1480,后续没有其他分片
- proto ICMP (1), length 99 表示上层协议是ICMP,当前IP包长度为99。其中20位为IP头,剩余79为剩余的ICMP协议部分。在第二个IP分片中不再包含ICMP协议头,因为在IP模块重组时可以从第一个分片中拿到相关信息,重复发送没有意义。
// 监控icmp协议
tcpdump -ntv -i bond0 icmp
tcpdump: listening on bond0, link-type EN10MB (Ethernet), capture size 65535 bytes
IP (tos 0x0, ttl 127, id 37235, offset 0, flags [+], proto ICMP (1), length 1500)
10.1.45.14 > 10.1.60.34: ICMP echo request, id 1, seq 7440, length 1480
IP (tos 0x0, ttl 127, id 37235, offset 1480, flags [none], proto ICMP (1), length 99)
10.1.45.14 > 10.1.60.34: icmp
IP (tos 0x0, ttl 64, id 49805, offset 0, flags [+], proto ICMP (1), length 1500)
10.1.60.34 > 10.1.45.14: ICMP echo reply, id 1, seq 7440, length 1480
IP (tos 0x0, ttl 64, id 49805, offset 1480, flags [none], proto ICMP (1), length 99)
10.1.60.34 > 10.1.45.14: icmp
IP 数据包的路由和转发
IP模块工作流程
从右到左来观察IP模块的工作流程
- 收到数据链路层的IP数据报之后,先处理IP数据报头部,无误之后开始分析头部信息。
- 首先是否设置了源站选路选项(松散源路由选择或者严格原路由选择),如果设置则由数据报转发子模块处理。
- 严格的源路由选择。发送端指明 I P数据报所必须采用的确切路由。如果一个路由器发现源路由所指定的下一个路由器不在其直接连接的网络上,那么它就返回一个“源站路由失败”的ICMP差错报文。
- 宽松的源站选路。发送端指明了一个数据报经过的 I P地址清单,但是数据报在清单上指明的任意两个地址之间可以通过其他路由器。
- 如果IP数据报头部中目标地址是本机,则IP模块根据数据报中的上层协议类型转发。如果不是给本机的,则通过数据报转发子模块转发。
- 数据报转发会先检查是否可以转发,不可以直接丢弃,可以转发则进行一些操作交给IP 输出模块。
- 确定转发的下一跳目的地,以及通过那个网口转发就是IP的路由过程,通过路由表实现。
- IP输出维护所有等待发送的IP数据报,其中可以是需要转发的IP数据报也可以是本机产生的上层协议(TCP/UDP/ICMP等)包装后的IP数据报。
- 虚线标注的是路由表更新的过程,可以通过路由协议或者route命令更新。
路由表
>> route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.1.60.0 * 255.255.255.0 U 0 0 0 bond0
link-local * 255.255.0.0 U 1006 0 0 bond0
172.17.0.0 * 255.255.0.0 U 0 0 0 docker0
default 10.1.60.254 0.0.0.0 UG 0 0 0 bond0
字段 | 含义 |
---|---|
Destination | 目标网络或主机 |
Gateway | 网关地址,*表示本机 |
Genmask | 网络掩码 |
Flags | 路由标志 |
Metric | 路由距离 |
Ref | 引用次数 linux中未使用 |
Use | 使用次数 |
Iface | 对应的网卡接口 |
路由表匹配
- 数据报中目的地址与路由表中主机地址完全匹配的,没有匹配的进入步骤2
- 数据报目的地址经过掩码计算后匹配的,如果有多条选择掩码最长的
- 如果以上都不匹配,使用默认路由项目,通常下一跳是网关
路由表更新
- 路由表可以通过route命令添加或删除
- 大型路由器一般通过BGP、RIP、OSPF等协议来动态自动更新路由表。
IP转发
对于主机来说一般只发送接收数据,转发功能是默认关闭的。
对于转发操作,转发子模块会进行如下操作。
- 检查TTL值,如果为0丢弃
- 是否开启严格路由选项,检查目标IP是否为本机某个IP,不是发送一个ICMP源站选路失败给发送端
- 可能发送一个ICMP重定向报文给源端,告诉更合理的下一跳路由
- TTL减一
- 处理IP头选项
- 根据需要进行IP数据报分片
荐一个零声学院免费教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:
链接