【Linux】网络层协议——IP

一、IP协议

在前面,我们学习了应用层和传输层,接下来,我们来学习网络层,网络层的主要功能是在复杂的网络环境中确定一个合适的路由。

1.1 IP协议的基本概念

  • 主机:配有IP地址,有可以进行路由控制的设备
  • 路由器:配有IP地址,又能进行路由控制
  • 节点:主机和路由器的统称

1.2 IP协议头的格式

  • 4位版本号:指定IP协议的版本,对于IPv4来说,就是4
  • 4位头部长度:IP头部的长度是多少个32bit,也就是4的字节数,4bit表示的最大数字是15,因此IP头部最大的长度是60字节
  • 8位服务类型:3位优先权字段(已经弃用),4位TOS字段和1位保留字段(必须置为0),4位TOS分别表示为:最小延时,最大吞吐量,最高可靠性,最小成本,这个四者相互冲突,只能选择一个,对于ssh/telnet这样的应用程序,最小延时比较重要;对于ftp这样的程序,最大吞吐量比较重要
  • 16位总长度:IP数据报整体占多少个字节
  • 16位标识:唯一的标识主机发送的报文,如果IP报文在数据链路层中被分片了,那么每一个片里面的这个ID都是相同的
  • 3位标志字段:第一位保留(保留的意思是现在不同,但是还没想好,说不定在以后就要用到);第二位置为1表示禁止分片,这时候如果报文的长度超过MTU,IP模块就会丢弃报文;第三位表示"更多分片",如果分片的话,最后一个分片置为0,其他都是1,类似于一个结束标记。
  • 13位分片偏移:是分片相对于原始IP报文开始处的偏移,其实就是在表示当前分片在源报文中处在哪个位置,实际偏移的字节数是这个值乘以8得到的。因此,除了最后一个报文之外,其他报文的长度必须是8的整数倍(否则报文就不连续了)
  • 8位生存时间:数据报达到目的地的最大报文跳数,一般都是64,每次经过一个路由,TTL -= 1,一直减到0还没有到达的话,就可以将其丢弃,这个字段主要是用来防止出现路由循环的
  • 8位协议:表示上层协议的类型
  • 16位头部校验和:使用CRC进行校验,来鉴别头部是否损坏
  • 32位源地址和32位目标地址:表示发送端和接收端
  • 选项字段(不定长,最多40字节)

二、网段划分

IP地址分为两个部分:网络号和主机号。

  • 网络号:保证相互连接的两个网段具有不同的标识
  • 主机号:用一个网段内,主机之间具有相同的网络号,但是必须要有不同的主机号
  • 不同的子网其实就是把网络号相同的主机放在一起
  • 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复

通过合理设置主机号和网络号,就可以保证在相互连接的网络中,每台主机的IP地址都不相同。那么问题来了,手动管理子网内的IP是一个相互麻烦的事情。

  • 有一种技术叫做DHCP,能够自动的给子网内新增主机节点分配IP地址,避免了手动管理IP的不便。
  • 一般的路由器都带有DHCP功能,因此路由器也可以看做一个DHCP服务器。

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

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

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

针对这种情况提出了新的划分方案,称为CIDR:

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

三、特殊的IP地址

  • 将IP地址中的主机地址全部设为0,就成为了网络号,代表这个局域网
  • 将IP地址中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包
  • 127.* 的IP地址用于本地环回测试,通常是127.0.0.1,其不走到网络,在IP层直接走到上层交付

3.1 IP地址的数量限制

我们知道,IPv4版本的IP地址是一个字节数为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地址,从源头上解决了IPv4数量不同的问题,但是目前IPv6还没有普及。

3.2 私有IP地址和公有IP地址

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

3.2.1 私有IP地址的范围

私有IP地址的范围:(包含在这个范围中的地址都称为私有IP地址,其余的全部称为全局IP地址或者公网IP地址)

  • 10.* :前8位是网络号,一共有16777216个地址
  • 172.16. * 到 172.31. * :前12位是网络号,一共有1048576个地址
  • 192.168. *:前16位是网络号,一共有65536个地址

3.2.2 结合私有IP地址和公有IP地址

我们来回顾一下之前的知识点:IP地址是给目标服务器提供最终的地址,主机定位和路由;IP地址等于目标网络 + 目标主机;网络是被运营商精心设计的;网段划分:分类划分法和子网掩码;为什么要进行网络划分,目的是为了给出子网地址,进行路由查找的功能,先查找子网,再查找目标主机。

