文章目录
- 1、网络层IP
- 1.1 认识网络层
- 1.2 IP报文格式和IP报文切片
- 1.3 网段划分以及路由
- 2、数据链路层
- 2.1 以太网帧格式
- 2.2 ARP协议
- 3、其它重要协议或技术
- 3.1 DNS技术
- 3.2 ICMP协议
- 3.3 NAT技术
- 3.4 NAT和代理服务器
1、网络层IP
1.1 认识网络层
浅谈一下各层
应用层:通过前面http和https协议认识到,应用层的意义是为了读取完整报文、序列化和反序列化、处理协议问题。
传输层: tcp协议认识到,通过各种策略确保数据传输的可靠性和效率。其中传输层的数据称为数据段。
网络层: 接下来谈的网络层IP协议,其实是让主机具有一种将数据从A主机送到B主机的能力。(网络层IP协议有这种能力,但是不能保证数据一定能传输到,通过传输层的各种策略就为了保证其一定传输到)其中网络层的数据称为数据报。
数据链路层: 再往后走,认识到网络层让主机具有一种将数据报从A主机送到B主机的能力,但数据包从主机A到B中间也会经过很多其它的主机,数据链路层解决的就是局域网数据帧中一个主机到下一个主机的问题。
1.2 IP报文格式和IP报文切片
IP报文不是定长的,因为IP报文格式不仅有标准的20字节报头,还有选项字段。
其中有几个很容易理解
4位版本: 标识着ipv4版本的ip报文。(当然也有ipv6的,但因为不兼容所以有另一种格式)
4位首部长度: IP报文长度。(当然这个长度是一个单位长度,最终结果和tcp的一样是需要*4的)
8位服务类型: 其中3位弃用,1位保留,剩下4位TOS分别代表:最小延时、最大吞吐量、最高可靠性、最小成本。
16位总长度: IP数据报整体占多少个字节。
通过以上4个字段,就可以知道IP协议是如何封装和解包的。
封装: 在原来的数据基础上添加一个结构体对象。(因为报头本质就是一个位段)
解包: 因为在报头字段中有对应的报文总长度和报头长度,两个相减就能得到有效载荷向上交付。
因为IP报文中有对应的8位协议字段,因此报文在分发的时候,通过对应协议就能确定交付给传输层什么协议。
8位生存实际(TTL): 由于主机将数据传输到另一个主机中间会有很多的节点(主机和路由),因此网络会出现BUG或者对端主机不可达等不可因素,导致IP报文在网络中长时间游离,而不消失(因此会导致网络拥堵,垃圾数据堆集),当生存时间为0时,报文直接丢弃。
16位首部校验和: 接收方会通过该字段进行校验,从而检测报头是否损坏。
32位源IP地址和目的IP地址表示发送端和接收端。
剩余的字段需要先了解一些东西。
接下来让我们浅了解一下数据链路层。
IP报文的切片
之前在认识TCP/IP五层模型时,初步知道数据链路层负责设备之间数据帧的传送和识别。其中以太网和令牌环网工作在数据链路层。其中局域网中因为碰撞域的原因数据会发生冲突,因此要确保数据传输冲突的概率比较低,因此在底层规定了以太网的最大传输单元(MTU)为1500字节。因此上层网络层就不能发送太大的IP报文,就要分片。
那么对IP进行分片,由谁来做? 对方全部收到后,由谁组装?
答案是发送方网络层进行分片,对方网络层进行组装(就好比很重的主机如果要进行快递,需要分开打包,但是分开打包这个工作快递人员不会做,而是将风险给物主,另一方收到后组装也是如此)。无论是对发送方还是接收方,分片和组装行为,双方的传输层都是不知道的,也不关心,这也就是分层上的解耦。
那分片的程度应该是怎么样的?
对于IP报文来说,如果分片后在传输的过程中部分丢了,在IP报文看来就是整体丢了,就无法向上发送。重要的是,分片的报文一定比单个报文丢包率高,并且分片越多丢失的概率越大。因此网络层最好别分片,或是别分片太多
虽然网络层不建议分片,但IP报文的分片用这三个字段就能实现,这种分片的思想很值得我们学习。
先看剩下的几个字段
3位标识: 第一位不用,第二位为1表禁止分片,第三位表示“更多分片”
13位片偏移: 表示当前报文相较于原文所处的偏移位置。实际偏移的位置是通过这个值*8得到的。
那么具体如何分片和组装问题?首先值得注意的是,分片后,每一片都会有完整的报头,也就是一个完整的报文。
1、先要识别该报文是被分片的。 因为接收端网络层可能也收到很多其它主机的数据段。其中有分片的有没分的。通过中间的3位标识的第三位进行判断,1代表是一个分片,0就说明是这个分片的最后一个。
2、将序号相同的报文先收集到一起。 通过16位标识字段,就能将id相同的切片放到一起。
3、正确的进行组装。 通过数据包中的13位片偏移值进行排序,从小到大排序就能把数据包组合了。
一些问题:
1.数据传输是一定会乱序的,接收端可能会先收到特定id的3位标识符第三位是0的报文,那该如何区分它是切片呢? 很简单通过偏移值不为0就可以确认。
2.收集怎么保证收集完了? 只要收集到3位标识符第三位是0的切片就行了。
3.那又如何保证收集完整呢? 通过偏移值的排序后,开头的通过判断偏移值位0,结尾的通过3位标识符第三位是0判断,中间丢失通过起始偏移量+报文长度,就能定位下一个切片的起始偏移量,如果不匹配就说明丢失。
合并好后,也会通过16位首部校验和来看报头有没有问题,如果数据有问题自然会经过传输层的校验和检测。
具体的分片
前面稍微提了一下,数据链路层MTU(最大传输单元)是1500字节,假设如果有3000字节需要传输,那具体是怎么分片的呢?
3000字节 - 2980字节有效载荷 20字节报头,又因为一个切片需要完整报头,那么应该这样细分。
20 + 1480 = 1500 (此时剩下1500有效载荷)
20 + 1480 = 1500 (此时剩下20有效载荷)
20 + 20 = 40 (这样分三个报文)
分片对UDP和TCP有影响吗?
tcp影响不大,因为tcp有各种策略保证其可靠性。udp不可靠的特性让其直接受影响。
如何做到减少分片?
网络层是否分片是要看数据的多少的。数据是从传输层传给网络层的,因此是否分片根本应该是由传输层决定的。(如果传输层能一次传适量的数据,网络层就不需要分片了)。因此传输层不仅需要考虑对方接收能力、网络拥塞问题,还需要尽可能考虑可能丢包问题,所以传输层在传输数据时也要有自己的基本大小。
一般在三次握手的时候,就会协商单次传输数据的报文大小!
1.3 网段划分以及路由
IP是如何找到对方的主机呢?
IP的构成是由目标网络和目标主机构成的。IP是XX:XX:XX:XX这样的4字节格式,前3字节代表目的网络,后1个字节代表目的主机。
网络号:保证相互连接的两个网段具有不同的标识。
主机号:在同一网段中(同一网络号),主机间具有相同的网络号,但主机号一定不同。
网段就是相同网络号的所有主机的聚合。
ip在路由的时候,在路上先更加目的网络进行路由,找到目标网络之后,再根据目的主机号进行数据转发。(路由器能跨两个网段进行数据转发,就一定需要两个不同的网络接口配有不同的IP地址。)
IP地址能在互联网中标识唯一主机,那么就代表曾经一定已经有角色已经将全球的IP进行过地址划分。
早期通过将IP32位划分为5个类,每个类通过前几位比特位进行分类。
随着互联网的飞速发展,这种方案局限性很快显现出来。比如A类的一个子网是可以容量最大的主机的,但是一般一个子网是不会有这么多的。因此就会有很多浪费的情况。
针对这种浪费的情况,提出了新的划分方式CIDR(无类别域间路由),通过子网掩码的方式,能够最大程度的提高IP的利用率。
让每个子网都配有一个子网掩码,用子网掩码来区分网络号和主机号。
1101 0101(IP)
& 1111 1100(子网掩码)
= 1101 0100(110101就是网络号)
(想要主机号多点子网掩码就在尾部多填一个0【1111 1000】,想要主机号少点就多填一位1【1111 1110】)
- 子网掩码是一个32位的正整数。通常用一串“0”来结尾。
- 通过将IP地址和子网掩码进行 “按位与” 操作,得到的结果就是网络号,而剩下的位从0到填满就是所有子网的范围。
- 子网掩码也会被配置到路由器中,通过不断的按位与,进行子网划分。
网络划分
互联网中那么多的主机,通过IP是如何找一台主机的?
发送一个数据的前提是需要先找到目标机器(目标网络+目标主机),找的过程本质就是排除的过程。如果类似学号一样,通过几位特定号码找到确定的院校,再通过几位特定号码找到班级,再通过特定号码找到学生,这就完成了一个划分,在便于查找的同时排除了一大堆。
网络划分就是一种类似的方式。国家1如果有IP开头为10的报文,就在自己国家内进行转发。国家1如果有IP为11开头的报文,就需要通过对外路由传给国家2。
IP还能继续划分。通过类似上述的方式,通过划分IP位段,就能达到标识不同区域的效果。再通过建立相关基础设施就能将不同的网络之间连接起来。
但也不能简单的一层一层将IP进行划分,因为IP是有限的。因此需要有一些局域网的机制。
特殊的IP地址
- 将IP地址中的主机地址全设置为0,就成为了网络号,代表这个局域网。
- 将IP地址中的主机地址全设置为1,就成了广播地址,用于给同一链路中相互连接的所有主机发数据包。
- 127.* 这样的IP地址通常用于本地环回测试,通常是127.0.0.1。(本地环回的数据不会往网络中走,而是自顶向下到达数据链路层经过判断,再自底向上交付)
IP地址的数量限制
IPv4(32字节)有42亿多种,随着互联网发展,如果每台主机都要有一个IP地址,这就意味着一共只能有42亿多主机接入网络,实际上有些特殊IP的存在,并且IP是通过网卡决定的,一个主机还不止一个网卡,一个人也可能有多种设备。因此IP地址必然会出现严重不足。
CIDR并没有解决其不足问题,只是提高了利用率。
这时有三种解决方式:
1、动态分配:只给接入网络的设备提供IP,但有很多主机是需要7*24小时工作的,因此这种方法也不行。
2、NAT技术。(这种行)
3、IPv6技术,它和IPv4不相关也不兼容,目前该技术未普及。
私有IP和公网IP
通过组建局域网,让一些特定IP地址只用于局域网内通信,而不直接连到互联网上,RFC 1918规定了以下用于组件局域网的私有IP地址。
- 10.*,前8位是网络号。
- 172.16.* 到 172.31.*,前12位是网络。
- 192.168.*,前16位是网络号。
这个范围里的,都是私有IP,其余则称为公网IP。
- 一个路由器可以配置两个IP地址,一个是WAN口IP,一个是LAN口IP(子网IP)
- 路由器LAN口连接的主机,都从属于当前这个路由器的子网中。
不同的路由器,子网IP其实都是一样的(通常是192.168.1.1).子网内的主机IP地址不能重复,但是子网之间的IP地址就可以重复。- 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点,这样的运营商路由器可能会有很多级,最外层的运营商路由器,WAN口IP就是一个公网IP了。
- 子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(LAN口IP替换成WAN口IP),这样逐级替换,最终数据包中的IP地址称为一个公网IP。这种技术就称为NAT(网络地址转换)。
- 如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有外网IP的服务器上。
因此一个局域网中的数据,想要发送到公网,是需要不断替换原IP。(如何回来后面说)
同时不同局域网内的主机都用同一套私有IP,这就隐性的增加了大量的ip。(这也使得推动ipv6的动力不足了。)
路由
一个主机将数据传给另一个主机,是需要经过多个路由器进行路由,"一跳一跳"进行"问路"找到对方的。
当IP数据包到达路由器时,路由器会先查看目的IP。路由器会通过自身路由表决定这个数据包传给指定的主机还是下一个路由器。依次反复,直到到达目的IP主机。
Linux下通过route
命令可以查看主机内核路由表
其中:
Destination 代表所处的子网的网络号
Gateway 代表网关,有gateway的代表默认路由器。
Genmask 代表子网掩码
Flags 其中U代表当前条目是有效的,G代表是一个路由器。
Iface eth0代表硬件接口,发消息和收消息都从这个接口进行。
当收到一个ip地址时,通过和每一条的子网掩码进行按位与,看是否和网络号匹配,如果匹配成功就再通过eth0发出去,如果没有匹配的就根据默认default以及eth0发出去。
2、数据链路层
在之前网络层IP中,IP通过路径选择将数据包具有从主机A跨网送到主机B的能力。数据链路层要解决的是数据包是如何从当前到“下一跳”的能力,也就是解决如何局域网内转发。通过网络IP和数据链路就能解决既能找路又能走的问题,而如果路上出问题了,传输层就能帮助可靠地到达,当数据到达,应用层就能对数据进行各种处理和解析。
又因为路由器是横跨两个局域网,那么将数据包传给路由器,其实就是一个子网到另一个子网的过程,也就是跨网络。
那么数据如何在内网中进行转发呢?
2.1 以太网帧格式
以太网和令牌环网是局域网中的两套标准。
以太网帧格式如下:
数据: 数据通常是上层的IP报文。(后面也会讲到,也可能是ARP报文)
目的MAC地址和源MAC地址: MAC地址全球唯一,其强调唯一性。(但要求局域网内唯一性就行了)
封装和解包: 在数据基础上通过添加报头字段达到封装,再通过固定的666固定大小报头字段就可以完成解包。
CRC: 对报头进行校验和的字段。
分发: 通过类型字段判断向上具体交付什么有效载荷类型。(比如类型位0800时,传的就是IP数据包)
局域网通信原理和MTU
一个局域网内是有很多台主机的,其中每台主机都有唯一的MAC地址。
假设如果MAC地址为M1的主机M1和M6进行通信。
其实在局域网内M1主机将以太网帧传给M6主机时,整个数据包是会被这个区域内所有主机看到的。可以将此时的网络看作一个共享资源,每个主机都会通过数据链路层接收这个数据包,在识别目的MAC地址是否和自己匹配后选择是否丢弃。当M6识别成功就将对应数据包向上进行交付。
在局域网内,是一定会有多台主机同时发送数据的情况。局域网也被称为一个碰撞域,当多台主机发送消息时,数据在网络中就会发生碰撞,造成数据不可达。因此网络可以看作是一种临界资源,任何时刻只能有一个主机进行访问。
局域网中主机越多越好还是越少越好?
答案肯定是越少越好,但也避免不了多的情况。
因此引入了交换机,对局域网划分了多个子区域。
交换机使得局域网:
1、当主机在同一子区域内,发送的数据包不会扩散。
2、当不在同一子区域时也能横跨子区域,当到达后也不会扩散。
3、当然不同区域如果经常通信,也会被划分到同一区域。
认识MTU
在局域网中,数据包也一定更长更容易碰撞。因为越长越有概率和其它数据相遇。以太网帧因此一般体积不要太大,以太网帧必须向上提要求,因此有了MTU(最大传输单元)。
MTU规定上层网络层最大交给数据链路层的数据为1500字节。(不同网络也有不同的MTU)
后续网络层如果要传一个大于MTU的数据包,就需要在网络层自己分片。
2.2 ARP协议
通过以上,我们认识到通过网络层和数据链路层实现了数据从一端主机到另一端的能力,再通过传输层保证了数据传输的可靠性。这一切看似很完美但是还有问题。
主机A可以通过MAC帧,固定的源IP地址和目的IP地址,以及源MAC地址和目的MAC地址的不断转换最终到达目的主机,但有个问题。
主机一开始是如何知道下一条的MAC地址呢?(局域网有广播,但是这种方法很挫)
因此需要ARP协议,将IP转换成MAC地址。
首先要注意的一点,在同一局域网内,虽然彼此不知道对方的MAC地址,但是是可以通过一些手段进行通信的。
ARP数据报格式
ARP协议属于数据链路层,在同层中ARP协议属于MAC帧协议的上层。虽然在MAC帧上层,但都属于数据链路层。
当MAC帧类型字段为0806时,对应有效载荷就是上层的ARP数据报。
当一台主机进行通信时,其中:
硬件类型: 表示下层局域网是什么标准。(1代表以太网)
协议类型: 协议类型指要转换的地址类型,0x0800为IP地址
硬件地址长度对于以太网是6字节,协议地址长度对于IP地址是4字节。
发送端以太网地址知道。
发送端IP地址和目的IP地址也都知道。
唯独目的以太网地址不确定。
一开始不确定目的MAC地址那怎么办呢?
MAC帧一开始会以广播的方式,交给局域网中的所有主机,每个主机都会对MAC帧进行处理。将其中ARP报文交付给上层。上层通过处理ARP报文字段,首先识别目的IP地址,如果发现IP地址不是自己的,就会将ARP层的ARP报文丢弃。当目标主机匹配到了IP地址,此时目标主机会发送一个ARP应答报文。此时所有的MAC信息和IP信息都能确定。这一次,其它主机也能都收到MAC帧,但由于目的MAC地址是确定的,所以直接在MAC帧协议这一层就将MAC帧丢弃了。此时接收端收到了这一次发送端的以太网地址,这就确定好了两个主机各自的MAC地址。
op字段:1代表ARP请求,2代表ARP应答。因为每个主机都是可以向对方发消息的,因此也就有发送报文和发送回应后的报文,通过这个字段也就解决了主机这次建立的ARP报文,是请求报文还是应答报文。因此收到报文后,第一检测的应该是op字段。
当然也不是每一次通信都要通过ARP协议进行确认对方的MAC地址
通过第一次ARP协议之后,目的IP和目的MAC地址的映射就需要被缓存起来,谁请求谁缓存。这个缓存是暂时缓存,有时效一般是20-30分钟。
Linux上通过arp -a 就能查看对应目的IP和目的MAC地址的映射
综上,通过IP地址MAC帧一定能到达目的主机的同一网络,在每一局域网内此时虽然不知道目的主机的MAC地址,但是通过ARP协议的一来一回,就能完成目的IP到目的MAC地址的转换和对应映射存储。在之后就能正常完成数据包转发。
3、其它重要协议或技术
3.1 DNS技术
DNS是一整套从域名映射到IP的系统。
IP地址是数字,在互联网推广中是非常不方便的,域名的可读性在为用户提供服务时非常有必要,因此就有域名转换成IP的需求。DNS因此而生。
域名简介
域名使用 . 进行连接
比如www.baidu.com
- com: 一级域名。表示这是一个企业域名,同级的还有"net"(网络提供商),“org”(非盈利组织),“gov”,"edu"等。
- baidu: 二级域名,公司名
- www:只是一种习惯用法,其实访问时也可以不用带。
IP地址不方便记忆,于是通过发明一个主机名的东西,使用hosts文件来描述主机名和IP地址的关系。
最初,通过互联网信息中心(SRI-NIC)来管理这个hosts文件的。
- 如果一个新的计算机要接入网络,或者某个计算机IP变更,都要到信息中心申请变更hosts文件。
- 其它计算机也需要定期下载更新新版本的hosts文件才能正确上网。
- 老技术也被保存了下来,通过cat /etc/hosts也能查看到。
这就太麻烦了,于是有了DNS系统。
- 一个组织的系统管理机构,维护系统内的每个主机的IP和主机名的对应关系。
- 如果新计算机接入网络,将这个信息注册到数据库中。
- 用户输入域名的时候,会自动查询DNS服务器,由DNS服务器检索数据库,得到对应的IP地址。
不过,现实中也会有一个域名需要访问多个服务器的需求。
如果大量用户通过一个域名访问一个服务器的话,对于这个服务器来说压力就比较大了。如果在访问服务器之前,通过一个域名与多个子域名进行映射,子域名再映射到多个IP,通过随机IP访问,让请求分别访问不同的服务器。这种方式就可以实现机房间的负载均衡。
实际上浏览器其实也会有一定方式将常用的域名和IP映射进行保存在本地。
3.2 ICMP协议
ICMP是一个网络层协议。
一个新搭好的网络,往往需要先通过一个简单的测试,来判断是否可以正常网络通信。但IP协议不能提供一个可靠的传输,如果丢包了,IP协议并不能通知传输层是否丢包以及丢包原因。
通过ICMP协议就能很好解决这个问题。ICMP有以下功能:
1、确认IP报是否到达目标地址。
2、返回IP报丢包原因。
不过要注意的是ICMP是基于IPv4的,并且也是基于IP协议工作的,但是并不属于传输层,因此把它归于网络层。
ICMP报文格式
ICMP分为两类报文,一类是通知错误原因,一类是用于诊断查询。
通过不同的类型使得内容不一样。
ping命令
通过ping命令,能先发送一个ICMP Echo Request给对面,对面后续会返回一个ICMP Echo Reply。
一个注意的坑:ping没有对应的端口,它是基于ICMP协议的,是属于网络层的。端口号是传输层的内容,ICMP不关注端口号。
traceroute命令
traceroute命令也是基于ICMP协议的命令,能打印出可执行程序到目的主机之前经历了哪些路由器。
3.3 NAT技术
之前讲过ipv4协议中,IP地址数量不足的问题。通过NAT技术将私有IP对外转换成全局IP,很多学校、家庭和公司的每个终端都采用相同的私有IP,在路由器或服务器上采用各自唯一的全局IP。
在一台主机需要访问公网时,需要在IP报文中填写源IP地址和目的IP地址,IP报文通过家用路由器和运营商路由器最终到达公网访问特定IP主机。在这个过程中每经过一个路由器都要发生源IP地址的转换(比如【源IP地址是192.168.1.201、目的IP地址是122.77.241.3】转换成【源IP地址10.1.1.2、目的IP地址不变】),通过跨越多个路由器,经过多次转换,最终到达目的主机的网络。
当然以上只是数据发送出去的过程,那么数据回来该怎么办?此时主机收到的并不是最初的IP地址。
这时候就需要NAPT,其实也很简单,在发出去的过程中,每经过一次IP转换,对应的IP+port映射关系就会保存生存一个转换表,当数据报返回时,通过映射关系层次转换成原本的IP地址进行访问。(TCP情况下,建立连接时,就会生成转换表;在断开连接后,就会删除这个表)
NAT技术的缺陷
- 无法从NAT外部向内部服务器建立连接。(如果直接通过主机访问外网跳过路由器,就没有转换表的建立,但也有NAT内网穿透技术)
- 转换表的生成和销毁都要额外开销。
- 通信过程中一旦NAT设备异常,即使存在热备,所有TCP连接也都会断开。
3.4 NAT和代理服务器
路由器往往都具有NAT设备的功能,通过NAT设备进行中转,完成子网设备和其它子网设备的通信过程。
什么是代理服务器?
第一种场景
其实在一些学校,如果宿舍中主机访问一个网站(比如百度),在连接校园网的前提下,请求是不能直接访问百度的,而是需要先将请求发送到学校的代理服务器,由学校的代理服务器向运营商请求,来替我们进行访问。因此在代理服务器中就有一些不被察觉的规则,我们不知道其存在。
这种替我们代理的称为正向代理。
一般它可以进行以下工作。
1、对访问请求过滤或拦截。(这也一定程度上保护内网,保护学校信息健康)
2、提高效率(比如在代理服务器上缓存电影,当其它人看的时候就直接传给对方)
3、身份认证(比如校园网账号密码访问)
4、限流拦截(常见的校园网限速)
第二种场景
当有大量用户的请求访问一个公司的主机时,公司内机器不能被直接访问,一般服务器集群外都有一个代理服务器,将收到的请求通过某种算法推送给某台机器,避免大量请求访问一台主机,而机器收到请求后处理完,机器直接返回给用户,不需要再通过代理服务器,这种服务器就是反向代理服务器,将请求均衡的发送到机房服务器。
这种代理服务器有一般有以下好处
1、负载均衡
2、保证内网安全(防止恶意攻击,通过黑白名单限制访问)
3、暴露漏洞(钓鱼执法)
反向代理之前还有一层防火墙,大型路由器上面安装防火墙。对请求进行判断进行一定拦截。
代理服务器好像和NAT有点相似,都是有一端向另一端发送信息的过程中存在中间进行交互的一端。
NAT和代理服务器的区别
在应用上: NAT是建立在网络基础设备上,解决的是IP不够的问题。代理服务器是建立在应用上,常用于加速器。
在层次上: NAT是在网络层上的,代理服务器往往工作在应用层。
在使用范围上: NAT一般在局域网出口部署,代理服务器可以在局域网中做,也可以在广域网中做。
从部署部位来看: NAT一般都是在防火墙、路由器中部署,而代理服务器则是一个软件程序,部署在服务器上。
本章完~