OSI 七层模型简单理解

这篇文章是以现代计算机网络硬件为基础编写的,主要介绍了现代硬件环境下应该了解的网络知识,能够为网络编程打下一个较好的基础。

第一次接触不一定能理解全部内容,但当你对网络编程有一定了解后,也可以回来再看看?

物理层

  • 这一层是电子信息系的事,不是计算机系的事。

  • 这一层可以实现在两台设备间不稳定的传输数据

  • 这一层数据传输的基本单位是 bit。

数据链路层

这一层的主要设备是交换机。

多台主机和交换机,网线构成了一个 LAN。

数据单位

数据层的数据传输单位是 Frame (帧),帧包括帧头,帧体,帧尾,帧头包括数据 src 和 dst 的 MAC 地址,帧尾包含一些校验信息。

数据链路层保证了 LAN 中数据传输的可靠性。

以其中一种机制为例:

  • 发送方在发送帧的时候,会等待一个 ACK 确认,如果没有等到 ACK 确认,则会重传该帧,直到所有数据帧得到 ACK 确认时结束传输。
  • 接收方会根据帧尾的校验信息确认帧体数据无误,无误后发送 ACK 确认。

交换机功能

数据链路层中,每台设备具有唯一 MAC 地址(这是出厂时烧在网卡上的唯一标识)。

交换机主要用于根据数据帧的 MAC 地址在主机间正确转发数据帧。

MAC 地址学习

交换机有若干个口可以插,如果可能,交换机收到数据后,只会往目标 MAC 的那个端口发。

如果交换机没记录目标 MAC 的端口,则会进行依次广播,根据 ACK 机制,在目标计算机回传 ACK 包时,记录这条信息,并将 MAC 对应上。

这是大部分交换机采用的策略。

当然,有更加复杂的机制来处理诸如 "把 1 口的线转插到 2 口" 这种事。

一个端口能对应多个 MAC 地址,所以你把交换机和交换机插在一起,也能正常组网。

网络层

网络层的主要设备是路由器(Router),主要协议是 IP 协议

数据链路层组网完毕后,形成一个 LAN,通过路由器,可以将若干个 LAN 连接成一个更大的 LAN。

我们说的 Internet,就是一个世界范围的 LAN。

MAN、WAN 本质都是 LAN,只是规模不同。

IP 协议

公网 IP 和私网 IP

公网IP地址(Public IP Address)是指在全球互联网范围内可以直接访问的IP地址。这些地址是唯一的。

众所周知,公网 IP 是从 0.0.0.0255.255.255.255 的,其中有三段不会被分配,可以用于建立子网

  • 10.0.0.0 - 10.255.255.255,又记作 10.0.0.0/8
  • 172.16.0.0 - 172.31.255.255,又记作 172.16.0.0/12
  • 192.168.0.0 - 192.168.255.255,又记作 192.168.0.0/16

后面那个数字指前缀长度

一般的电脑是没有公网 IP 的,所以不能直接在互联网上被访问。

但是你能 ipconfig/ifconfig 出来一个 IP 地址,注意观察的话:

  • 以你车的校园网为例,它采用了 10.0.0.0/8 这个区段,大概能支持 \(1.6\times10^7\) 个设备,对你车来说是够用了。

  • 以你家的无线网为例,它采用了 192.168.0.0/16 这个区段,大概能支持 \(6.5\times 10^4\) 个设备,对你家来说是够用了。

IP 协议的特点

  • 无连接:IP协议是无连接的,即它不需要在发送数据前建立连接。给个 IP 地址,IP 协议就能尝试去把数据发过去。
  • 尽力而为的传输:IP协议只负责将数据报发送到目的地,但不保证数据的顺序、完整性或可靠性。数据丢失、重复或乱序需要由上层协议处理。

IP 协议可达性

两台机子能够使用 IP 协议相互通信当且仅当:

  • 两台机子处于同一子网下
  • 两台机子都拥有公网 IP。

没有特殊说明,后面的讨论中,默认是以上两种情况。

