Linux网络IP(下)(16)

文章目录


前言

本篇是我们 IP 篇的最后一篇了,马上就要迎来数据链路层了!!


一、网段划分

IP地址的构成

IP地址由网络号主机号两部分构成:

  • 网络号:保证相互连接的两个网段具有不同的标识
  • 主机号:同一网段内,主机之间具有相同的网络号,但是必须有不同的主机号

可以在IP地址的后面加一个 /,并在 / 后面加上一个数字,这就表示从头数到第几位为止属于网络标识,也就是网络号的意思,在这里,一个 IP32位 的地址,那么 前24位 就是属于网络号的范畴, 后面8位 就是属于主机号的标识

例如,下图中路由器连接了两个网段。对于网络标识来讲,同一网段内主机的网络标识是相同的,不同网段内主机的网络标识是不同的。而对于主机标识来讲,同一网段内主机的主机标识是不同的,不同网段内主机的主机标识是可以相同的

  • 不同的子网其实就是把网络号相同的主机放到一起
  • 如果在子网中新增一台主机,则这台主机的网络号和这个子网的网络号一致,但是主机号必须不能和子网中的其他主机重复

DHCP协议

实际手动管理 IP地址 是一个非常麻烦的事情,当子网中新增主机时需要给其分配一个 IP地址 ,当子网当中有主机断开网络时又需要将其 IP地址 进行回收,便于分配给后续新增的主机使用。

  • 因此对于 IP地址的分配和回收 一般不会手动进行,而是采用 DHCP (Dynamic Host Configuration Protocol,动态主机配置协议)技术。
  • DHCP 通常被应用在大型的局域网环境中,其主要作用就是集中地址管理、分配IP地址,使网络环境中的主机动态获得 IP地址、Gateway地址、DNS服务器地址 等信息,并能够提升地址的使用率。
  • DHCP 是一个基于 UDP 的应用层协议,一般的路由器都带有 DHCP功能 ,因此 路由器 也可以看作一个 DHCP服务器

当我们连接 WiFi 时需要输入密码,本质就是因为路由器需要验证你的账号和密码,如果验证通过,那么路由器就会给你动态分配了一个IP地址,然后你就可以基于这个IP地址进行各种上网动作了

先找目标网络,再找目标主机

当 IP 要将数据跨网络从一台主机发送到另一台主机时,其实不是直接将数据发送到了目标主机,而是先将数据发送到目标主机所在的网络,然后再将数据发送到目标主机(也就是说其实先是网络号在发挥作用,其次才是主机号)

因此数据在路由时的第一目的并不是找到目标主机,而是找到目标网络所在的网络,然后再在目标网络当中找到目标主机

数据路由时之所以不一开始就以找目标主机为目的,因为这样效率太低了,不然你想这个世界上那么多 IP ,难不成要一个一个遍历吗,想想就不可能,选择的本质也是排除,我们选择一个网络,相当于排除了其他网络的那么多IP,很显然这提高了传输的准确性和速度,总的来说就是如下:

  • 找主机的过程本质是排除的过程,如果一开始就以找目标主机为目的,那么在查找的过程中一次只能排除一个主机
  • 而如果一开始先以找目标网络为目的,那么在查找过程中就能一次排除大量和目标主机不在同一网段的主机,这样就可以大大提高检索的效率

因此,8为了提高数据路由的效率*,我们对网络进行了网段划分

网段划分

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

因此,各类 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

当要判断一个 IP地址 是属于哪一类时,只需要遍历 IP地址 的前五个比特位,第几个比特位最先出现0值,那么这个IP地址对应就属于 A、B、C、D、E 类地址(你会发现设计的真的很巧妙)

子网划分

但随着网络的飞速发展,这种划分方案的局限性很快就显现出来了。

比如一些学校、公司、实验室等组织想要申请自己的局域网,由于 A类地址 的网络号只占7个比特位,因此A类地址可申请的网络只有 2^7 个,于是大多数组织都选择申请B类地址

由于B类地址的主机号占 16个 比特位,因此理论上一个B类网络当中允许有 65536 台主机,但实际网络架设中,一般不会存在一个局域网当中有这么多主机的情况,也就意味着大量的 IP地址 实际都被浪费掉了

