IP 协议

目录

网络层的定位

IP的构成

IP报头

4位版本

4位首部长度

8位服务类型

16位总长度

8位协议

16位首部检验和

8位生存时间

32位源IP与目的IP

网段划分

私有IP和公网IP

路由

IP分片和组装

16位标识

3位标志

13位片偏移


网络层的定位

IP协议是网络层最经典的协议,IP提供了一种能力,把数据从A主机跨网络送到B主机的能力,而传输层(TCP)提供的能力是将数据从A主机跨网络可靠地送到B主机的策略和方案!!

总结一下,传输层提供的是指导方案,是理论决策,网络层是执行者角色,传输层提供的是可靠性方案,并不意味着每次跨网络传输,数据都能完全可靠地到达~

可靠地跨网络传输,毕竟再厉害的人也会有失误,再顶级的程序员也会写bug~

IP的构成

你家在陕西,要去重庆解放碑旅游,你现在在陕西境内,问路肯定不会直接问解放碑怎么走,而是先问重庆怎么走,等你到重庆后,才会问当地人解放碑怎么走~

网络中报文的转发也是如此,先确定报文到哪个目标网络,到达目标网络后再确定到达哪个主机,因此IP地址也是由两部分构成的,IP = 目标网络 + 目标主机

IP报头

4位版本

指定IP协议的版本,对于IPV4来说,就是4

4位首部长度

4位首部长度标识的是IP报头的长度,取值范围0000,1111,最大值是15,单位长度依旧是4字节,报头的最大长度为15*4=60字节,选项最大是60-20=40字节!!

8位服务类型

3位优先权字段(已经弃用),4位TOS字段, 和1位保留字段(必须置 为0). 4位TOS分别表示: 最小延时,最大吞吐量,最高可靠性,最小成本,这四者相互冲突, 只能选择一个,对于ssh/telnet 这样的应用程序, 最小延时比较重要;对于ftp这样的程序,最大吞吐量比较重要

16位总长度

16位总长度标识整个IP报文的长度,有效载荷 = 16位总长度 - 4位首部长度,就可以将报头和有效载荷分离,因此IP报文报头和有效载荷分离采取的是自描述字段!!

8位协议

不同的协议在内核中有不同对应的数字,8位协议表示的是上层协议的类型,可以做到向上交付!

16位首部检验和

使用CRC进行校验,来鉴别头部是否损坏

8位生存时间

光电信号在网络中是会衰减的,因此网络中存在一种设备叫做集线器,是用于放大信号的,因此两个主机相隔非常远也照样能收到对方的消息!!

网络是人搭建的,是人参与的就一定会有 bug,这就可能导致有些报文在网路中转发的时候一直在转圈圈,也就是出现了环路,一直无法抵达目的地,一直不会消散,一直消耗网络资源!

8位生存时间指的是数据报到达目的地的最大报文跳数,一般是64,每次经过一个路由,TTL-=1,一直减到0还没到达,那么就丢弃了,这个字段主要是用来防止出现路由循环!

32位源IP与目的IP

我们在 socket 编程时,为啥定义的是4字节IP呢,就是因为在IP报头中,IP字段是32位的,socket = IP(网络层) + port(传输层)

网段划分

IP是被精心设计过的,IP = 网络号 + 主机号,现实生活中,学号也是精心设计过的!!不同学校的学号设计规则可能不太一样,但一定是有规律的,比如学号的开头几位可能是入学年份/年级、中间是学院编号、最后是学院内学生编号,我们此处简化逻辑,认为学号由两部分构成,学号 = 学院号 + 院内学生号,这种设计使得 学号具有唯一性 + 具有很强的指向性,不仅能唯一标识一个学生,还能顺藤摸瓜找到该学生~

举个例子:

现在有6个学院,编号依次为01-06,每个学院有很多学生,每个院有自己的院群,学生的学号遵循上文所述规则,每个学院都有一个院学生会主席,这些院学生主席也拉了一个群~

有一天,张三捡到了一个钱包,钱包中有学生证,但只能看到学号06321,张三要根据学号将钱包物归原主。张三一看学号是06321,一看开头数字是06,肯定知道不是自己学院的,于是在群里@计院学生会主席,并将自己的电话给了学生会主席,计院主席在学生会主席群里@其他学院学生会主席,机械学院的学生会主席一看,学号06开头,是机械学院的,于是在自己的院群里问了一下321是哪个学生,于是找到了李四,李四打通了张三的电话最终拿到了钱包!