注意这里的限定,平时你的机子和百度通信,你是没有公网 IP 的,和百度也不在一个子网下,这个时候你们就不是用 IP 协议直接通信的,而是有更复杂的机制。

子网划分

实际应用过程中,会对子网做更细一步的划分。

不过要注意,在第一次的划分中,所有的 IPV4 地址被保留了三段作为私有地址,这三段私有地址可以被多个子网使用。

也就是说,在整个 Internet 中,可以有多个子网 S1, S2, S3....,它们都使用同一段私有地址。(例如你家和小明家宽带都用的 192.168.0.0(16) 这一段)

但是,对子网的下一步划分,就无法多次使用同一段了,这个层次的划分局限于将子网的私有地址分成若干块,每一个小子网得到一块。不同的小子网无法使用同一个 IP。

当然,小子网可以继续做划分。

最后,有一个子网中的所有设备都被数据链路层(交换机和以太网线)连接起来了,如果两台设备处于这样一个子网中,我们称这两个设备相邻。有时候相邻会和处于同一子网中混淆。

子网掩码

子网掩码用于判断两个 IP 地址是否处于同一个子网(不是指相邻)。

上文介绍了一个复杂的子网划分机制,子网掩码用于判断两个 IP 地址是否处于同一子网。

例如,有子网 A,B,C,其中 B,C 是 A 子网划分出来的两个子网,其中

  • A
    • IP 段:192.168.0.0/16
    • 子网掩码:255.255.0.0
  • B
    • IP 段:192.168.1.0/24
    • 子网掩码:255.255.255.0
  • C
    • IP 段:192.168.2.0/24
    • 子网掩码:255.255.255.0

那么,对于 M1:192.168.2.16,M2:192.168.1.16,M3:192.168.1.17 三台机器来说,在子网 A 处,M1,M2,M3 处于同一子网,但在子网 B,C 处,M1 和 M2 不处于同一子网。

一般的子网掩码的低若干位是 0,IP 和子网掩码按位与,结果相同则处于同一子网。

主机发送数据包时,根据目标 IP 地址和子网掩码计算是否处于同一子网,如果处于同一子网,则直接走数据链路层发送过去。

默认网关

一个子网一般只有一个默认网关,这个默认网关一般就是路由器,路由器的有关知识会在下一部分讲到。

如果你用 "网络属性" 去看过 IPV4 地址协议,就会看到这个选项是和子网掩码在一起的。

  • 默认网关和路由器:路由器负责处理不同子网之间的通信,它的每个槽接入的是不同的子网。如果 IP 协议发送的数据的目标 IP 不在同一子网,则会发往默认网关,默认网关再来处理这个数据,将它发往正确的地方。
  • 自动 DHCP:现在一般不用手动去设置默认网关、IP 地址、子网掩码,都是采用 "自动DHCP" 方式自动分配。

路由

ARP 协议

ARP 协议的工作范围是子网,以下场景均发生在同一子网内。

ARP 协议是介于数据链路层和网络层之间的协议,用于通过 IP 地址查询 MAC 地址。

IP 协议的数据包是对数据链路层的数据包外面包了一个,但是有个问题。IP 协议的标准是:知道 IP 就能尝试发过去。但是数据链路层的包里是需要包括 MAC 地址的,那我不知道 MAC 地址怎么办?

这个时候需要 ARP 发挥作用,在不知道 MAC 地址时,主机会发送一次 ARP 广播,查询目标 IP 对应的 MAC 地址,目标主机收到查询后(查询中包含源主机的 MAC),会向源主机发送一次回复,源主机得到对应的 MAC 地址。

交换机如何处理 ARP 广播:广播类消息的 MAC 会设置为泛洪帧,即FF:FF:FF:FF:FF:FF),交换机会将该帧从除接收端口以外的所有端口发送出去,以便局域网内的所有设备都能收到。

路由器

IP 协议的关键是可以在不同子网中通信,路由器是实现不同子网通信的关键设备。一个子网要和其它子网连接,则必须为子网配置路由器。

一般来说,一个路由器会属于两个以上的子网,可以成为多个子网的默认网关。