为了避免这种情况,于是又提出了新的划分方案

在原有的五类网络的基础上继续进行子网划分,这也就意味着需要借用主机号当中的若干位来充当网络号,此时为了区分 IP地址 中的网络号和主机号,于是引入了子网掩码(subnet mask)的概念

每一个子网都有自己的子网掩码,子网掩码实际就是一个 32位的正整数 ,通常用一串"0"来结尾

将IP地址与当前网络的子网掩码进行"按位与"操作,就能够得到当前所在网络的网络号

此时一个网络就被更细粒度的划分成了一个个更小的子网,通过不断的子网划分,子网中IP地址对应的主机号就越来越短,因此子网当中可用IP地址的个数也就越来越少,这也就避免了IP地址被大量浪费的情况

比如在某一子网中将 IP地址 的 前24位 作为网络号,那么该网络对应的 子网掩码 的 32个比特位 中的前24位就为1,剩下的8个比特位为0,将其用点分十机制表示就是 255.255.255.0

假设该子网当中有一台主机对应的 IP地址 是 192.168.128.10 ,那么将这个 IP地址 与该网络对应的子网掩码 进行"按位与"操作后得到的就是 192.168.128.0 ,这就是这个子网对应的网络号

实际在用子网掩码与子网当中主机的IP地址进行"按位与"操作时,本质就是保留了主机IP地址中前24个比特位的原貌,将剩下的8个比特位的值清0了而已 ,也就是将主机号清0了,所以"按位与"后的结果就是该网络对应的网络号

需要注意的是,子网划分不是只能进行一次,我们可以在划分出来的子网的基础上继续进行子网划分

因此一个数据在路由的时候,随着数据不断路由进入更小的子网,其网络号的位数是在不断变化的,准确来说其网络号的位数是在不断增加的,这也就意味着IP地址当中的主机号的位数在不断减少。最终当数据路由到达目标主机所在的网络时,就可以在该网络当中找到对应的目标主机并将数据交给该主机,此时该数据的路由也就结束了

一直到后面,又出现了新的划分方案叫做CIDR,全称是 Classless Inter-Domain Routing,中文翻译为无类别域间路由。

二、特殊的IP地址

并不是所有的 IP地址 都能够作为 主机的IP地址 ,有些 IP地址 本身就是具有特殊用途的。

  • 将 IP地址 中的主机地址全部设为0,就成为了网络号,代表这个局域网。
  • 将 IP地址 中的主机地址全部设为1,就成为了广播地址,用于给同一个链路中相互连接的所有主机发送数据包。
  • 127.*的IP地址用于本机环回(loop back)测试,通常是 127.0.0.1 。
    也就是说,IP地址中 主机号为全0 的代表的是当前局域网的网络号, IP地址 中 主机号为全1 的代表的是广播地址,这两个 IP地址 都是不能作为主机的 IP地址 的。因此在某个局域网中最多能存在的主机个数是 2^主机号位数 − 2

本机环回基本原理

本机环回会将数据贯穿网络协议栈,但最终并不会将数据发送到网络当中,相当于本机环回时不会将数据写到网卡上面。

本机环回的目的就是将数据自顶向下贯穿协议栈,进行一次数据封装的过程的过程,然后再自底向上贯穿协议栈,进行一次数据的解包和分用,用于测试本地的网络功能是否正常。

本机环回的基本原理:

  • 当数据到达 IP层 需要继续向下交付时,如果是环回程序,那么 IP输出函数 会将该数据放入到 IP输入队列 当中,然后再由 IP输入函数 读取上去
  • 而 IP输入函数 将数据读取上去的本应该是链路层交付上来的数据,因此该数据后续就会被当作从网络中读取上来的数据看待,各层协议会对该数据依次进行解包和分用。
  • 如果不是环回程序的话,那么接下来就会判断该数据对应的 目的IP地址 是否为 广播或多播地址 ,或者目的IP地址是否与本主机的IP地址相同,如果是则也会将该数据放入到IP输入队列当中,等待IP输入函数将其读走。
  • 只有判断程序不是环回程序,并且也不是广播或多播,或发给本主机的数据后,才会用 ARP获取 该数据目的主机的以太网地址并进行后续数据发送的操作。


