IP协议是TCP/IP协议族的核心协议,也是socket网络编程基础之一。本章从两个方面讨论IP协议:
IP协议是TCP/IP协议族的动力,为上层协议提供无状态、无连接、不可靠的服务。
IPv4头部结构如下图,其长度通常为20字节,除非含有可变长的选项部分。
当Ip数据报的长度超过帧的MTU时,将被分片传输。分片可能发生在发送端,也可能发生在中转路由器上,而且可能在传输过程中被多次分片,但只有在最终的目标机器上,这些分片才会被内核中的IP模块重新组装。
IP头部中的如下三个字段给IP的分片和重组提供了足够的信息:数据报标识、标志和片偏移。
一个数据报的每个分片都具有自己的IP头部,它们具有相同的标识值,但具有不同的片偏移。并且除了最后一个分片外,其他分片都将设置MF标识。此外,每个分片的IP头部的总长度字段将被设置为该分片的长度。
以太网的MTU是1500字节(可通过ifconfig或netstat命令查看),以此它携带的IP数据报的数据部分最多是1480字节(IP头部占用20字节)。考虑用IP数据报封装一个长度为1481字节的ICMP报文(包括8字节的ICMP头部,所以其数据部分长度为1473字节),则该数据报在使用以太网传输时必须被分片,如下图所示:
注意:
ICMP报文的头部长度取决于报文的类型,其变化范围很大。上图以8字节为例,后面例子用到的ping程序使用的ICMP回显和应答报文的头部长度是8字节。
sudo tcpdump -ntv -i enp2s0 icmp ping 192.168.6.16 -s 1473
tcpdump输出一个IP数据报的两个分片内容如下:
这两个分片的标识值都是11816,说明它们是同一个IP数据报分片。第一个分片的片偏移值为0,而第二个则是1480。很显然,第二个分片的偏移值是加上也是第一个分片的ICMP报文的长度。而一个分片设置了MF标识表示还有后续分片,所以tcpdump输出“flags[+]”。而第二个分片则没有设置任何标识,所以tcpdump输出“flags[none]”。这两个分片长度分片分别是1500字节和21字节,与IP分片示意图描述的一致。
最后,IP层传递给数据链路层的数据可能是一个完整的Ip数据报,也可能是一个IP分片,它们统称为IP分组(packet)。
IP模块工作流程:
IP协议的一个核心任务是数据报的路由,即决定发送数据报到目标机器的路径。IP模块的基本工作流程如下:
首先从右往左来分析上图,当IP模块接收到来自数据链路层的IP数据报时,首先对该数据报的头部进行CRC校验,确认无误后就分析其头部的具体信息。
IP数据报应该发送到哪个下一跳路由(或者目标机器),以及经过哪个网卡来发送,就是IP路由过程(即上图中“计算下一跳路由”子模块)。IP模块实现数据报路由的核心数据结构是路由表。这个表安装数据报的目标IP地址分类,同一类型的IP数据报将被发往相同的下一跳路由器(或目标机器)。
IP输出队列中存放的是所有等待发送的IP数据报,其中除了需要转发的IP数据报外,还包括封装了本机上层数据(ICMP报文、TCP报文段和UDP数据报)的IP数据报。
IP路由策略:上图中虚线箭头显示了路由表更新过程。这一过程是指通过路由协议或者route命令调整路由表,使之更适应最新的网络拓扑结构。
路由机制:
路由表实例说明:
该路由表包括三项,每项都包含8个字段,如下所示:
说明:
第一项的目标地址是default,即默认路由项。该路由项包含G标志,说明路由下一跳目标是网关,其地址为192.168.6.1。另一个路由项目标地址是192.168.6.0,它只本地局域网。该路由项网关地址为* ,说明数据报不需要路由中转,可以直接发送到目标机器。
IP路由机制的工作步骤:
因此,对于上图而言,所有发送到IP地址为192.168.6.*的机器的IP数据报都可以直接发送到目标机器,而所有访问因特网的请求都将通过网关来转发(匹配默认路由项)
路由表更新:
sudo route add -host 192.168.1.109 dev enp1s0 sudo route del -net 192.168.1.0 netmask 255.255.255.0 sudo route del default sudo route add default gw 192.168.1.109 dev enp1s0
第1行表示添加主机192.168.1.109对应的路由项。设置后,从本机发往109的IP数据报缴通过网卡enp1s0直接发送至目标机器的接收网卡。
第2行表示删除网络192.168.1.0对应的路由项。此时除了109机器外,本机无法访问局域网内任何其他机器。
第3行表示删除默认的路由项。这样做的结果是无法访问英特网。
第4行表示重新设置默认路由项,不过这次网关是机器109,而不是能直接访问的因特网路由器。经过上述修改后路由表内容如下:
Destination Gateway Genmask Flags Metric Ref Use Iface ken-machine * 255.255.255.255 UH 0 0 0 enp1s0 default 109-machine 0.0.0.0 UG 0 0 0 enp1s0
新路由表中,第一个路由项是主机路由项,所以被设置了H标志。
通过route命令或其他工具手工修改路由表是静态路由更新方式。但对于大型的路由器,通常通过BGP(Border Gateway Protocol,边际网关协议)、RIP(Routing Information Protocol,路由信息协议)、OSPF等协议来发现路径,并更新自己的路由表。这种更新方式是动态的、自动的。
不是发给本机的IP数据报将由数据报转发子模块来处理。路由器都能执行数据报的转发操作,而主机一般只发送和接收数据报,因为主机上/proc/sys/net/ipv4/ip_forward内核参数默认为0。我们可通过修改其值来激活主机的数据报转发功能。
echo 1 > /proc/sys/net/ipv4/ip_forward
对于允许IP数据报转发的系统(主机或路由器),数据报转发子模块将对期望转发的数据报执行如下操纵:
ICMP重定向报文
格式如下:
ICMP报文头部包含3个固定字段:8为类型、8为代码和16为校验和。ICMP重定向报文的类型值=5,代码段有4个值可选,用来区分不同的重定向类型。主机重定向时,代码值=1。
ICMP重定向的数据部分给接收方提供如下两个信息:
接收主机根据这连个信息就可以断定引起重定向的IP数据报应该使用哪个路由器来转发,并且以此来更新路由表(通常是更新路由表缓冲,而不是直接更改路由表)。
/proc/sys/net/ipv4/conf/all/send_redirects内核参数指定是否允许发送ICMP重定向报文,而/proc/sys/net/ipv4/conf/all/accept_redirects内核参数则指定是否允许接收重定向报文。一般来说,主机只能接收ICMP重定向报文,而路由器只能发送ICMP重定向报文。
主机重定向应用举例:
第4章中,我们把机器ken-machine网关设置为109-machine,第5章中又设置了109-machine的数据报转发功能,因此机器ken-machine将通过109-machine来访问因特网。比如在ken-machine执行ping命令:
$ ping www.baidu.com PING www.a.shifen.com (119.75.217.56) 56(84) bytes of data. From 109-machine(192.168.1.109): icmp_sep=1 Redirect Host(New nexthop:192.168.1.1) 64 bytes from 119.75.217.56: icmp_seq=1 ttl=54 time=6.78 ms ---------www.a.shifen.com ping statistics--------- 1 packets transmitted ,1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 6.789/ 6.789/ 6.789/0.000 ms
从ping命令的输出来看,109-machine给ken-machine发送了一个ICMP重定向报文,告诉它请通过192.168.1.1来访问目标机器,因为这对于ken-machine来说是更合理的路由方式。当主机ken-machine收到这样的ICMP重定向报文后,它将更新其路由表缓冲(使用命令 route -Cn查看),并使用新的路由方式来发送后续数据报。总结如下图所示:
注:笔记来源《Linux高性能服务器编程》
原文:https://www.cnblogs.com/zhongqifeng/p/14832153.html