路由器拥有一个 IP 地址,路由器的每个插槽有一个独立的 MAC 地址。

ARP 协议在路由器上的实现

  • 为什么 ARP 的工作范围是子网?

    进行 ARP 广播时,如果 IP 不在该子网内,路由器会返回接入该子网端口的 MAC。

    这样会为子网中的设备提供一个数据链路层的假象:所有的子网外设备的 MAC 地址均是网关设备的 MAC,这个假象会对网络系统的设计带来巨大的便利。

    这里 IP 是否在子网内是由默认网关(路由器判断的),因此,默认网关也需要配置子网掩码。

  • 这样搞不会导致数据包到了目标子网后 MAC 出错吗?

    MAC 在数据链路层中发挥作用,也就是说 MAC 地址仅仅负责一个子网中的通信。数据经过默认网关(路由器)发向其它子网时,会改动数据中的 MAC 地址,将其改为发送槽的 MAC。

    不妨假设两个子网的路由器位于同一子网,这样可以将数据包准确的发送到对应子网(路由器处)去,路由器再通过 ARP 协议查询子网中对应 IP 的 MAC 并修改然后发过去。

路由表

"路由" 是指数据包从源设备到目标设备传输路径选择的过程

子网外的数据发到路由器后,路由器需要选择一个端口发过去。可能有很多种从子网 S1 到子网 S2 的路径,路由的作用就是去选择一条最好的路径。

路由器通过路由表查找最佳的端口选择,路由表并不是一张表,而是一组策略的集合,通过路由表中的策略和目标 IP 来确定数据走哪个端口。

路由的方式主要有三种:

  • 直连路由:和路由器直接连接的其它路由器与路由器所在的(若干个)子网存在直接路由,也就是可以直接找到这些对象的 IP 地址。
  • 静态路由:人工配置的 IP/IP段 应该走的端口。
  • 动态路由:路由器之间通过一些算法交换自己的直连路由信息,动态构建路由表。
  • 默认路由:以上规则失效时,走一个默认的端口(通常指向上级路由器,常见于家庭路由器)

我们接触和使用的路由器网络很简单,仅通过动态路由的方式就能完美实现局部的路由。

网络服务商所用的路由器连接结构非常复杂,要处理广域的 IP 路由,往往需要大型计算机的支持。

现代无线路由器

现代无线路由器有自组网的功能。

路由器的几个端口同时也具备交换机的功能,它一般能自动判断一个插槽到底接入的是一个子网还是一个数据链路层对象,如果是后者,这个插槽将发挥交换机的作用。

一个示例

网络拓扑结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
子网1:192.168.1.0/24  
|
[路由器](接口1:192.168.1.1,接口2:192.168.2.1)
|
子网2:192.168.2.0/24

子网1设备:
- 交换机1(无需IP)
- PC1:192.168.1.10/24,网关192.168.1.1
- PC2:192.168.1.20/24,网关192.168.1.1

子网2设备:
- 交换机2(无需IP)
- PC3:192.168.2.10/24,网关192.168.2.1
- PC4:192.168.2.20/24,网关192.168.2.1
  1. 路由器
    • 接口1(连接子网1):IP 192.168.1.1,子网掩码 255.255.255.0
    • 接口2(连接子网2):IP 192.168.2.1,子网掩码 255.255.255.0
    • 路由表自动包含直连网络 192.168.1.0/24192.168.2.0/24
  2. 交换机1和交换机2
    • 仅作为二层设备,根据MAC地址转发数据帧,无需配置IP。
  3. 终端设备
    • PC1/PC2的子网掩码为 255.255.255.0,网关指向路由器的 192.168.1.1
    • PC3/PC4的子网掩码为 255.255.255.0,网关指向路由器的 192.168.2.1