各个学院本质是一个个子网,院学生会主席本质是路由器,院学生会主席之间组建的群叫做公网,06321的06本质就是网络号,321本质是主机号,当报文到达目标网络之前,只关心网络号!

归还钱包本质是在查找学生,如果直接线性遍历所有的学生,效率太低,因为一次只能淘汰一个学生,而通过精心设计了学号,一次可以淘汰一个学院/多个学院的学生,效率大大提高!

总结:网段划分是运营商来做的,目的就是提高在全网中定位主机的效率!

如何进行网段划分呢?

上图中有两个子网,两个子网的IP的前24位用于网络标识,后8位是主机标识,不同的子网IP的网络标识必然是不一样的,不同的子网内可以出现相同的主机标识,同一个子网的不同主机,主机标识必然是不同的!!路由器横跨了两个子网,配有两个子网的网络标识的IP地址!!

通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同。那么问题来了, 手动管理子网内的IP,是一个相当麻烦的事情。有一种技术叫做DHCP,能够自动的给子网内新增主机节点分配IP地址,避免了手动管理IP的不便。一般的路由器都带有DHCP功能,因此路由器也可以看做一个DHCP服务器!

过去曾经提出一种划分网络号和主机号的方案,把所有IP地址分为五类,如下图所示:

A类 0.0.0.0 到 127.255.255.255

B类 128.0.0.0 到 191.255.255.255

C类 192.0.0.0 到 223.255.255.255

D类 224.0.0.0 到 239.255.255.255

E类 240.0.0.0 到 247.255.255.255

随着Internet的飞速速发展,这种划分方案的局限性很快显现出来,大多数组织都申请B类网络地址,导致B类地址很快就分配完了,而A类却浪费了大量地址;

例如申请了一个B类地址,理论上一个子网内能允许6万五千多个主机,A类地址的子网内的主机数更多,但是实际网络架设中,不会存在一个子网内有这么多主机的情况,因此大量的IP地址都被浪费掉了!!

针对这种情况提出了新的划分方案,称为CIDR(Classless Interdomain Routing)(无类别域间路由):

CIDR引入一个额外的子网掩码来区分网络号和主机号,子网掩码也是⼀个32位的正整数. 通常用一串 "0" 来结尾,将IP地址和子网掩码进行 "按位与" 操作, 得到的结果就是网络号,网络号和主机号的划分与这个IP地址是A类、B类还是C类无关;

按照传统的划分方法,0000 0011 24位主机号 属于A类IP地址,主机号是后面24位,那么该网段内可以有 2^24 IP地址,可是压根没有这么多的主机,造成了IP地址的浪费!!!我们可以再将24位主机号中的8位再拿出来作为网络号,进行进一步的细分!

0000 0011 0000 0001 16位主机号

0000 0011 0000 0010 16位主机号

0000 0011 0000 0011 16位主机号

......

由于将前16位作为网络号,那么子网掩码就是 255.255.0.0,子网掩码的本质就是为了提高分类划分法IP的利用率!!

下面举两个划分子网的例子:

例1:

例2:

IP: 140.252.20. 0100 0100

掩码:255.255.255.1111 0000 后4位是主机号,能表示的主机最多是15个!

&: 140.252.20. 0100 0000 -> 140.252.20.64

IP地址和子网掩码还有⼀种更简洁的表示方法,例如140.252.20.68/24,表示IP地址为140.252.20.68, 子网掩码的高24位是1,也就是255.255.255.0

特殊的IP地址

• 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网;

• 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同⼀个链路中相互连接的所有主机发送数据包;

• 127.* 的IP地址用于本机环回(loop back)测试,通常是127.0.0.1

IP地址的数量限制

我们知道,IP地址(IPv4)是⼀个4字节32位的正整数,那么⼀共只有2的32次方个IP地址,大概是43亿左右,而TCP/IP协议规定,每个主机都需要有⼀个IP地址,这意味着, ⼀共只有43亿台主机能接入网络么?

实际上, 由于⼀些特殊的IP地址的存在, 数量远不足43亿;另外IP地址并非是按照主机台数来配置的, 而是每⼀个网卡都需要配置⼀个或多个IP地址.

CIDR在一定程度上缓解了IP地址不够用的问题(提搞了利用率,减少了浪费,但是IP地址的绝对上限并没有增加),仍然不是很够用,这时候有三种方式来解决:

• 动态分配IP地址: 只给接入网络的设备分配IP地址. 因此同⼀个MAC地址的设备, 每次接入互联网中,得到的IP地址不一定是相同的;

• NAT技术(下文会重点介绍);

