RFC 791
Internet Protocol —— 无连接数据报、20–60 字节首部、分片与 TTL。后续几乎所有样本都包在这一层外面。
RFC 791 把 IP 定义成无连接、尽力而为的数据报服务:不保证顺序、不保证送达、不建立连接。可靠性留给 ICMP 反馈和 TCP 这类上层。ToS 字节后来被 DSCP/ECN 重画(RFC 2474),Identification 的语义也被 RFC 6864 收紧;读 791 时把图记住,再记住哪些比特被后文改写。
图 4:IPv4 首部
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
Figure 4.
Note that each tick mark represents one bit position.
注解
每一格是 1 bit,一行 32 bit。无选项时 IHL=5,首部 20 字节;IHL 最大 15,即 60 字节。Options 在抓包里少见,IHL>5 才有。
Version 本文件只描述 4。看到 6 就不是这份首部了。
长度、标志、TTL、协议、校验和
Total Length: 16 bits
Total Length is the length of the datagram, measured in octets,
including internet header and data. This field allows the length of
a datagram to be up to 65,535 octets. Such long datagrams are
impractical for most hosts and networks. All hosts must be prepared
to accept datagrams of up to 576 octets (whether they arrive whole
or in fragments). It is recommended that hosts only send datagrams
larger than 576 octets if they have assurance that the destination
is prepared to accept the larger datagrams.[……节选 Identification,下接 Flags]
Flags: 3 bits
Various Control Flags.
Bit 0: reserved, must be zero
Bit 1: (DF) 0 = May Fragment, 1 = Don't Fragment.
Bit 2: (MF) 0 = Last Fragment, 1 = More Fragments.
0 1 2
+---+---+---+
| | D | M |
| 0 | F | F |
+---+---+---+[……节选页眉,下接 Fragment Offset / TTL / Protocol / Header Checksum]
The fragment offset is measured in units of 8 octets (64 bits). The
first fragment has offset zero.
Time to Live: 8 bits
This field indicates the maximum time the datagram is allowed to
remain in the internet system. If this field contains the value
zero, then the datagram must be destroyed. This field is modified
in internet header processing. The time is measured in units of
seconds, but since every module that processes a datagram must
decrease the TTL by at least one even if it process the datagram in
less than a second, the TTL must be thought of only as an upper
bound on the time a datagram may exist. The intention is to cause
undeliverable datagrams to be discarded, and to bound the maximum
datagram lifetime.
Protocol: 8 bits
This field indicates the next level protocol used in the data
portion of the internet datagram. The values for various protocols
are specified in "Assigned Numbers" [9].
Header Checksum: 16 bits
A checksum on the header only. Since some header fields change
(e.g., time to live), this is recomputed and verified at each point
that the internet header is processed.
注解
Total Length 含首部。576 是“所有主机必须收得下”的下限,不是以太网 MTU。以太网上常见的是 1500 字节 IP 包。
DF / MF / Offset 三件套决定分片。每片起点按 8 字节对齐;MF=1 的非末片数据长度必须是 8 的倍数,末片可以不是。DF=1 时中间路由器不得再切,只能丢并(通常)回 ICMP Type 3 Code 4——这是 PMTUD 的扳机。
TTL 名义是秒,实现上每台处理模块至少减 1,所以它是跳数上限。减到 0 丢弃,这是 traceroute 的原理。TTL 一变,首部校验和必须重算。
Protocol:1=ICMP,6=TCP,17=UDP,89=OSPF。它不是端口号。
易误解:“IP 校验和保护整包”。原文写得很死:on the header only。TCP/UDP 校验和含 IPv4 伪首部;ICMPv4 校验和只覆盖 ICMP 报文本身,没有伪首部。
谁切、谁拼、哪些字段会变
The internet identification field (ID) is used together with the
source and destination address, and the protocol fields, to identify
datagram fragments for reassembly.[……节选页眉。未分片条件见下条注解;此处从完整句开始]
If an internet datagram is fragmented, its data portion must be
broken on 8 octet boundaries.[……节选片数上限说明]
Every internet module must be able to forward a datagram of 68
octets without further fragmentation. This is because an internet
header may be up to 60 octets, and the minimum fragment is 8 octets.
Every internet destination must be able to receive a datagram of 576
octets either in one piece or in fragments to be reassembled.
The fields which may be affected by fragmentation include:
(1) options field
(2) more fragments flag
(3) fragment offset
(4) internet header length field
(5) total length field
(6) header checksum
If the Don't Fragment flag (DF) bit is set, then internet
fragmentation of this datagram is NOT permitted, although it may be
discarded. This can be used to prohibit fragmentation in cases
where the receiving host does not have sufficient resources to
reassemble internet fragments.
注解
重组键是 (源 IP, 目的 IP, Protocol, Identification)。同一数据报的各片 ID 相同。重组发生在目的主机,中间路由器通常只转发片,不拼回去。
未分片的包:MF=0 且 Offset=0。只看 MF=0 不够——最后一片也是 MF=0,但 Offset≠0。
68 与 576 是两道不同的门槛:转发模块必须能原样转发 68 字节(最长首部 + 最小片);目的主机必须能收 576。现代网络更常见的是靠 PMTUD 避免中间分片。
RFC 6864 之后,Identification 对原子数据报(DF=1 且未分片)不再承担“唯一标识待重组报文”的旧义务。考试若问 791 原文,仍按上面四元组答。
抓包对照
Wireshark 树里的 Internet Protocol Version 4 与线上字节一一对应。过滤器 ip、ip.addr == …、ip.flags.df == 1。
- 直接可见:版本、IHL、DS 字段、总长、ID、标志、片偏移、TTL、协议、首部校验和、源/目的 IP。
- 看不见(或需重算):伪首部;下一跳 MAC(那是以太网的事,每跳都换)。
- NAT 后源 IP / 有时源端口会变。791 的“端到端地址不变”只适用于无 NAT 的教学模型。
考点与易错点
- IHL 以 4 字节为单位,最小 5(20 B),最大 15(60 B)。
- 校验和只覆盖首部;TTL 每跳变化后必须重算。
- 每片起点按 8 字节对齐;MF=1 的非末片数据长度必须是 8 的倍数,末片可以不是。未分片 = MF=0 且 Offset=0。
- DF=1 禁止中间分片,过大则丢,常触发 ICMP Fragmentation Needed。
- TTL 名义是秒、实现是跳数。traceroute 靠它骗出 Time Exceeded。
- Protocol 是“交给谁”(1/6/17),不是端口。端口在 UDP/TCP 首部。