PC1 到 PC3 的通信示例如下:

  1. 判断目标子网 PC1(192.168.1.10)检查目标IP 192.168.2.10,发现不在同一子网(通过子网掩码计算)。
  2. 发送到默认网关
    • PC1将数据包的目标MAC地址设置为路由器接口1的MAC地址(通过ARP协议获取)。
    • 数据包通过交换机1转发到路由器的接口1。
  3. 路由器处理
    • 路由器解封装数据包,检查目标IP 192.168.2.10 和路由表,发现属于直连子网2。
    • 将数据包从接口2(192.168.2.1)转发到子网2。
  4. 子网2内传输
    • 路由器通过 ARP 获取 PC3 的 MAC 地址(若缓存中无记录)。
    • 数据包目标 MAC 改为 PC3 的 MAC,通过交换机2转发到PC3。
  5. 响应返回 PC3 的响应数据包反向执行相同流程,通过路由器回到 PC1。

NAT

本科期间任何一本教科书都不会教你 NAT 相关的知识,但现在这个年头不懂 NAT 是很难做好网络编程的。

NAT 能干什么

  • 地址转换

    NAT 设备的主要功能是将一个 IP 地址空间中的地址转换为另一个地址空间中的地址。例如,它可以把私有IP地址(如192.168.x.x)转换为公网IP地址,或者将公网 IP 地址转换为私有 IP 地址。

    • 这个操作常用于让子网中没有公网 IP 的设备能够访问公网。例如,你的计算机通过通信服务商的 NAT 设备访问各种公网网站。
    • 也可以用于进一步拓展子网可用 IP,例如通过保留私有 IP 组了一个公网下的一级子网,一级子网向你的二级子网分配了少量 IP 地址,然后你发现这些 IP 地址不够用,于是可以在你的二级子网配置一个 NAT 设备,二级子网内部采用更大的地址空间,和一级子网通信时采用 NAT ,就像一级子网和公网通信那样。这种 NAT 也被称为多层 NAT
  • 隐藏内部网络

    NAT 可以隐藏内部网络的拓扑结构和设备 IP 地址,增强网络的安全性。

    事实上你裸奔的电脑没遭到黑客的攻击就是 NAT 在默默守护。

NAT 怎么布置

NAT 设备一般布置在出口网关处(其实出口网关大部分时候是默认网关),NAT 发挥地址转换作用

NAT 的分类和原理

NAT 主要有三种:

  1. 静态 NAT(Static NAT)

    原理:将内部网络中的每个私网 IP 地址与一个固定的公网 IP 地址进行一对一的映射。这种映射关系是预先配置好的,不会随着时间或网络连接的变化而改变。

  2. 动态 NAT(Dynamic NAT)

    原理:将内部私网 IP 地址动态地映射到一组公网 IP 地址池中的地址。当内部设备有访问外部网络的需求时,NAT 设备从公网 IP 地址池中选择一个可用的公网 IP 地址,并建立私网地址和公网地址的映射关系。这种映射关系在一定时间内有效,当连接结束或超时后,映射关系被释放,公网 IP 地址可以重新分配给其他内部设备。

  3. PAT(Port Address Translation,端口地址转换)

    原理:允许多个内网设备共享一个公网 IP 地址,通过不同的端口号来区分不同的内网设备。当内网设备发送数据到外网时,NAT 设备会将数据包的源 IP 地址转换为公网 IP 地址,并分配一个未使用的端口号。返回的数据包通过端口号来确定目标内网设备。它是日常中最常见的 NAT 方式,有效地解决了 IPv4 地址不足的问题,适用于家庭和小型企业网络。

NAT 穿透

NAT 很好,但是有时候你期望你的电脑能够在公网上被访问。(例如开 MC 服务器时)

由于你的电脑并没有公网 IP,所有的网络通信都是通过 NAT 完成的,所以你的电脑无法被外部直接访问,这时候我们就需要 NAT 穿透来完成间接访问。

  • Q:我用 IP 工具可以查到我电脑公网 IP 呀?为什么不能用这个 IP。

  • A:首先这个 IP 是动态分配的,随时可能会变,其次运营商有运营商的安全考虑,不允许外部通过 NAT 开放的端口主动建立连接。

    你打游戏时看上去是服务器向你请求数据,实际上这个过程是会话层实现的,主动建立会话的是你。