• IPv6: IPv6并不是IPv4的简单升级版. 这是互不相干的两个协议,彼此并不兼容;IPv6用16字节128位来表示一个IP地址;但是目前IPv6还没有普及。

私有IP和公网IP

如果一个组织内部组建局域网,IP地址只用于局域网内的通信,而不直接连到Internet上,理论上使用任意的IP地址都可以,但是RFC 1918规定了用于组建局域网的私有IP地址!

• 10.*,前8位是网络号,共16,777,216个地址

• 172.16.*到172.31.*,前12位是网络号,共1,048,576个地址

• 192.168.*,前16位是网络号,共65,536个地址

换句话说,在所有的IPV4地址中,划分出一部分IP地址作为私有IP,私有IP只能构建子网,不能出现在公网上!

那局域网是谁来组建的呢?是家用路由器,家用路由器不仅有路由功能,还有组建局域网的功能!

如上图所示,家用路由器在出厂的时候就分配了私有IP(子网IP),网络号就已经确定了,在家用路由器下使用相同的网络号分配给家里上网的主机,不同的家用路由器的子网IP是完全可以相同的,并且不同的子网内,家庭端也可以出现完全相同的IP地址,这就变相增加了IP地址的绝对上限了!

我们国家整个网络基础设施都是由三大运营商搭建的,农村现在也能上网是因为运营商将网络下沉了,因此家用路由器一端连接的是家庭端(LAN口),另一端连接的是运营商路由器(WAN口),家用路由器的本质就是运营商路由器搭建的子网的其中一个主机节点!而运营商路由器的WAN口,搭建的是一个公网IP!!!

运营商做了基础设施建设,因此家用路由器上网,必须经过运营商企业路由器的转发,因此我们上网的流量费都是交给了运营商,欠费了/访问非法网址,运营商就能直接拦截你上网!

家庭端的主机是如何将数据发送到公网主机的?

假如家庭端的一个主机发送了一个报文: src:192.168.1.201,dst:122.77.241.3,data:获取一个短视频,主机对比 dst 和 自己所在的网络地址,知道这个报文不是发给自己所在网络的,于是交给了家用路由器,家用路由器继续对比dst与自己的WAN口IP,发现和WAN口IP所在的网络也不同,于是继续交付给运营商路由器,运营商路由器继续对比,发现dst和自己的WAN口IP处于同一个网络,于是就发送到了公网中,最终到达了目标主机!

目标主机要将短视频推送给src主机,于是封装报文:src:122.77.241.3,dst:192.168.1.201,data:短视频内容,此时就有问题了,几个子网内都有 IP为 92.168.1.201 的主机,不知道如何转发了!!并且子网ip是绝对不能出现在公网上的!!

那真实的报文从内网到公网的过程是怎样的呢?

报文在从内网转发到外网时,路由器会自动进行内网IP替换,自动用路由器的WAN口IP替换掉,继续用刚才的例子,假如家庭端的一个主机发送了一个报文: src:192.168.1.201,dst:122.77.241.3,data:获取一个短视频,到达家用路由器后,家用路由器将报文转出去之前,将src 替换为自己的WAN口IP,src:10.1.1.2,然后转发给运营商路由器,运营商路由器将报文转出去之前,将src 替换为自己的WAN口IP,src:122.77.241.4,最终到达目标主机,目标主机回应报文时:src:122.77.241.3,dst:122.77.241.4,于是根据 dst 就可以顺利的从公网转发到公网到子网的出入口路由器(运营商路由器),至于在内网中最终如何到达目标主机,我们下文讲解NAT技术时详细讲解!

理解公网

真实的网络结构非常复杂,既涉及到划分公网IP的组织,ICANN,还要在全球范围内进行区域划分, 比如亚太,北美,欧洲等,又要考虑各个国家内部的ISP代理,整体拓扑非常复杂,我们简化所有过程,认为全球范围内的IP地址是按照国家划分的,简单理解公网即可。

如上图所示,首先是国家申请IP地址,将前8个比特位用于标识国家的网络号,给俄罗斯分配1.0.0.0,美国分配 2.0.0.0,依次类推,每个国家配有一个国际路由器,俄罗斯的国际路由器WAN1口IP地址为 1.0.0.1,美国的国际路由器WAN1口IP地址为 2.0.0.1,依次类推,将所有的国际路由器组建国际骨干网络,类似于所有的学生会主席建立一个群,然后所有的路由器在该网络内广播自己的网络号、IP地址,这个过程叫做路由条目交换算法,这样所有的国际路由器都建立了路由表条目,如图所示的网络地址、子网掩码、下一跳地址、以及相关说明,这就完成了第一次子网划分!!!