而对于真正的外发,它的情况是这个样子的:

路径三:发给外部主机的数据(真正的外发)

  • 场景:你从本机访问 http://www.google.com
  • 生成数据:生成数据包,目的IP是Google服务器的IP。
  • 判断环回:不是环回地址。
  • 判断目的地:目的IP不是本机IP,也不是广播/多播地址。
  • 外部发送:此时,IP层才确认这个数据包需要真正发送出去。
  • ARP查询:通过ARP协议获取下一跳路由器或目标主机的MAC地址。
  • 网络发送:将数据封装成帧,通过物理网卡发送到外部网络。
c 复制代码
// 伪代码:IP输出函数
// 所以说本地环回最多到达网络层就结束了
int ip_output(packet) 
{
    // 检查是否是发往本机的数据
    if (packet->dst_ip == LOOPBACK || 
        packet->dst_ip == MY_IP || 
        packet->dst_ip == BROADCAST) 
        {
        
        // 内部环回:直接放入输入队列
        ip_input_queue.enqueue(packet);
        return SUCCESS; // 发送"成功",但实际没发出去
    }
    
    // 真正的外部数据:继续向下发送
    return ethernet_send(packet); // 进入数据链路层
}

三、IP地址的数量限制

IP地址数量不足问题

我们知道,IP地址(IPv4)是一个 4字节32位 的正整数,因此一共有 2^32 个 IP地址 ,也就是将近 43亿个IP地址 。但 TCP/IP协议 规定,每个主机都需要有一个 IP地址

现在全世界人口已经有70多亿了,就算有一半的人没有智能手机,算下来也有30多亿台智能手机需要IP地址。

随着科技的发展,我们使用的电脑、智能手表、智能冰箱、智能洗衣机等设备如果要入网也是需要IP地址的。

另外,IP地址并不是按照主机台数来配置的,因此一个主机可能需要多个IP地址,更别谈还有很多组网的路由设备也需要IP地址,以及一些 特殊的IP地址 不能使用的问题。

所以 43亿个IP地址 其实早就不够用了,因此才提出了 CIDR 的方案对已经划分好的五类网络继续进行子网划分,其目的就是为了 减少IP地址的浪费 ,根本原因就是IP地址本来就不够了,所以不能够再浪费了。

CIDR虽然在一定程度上缓解了 IP地址 不够用的问题,因为 CIDR提高了IP地址的利用率 ,减少了浪费,但IP地址的绝对上限并没有增加

那么如何解决呢?

  • 动态分配IP地址:只给接入网络的设备分配 IP地址 ,因此同一个 MAC地址 的设备,每次接入互联网中,得到的 IP地址 不一定是相同的,避免了 IP地址 强绑定于某一台设备。
  • NAT技术:能够让不同局域网当中同时存在两个相同的 IP地址 , NAT技术 不仅能解决 IP地址 不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。
  • IPv6: IPv6 用 16字节128位 来表示一个 IP地址 ,能够大大缓解 IP地址 不足的问题。但 IPv6 并不是 IPv4 的简单升级版,它们是互不相干的两个协议,彼此并不兼容,因此目前 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个地址。

包含在这个范围中的,都称为私网IP,其余的则称为公网IP(或全局IP)

我们连接云服务器时,连接的这个IP地址就是云服务器的公网IP地址

我们可以通过 ifconfig 命令来查看我们这台机器的 私网IP ,其中 网络接口 lo(loop) 代表的是本地环回,而 eth0 代表的就是我这台机器的网络接口,可以看到我的 私网IP地址 是 10.1.20.8

需要注意的是,这里连接云服务器时的 IP地址 119.29.74.118 ,是云服务器的 公网IP ,由于我使用的是腾讯云,因此这里的 10.1.20.8 是我这个云服务器在腾讯内部的 私网IP ,可以看到这个IP正好在 第一种私网IP范围内

我们为什么要给运营商交钱呢?

我们享受的是互联网公司提供服务,但为什么需要向运营商交钱呢?

实际网络通信的基础设施都是运营商搭建的,我们访问服务器的数据并不是直接发送到了对应的服务器,而是需要经过运营商建设的各种基站以及各种路由器,最终数据才能到达对应的服务器。

