1. 概述
网络层(Network Layer)位于TCP/IP协议族的第三层,它主要作用是负责在网络上的设备之间传输数据信息。在传输数据时,它将一个包含目的主机IP和源主机IP地址的标头添加到从传输层下来的数据包前面 ,然后下发给数据链路层。在接收数据包时候,它将拆包并判断该数据包中的目的IP是否为本机IP地址,若果是,那么将IP层的标头拆掉后输送到位于上一级的传输层。所有TCP,UDP,ICMP和IGMP数据都以IP数据报的形式在网络上传输。
图片来自Microchip
2. Wireshark与TCP/IP协议族对应关系
Wireshark是一个强大的网络协议分析器。点击该数据包列表中某一个数据报,则会展开如图中所示列表信息,分别是物理层、数据链路层、网络层、输出层和应用层。它和TCP/IP协议族中五层模型刚好相对应。在明确了这个对应关系之后,对网络分析有不少的帮助。
3. IP标头
在对网络(网际协议)层的概念有了大致了解后,接下来开始探讨关于IP标头的结构关系,以及该标头结构图中每个字段的所充当角色。
3.1 IP标头结构类型声明
以下结构数据类型声明来自tcpdump抓包工具的源码ip.h(另有ip6.h文件,即声明的是ip6的标头结构类型)文件实现。可以看到,其中有数据包头长度、版本号、服务类型、总长度、标识符、标志+分段偏移量、生存时间、协议、首部校验和、源IP和目的IP地址等字段。
/*
* Structure of an internet header, naked of options.
*
* We declare ip_len and ip_off to be short, rather than u_short
* pragmatically since otherwise unsigned comparisons can result
* against negative integers quite easily, and fail in subtle ways.
*/
struct ip {
nd_uint8_t ip_vhl; /* header length, version */
#define IP_V(ip) (((ip)->ip_vhl & 0xf0) >> 4)
#define IP_HL(ip) ((ip)->ip_vhl & 0x0f)
nd_uint8_t ip_tos; /* type of service */
nd_uint16_t ip_len; /* total length */
nd_uint16_t ip_id; /* identification */
nd_uint16_t ip_off; /* fragment offset field */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
nd_uint8_t ip_ttl; /* time to live */
nd_uint8_t ip_p; /* protocol */
nd_uint16_t ip_sum; /* checksum */
nd_ipv4 ip_src,ip_dst; /* source and dest address */
};
复制代码
3.2 IP标头图表
用图表方式将上面声明的结构类型(struct ip) 中按照各成员声明的顺序方式画出来,其效果如下图所示。
图片来自NMAP
很显然,图标方式更加直观。
3.3 IP标头各字段含义
3.1.1 版本(Version)
该字段位于IP标头结构中的第一个,用以说明该数据包/报中IP的版本号,是IPv4还是IPv6.
3.1.2 首部长度(Header Length )
首部长度字段,也称为Internet Header Length(IHL)。该字段仅表示IP首部的长度。由于IP标头结构中包含“可选字段”,因此,IP首部大小是可变化的。通常情况下,IP首部大小是20字节。如3.1节中的IP首部结构体类型声明,通常情况下,IP首部中的可选字段都是没有用到的。
Because this is also a 4-bit field, the IPv4 header is limited to a maximum of fifteen 32-bit words or 60 bytes.
The normal value of this field (when no options are present) is 5. There is no such field in IPv6 because the header length is fixed at 40 bytes.
意指:IPv6固定40字节,IPv4可以是20~60字节。
3.1.3 服务类型(Type-of-Service )
该字段由两部分组成,则RFC2474之前,是将该字段划分为了:优先级和(Precedence)和服务类型(Type of Service)两部分。
前面高位3字节是优先级,后面4位是服务类型,最后一位没有使用,被保留并设置为0。
但是RFC2474中,把服务类型字段(TOS)中的8位字重新进行了定义。前面6位用来表示“差分服务(流量优化)”,后面2位用来表示“拥塞通知”,如上图所示。
3.1.4 总长度(Total Length)
该字段表示IP层级中“ip首部+数据”两部分的总和,
3.1.5 标识符(Identification)
网络中发送的每一个数据包(报)都被分配一个唯一的ID(标识符)。若某个数据包大小超过MTU(最大传输单元)值,那么它需要被拆分为多个数据包进行发送(所谓的分段),然后接收方对收到的数据重新进行组合排序并打包成一个整体。它的依据是:分段中的每个数据包其中的的“标识符”字段都是相同值。
3.1.6 标志(Flags)
标志(Flags)字段在IP首部结构中占3个位空间大小,即3/8字节。位0(保留字段,默认0)、位1和位2这三个位所扮演角色如下:
若某个数据包超过MTU所支持的范畴,需要分段(假若是3个分段)。那么对于第一个和第二个分段的数据包,其中位1=0,位2=1。对于第三个分段数据包,位1=0,位2=0.表示该分段是最后一个分段数据包,后面再无属于相同数据包标识ID的分段数据包了。
3.1.7 分段偏移量(Fragment Offset)
该字段只有在数据包被分段时候才使用,即Flags中位1 = 0的时候。若数据包被分段,该字段(分段偏移量)说明了在把各个分段重组成一个数据包时候(目标主机-即接收数据方),当前分段数据包中的数据应该放在整个完整数据包的哪个位置。
3.1.8 生存时间(Time-to-Live)
用来标记该数据包还能在网络中传输的剩余距离。虽然通常是以秒为单位来进行定义TTL(Time to Live)。但是实际上数据包的生存时间(TTL)字段被实现为在被网络中的路由器丢弃包之前,还能够穿过的跳数。典型的TTL值是32、64和128.
3.1.9 协议(Protocol)
IPv4报头中的协议字段包含一个数字,该数字指示在数据报的有效负载部分中找到的数据类型。最常见的值是17(对于UDP)和6(对于TCP)。该字段提供了一个多路复用特性,这样IP协议就可以用来承载多个协议类型的有效负载。虽然该字段最初指定了数据报正在封装的传输层协议,但现在它可以识别被封装的协议,它可能是传输协议,也可能不是。
The Protocol field in the IPv4 header contains a number indicating the type of data found in the payload portion of the datagram. The most common values are 17 (for UDP) and 6 (for TCP).
This field provides a demultiplexing feature so that the IP protocol can be used to carry payloads of more than one protocol type. Although this field originally specified the transport-layer protocol the datagram is encapsulating, it now can identify the encapsulated protocol, which may or not be a transport protocol. Other encapsulations are possible, such as IPv4-in-IPv4 (value 4).来自The Internet Protocol (IP)。
同样,物理层也有一个字段指明了其有效负载部分的以太网类型、数据链路层部分某个字段类型指明其有效负载部分的IP数据包类型。如图所示:
在网络层中,常用到的协议字段有以下几个:
更多的协议字段参考:Protocol Numbers。
3.1.20 首部校验和(Header Checksum)
该字段提供了对IP首部内容进行出错检测的功能。首部校验和字段仅在IPv4报头上计算,这意味着IPv4数据报(例如TCP或UDP数据)的有效负载不会被IP协议检查是否正确。为了确保有效负载已经正确交付,其他协议必须使用它们自己的数据完整性检查机制来覆盖报头之后的任何重要数据。几乎所有封装在IP中的协议(ICMP、IGMP、UDP和TCP)在它们自己的报头中都有一个校验和,用于覆盖它们认为重要的报头和数据,也用于覆盖它们认为重要的IP报头的某些部分(一种“分层冲突”的形式)。用于计算校验和的算法(也被大多数与Internet相关的协议使用)有时被称为Internet校验和。当IPv4数据报经过路由器时,由于TTL字段的减少,它的报头校验和必须改变。
3.1.20.1 Header Checksum algorithm
3.1.20.2 IPv4 Header Error Checksum Calculator
IPv4 Header Error Checksum Calculator是一款用来检验IP报头“首部检验和”字段值是否正确的在线工具。
界面非常直观简洁,对于问题的排查,能够带来很高的效率。
3.1.21 源IP地址(Source Address)
发送数据的本机IP地址。如主机A发送数据给主机B,则该字段为主机A的ip地址信息。
3.1.22 目的IP(Destination Address )
待接收发送数据的主机IP地址。如主机A发送数据报文给主机B,则该字段值为主机B的IP地址。
3.1.23 可选字段(Options)
IP提供了一些可选字段,来扩展其功能。如常用到的时间戳、记录路由等选项。其次还有一些填充字段使得IP数据包的首部长度是32位的整数,如果不是4字节的整数,则用0去进行填充。
IP options may be selected on a per-datagram basis. Many of the options are no longer practical or desirable because of the limited size of the IPv4 header or concerns regarding security. With IPv6, most of the options have been removed or altered and are in the basic IPv6 header but are placed after the IPv6 header in one or more extension headers.
关于“可选字段”更多细节,可参考 IP Options
3.1.24 数据(Data)
该字段中的值是上一层TCP数据段(TCP首部+TCP数据部分)的报文数据信息。
图片来自 IP Protocol Header Fundamentals Explained with Diagrams
3. 总结
本节对网络(网际协议)层所处TCP/IP协议族层级位置以及其功能特性作了说明。之后便对IP的标头结构进行描述,同时对标头中的各字段也作了较为详细的交代。