每个国家又有很多区域,可以进一步子网划分!以我们国家为例,再来8个比特位进一步将5.0.0.0网络进行子网划分,比如5.1.0.0 代表陕西、5.2.0.0代表河南...以此类推,每个省份配有一个省间路由器,陕西省的路由器的WAN1口IP地址为5.1.0.1,河南省的路由器的WAN1口IP地址为5.2.0.1...以此类推,将所有的省间路由器组建国内骨干网络,然后进行路由条目交换算法(包括中国的国际路由器的WAN2口),此时中国的国际路由器中就不仅有其他国家的网络信息了,还有国内各个省份的网络信息了,完成第二次子网划分了!

陕西省还有各个市,再拿出6位,继续进行第三次子网划分...

俄罗斯内的主机访问 5.1.16.x的过程

IP地址不是1开头的,不是发给自己国内的,于是转发到俄罗斯的国际路由器,该路由器根据路由表,将该IP地址与每一条路由项的子网掩码按位与,发现是要发往中国的,于是转发到下一跳地址5.0.0.1,到达中国的国际路由器,该路由器查找路由条目,发现和5.1.0.0匹配,发现是发给陕西的,于是转发给下一跳地址5.1.0.1...再重复一次这个过程,报文最终到达西安的出入口路由器!

总结:我们这个网络是精心设计过的,根据目标IP能找到目标主机,不是因为IP本身,而是网络拓扑结构决定的,是子网划分和路由配置决定的!

路由

路由就是在复杂的网络结构中,找到一条通往终点的路线。路由的过程,就是"一跳一跳"问路的过程,所谓"一跳"就是数据链路层的一个区间,具体在以太网中指从源MAC地址到目的MAC地址之间的帧传输区间。

IP数据包的传输过程也和问路一样的,当IP数据包到达路由器后,路由器先查看目的IP,路由器决定这个数据包是直接发送给目标主机还是需要发送给下一个路由器,依次反复,一直到达目标IP地址!那么如何判定当前这个数据包发送到哪里呢?这就依靠每个节点内部维护一个路由表!

如果目的IP命中了路由表,直接转发即可,路由表的最后一行,主要由吓一跳地址和发送接口两部分组成,当目的地址与路由表中其他行都不匹配时,就按缺省路由条目规定的接口发送下一跳地址!

假如某主机上的网络接口配置和路由表如下:

这台主机有两个网络接口,一个网络接口连到192.168.10.0/24网络,另一个网络接口连到

192.168.56.0/24网络,路由表的Destination是目的网络地址,Genmask是子网掩码,Gateway是下一跳地址,Iface是发送接口,Flags中的U标志标志此条目有效(可以禁用某些条目 ),G标志表示此条目的下一跳地址是某个路由器的地址,没有G标志的条目表示目的网络地址是与本机接口直接相连的网络,不必经路由器转发

转发过程例1: 如果要发送的数据包的目的地址是192.168.56.3

  • 跟第一行的子网掩码做与运算得到192.168.56.0, 与第一行的目的网络地址不符

  • 再跟第二行的子网掩码做与运算得到192.168.56.0, 正是第二行的目的网络地址, 因此从eth1接口发送出去;

  • 由于192.168.56.0/24 是与eth1接口直接相连的网络, 因此可以直接发送到目的主机, 不需要经路由器转发;

转发过程例2: 如果要发送的数据包的目的地址是202.10.1.2

  • 依次和路由表前几项进行对比, 发现都不匹配;

  • 按缺省路由条目, 从eth0接口发送出去, 发往192.168.10.1路由器;

  • 由192.168.10.1路由器根据它的路由表决定下一跳地址;

IP分片和组装

事实:网络层交付给数据链路层的报文长度(也就是数据链路层的有效载荷)不能超过1500字节(MTU,最大传输单元)

如果网络层交付给链路层的报文长度超过了MTU,就要进行分片,也就是将一个报文拆成多个片段,再交付给数据链路层,最后发送到网络中!!对端网络层收到了分片的IP报文,就要进行组装,组装好了之后再将整个完整的报文交付给上层的传输层,IP分片和组装的整个过程传输层是不知道的,也不需要知道!!!

16位标识

唯一标识主机发送的报文,如果IP报文在数据链路层被分片了,那么每一个片里面的16位标识都是相同的!

3位标志

第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。

第二位为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。

第三位表示"更多分片", 如果分片了的话,最后一个分片置为0,其他是1,类似于一个结束标记

13位片偏移