以下是常用的 NAT 穿透的方法:

  • 内网穿透:一般情况这是唯一能用的方法。
  • UDP/TCP 打洞:一般用不了。

AP 隔离

有时候不希望同一子网的设备能够相互访问,这个时候可以开启 AP 隔离。

AP 隔离在数据链路层上丢弃访问子网内设备相互访问的数据包(与默认网关的除外),来禁止子网设备相互访问。

一般来说,AP 隔离是在无线路由器上开启的,但是 AP 隔离是一个数据链路层的操作,为什么会这样呢?

我们前面提到了现代无线路由器其实既是网络层设备,又是数据链路层设备和物理层设备,所以一般会在这里操作。

因此,如果两台计算机在子网中直接用物理层设备连接(以太网线),这种 AP 隔离是不生效的。

又一个示例

你车的计算机楼开启了 AP 隔离,计算机楼的设备之间无法通过内网相互通信。

但你车校园网整体是一个子网,计算机楼是进一步划分的子网,宿舍楼开的服务器不在计算楼子网内,没有开启 AP 隔离,可以通过子网访问。

所以出现了:计算机楼可以访问宿舍楼的服务器,但是别的地方无法访问计算机楼的服务器。

事实上这个问题在帆软杯的时候出现过,我们把服务器搬到宿舍楼后就能正常访问了。

闲话

  • 路由器和交换机都很便宜,几十块钱就能买一个,网线就更便宜了,可以试着自己买点回来组网。
  • 网络层是 OSI 七层中最复杂的一层,后面没有这么难了。
  • 校园网这个环境特别适合开展网络实践,可以多自己动手试一试。

传输层

传输层的主要目的是在源节点和目的节点的应用程序之间建立、维护和终止端到端的通信连接。

平日用到的端口,就是传输层的概念。

UDP 协议

UDP 协议是一种无连接的、不可靠的、基于数据报的传输层协议。它在数据传输前不需要建立连接,传输效率较高,但不提供可靠的数据传输保证,适用于对实时性要求较高但对数据丢失不太敏感的应用,如视频直播、在线游戏、DNS 查询等。

它和 IP 协议的区别就是它支持端口(port)号了,而 IP 协议的传输中不涉及端口。

UDP 协议本质就是在 IP 协议数据包再简单套了 UDP 头部,包含端口信息。

TCP 协议

TCP 协议是一种面向连接的、可靠的、基于字节流的传输层协议。它在数据传输前需要建立连接,传输过程中提供可靠的数据传输和流量控制等服务,适用于对数据传输可靠性要求较高的应用。

下面是老生常谈的三次握手和四次挥手。

连接管理机制

  • 第一次握手 :客户端向服务器端发送一个包含 SYN 标志位的 TCP 段,请求建立连接。
  • 第二次握手 :服务器端收到客户端的 SYN 包后,如果同意建立连接,就发送一个包含 SYN 和 ACK 标志位的 TCP 段作为回应,其中 ACK 对客户端的 SYN 进行确认,同时发送自己的 SYN 来请求客户端对自己的连接进行确认。
  • 第三次握手 :客户端收到服务器端的 SYN + ACK 后,再发送一个 ACK 包作为确认,从而完成三次握手过程,建立起可靠的 TCP 连接。

数据传输机制

  • 可靠传输 :采用 “确认应答机制”(ACK),发送方在发送完数据后,会等待接收方的确认应答信号。如果在规定的时间内没有收到确认应答,发送方会重新发送数据。
  • 按序传输 :发送方将数据分割成多个小的分组(数据段),为每个数据段分配一个唯一的序列号,接收方根据序列号重新组装接收到的分组,确保数据按照正确的顺序传输。
  • 流量控制 :通过滑动窗口机制来控制数据的传输速率。发送方会维护一个发送窗口,表示可以连续发送而无需等待应答的字节的数量。接收方则通过通知窗口的大小(窗口通告)来告知发送方当前的接收能力,发送方根据接收方的通告调整发送窗口的大小,避免发送过快导致接收方无法处理而丢弃数据,从而实现流量控制。

