Jerry's Blog

Recording what I learned everyday

View on GitHub


30 January 2020

Network(4) -- The Internet Protocol (IP): IPv4, Addressing, IPv6, and More

by Jerry Zhang

IPv4的数据包格式

network layer的数据包叫做datagram.

IPv4 datagram format

一个IP数据包包含20个字节的头部信息(假设没有可选项)。如果携带的是TCP segment,那么这个数据包就有40个字节的头部信息(IP头20个字节,TCP头20个字节)

IPv4数据包分段

Ethernet frames可以携带最多1500字节的数据。链路层可以携带数据的最大值叫做maximum transmission unit(MTU)。因为IP包需要封装在链路层的包里面,所以IP包的长度受到MTU严格的限制。限制大小不是问题,问题是可能用到不同的链路层协议,每个协议可能会有不同的MTU。

假设现在路由器收到一个IP datagram数据包,正想转发出去,结果发现输出链接的MTU小于当前这个数据包。怎么办?只能把它拆分成多少链路层的数据包,link-layer frame,然后分别发出去。这些小包叫做fragment碎片。

这些碎片到达之后需要重新组装。IPv4的设计者感觉重新组装会使这个协议非常复杂并使路由器性能下降。因些只在最终端才去重新组装。

当终端主机接收到一连串的数据包后,它需要确定哪些是碎片,哪些是原来的完整的。如果一些包是碎片,它还要继续确定什么时候收到的上一个碎片,怎么把这些碎片重新组装好。因此IPv4的设计者设计了identification, flag, and fragmentation offset这三个字段。当datagram数据包被创建时,发送的主机就盖个戳,指定id和发送接收地址。一般来说,主机每发送一个datagram数据包,它就增加一个id号。当一个路由器需要分成碎片时,就用原来的起始地址,目标地址,以及ID来区分。当最终的接收者从一个发送者收到一系列包的时候,它就会检查id来确定哪些是属于同一个原始数据包的。因为IP是不可靠的服务,为了确保收到了最后一个碎片,最后一个碎片的flag会被设置为0,所有其他碎片都设置为1。同时,为了确定是否有碎片丢失,offset这个字段用来指定这个碎片在原始的datagram里的什么位置。

IPv4寻址

首先说说主机和路由器是怎么连接到网络中的。一台主机一般只有一个单一的连接连到网络。主机和物理连接线的交界叫做interface(接口)。路由器就会有多个链接,之间的交界也叫做接口。因为每个主机和路由器都能发送和接收数据包,因此每个接口都需要有它自己的IP地址。因此,技术上说,一个IP地址是与一个接口相关联的,而不是与一台主机或是一个路由器相关联的。

每个IP地址32位,大约40亿个可用的IP地址,用dotted-decimal notation来表示。在每一台主机和路由器上的每一个接口,都必须有一个全球唯一的IP地址(除了NAT后面的那些接口)。这些地址不能随意选择。IP地址的一部分由它所在的子网决定。多台主机和一个路由接口可以构成一个子网。我们可以指定一个地址给这个子网,比如223.1.1.0/24。/24的意思是前24位定义了这个子网。书中Figure 4.18这个子网是由三个主机的接口和一个路由接口组成的。

网络地址的分配策略叫Classless Interdomain Routing(CIDR),它定义了子网寻址的表示方法。32位的IP地址被分成两部分,a.b.c.d/x,x表示第一部分有多少位。最左边的x位构成了这个IP地址的网络部分,也叫prefix或者network prefix。一个组织一般会被分配一块连续的地址。这样,这个组织内的所有设置就可以有相同的前缀。当我们学BGP路由协议时就会知道,组织外的路由器只考虑前缀。这就极大地减少了转发表的大小。剩下的32-x位就用来在这个组织内部转发。这些剩下的bits可能还有下面的子网结构。比如a.b.c.d/21可能代表一个组织,a.b.c.d/24可能表示该组织内部的某一个子网。

在使用CIDR以前,网络的某一部分只能用8,16,24个bits进行分割,也叫classful addressing, 分别叫做A,B,C网。C类网只有254个地址,对大多数组织来说太少了。而B类网可以有65534(书里这个数字写错了)个主机。利用效率非常低下。

比如一个ISP对外广播说发送给我所有匹配200.23.16.0/20的数据包,那么外界并不知道它内部其实还有8个子网。这种用单一的一个前缀来广播多个子网的方法也叫地址聚合address aggregation或者路由聚合route aggregation。

但是思考这样一个问题,如果一家公司收购了另一家公司,然后母公司的一个组织单位想通过这个子公司连接到网络,这时怎么办?比如母公司IP地址是200.23.16.0/20,子公司IP地址是199.31.0.0/16,那个组织单位的IP地址是200.23.18.0/23,并不在这个地址范围内。一般的解决办法是,这个组织保持它的IP地址不变,但是被收购的子公司就需要对外宣称,发给我所有匹配199.31.0.0/16或者200.23.18.0/23的包。那么以后外界就会通过longest prefix matching最长匹配法则,来路由到正确的地址。

IP broadcast address 255.255.255.255。当一个主机用这个目标地址发送数据包时,消息就会被发送到同一个子网中的所有主机。路由器也可以转发这个消息给它邻居子网。(尽管一般它们不转)

获得一块地址

网络管理员首先联系ISP。比如,某个ISP拥有地址块200.23.16.0/20。他们就可以把这些地址分成8等份连续的地址块。那ISP这些地址是从哪里来的呢?IP地址是由the Internet Corporation for Assigned Names and Numbers(ICANN)统一分配的。他们也负责管理DNS根服务器,还负责分配和解析域名。

获得一个主机地址:Dynamic Host Configuration Protocol动态主机配置协议

一个组织获得一块地址后,就能分配单个IP地址给主机或者路由接口了。系统管理员一般会手动给路由器配置IP地址。主机的地址一般使用Dynamic Host Configuration Protocol(DHCP)。通过这个协议,主机可以自动获得IP地址。可以配置为某台主机每次连接到网络时都会被分配同一个IP,也可以配置为分配一个临时IP。DHCP可以自动把主机连接到网络中,因此也被称作plug-and-play or zeroconf协议。这个协议非常适合用于频繁更换网络的场景,比如一个学生经常从图书馆走到教室又走到卧室。

DHCP是一个客户端服务端的协议,客户端新进入一个网络希望获得网络配置信息,包括它自己的IP地址。在最简单的情况下,每个子网都会有一个DHCP server。如果没有的话,就需要一个知道这个网络DHCP服务器地址的DHCP relay agent(中继代理,一般就是一个路由器)。

对于一台新进入网络的主机,DHCP分4步:

  1. DHCP server discovery: 新到的主机第一件事就是要找到DHCP服务器。这一步是通过DHCP discover message实现的。客户端通过一个UDP的包把该消息发送到port 67。但是这个包发送给谁呢?主机不知道要跟谁联系,因此创建一个IP datagram,用255.255.255.255作为目标IP,广播出去,把自己的IP设置为0.0.0.0。
  2. DHCP server offer(s): 一个DHCP服务器接收到一个DHCP discover message之后,就会用一个DHCP offer message响应客户端,也通过255.255.255.255(因为此时客户端还没有IP地址呢)。因为一个子网中可能不止有一个DHCP服务器,所以客户端可能会接收到多个offer。每个offer都包含一个交易ID,
tags: Network