TCP/IP协议系列
在TCP/IP网络模型中,虽然说划分了五层,但是对物理层和数据链路层,TCP/IP并并没有做什么规范和限制,TCP/IP以这两层的功能是透明的为前提。所以,在网络层我们才真正的开始接触到TCP/IP协议。网络层是TCP/IP协议的心脏,是最核心的所在。
网络层的职责
回顾一下数据链路层的职责,是让处于同一个数据链路中的主机可以互相通信。而网络层的职责范围就更大了,让世界上任何两台已连网的主机之间都能实现互相通信。
为了实现这个目标,我们需要解决如下的几个问题:
- 寻址,给世界上所有的主机分配唯一的地址,用来定位主机的位置;
- 路由,我们需要能通过地址找到从发送端到接收端的最佳路径;
- 数据包转发,找到路径以后,我们需要正确的把数据包通过中转站发送到接收端;
Tip
在网络层有几个概念需要统一,所有接入网络的设备,我们都称为节点;配置有IP地址同时具有路由、转发等功能的设备,我们叫做路由器或者三层交换机;配置有IP地址但是不具备路由、转发功能的设备,我们叫做主机。
IP协议
IP协议是TCP/IP在网络层的核心协议,IP协议就是为了解决寻址、路由和数据包转发等问题。
寻址
在数据链路层的时候我们已经接触过了寻址的概念((看这里)[https://blog.npex.top/post/20.html#mac地址),数据链路层使用MAC地址作为主机唯一地址,那在网络层是否也可以使用MAC地址呢?
答案是不行的,虽然MAC地址是唯一的,能够唯一标识一台主机,看上去是可行的,但是在网络层使用MAC地址标识主机会遇到很大的麻烦。
在数据链路层,接入网络的主机数量是有限的,所以交换机维护一个地址映射表是完全可行的。但是在网络层,接入的主机数据已经不是一个数量级了,所以维护一个MAC地址的映射表就不可能了。
所以在网络层,IP协议设计了新的地址,就是IP地址。接下来就看看IP地址是怎么设计的。
IP地址的格式
IP地址的格式如下:
IP地址使用4字节共32位表示,平时我们看到的IP地址都是使用十进制点符号表示的,例如:192.168.10.12 。
IP地址由网络地址和主机地址两部分组成:网络地址用来唯一定位一个网络,主机地址用来唯一定位该网络能的唯一主机。
网络地址和主机地址是一个此消彼长的关系,网络地址的位数越多,我们能划分的网络个数就越多,但是单个网络中能容纳的主机数量就越少(因为网络地址占的位数多,主机地址的位数自然就少了);网络地址的位数越少,单个网络能容纳的主机数就越多,但是能划分的网络个数就越少。
接下来看一下IP地址分配的问题,首先看看我们的需求:
- 一个局域网我们称之为一个网络,网络内的主机都应该分配到IP地址;
- IP地址的网络位部分,我们叫做网段地址,网络位相同的IP地址就位于同一个网段,同一个网段的主机应该在同一个局域网中,方便我们对主机寻址;
- 网段能容纳的主机数量尽量匹配局域网内的主机数量,避免IP地址的浪费;
第一种分配方法
为了满足上面的需求,我们将网段根据能容纳主机的多少分成几个级别,然后给不同规模的网络分配不同级别的网段,这样就可以保证网络内的每台主机都有IP地址,同时他们也在同一个网段内,并且能尽量减少IP地址的浪费。
根据上述思路,我们将IP网段划分为了ABCDE五类。
A类
A类地址是0开头,网络位占8位,主机位占24位,网段从0.0.0.0到127.0.0.0,一个网段最多可以容纳16777214台主机。
B类
B类地址是10开头,网络位占16位,主机位占16位,网段从128.0.0.0到191.255.0.0,一个网段最多可以容纳65534台主机。
C类
C类地址是110开头,网络位占24位,主机位占8位,网段从192.0.0.0到223.255.255.0,一个网段最多可以容纳254台主机。
D类
C类地址是1110开头,网络位占32位,没有主机位,网段从224.0.0.0到239. 255. 255. 255,D类地址没有主机位,所以是特殊用途,一般用来做多播之类的功能。
E类
E类地址实际上是未划分的地址,是1111开头,保留使用。
总结
如上,我们把IP网段划分为了5种类型,我们就可以根据不同网络规模的需求,分配匹配的网段了,我们暂且把这种分配方法叫做分级法。
第二种分配方法
分级法有什么问题吗?肯定有,要不然就不会再出另外的方案了,问题如下:
- 低估了网络发展的速度,网段不够用了;
- 分级太过粗糙,ABC类地址容纳的主机数量跳跃幅度太大,所以一个网段分配出去,往往浪费的地址还是非常多;
总结一下,分级法的问题是分级太过粗糙了,为了解决这个问题,我们就必须摒弃掉这种固定的分级方式,转而使用灵活的网段划分方法。
假如现在有一个局域网内有255台设备,使用分级法就必须给这个网络分配一个B类网段,结果就是这个网段内的大部分地址都被浪费了。
如果我们可以把两个C类网段合并一下,然后分配给这个局域网,浪费就会大大减少了。合并的方法就是把C类地址的网络地址借一位给主机地址,这样这个网络能容纳的主机数就翻倍了。
这种分配方法叫做CIDR(无类别域间路由)。
在分级法中,不同的IP地址天然的就携带了网络位的信息,但是使用CIDR方法就发生了变化,网络位的长度不再是固定的了,所以引入了新的网络位表示方法。
例如地址:192.168.10.12,如果是分级法,这个地址默认就是C类地址,网络位占24位。但是在CIDR中需要这样表示:192.168.10.12/24,24表示网络位占24位。
CIDR进一步提升了IP地址的利用率,浪费的就更少了;同时可以根据网络规模任意的指定网络位长度,也相当于增加了网段的个数。
私有地址
一般情况下,一台主机要接入互联网,我们需要分配一个IP地址给它,这个IP地址要保证在全世界的任何一个地方都能寻址到这台主机,这个IP地址我们叫做公网地址。
还有一种情况,有些组织或者公司的内部网络,并不需要联网,但是如果要使用TCP/IP协议,网络中的主机也必须有IP地址,这种情况下的话就没必要分配公网地址给这些主机了,所以在IP地址划分的时候,划分了一部分地址作为内网地址,也就是私有地址。
在分级法中,ABC类地址都保留了一段作为私有地址,分别如下:
- A类地址中,私有地址的范围为:10.0.0.0到10.255.255.255;
- B类地址中,私有地址的范围为:172.16.0.0到172.31.255.255;
- C类地址中,私有地址的范围为:192.168.0.0到192.168.255.255;
那么分配私有地址有什么好处呢?
分配给广域网的IP地址必须是唯一的,就像身份证一样。但是局域网就不一样了,两个局域网之间本身是不互通的,所以他们是可以复用同一套IP地址的,这样也是非常大程度上节约了IP地址。
Note
私有地址的网段范围并没有什么必要记忆,知道ABC都有私有地址即可,问题来了,私有地址使用哪个网段应该如何选择呢?
子网掩码
IP地址的网络位还有一种表示方法,就是子网掩码,如下图:
子网掩码是IP地址的一个属性,表示的是IP地址的网络位,子网掩码的规则也很简单,网络位都为1,主机位都为0。
所以CIDR表示法和子网掩码就是IP地址网络位的两种表示方法,仅此而已。相比较CIDR而言,子网掩码更容易参与计算,例如子网掩码和IP地址做与运算就可以得到IP地址的网段。
IPv4和IPv6
IPv4
使用32位表示的这种IP地址叫做IPv4,IPv4理论上最大能有2的32次方个IP地址可用,大概是43亿个左右。排除掉特殊作用的地址、分配给内网地址、未定义的地址的等等,剩下可用的总共大约40亿个左右。
现实的情况是,局域网内的设备基本全部使用私有地址分配,然后通过NAT等方式来访问公网,如果是商业宽带,可以从ISP处得到一个公网IP地址;如果是家庭宽带,很有可能得到的是一个NAT的私有地址。
即使是这样,IPv4地址也基本上已经全部分配完了,所以能看出来网络的发展速度是远超当初协议的设计者的想象的。
IPv6
当IPv4已经无法顺应时代需求的时候,IPv6就应运而生了,IPv6采用128位来表示,所以理论上IPv6能容纳的主机数为2的128次方。但是IPv6替换IPv4仍然任重道远。
路由
在网络世界里,两台主机的通信,实际上就是数据包从发送端主机一路传输到接收端主机的过程。这个过程很想是现实世界中的快递包裹运送的过程,发件方就是发送端,收件方就是接收端,数据包的投递过程就是快递公司将包裹送达的过程。
大家肯定都有过网购的经历,商家发货以后,快递员揽收,然后快递会到达最近的快递点,然后送到发件城市的转运中心,然后转运到到件城市的转运中心,发件地址不同或者快递不同可能中转的次数也不同,然后快递被送到到件地址的营业部,然后快递员送货。
不知道大家是否有过疑问,转运中心怎么知道这个快递下一个站点要送去哪里呢?他们肯定是有一个表格,记录了哪个地区的快递应该送到哪个转运中心。回到网络层,这个表格就是路由表(Routing Table),使用IP协议的网络节点都必须持有路由表,路由表决定了数据包该往哪里送。
这里有两个关键的问题:
- 路由表怎么来的;
- 路由表要怎么用;
再讨论这两个问题之前,我们先了解一个工作在网络层的设备:路由器。
路由器
路由器这个设备相信家家户户都有了,有些大户人家甚至有好多个。由于它工作在第三层,所以也叫他三层交换机。前面聊到的物理层和数据链路层都是针对局域网,路由器作为网络层的设备,就是连接局域网和广域网的桥梁。
路由器通常由两种类型的接口:WAN口和LAN口,如下图:
WAN和LAN前台由提到过,WAN就是广域网,LAN就是局域网,所以路由器一个端口接在广域网,一个端口接在局域网,所以说他是连接局域网和广域网的桥梁再形象不过了。因为路由器既在局域网,又在广域网,所以路由器自己就有会两个IP地址:局域网地址,用来和局域网设备通信;广域网地址,用来和广域网通信。
Tip
如今的路由器,不一定只有一个WAN口,如果有多个WAN口,并且同时连接到了不同的广域网,那么也就会有多个广域网IP。
路由器主要承担如下的几种职责:
- 路由:路由写在了路由器的名字里,这个职责的重要性就不言而喻了,路由器会维护一个路由表,发送到它这里的包都会根据路由表的规则进行转发;
2.DHCP:如果局域网内设备众多,如果每一个都要手动指定IP,那就太辛苦了,所以自动管理IP的任务也落到了路由器头上,也就是DHCP服务;
路由表怎么用
所有支持IP协议的网络节点都会维护自己的路由表,先看一下路由表怎么使用,借用一张《图解TCP/IP》书中的一张图:
这张图展示了路由的过程,路由的过程就是寻找下一个节点的过程,现在了解一下路由过程中的一些概念:
- 路由表:路由表的形式就是类似图上的表格,要注意的是,第一列准确的说是网段地址,使用的是CIDR表示法,第二列是网段对应的目标IP地址;
- 源地址和目标地址:源地址是发送端的IP地址,目标接收端的IP地址;
- 默认路由:也可以叫默认网关,英文叫做Default Gateway,如果我们在自己的路由表里面找不到匹配的条目,就把数据包送到默认网关;
Tip
上图中没有展示路由器的默认网关地址,实际上路由器也有默认网关,路由器的默认网关是从WAN口获取的,试想一下,如果一个IP地址不在自己管理的LAN内,那么唯一的选项就是把数据包从WAN口送出去,很合理吧?
路由表是怎么来的
生成和维护路由表使用到一种协议叫做路由协议,路由协议也工作在第三层,依赖IP协议,它们的目标是生成高效的路由表来帮助节点选择最高效的转发路径。
路由协议涉及的内容很多,但是并不影响理解网络层(关键是我不懂),所以先跳过,后面另外整理。
数据转发
在通过路由找到下一个节点以后,现在就要把数据发送出去了。
发送数据需要调用数据链路层,数据链路层需要目标节点的MAC地址,但是我们现在只有IP地址,要怎么拿到MAC地址呢?
这里使用的就是ARP协议,ARP协议就是来解决只知道IP地址,不知道MAC地址的问题的,通过ARP协议我们就可以拿到下一个节点的MAC地址。
知道下一个节点的MAC地址以后,我们就要把数据发送过去了,在发送之前,IP协议也和以太网协议一样,需要在数据上面附加上协议的一些数据,来实现网络层的相关功能。
Tip
ARP协议的详细内容看这里
数据封装
之前我们了解过数据链路层对数据的封装,主要塞进去了源地址和目标地址、校验位等等信息。IP协议也对数据有一层封装,实际上IP层的封装比数据链路层要复杂一些,下面看看IP协议(IPv4)对数据的封装:
在数据链路层,封装完成的数据整体我们叫做一个数据帧(Data Frame),在IP协议中,我们称之为IP数据报(IP Datagram)。IP协议的首部总共占20 bytes,虽然和数据链路层在大小上差不了太多,但是携带的信息明显多得多了。
-
Version(版本号):占4位,记录的是IP协议的版本号,例如IPv4协议是版本4,IPv6是版本6,值得注意的是IPv6并不是IPv4的升级版本,它们是互相独立的协议版本,后面的数字只是用以区分而已;
-
IHL(Internet Header Length:首部长度):占4位,通常情况下IP首部长度位20 bytes,但是IP首部中存在可选项字段,也就是图中黄色的部分,可能会导致首部超出20 bytes,值得注意的是,这里的首部长度的单位是4 bytes,也就是说正常20 bytes的首部这个值是5,这样处理的原因我猜是4位能表示的长度有限;
-
ToS(Type Of Service:服务类型):占8位,表示的是上层服务期望能得到的可靠性,实际上这个字段基本没有投入使用,就不看了;
-
Total Length(总长度):占16位,表示的是首都加上数据部分的总长度,16位能表示的总长度为65535字节;
-
Identification(ID:标识)/Flags(标志)/Fragment Offset(分片偏移量):分别占16位、,3位和13位,这3个字段记录的都是分片相关的数据,标识是分片的ID,表示分片的顺序;标志分片的信息;偏移量表示的是当前分片相对于原始数据的位置,第一个分片是0,单位是每8字节,也就是没8字节记录为1;
-
Time To Live(TTL:生存时间):占8位,这里实际上不是时间的概念,而是经过路由器的个数,每经过1个就减1,减到0就丢弃,是为了避免IP包在网络内无限传递的问题,8位最多256,也就是说IP数据报最多转发256次就一定会丢弃;
-
Protocol(协议):占8位,表示上层协议是什么,可以类比数据链路层的Type字段;
-
Header Checksum(IP首部校验和):占16位,这里也可以类比数据链路层的FCS,但是要注意的是,这里只是首部的校验和,和数据无关;
-
Source Address(源地址)/Destination Address(目标地址):可以类比数据链路层的同字段,但是这里记录的是IP地址,作用就是让中间所有转发的节点都能知道数据报的来源和目的地;
分片
在聊数据链路层的时候知道了有一个MTU的概念,就是数据链路层能传输的最大数据帧大小,通常来说数据部分最大位1500字节。网络层的目标就是尽量让封装完成的数据报不要超过这个数字,避免数据链路层拆帧,所以当上层协议传入的数据报大于数据链路层的MTU时,IP协议就要对数据做分片。
发送
现在数据已经分好片了,也组装成了IP数据报的格式,同时也获取到了下一个节点的MAC地址,就可以调用数据链路层把数据发送出去了,那么在发送阶段IP协议还需要处理什么呢?
IP协议的数据发送逻辑是基于“尽力而为”的思路设计的,也就是说,IP协议会尽量把IP数据报送出去,但是并不保证一定能够到达,也不做重试,这些都交给上层协议来处理。
导致数据无法到达的情况有很多种,例如:目标主机的网络不通、目标主机是关机的状态、转发的跳数超过了TTL等等都会导致IP数据报被丢弃。
那当IP数据报被丢弃的时候怎么告知给上层协议的,答案是通过ICMP,丢弃IP数据报的节点会通过ICMP协议向发送端回送一个ICMP消息,通知发送端IP数据报被丢弃的具体原因。
但是要注意的是,IP协议不会直接处理ICMP回送过来的错误信息,这个信息会直接交由上层协议来处理。
Tip
有关ICMP协议的内容在这里
其他网络层协议
DHCP
DHCP设计出来是用来搞定IP地址分配的问题的。试想一下一个大型局域网如果有1000个节点,每个节点都需要网络管理员来设置和维护IP地址,工作量肯定会非常大,还需要管理员能记录所有已分配的地址和未分配的地址信息。
所以就需要一个管理IP地址分配的服务,也就是DHCP服务,通常由局域网内的路由器来承担这个职责。
DHCP服务提供了如下几个能力:
- 管理可用的IP地址池;
- 自动给新加入网络的节点设置IP信息,包括IP地址,子网掩码,默认网关等等;
- 管理IP地址租期,给IP地址续期或回收;
DHCP发现
DHCP通过4次请求完成IP地址的分配。
NAT
NAT的背景上面有聊到过一些,原因还是因为IP地址的不足,导致没办法给每台接入网络的主机都分一个全局地址,但是主机又要接入广域网,那怎么办呢?NAT就应运而生了。
NAT的思路是在局域网内,主机都分配私有地址,当局域网内的主机作为发送端发送数据到广域网时,在路由器中,对发送端的IP地址做一次转换,转换成公网地址;在局域网主机作为接收端时也是一样的处理方式,路由器接收到数据时,会将全局地址转换为私有地址,然后转发给对应的主机。
从上面的描述可以看出来,路由器中肯定维护了一张映射表,来搞定转发的规则。但是如果内网中所有的主机共用同一个全局地址,该怎么映射呢?
这就是NAT的别扭之处,因为全局地址只有一个,无法同时映射到多个私有地址,所以NAT用到了IP地址+端口号来做映射。我们知道网络层IP地址是唯一地址,但是NAT中无法仅使用IP地址完成功能,提前引入了传输层的端口号,那么NAT到底是网络层协议还是传输层协议呢?
实际上,NAT协议还是划分为网络层协议,因为他的能力还是服务于网络层。