因为运营商为我们提供了通信的基础设施,所以我们交网费实际就相当于购买入网许可一样。

没有运营商提供的这些基础设施,就不会诞生所谓的互联网公司,因为互联网公司是诞生在网络通信基础之上的。

也就是说,用户上网的数据首先必须经过运营商的相关网络设备,然后才能发送到互联网公司对应的服务器。因此所谓的网段划分、子网划分等工作实际都是运营商做的。

数据是如何发送到服务器的

路由器是连接两个或多个网络的硬件设备,在路由器上有两种网络接口,分别是 LAN口 和 WAN口

(其实既然能跨网络通信,你应该也能猜到路由器是要有两个端口的)

  • LAN口(Local Area Network):表示连接本地网络的端口,主要与家庭网络中的交换机、集线器或PC相连。
  • WAN口(Wide Area Network):表示连接广域网的端口,一般指互联网。

我们将 LAN口 的 IP地址 叫做 LAN口IP ,也叫做 子网IP ,将 WAN口 的 IP地址 叫做 WAN口IPO ,也叫做 外网IP 。

我们使用的电脑、家用路由器、运营商路由器、广域网以及我们要访问的服务器之间的关系大致如下:

  • 不同的路由器,子网IP其实都是一样的(通常都是 192.168.1.1 ),子网内的 主机IP地址 不能重复,但是子网之间的 IP地址 就可以重复了
  • 每一个家用路由器,其实又作为运营商路由器的子网中的一个节点,这样的运营商路由器可能会有很多级,最外层的运营商路由器的 WAN口IP 就是一个 公网IP 了
  • 如果希望我们自己实现的服务器程序,能够在公网上被访问到,就需要把程序部署在一台具有 外网IP 的服务器上,这样的服务器可以在阿里云/腾讯云上进行购买

一旦发现数据包的 IP地址 属于私有地址范围,立即丢弃,不进行路由转发,所以 私有IP 不能在公网上出现,不然的话, IP地址 就失去了它的特性 - 全球唯一性!

现在可以用一个比喻来点出我们的 NAT 这个概念了!

其实还有个原因,那就是假如我们的主机都有公网IP了,那也就可以越过运营商了,也就不好管理你的可能非法访问网络和收费了,这也是运营商所不能接受的

两个局域网当中的主机不能不跨公网进行通信

  • 两个局域网当中的主机理论上是不能不跨公网进行通信的,因为一个主机要将数据发送给另一台主机的前提是得先知道另一台主机的 IP地址 。
  • 即便现在这个主机知道了另一台主机的IP地址,但有可能这两台主机的 IP地址 是一样的,因为它们的IP地址都是 私网IP地址 。
  • 当这一台主机发送数据时将目的IP地址填成和自己相同的 IP地址 ,操作系统就会认为这个数据就是要发给自己的,而不会向外进行发送了。

所以数据要从一个局域网发送到另一个局域网,如果不经过公网是基本上不可能的。我们在和别人聊天的时候,也不是直接将数据从一个局域网直接发送到了另一个局域网,而是先将数据经过公网发送到了服务器,然后再由服务器将数据经过公网转发到了另一个局域网。

但是凡是也都有例外,确实存在一种技术叫做内网穿透能跨公网进行局域网到局域网之间的通信

DS生成的步骤如下:
第1步:注册------告诉大家我在哪儿

  • 你(A) 和 朋友(B) 都主动给 中介(S) 打电话。

  • A -> S:"中介你好,我是A,我现在用的这个电话是 [1.1.1.1:50000]。"(1.1.1.1是公寓A的公网地址,50000是保安给你分配的临时外线号码)

  • B -> S:"中介你好,我是B,我的电话是 [2.2.2.2:60000]。"

  • 中介(S) 现在知道了:

  • A 可以通过 [1.1.1.1:50000] 联系。

  • B 可以通过 [2.2.2.2:60000] 联系。

关键点1:因为是A和B主动打给S的,所以公寓的保安(NAT)允许这个通话建立,并记录了:"从 A-101 打往 市中心广场S 的电话,以后都从这个外线号码 50000 出,并且S打回这个号码的电话要转给A-101。" 这就创建了一个临时的映射规则。