是分片相对于原始IP报文开始处(以IP报文的有效载荷开始处)的偏移,其实就是在表示当前分片在原始报文中处在哪个位置

比如IP报文的有效载荷是3000字节,因为每个分片都要携带IP报头的,我们认为报头不携带选项,是标准的20字节,那么需要分3片,第一片报头20字节+有效载荷1480字节,第二片报头20字节+有效载荷1480字节,第三片报头20字节+有效载荷40字节,第一片13位片偏移为0,第二片13位片偏移为1480,第三片13位片偏移为2960

分片和组装需要解决哪些问题呢?

1.一个报文超过MTU被分成了多片,有的报文没有超过MTU没有分片,都发送到网络中了,对端主机如何知道哪些报文是分片的报文,哪些报文是没有分片的报文?

答:所有分片的报文除了最后一片,其他分片3位标志的第三位都是1,而完整报文和分片报文的最后一片的第三位都是0,但是分片报文的最后一片片偏移不为0!因此判断一个报文是否分片了:

if(更多分片 == 1 || 片偏移 > 0) return "分片了";

else return "没有分片";

2.可能有多个报文都进行了分片,如何知道哪些分片是属于哪一个报文的?

答:16位标识相同的就是同一个报文!

3.能够知道哪些报文分片了,如何能完整收集并组装所有分片的呢?

答:已经能判断某一个报文是否分片了,只要拿到了一个分片了的报文,立马提取16位标识,找出所有相同16位标识的报文!!如果这些报文中没有片偏移为0的报文,说明第一个分片丢了,直接丢弃整个报文,如果没有更多分片为0的报文,说明最后一个分片丢了,直接丢弃整个报文;如果第一片和最后一片都没有丢,将剩余的报文按照13位片偏移数字排序,就可以判断中间是否有分片丢失以及组装出整个报文!!

分片丢失问题

注意:如果某个报文的某个分片丢了,IP层是做不到只重传某个分片的!对端主机会将该报文的其他分片都丢弃了,要重传就要将所有的分片都进行重传!!

分片会导致丢包的概率增加,比如网络条件相同的情况下,一个报文丢失的概率是固定的,而将一个报文拆成了很多分片,那么只要有1个分片丢失了,整个报文就认为丢了,变相增加丢包概率,因此分片绝不是IP通信的主流!!

13位片偏移 vs 16位报文总长度

16位报文总长度最大能表示 2^16-1 = 65535 字节长度的报文,而13位片偏移最多能表示 2^13 = 8192 个不同的数字,这不就意味着报文长度超过了 8192 了,有些分片的片偏移是无法用13位表示的嘛?

实际上13位片偏移在存储的时候,存的是实际偏移的字节数 / 8,相当于每8个字节是一个偏移单位,实际存储的是偏移的单位数,对端主机在提取时,将偏移的单位数 * 8,就是实际偏移的字节数 !8192 * 8 == 65536,相当于用13位长度表示了16位的数字!!

要不要分片是IP层决定的嘛?

IP的有效载荷是来自传输层的,要不要分片,不是IP层说了算的,而是传输层决定的!数据链路层报文有效载荷最大是1500字节,倒逼网络层报文有效载荷最大是1500-20=1480,倒逼传输层报文有效载荷最大时1480-20=1460,1460也就是MSS(最大段尺寸)的值!

相关推荐
笨鸟先飞,勤能补拙12 小时前
Web 服务器与计算机网络全景原理
运维·服务器·前端·网络·人工智能·计算机网络·web安全
拾光Ծ15 小时前
【Linux网络】数据链路层详解:以太帧与ARP协议 + 代理服务器与内网穿透,内网打洞
计算机网络·内网穿透·数据链路层·arp·代理服务器·内网打洞·以太帧
JZZC216 小时前
38.IPv6——静态配置
计算机网络·ipv6
ly76892 天前
计算机网络:从分层模型到 TCP/IP、HTTP 与网络排查
网络·tcp/ip·计算机网络
我爱cope2 天前
【计算机网络 | 物理层5:时分复用、频分复用与波分复用:一条链路如何服务多个用户?】
网络·学习·计算机网络
上岸社社长2 天前
2027届国网计算机类备考指南:时间线、考纲与复习规划(附资料)
计算机网络
四代水门2 天前
三、计算机网络
服务器·计算机网络·asp.net
hxhy003 天前
计算机网络
计算机网络
llllll1524 天前
深入浅出计算机网络:从 TCP 可靠传输到 DNS 解析核心原理
网络协议·tcp/ip·计算机网络