拥塞控制机制

  • 慢启动 :在一开始的时候,发送方将发送窗口的大小设置为一个较小的数值(由慢启动门限值决定),然后随着每收到一个确认应答增量增加发送窗口,以快速探测网络能够支持的传输速率。
  • 拥塞避免 :当发送窗口增加到慢启动门限值时,改为按线性规律缓慢增加发送窗口,即每次收到一个确认应答时,以加法的方式(如每次增加 1 个基本单位)增大发送窗口,使得网络处于一种比较平稳的状态,防止网络拥塞突然发生。
  • 快重传 :当发送方连续收到三个重复的确认应答(接收方通过发送重复的 ACK 来告知中间某个数据段已经丢失),就立即重传对方尚未收到的数据段,而不是等待超时定时器溢出,这样可以快速恢复通信过程。
  • 快恢复 :在执行快重传后,发送方假设网络现在有一些拥塞,因此需要将慢启动门限值减少到当前发送窗口大小的一半,并且将发送窗口设置为慢启动门限值,然后进入拥塞避免阶段,按照拥塞避免的机制来逐步增加发送窗口。

连接关闭机制

  • 第一次挥手 :客户端主动发起关闭连接请求,向服务器端发送一个包含 FIN 标志位的 TCP 段。
  • 第二次挥手 :服务器收到 FIN 后,向客户端发送一个包含 ACK 标志位的 TCP 段作为确认,通知客户端已收到关闭请求。
  • 第三次挥手 :服务器端处理完需要完成的任务后,向客户端发送一个包含 FIN 和 ACK 标志位的 TCP 段,请求关闭连接。
  • 第四次挥手 :客户端收到服务器端的 FIN + ACK 后,再发送一个 ACK 包作为确认,完成四次挥手过程,正式关闭 TCP 连接。

会话层

会话层的主要功能是建立、维护和终止两个通信系统之间的会话连接。它负责管理会话的生命周期,包括会话的建立、数据传输过程中的会话管理和会话的正常或异常终止。

会话层很少说协议什么的,下面的介绍主要是 AI 生成我纠正的,大概了解即可。

会话的建立

当两个系统需要进行通信时,会话层会协商会话的参数,如会话的类型(单工、半双工或全双工)、会话的优先级等。例如,在一个视频会议系统中,会话层会建立一个全双工的会话,以确保参会者可以同时进行音频和视频的发送和接收。

而数据的来回传输都是通过 TCP 协议进行的。

会话管理

在会话进行过程中,会话层会监控会话的状态。如果出现网络故障或者数据传输错误等情况,会话层会采取相应的措施来恢复会话。例如,当网络出现短暂的中断后,会话层可以重新建立连接,使会话能够继续进行。同时,它还可以对会话中的数据传输进行流量控制,防止数据发送过快导致接收方处理不过来。

会话终止

会话层负责正常地关闭会话连接。当通信双方完成数据交换后,会话层会按照一定的协议来终止会话,确保双方的资源得到正确释放。例如,在文件传输完成后,会话层会发送一个会话终止请求,得到对方确认后,关闭会话连接。

会话层与传输层的区别

传输层的 TCP 协议和会话层都是可靠传输,但是它们有一定区别。

TCP 的传输是单向的,一次性的,会话层这块就是完整的,双向的交流。

表示层

表示层的存在感挺弱的,这里不讲。

应用层

应用层是 OSI 模型的最高层,是用户与网络之间的直接接口。它主要负责为用户提供应用程序服务,包括电子邮件、文件传输、远程登录、Web 浏览等常见网络应用。应用层协议为应用程序提供访问网络的手段,使得用户可以在不同计算机之间进行各种形式的通信。

DNS 协议

DNS 协议中文名为 "域名服务协议",用于将域名(例如 www.huanyp.cn)转换为 IP 地址。

DNS 服务器也在 IPV4 的配置里。