第2步:打洞------核心动作(对应图中的"打洞阶段")

  • 现在中介S要帮A和B直接建立联系了。
  • 中介S 分别告诉A和B对方的公网地址:
  • S对A说:"B在 [2.2.2.2:60000],你现在就给他打个电话。"
  • S对B说:"A在 [1.1.1.1:50000],你现在就给他打个电话。"

"探路"与"开洞":

你(A) 立刻按照S给的地址,向 [2.2.2.2:60000] 拨出电话。

这个电话到了公寓B的保安(NAT_B) 那里。保安一看:"这是个陌生号码 [1.1.1.1:50000],B-202没说要接他的电话。" 于是,保安大概率会挂断/拒绝这个电话。

但是! 这个"探路"电话极其重要!它在你自己公寓的保安(NAT_A) 那里创建了一条新的规则:"

允许从 [2.2.2.2:60000] 打回来的电话,接进来给A-101。

" 这就是 "开洞"!你主动向外喊话,相当于在你的防火墙上钻了一个指向B的、有方向的洞。

"连接"建立:

几乎在同时,你的朋友(B) 也向你的地址 [1.1.1.1:50000] 拨出了电话。

这个电话到达了公寓A的保安(NAT_A)。保安一查记录:"咦,刚刚A-101不是正要联系这个 [2.2.2.2:60000] 吗?规则已经创建好了。" 于是,保安允许这个电话通过,并转接给了A-101!

同理,在B那边也发生着类似的过程,A的探路包也为B打开了一个洞。

第三步:理解关键------为什么这样能成功?

核心诀窍:利用 NAT 的一个基本特性------"内主动,外通 "。即:只要内网设备主动向外发起过连接,NAT就会允许对应的外部主机连接回来

"打洞"的本质:就是让 A和B 互相主动地向对方的公网地址发送一个数据包。这个数据包本身可能被对方丢弃,但其真正目的是在自己的路由器上为对方"预留一个后门"。

时机非常重要:A和B必须几乎同时向对方发送"探路"包,这样才能确保当对方的包到达时,我这里的"洞"已经开好了。

五、路由

数据在路由的过程中,实际就是一跳一跳(Hop by Hop)"问路"的过程。所谓"一跳"就是数据链路层中的一个区间,具体在以太网中指从 源MAC地址 到 目的MAC地址 之间的帧传输区间

IP数据包 的传输过程中会遇到很多路由器,这些路由器会帮助数据包进行路由转发,每当数据包遇到一个路由器后,对应路由器都会查看该数据的 目的IP地址 ,并告知该数据下一跳应该往哪跳。

路由器的查找结果可能有以下三种:

路由器经过路由表查询后,得知该数据下一跳应该跳到哪一个子网

路由器经过路由表查询后,没有发现匹配的子网,此时路由器会将该数据转发给默认路由

路由器经过路由表查询后,得知该数据的目标网络就是当前所在的网络,此时路由器就会将该数据转给当前网络中对应的主机

路由表查询的具体过程

每个路由器内部会维护一个路由表,我们可以通过 route命令 查看云服务器上对应的路由表

到最后其实也就是到了局域网通信了,这个时候又到了数据链路层了,没事,我篇会跟大学再来细细讲解


总结

要到 数据链路层 喽,也就是我们 TCP/IP 四层模型的最后一层了!

相关推荐
2501_941982053 分钟前
Go 进阶:发送文件/图片消息的流程与实现
开发语言·后端·golang
2301_800256117 分钟前
第十一章中的函数解读(1)
后端·asp.net
喵爸的小作坊9 分钟前
StreamPanel:一个让 SSE 调试不再痛苦的 Chrome 插件
前端·后端·http
神奇小汤圆10 分钟前
字符串匹配算法
后端
无限大616 分钟前
为什么网站需要"域名"?——从 IP 地址到网址的演进
后端
树獭叔叔22 分钟前
LangGraph Memory 机制
后端·langchain·aigc
Empty_77722 分钟前
K8S-网络原理
网络·容器·kubernetes
Java编程爱好者25 分钟前
OpenCVSharp:了解几种特征检测
后端
爱学习的小可爱卢29 分钟前
JavaEE进阶——SpringBoot统一功能处理全解析
java·spring boot·后端·java-ee