【Linux网络】深入理解网络层:从IP协议格式,子网划分到NAT与路由机制

目录

  • 一、网络层
  • [二、IP 协议格式](#二、IP 协议格式)
    • [2.1 IP 报头字段](#2.1 IP 报头字段)
    • [2.2 IP 报文分片与组装](#2.2 IP 报文分片与组装)
  • 三、子网划分
    • [3.1 为什么要子网划分?](#3.1 为什么要子网划分?)
    • [3.2 怎么子网划分?](#3.2 怎么子网划分?)
    • [3.3 子网掩码](#3.3 子网掩码)
  • 四、私有IP和公网IP
    • [4.1 私有 IP](#4.1 私有 IP)
    • [4.2 公网 IP](#4.2 公网 IP)
    • [4.3 一张图理解](#4.3 一张图理解)
  • 五、理解公网
    • [5.1 运营商](#5.1 运营商)
    • [5.2 公网](#5.2 公网)
    • [5.3 NAT技术](#5.3 NAT技术)
  • 六、路由

一、网络层

网络层是计算机网络体系结构的第三层(OSI七层模型和TCP/IP 五层协议)。

网络层主要为了实现异构网络,统一互联 ,并为数据包在源主机和目的主机之间选择最佳的传输路径

二、IP 协议格式

IP 协议是网络层最重要的协议,负责将数据包跨网络从主机A 传输到主机B。

IP 协议如何完成数据传输,就必须弄懂IP 的协议格式。

c 复制代码
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
    __u8    ihl:4,          /* 首部长度,单位4字节,最小5 */
            version:4;      /* IP版本,IPv4为4 */
#elif defined (__BIG_ENDIAN_BITFIELD)
    __u8    version:4,      /* IP版本 */
            ihl:4;          /* 首部长度 */
#else
#error  "Please fix <asm/byteorder.h>"
#endif
    __u8    tos;            /* 服务类型 (Type of Service) */
    __be16  tot_len;        /* 总长度 (整个IP包长度,字节) */
    __be16  id;             /* 标识符,用于分片重组 */
    __be16  frag_off;       /* 分片偏移和标志 (DF, MF等) */
    __u8    ttl;            /* 生存时间 (Time To Live) */
    __u8    protocol;       /* 上层协议 (如TCP=6, UDP=17) */
    __be16  check;          /* 首部校验和 */
    __be32  saddr;          /* 源IP地址 */
    __be32  daddr;          /* 目的IP地址 */
    /* 选项字段开始,长度可变,由ihl决定 */
};

2.1 IP 报头字段

(1)4位版本

指明IP 协议的版本:IPv4IPv6。4即IPv4,6即IPv6。

(2)4位首部长度

IP 协议与TCP 协议的报头部分相同,由定长的20字节和选项组成。报头长度 = 4位首部长度 * 4(4位代表0 ~ 15,即 0 ~ 60,定长为20,则报头大小 20,60)。

(3)8位服务类型

(4)16位总长度

IP 报文的大小。

(5)8位生存时间

网络的拓扑结构已经非常复杂了,如果路由器的路由表配置错误或者发生回环,一个IP 数据包就可能会在几个路由器之间来回"循环 "打转。

这些无法到达目的地的报文会一直在网络中占用带宽和路由器资源,最终导致网络拥塞崩溃。所以,设置一个生存时间,一旦时间耗尽,路由器就会将数据包丢掉。

(6)8位协议

标识上层的协议类型:TCP ,UDP等,告诉目的主机的网络层,这个IP 数据包的"有效载荷"部分装的是什么上层协议的数据,从而交由哪个协议模块处理。

(7)16位首部校验和

检测IP 数据报首部在网络传输过程中是否发生了错误(如比特位翻转,数据损坏)。

(8)32位 源/目的IP

标识发送端和接收端。

IP 协议如何完成报头和有效载荷的分离和分用?

  • 分离:4位首部长度。
  • 分用:8位协议。

2.2 IP 报文分片与组装

还剩下中间三个字段,用于IP 报文的分片与组装。为什么要对IP报文进行分片呢?

数据链路层规定:IP 报文长度不能超过1500字节(MTU)

当IP 报文长度超过1500字节,网络层就需要对报文分片。属于该报文的16位标识字段相同,即未来接收端根据16位标识就能判断哪些分片属于一个报文。

三位标志

  • 第一位保留(保留的意思是现在不用,但是还没想好说不定以后要用到)。
  • 第二位置为1表示禁止分片,这时候如果报文长度超过MTU,IP模块就会丢弃报文。
  • 第三位MF标志:表示"更多分片",如果分片了的话,最后一个分片置为0,其他是1。类似于一个结束标记。

13位片偏移 :标识当前分片的有效载荷在原始未分片IP 数据包有效载荷中的相对起始位置,即计算片偏移时,不考虑IP 报头长度。

片偏移的单位是8字节,因为IP 报文的最大长度为16位( 2^16 - 1 = 65536字节),而片偏移只有13位,所以让13位片偏移乘以8表示实际偏移量。

假设一台主机需要发送 3800 字节的数据载荷,加上 20 字节固定 IP 报头,总长为 3820 字节。通过 MTU = 1500 字节的以太网链路(最大可承载数据载荷为 1500 - 20 = 1480 字节)时,分片过程如下:

分片序号 有效载荷范围 载荷长度 MF标志 片偏移
分片1 0~1479 1480 1 0/8=0
分片2 1480~2959 1480 1 1480/8=185
分片3 2960~3799 840 0 2960/8=370

(1)怎么判断报文分片了?

如果接收到的IP 报文MF = 1,即表明该报文后面还有分片,即该报文是分片;即使MF = 0,片偏移不为零也可以判断是分片。

(2)如何组装?

首先,根据16位标识判断分片是否属于同一个报文;然后,根据MF + 片偏移排序拼接(按顺序放到接收缓冲区)。

(3)分片多了好吗?

显然,分片多了,丢包概率增加(如果接收方发现分片丢了,就会将其他分片丢掉,发送方收不到ACK,就会超时重传整个报文)。

现在就理解了,为什么在滑动窗口中要将数据划分位一段一段发送,即控制TCP报文长度不超过1500 - 20(IP报头无选项)= 1480字节。


三、子网划分

3.1 为什么要子网划分?

先讲一个故事:张三捡到一个钱包,钱包里只有一个只能看清楚学号的学生证,怎么快速把钱包还给失主。

背景:学校设计了学号(院号+专业号+班级),所以通过学号可以找到快速定位到每一个学生。

张三捡到钱包,把这个人的学号发送到自己的院群,学生会主席发现学号开头是06,肯定不是本学院的,所以学生会主席把学号转发到校群,机械学院学生会主席发现这是自己学院的,于是将学号转发到自己学院,李四立马发现是自己的钱包找到了。

如果没有将学号按照学院+专业+班级这样设计,而是对每个学生进行依次编号,那么张三再要把钱包还给李四,就需要找人一个一个的问:"你的学号是不是06321"。

张三和李四就像两台主机,主机A想把报文交给主机B。IP 让主机A能够找到主机B,子网划分就类似于划分学院,带上唯一编号,这样在进行查找时就能够更快的淘汰其他主机,缩小查找范围,大大提高了查找的效率。


3.2 怎么子网划分?

IP 由网络号和主机号构成

  • 同一个子网中网络号相同,不同子网的网络号不同。
  • 同一个子网中主机号不同,不同子网的主机号可能相同。

子网划分是本质就是在32位IP 中划分网络号

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

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

那么对于不同的子网,如何互相连通呢?

由路由器进行连接,所以一个路由器至少有两个IP:

  • WAN 口IP:即外网IP,面向运营商。
  • LAN 口IP:即内网IP,面向局域网。

3.3 子网掩码

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

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

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

所以,引入了子网掩码。

  • 子网掩码是一个正整数,前一部分全1,后一部分全零;
  • 子网掩码与IP 按位与之后得到网络号;

通过子网掩码就可以灵活的控制网络号,避免了浪费IP。当子网主机较多就可以设置子网掩码小一点,反之就可以将子网掩码设置大一点。

子网掩码能不能解决IP不足的问题?

子网掩码本质是提高了IP的利用率,所以可以缓解IP不足的压力,但不能增加IP的数量。


四、私有IP和公网IP

公网 IP 是互联网上的"全球唯一身份证",用于在公网上标识一台设备;而 私有 IP(内网 IP)是局域网内部使用的"私有编号",专门用于局域网内部设备之间的通信。

4.1 私有 IP

为了避免 IPv4 地址过快枯竭,RFC 1918 规范专门划出了三段地址作为私有 IP 地址空间。任何组织和个人都可以无须申请、免费在局域网内部使用这些网段:

  • A 类私有地址:10.0.0.0 ~ 10.255.255.255掩码 /8,常用于大型企业网、云厂商 VPC 内部网络)

  • B 类私有地址:172.16.0.0 ~ 172.31.255.255掩码 /12,常用于中型企业或 Docker 容器网络)

  • C 类私有地址:192.168.0.0 ~ 192.168.255.255掩码 /16,最常见于家庭及小型办公室路由器)

主要特点:

  • 可重复使用 :不同局域网(例如你家和邻居家)可以同时使用同一个私有 IP(如 192.168.1.100),彼此独立互不干扰 ,所以通过这种方式就可以解决IP 不足的问题

  • 公网不可直接路由:互联网上的骨干路由器会自动丢弃源或目的地址为私有 IP 的数据包,外部设备无法直接访问局域网内的私有 IP。

  • 免费且本地管理:由本地路由器通过 DHCP 协议自动分配,不收取费用。

4.2 公网 IP

除了私有地址段以及特定用途的保留地址(如环回地址 127.0.0.1、链路本地地址 169.254.x.x)外,其余的合法 IPv4 地址都属于公网 IP。

主要特点:

  • 全球唯一:在同一个时间点,全球互联网中绝不会有两台设备拥有相同的公网 IP。

  • 公网直接可达:只要拥有公网 IP 并在对应的端口上监听,互联网上的任意设备均可以直接发起连接。

  • 统一规划与收费:由国际机构(IANA/APNIC)统一分配给宽带运营商(ISP)或云服务商,用户通过按月/按年付费来获取(如家用宽带分配的动态公网 IP,或云服务器租用的固定公网 IP)。

4.3 一张图理解

  • 路由器连接内网与外网,LAN 口IP 对内,WAN 口IP 对外。
  • 路由过程中,子网IP 不能出现在公网上,所以在内网转发时会将子网IP替换位路由器的WAN 口IP(NAT 技术)。
  • 我们在日常中接触到的都是子网IP,即路由器分配的IP。
  • 报文经过出入口路由器转发之后进入公网。

五、理解公网

5.1 运营商

运营商负责铺设,维护覆盖全球的通信网络,并为个人与企业提供数据传输通道。

以物流系统为例:运营商不仅修筑高速公路(骨干光缆)和村村通道路(小区光纤/基站),还负责调度与转运每一个"数据包裹",确保它们准确送达。

运营商层级结构:

以运营商网络与用户个人网络的分界点划分私网与公网:

  • 公网:包括骨干网、城域网以及接入网(运营商侧)。这是由运营商建设、维护并向公众提供开放数据传输能力的公共互联网。公网上的节点使用全球唯一的公网 IP 地址进行路由和通信。
  • 私网(局域网):即用户自建的内部网络,如家用路由器,公司内网。

以家用路由器为例:

  • 路由器的 WAN 口以外(外网): 连接运营商基站、OLT 光纤节点、城域网及骨干网,属于公网。

  • 路由器的 LAN 口以内(内网): 连接手机、电脑、电视等终端设备,属于私网(通常分配 192.168.X.X 或 10.X.X.X 这类私网 IP,通过 NAT 地址转换技术共享一个公网 IP 上网)。

假如今天你要发送应该请求到抖音的服务器,源IP为192.168.1.201(子网掩码前24位为1),目的IP 为122.77.241.3(子网掩码前24位为1)。

路由器在进行路由时,目的IP 按位与子网掩码得到网络号为 122.77.241,自己所在内网网络号为192.168.1,对比发现不同,则直接通过家用路由器转发给出入口路由器(运营商),同时将源IP 替换为路由器WAN 口IP(NAT);然后出入口路由器再次NAT,并将请求在公网路由到抖音服务器。


5.2 公网

公网即运营商建设、维护并向公众提供开放数据传输能力的公共互联网。公网上的节点使用全球唯一的公网 IP 地址进行路由和通信。

拥有公网IP 的设备可以直接跨地域进行通信,因为公网上的主干路由器维护这完整的公网路由表。

5.3 NAT技术

NAT(网络地址转化)技术:在内网访问外网时替换的是 IP 报头的源 IP 地址(SNAT),而在外网返回响应数据时,替换对应目的 IP 地址(DNAT)。

同一个内网中不同的局域网中的主机最终在转发到外网时,都用的是出入口路由器的WAN 口IP,所以,即使IP 相同也没事。即NAT 是解决IP地址不够用的手段之一,是路由器的一个重要功能。

在绝大多数常见的网络环境中,NAT 还包含了传输层端口号的修改(称为NAPT 网络地址端口转换)

今天西安的一个客户端(内网IP192.168.1.200:54321)与河北的服务器(公网IP 122.77.241.88:80)建立连接并通信:

客户端发送请求到服务端:

c 复制代码
[西安客户端] Source: 192.168.1.200:54321  | Destination: 122.77.241.88:80
     │ (经过西安家用路由器 SNAT)
     ▼
[运营商内网] Source: 10.1.1.2:60001       | Destination: 122.77.241.88:80
     │ (经过西安运营商路由器 SNAT)
     ▼
[城域网/骨干网] Source: 122.77.241.4:40001   | Destination: 122.77.241.88:80
     │ (骨干网 5.1.0.1 -> 5.5.0.1 路由转发,IP 保持不变)
     ▼
[河北出口网关] Source: 122.77.241.4:40001   | Destination: 122.77.241.88:80
     │ (经过河北出口路由器 DNAT)
     ▼
[河北服务器] Source: 122.77.241.4:40001   | Destination: 192.168.1.100:80

响应包反向回传客户端:

cpp 复制代码
 服务器发包:源: 192.168.1.100:80 目的: 122.77.241.4:40001 

河北出口 SNAT:转换为 源: 122.77.241.88:80 目的: 122.77.241.4:40001 

公网路由回传:从河北(5.5.0.1)通过骨干网路由回西安出口(122.77.241.4) 

西安两级 DNAT:反向还原为 10.1.1.2:60001 -> 192.168.1.200:54321,最终送达西安客户端 
  • 每次先将目的IP 和子网掩码进行按位与得到网络号,确定下一跳应该到哪个网段;
  • 经过路由器路由时如果IP 报头源IP为内网IP则替换为WAN 口IP,通常也会替换TCP/UDP 报头的端口号,同时建立映射关系(NAT 映射表)。
  • NATAT路由器将源地址从10.0.0.10替换成全局的IP 202.244.174.37
  • NATAT路由器收到外部的数据时, 又会把目标IP从202.244.174.37替换回10.0.0.10
  • 在NATAT路由器内部,有一张自动生成的,用于地址转换的表;
  • 10.0.0.10 第一次向 163.221.120.9 发送数据时就会生成表中的映射关系;

NAPT IP/Port转换:

如果局域网内,有多个主机都访问同一个外网服务器,那么对于服务器返回的数据中,目的IP都是相同的。此时NAT路由器不能判定将这个数据包转发给哪个局域网的主机?

NAPT就可以解决这个问题,使用 IP + port 来建立这个关联关系(NAPT 映射表)。

六、路由

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

路由器连接两个局域网,路由就是从局部到跨网络通信,每个路由器都会维护一张路由表,根据 IP报头的目的 IP 按位与 子网掩码得到目的网段的网络号,然后查路由表决定下一跳到哪个网段,依次类推,找到找到目的主机。

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

Interface(出接口)

含义: 路由器是依靠哪个物理或逻辑网卡(接口)把数据包发送出去的。

  • eth0 (WAN):路由器的外网口(广域网接口)。

  • vlan10 (LAN):路由器的内网口(局域网接口),通过 VLAN 虚拟出来的接口。

  • lo:本地环回接口(Loopback),数据包只会绕回到设备自身。

最后一项即缺省路由。

到这里网络层的讲解就结束了!

目前我们已经知道如何通过 IP进行路由,而怎么把报文交给路由器,以及目的主机,就需要数据链路层出手,下一篇我们就彻底弄清楚报文如何被送达目的主机。

相关推荐
zho_uzhou1 小时前
ubuntu服务端运行vue网页步骤
linux·服务器·vue.js·ubuntu
ltl10 小时前
纠删码原理与存储效率
linux
ltl10 小时前
MinIO 原理和架构:机制、AGPL 与上游 archived 风险
linux
林浩杨_10 小时前
linux搜索命令(grep+sed)
linux·命令模式
W.W.H.11 小时前
将驱动编译成模块并安装到rootfs
linux·物联网·wifi·rootfs·驱动
ltl11 小时前
io_uring 在生产环境翻车实录:内核 bug、资源泄漏和你不知道的限制
linux
ltl11 小时前
内存分配器擂台:jemalloc vs tcmalloc vs mimalloc vs glibc
linux
ltl11 小时前
Zero Copy 的肮脏秘密:在什么时候反而更慢
linux
数据知道11 小时前
宽字节注入、二次注入、堆叠注入:高级 SQLi 专题
linux·运维·安全·网络安全