工作过程

  1. 用户设备向本地 DNS 发起查询

    当用户在浏览器输入网址等需要解析域名时,请求发送到本地 DNS。例如,你输入 “www.example.com”,本地 DNS 会先检查自己的缓存。如果缓存中有这个域名对应的 IP 地址记录,它会直接返回 IP 地址给用户设备。

  2. 本地 DNS 向上级 DNS 或根 DNS 查询(如果需要)

    • 如果本地 DNS 缓存中没有该域名的记录,它会向上级 DNS 发起查询。每个本地 DNS 服务器通常都有一个包含上级 DNS 地址的配置文件。这些上级 DNS 通常是服务提供商(如 ISP)的 DNS 服务器。
    • 但是,当上级 DNS 也不能提供所需域名的解析结果时,最终的查找路径会到达根 DNS。根 DNS 是全球 DNS 层次结构的最顶级,负责维护顶级域名服务器(如 .com、.net 等顶级域名服务器)的地址信息。
  3. 层层查询直到解析完成

    • 根 DNS 会告诉本地 DNS 哪个顶级域名服务器负责管理目标域名的顶级部分。例如,对于 “www.example.com”,根 DNS 可能会指向管理 “.com” 域名的顶级域名服务器。
    • 然后本地 DNS 会联系这个顶级域名服务器,顶级域名服务器会进一步告诉本地 DNS 哪台权威域名服务器(通常是域名注册商或专业的 DNS 服务提供商)拥有 “example.com” 的详细信息。
    • 最终,本地 DNS 会直接联系到权威域名服务器,获取 “www.example.com” 对应的准确 IP 地址,并将结果缓存下来,以便下次快速响应同类请求。

HTTP 协议

HTTP 协议主要用于客户端与服务器通信,它的默认端口号是 80。

DNS 解析是不管端口的,如果你没有显示的在 IP/域名 后面指定端口,HTTP 会使用 80 端口和服务器程序通信。