运营商的工作是非常重要的。

  • 一个路由器中可以配置多个IP地址(至少两个以上),一个是WAN口IP,连接外部地址,一个是LAN口IP;我们在进行路由器的消息转发的时候,由于内网IP不能出现公网中,我们的报文在路由器中进行转发的时候,需要使用WAN口IP来替换报文中的源IP地址。
  • 路由器的LAN口连接的主机都从属于当前这个路由器的子网中
  • 不同的路由器中,子网IP地址其实都是一样的(通常都是192.168.1.1),子网内的主机IP地址不能重复,但是子网之间的IP地址就可以进行重复
  • 每一个家用路由器,其实又作为了运营商路由器的子网的一个节点,这样的运营商路由器可能会有很多级,最外层的运营商路由器的WAN口IP就是一个公网IP
  • 子网内的主机需要和外网进行通信时,路由器将IP首部中的IP地址进行替换(替换成为WAN口IP地址),这样进行逐级替换,最终数据报中的IP地址成为一个公网IP地址,这种技术就称为NAT(网络地址转换)
  • 如果希望我们自己实现的服务器程序能够在公网上被访问,就需要把程序部署到一条具有外网IP地址的服务器上,这样的服务器可以在阿里云/腾讯云上进行购买

3.3 路由

基本概念:在复杂的网络结构中,找出一条通往终点的路线。

例子一:

我们可以来举个例子,在最近《黑神话-悟空》比较火热,拿唐僧去西天取西经,唐僧在去往西天的途中,会经过不同的地方,每到一个地方都需要询问去西天怎么走,他的这个路由就是一跳一跳的问路的过程,所谓的这一跳就是数据链路层中的一个区间,具体在以太网中指的是从源MAC地址到目的MAC地址之间的帧传输区间。

但是这里我们还没有学习MAC帧的概念,这里需要注意的是在数据链路层中每经过一个区间,我们都需要将源MAC地址和目的MAC地址进行改变。要区别IP和MAC帧

IP数据报的传输过程和这个问路相似:

  • 当IP数据报到达路由器时,路由器会先查看目的IP
  • 路由器决定将这个数据报是能直接发送给目标主机的,还是需要发送给下一个路由器
  • 依次反复,一直到达目标IP地址

那么如何判断当前这个数据报应该发送到哪里呢??这个就依靠每一个节点内部维护一个路由表
例子二:

  • 路由表可以使用route命令查看
  • 如果目的IP命中了路由表,就直接转发即可
  • 路由表中的最后一行,主要由下一跳地址和发送接口两个部分组成,当目的地址与路由表中其他行都不匹配时,就按路由条目规定的接口发送到下一跳地址。

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

四、报文分片

4.1 在接收方的角度来看待分片

我们在网络中会收到大量的IP报文,多个客户端发送的IP报文,有的报文分片了,有的报文没有分片。

4.1.1 如何确定该报文是否分片

报文没有进行分片:

我们可以根据报文中的标志位来判断该报文是否分片了,更多分片 == 0 并且 片偏移 == 0

报文进行分片:

当报文进行分片的话,报文一共有三种情况:第一片,中间片,最后一片。每一个报文分片都有一个标识,该标识是一样的。

  • 第一片:更多分片 == 1 并且 片偏移 == 0
  • 中间片:更多分片 == 1 并且 片偏移 != 0
  • 最后一片:更多分片 == 0 并且 片偏移 != 0

4.1.2 保证收到所有的分片

我们可以根据片偏移来进行组装分片,因为片偏移是升序排序的。

4.1.3 分片进行组装交付

4.2 在发送方的角度来看待分片

我们在进行分片的时候,不能简简单单地直接将报文直接进行分片,因为IP报文即使进行了分片,这个IP报文还是IP报文,所以这个IP报文还是要带上其报头。在进行计算分片报文的大小还是要加上报文的大小。

相关推荐
律宏阔4 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔4 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴4 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千5 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei375 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei375 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei375 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
GeW5 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
百万蹄蹄向前冲5 小时前
双端同步!云服务器装最新Node.js v26.10全过程追踪
服务器·人工智能·node.js
GeW5 小时前
工业场景中的Linux与数据库选型:高端化转型的技术底座
linux