主要功能

  • HTTP 是一种请求 - 响应协议。客户端(通常是浏览器)向服务器发送一个 HTTP 请求,请求的内容可以是一个网页、一张图片、一段视频等资源。例如,当你在浏览器中输入一个网址(如http://www.example.com)并访问时,浏览器就会作为 HTTP 客户端向服务器发送请求。
  • 服务器在接收到请求后,会根据请求的内容进行处理,然后返回一个 HTTP 响应。这个响应包含了请求资源本身(如 HTML 文件、图像数据等),还有一些状态信息,如状态码。常见的状态码有 200(请求成功),表示服务器成功地处理了请求并返回了请求的资源;404(未找到),表示服务器找不到请求的资源。

协议特点

  1. 简单快速

    HTTP 协议的语法相对简单,它基于 TCP/IP 协议,使用明文传输数据。客户端和服务器之间的通信过程比较直接,不需要复杂的握手过程(与 SSL/TLS 协议等相比)。这使得 HTTP 协议能够快速地建立连接并传输数据,从而提高了网页浏览等操作的效率。

  2. 无状态性

    HTTP 协议本身是无状态的,也就是说,服务器不会记录客户端的状态。每次客户端请求和服务器响应都是独立的,服务器不会记住上一次客户端请求的内容。例如,当你访问一个电商网站的多个页面时,服务器不会自动记住你在上一个页面的操作(如添加商品到购物车),除非通过其他技术(如 Cookie 或者服务器端的会话存储)来保存状态信息。

  3. 灵活

    HTTP 协议支持多种类型的请求方法,如 GET(用于获取资源)、POST(用于提交数据)、PUT(用于更新资源)、DELETE(用于删除资源)等。这使得 HTTP 协议可以满足不同的应用场景需求,无论是简单的网页浏览,还是复杂的 Web 应用程序的数据交互。

协议版本

  1. HTTP/1.0

    这是最早的广泛使用的版本。它比较简单,每次请求 - 响应完成后,连接就会关闭。如果客户端需要再次请求资源,就需要重新建立连接。这种方式在资源较少、网络带宽相对紧张的早期互联网环境中还可以,但在现代复杂的网络应用中就显得效率较低。

  2. HTTP/1.1

    HTTP/1.1 引入了持久连接(Persistent Connection)的概念。在这种模式下,客户端和服务器之间的连接在一次请求 - 响应完成后不会立即关闭,可以被多个请求 - 响应过程共享。这样就减少了频繁建立和关闭连接所带来的开销,提高了传输效率。同时,HTTP/1.1 还增加了一些新的请求头和响应头字段,使得协议更加灵活和强大。

  3. HTTP/2

    HTTP/2 主要为了解决 HTTP/1.1 的一些性能瓶颈。它引入了多路复用(Multiplexing)技术,允许客户端和服务器同时发送多个请求和响应,而不需要等待前面的请求 - 响应过程完成。并且,HTTP/2 对数据进行了帧的划分和压缩等操作,进一步提高了数据传输的效率。这在现代的 Web 应用中,尤其是对于包含大量静态资源(如图片、脚本文件等)的网站,能够显著提高加载速度。

HTTPS 协议

HTTPS 协议本质是在 HTTP 协议的基础上加了一个 TLS/SSL 来保证传输过程的安全性,默认采用 443 端口。

几个编程细节的提醒

  • Python 的 http.server 不支持 HTTPS 协议,由于它没写 SSL/TLS 部分,所以在传输层就被扔包了,体现出来就是发了然后一点反应都没有,或者是单纯日志报一堆乱码但没有调用 handler。

TLS/SSL 协议

TLS/SSL 协议都是建立在 TCP 协议之上的,因此它们的通信本身是可靠的。

证书链验证机制

  • 证书颁发机构(CA)验证:服务器会向客户端提供 SSL 证书,客户端需要验证 SSL 证书是否有效,同时要验证颁发机构是否可信。这通常通过检查证书链来实现,证书链从服务器的 SSL 证书开始,经过一系列中间证书,最终到达客户端信任的根证书。如果根证书是可信的,并且证书链中的每个证书都是有效的,那么客户端就可以信任服务器的SSL证书。
  • 证书信息验证:客户端会检查 SSL 证书中的信息,如域名、有效期、公钥等,是否与实际情况相符。例如,证书中的域名应该与用户正在访问的网站域名完全匹配。证书有效性验证涉及 RSA 的签名机制,在数学上可以确保安全。

SSL 握手过程

  • 客户端发起连接:客户端(如浏览器)通过发送一个 "SH" 消息开始 SSL/TLS 握手过程。这个消息包含了客户端支持的 SSL/TLS 版本、加密套件(cs)、随机数(CR)和会话 ID。
  • 服务器响应:服务器收到 "ClientHello" 消息后,响应一个 "SH" 消息,选择一个双方都支持的加密套件和协议版本,并发送服务器随机数(SR)。
  • 证书传输:服务器发送其 SSL 证书给客户端。这个证书包含了服务器的公钥,以及由证书颁发机构(CA)签发的证书信息。
  • 证书验证:客户端验证服务器证书的有效性,包括证书是否过期、是否被撤销、证书链是否完整,以及证书的域名是否与服务器域名匹配。
  • 密钥交换:如果使用 RSA 密钥交换算法,客户端会生成一个临时的会话密钥(PMS),并使用服务器的公钥加密这个密钥,然后发送给服务器。服务器使用自己的私钥解密得到会话密钥。
  • 握手结束:客户端和服务器使用会话密钥生成最终的加密密钥,并使用这个密钥加密后续通信。客户端发送 "Finished" 消息,包含握手消息的哈希值,服务器也发送 "Finished" 消息,确认握手成功。

TLS 协议

上面说的 SSL 协议本身是没有漏洞的,但是 SSL 的实现中为了效率采用了 Padding Oracle 机制,因此衍生出一种叫做 POODLE(降级加密密文填充攻击) 的 MiTMA(中间人攻击)。

TLS 解决了这个问题,其它和 SSL 差别不大。

提醒

看完本文后,你应该有了一些基础的网络知识。

笔者必须提醒你,这些知识是危险的。

人类第一次仰望星空时,就已经具备了进行星际航行的能力;你了解这些知识后,与黑客技术也只剩下一层窗户纸了。

记住,知识是中立的,你应该用你的道德,去掌控你所拥有的知识。