敲下回车后都发生了什么

敲下回车后都发生了什么

某天在水群的时候看见了一句话"计网的几层也可以通过输入网址敲击回车后发生了什么串起来",刚好也在补基础,所以就窃取了灵感,学习一下计网的基础知识,顺便水一篇博客

每天我们都无数次通过浏览器这个通向全世界的窗口来上网冲浪,但鲜少有人注意当我们每次在地址栏输入网址,按下enter键后都发生了什么

浏览器解析URL

URL(同意资源定位符)是因特网中的唯一资源的地址。它是浏览器用于检索已发布资源(例如HTML页面,CSS文档,图像等)的关键机制之一。

理论上说,每个有效的 URL 都指向一个唯一的资源。

比如有这样一个URL:

https://www.example.com:443/path/index.html?name=alice#section

它可以拆成:

部分 含义
https 使用 HTTPS 协议
www.example.com 目标域名
443 端口号,HTTPS 默认 443
/path/index.html 请求路径
?name=alice 查询参数
#section 页面内片段,不会发送给服务器

浏览器首先要弄清楚三件事:

  1. 用什么协议访问?
  2. 访问哪个主机?
  3. 请求哪个资源?

如果没有显式写端口,浏览器会根据协议补默认端口:

协议 默认端口
HTTP 80
HTTPS 443

DNS解析

真正的网址看上去并不像你输入到地址栏中的那样美好且容易记忆。它们是特殊的数字,像 192.0.2.172。

这串数字叫做IP地址,它代表的是web上独一无二的位置。然而,它并不容易记忆,不是吗?那就是发明域名系统(DNS)的原因。这个系统使用特殊的服务器将你输入到浏览器(如“mozilla.org”)的网址匹配到网站真实的(IP)地址。

当你输入www.example.com时,浏览器需要先知道这个域名对应哪个IP地址

DNS 查询通常会按下面顺序尝试:

  1. 浏览器 DNS 缓存
  2. 操作系统 DNS 缓存
  3. hosts 文件
  4. 本地 DNS 服务器
  5. 根 DNS 服务器
  6. 顶级域 DNS 服务器,比如 .com
  7. 权威 DNS 服务器

最终得到类似结果:

www.example.com -> 93.184.216.34

这一步主要用到的协议是DNS协议,跑在最顶端的应用层

DNS 一般使用 UDP 53 端口,但在响应过大、区域传输等场景下也可能使用 TCP。

判断目标 IP 在不在同一个网络

拿到 IP 后,主机会判断目标地址是否和自己处于同一个局域网。

假设本机信息如下:

本机 IP:192.168.1.100
子网掩码:255.255.255.0
默认网关:192.168.1.1
目标 IP:93.184.216.34

通过子网掩码判断后,发现目标 IP 不在本地局域网。

于是数据不能直接发给目标服务器,而是先发给默认网关,也就是路由器。

这里涉及几个概念:

概念 作用
IP 地址 标识网络中的主机
子网掩码 判断两个 IP 是否在同一网段
默认网关 访问外部网络时的下一跳
路由表 决定数据包下一步发往哪里

这一阶段主要对应:

网络层次 协议 / 概念
网络层 IP、路由

为什么数据不能直接发给目标服务器呢?

我们先构建一个简单的网络:

当两台计算机需要通信的时候,你必须要连接他们,无论通过有线方式(通常是网线)或是无线方式(比如 WiFi 或蓝牙)。所有现代计算机都支持这些连接。

png1

通常一个网络不仅限于两台计算机。你可以尽你所想地连接计算机,但是情况立刻变得复杂了。如果你尝试连接,比如说十台计算机,每台电脑有九个插头,总共需要 45 条网线。

png2

为了解决这个问题,网络上的每台计算机需要连接到一个叫做网络交换机(network switch)的小型特殊计算机。交换机只干一件事:就像火车站的调度员,它要确保从一台计算机上发出的消息仅可以到达目标计算机。为了把消息发送给计算机 B,计算机 A 必须把信息发送给交换机,交换机将收到的信息转发给计算机 B。计算机 B 不会收到发给其他计算机的消息,发给计算机 B 的消息也不会传到局域网上的其他计算机上。

一旦我们把交换机加入到这个系统,我们的网络中便只需要十条网线:每台计算机一个插口,交换机上十个插口。

png3

网络中的网

到目前为止一切都很好。但是我们要连接成百上千、上亿台计算机呢?当然一台交换机覆盖不了这么远,但是,如果你阅读得比较认真,我们曾提到交换机像其他计算机一样,所以我们为什么不把两个交换机彼此连接呢?

png4

你可以想象我们可以无限地将交换机连接起来,形成这样的网络:

png5

但是在现实中,这样会导致许多工程问题。数据包需要经过的交换机越多,到达目的地的时间就越长。而且你不能只依赖这种树状结构的交换机集群,因为一旦某个交换机节点故障,就会导致大面积的断网,这会使你的网络变得脆弱。为了解决这个问题,我们将每个网络保持在一个较小的规模,并使用一种名为路由器(router)的设备来连接每个网络。路由器是一种负责在不同网络之间转发消息的计算机,其运作原理类似邮局:当数据包到达时,它会读取收件人的地址,直接将数据包转发给正确的收件人,而无需经过层层中转。

我们来解释一下上面这段话,

首先路由器比纯使用交换机好在哪:

首先,交换机工作在数据链路层(二层),转发依据是 MAC 地址。当一个设备想找到另一个设备时,它会发送广播帧(比如 ARP 请求),交换机必须把这个广播复制到所有端口。

如果只有几十台设备,广播影响可以忽略。但如果把全世界的设备都连成一个二层网络,任何一台设备发出的广播,都会瞬间扩散到整个地球。每一台设备都会不断收到海量与自己无关的广播,CPU 被占用,带宽被耗尽,这就是广播风暴。结果就是,全世界网络一起瘫痪。

其次,交换机靠 MAC 地址表来寻址,二路由器使用IP地址来寻址,这样做的好处是可以把全世界切割成无数小的子网。你发往“大洋彼岸”的数据,只需要知道下一跳路由器在哪,完全不需要知道对方具体的 MAC 地址。

第三点,路由器直接可以通过路由协议(OSPF、BGP等),可以像导航地图一样实时计算最佳路径。当某条海缆断了,路由器能动态绕行,这是交换机二层网络永远做不到的。

为什么某个交换机节点故障了会导致大面积的断网,但路由器不会

使用纯交换机组成树形结构的网络像是这样的:

            ┌─────────────┐
            │  核心交换机  │  ⬅️ 这台坏了 👇
            └──┬──┬──┬──┘
        ┌─────┘  │  └─────┐
   ┌────┴────┐   │  ┌────┴────┐
   │ 交换机A │   │  │ 交换机B │
   └──┬──┬──┘   │  └──┬──┬──┘
     PC1 PC2    PC3   PC4 PC5

核心交换机一旦宕机,所有的 PC 全部无法通信,整个网络完全瘫痪。即便交换机A、B都完好,它们也失去了与上层连接的通路,没有任何备用路径(因为树形结构没有环路,或者即便有环路也会被 STP 阻塞成无环树)。

但如果使用路由器把网络切成小块的话是这样的:

  网络1 (小)           网络2 (小)            网络3 (小)
  ┌─────────┐         ┌─────────┐          ┌─────────┐
  │ PC1 PC2 │         │ PC3 PC4 │          │ PC5 PC6 │
  └────┬────┘         └────┬────┘          └────┬────┘
       │                   │                    │
  ┌────┴────┐         ┌────┴────┐          ┌────┴────┐
  │ 路由器1  │◄───────►│ 路由器2  │◄────────►│ 路由器3  │
  └─────────┘         └────┬────┘          └─────────┘
                           ⬆️ 这台路由器2 挂了

网络2 内部:PC3 和 PC4 之间仍然可以互相通信(它们连在同一个交换机或路由器内网口,属于同一广播域,不依赖路由器2)。

网络2 访问外部:网络2 里的设备无法再访问网络1、网络3 以及互联网。

网络1 和网络3:它们之间的通信完全不受影响,可以继续正常互访。

结论:路由器2 的故障只让它负责的“网络2”对外断网,影响范围被牢牢限制在一个小区域内,没有扩散到其他网络。

而且路由器还支持冗余协议(如 VRRP/HSRP)和动态路由,所以可以这样设计:

        网络1                网络2 (关键网络)
       ┌──────┐            ┌──────┐
       │ R1   │            │ 虚拟网关 │  (VIP: 192.168.2.1)
       └──┬───┘            └──┬───┬──┘
          │                   │   │
          │      ┌────────────┘   └────────────┐
          │      │                             │
       ┌──┴──────┴──┐                     ┌────┴─────┐
       │   骨干网络   │                     │          │
       └──┬──────┬──┘                  ┌──┴──┐   ┌──┴──┐
          │      │                     │ R2a │   │ R2b │  (真实路由器)
          │      │                     └──┬──┘   └──┬──┘
          │      └──────────────┬────────┘         │
          │                     │                  │
          │                  ┌──┴──────────────────┴──┐
          │                  │   交换机 (网络2内部)    │
          │                  └─────┬──────┬──────────┘
          │                        │      │
          └─────(其他网络)─────   PC3    PC4

R2a 和 R2b 是一对冗余路由器,共同对外虚拟出一个“虚拟网关”(VIP)。

正常情况下,R2a 负责转发,R2b 处于备份状态。

一旦 R2a 宕机,R2b 会立刻接管虚拟网关,网络2 的内部设备对外通信几乎不受影响(仅丢失极少量正在传输的包)。

对于网络1 和更远的网络,动态路由协议会立刻发现 R2a 失效,将流量自动绕行到 R2b,整个互联网不会因为这一台路由器故障而瘫痪。

这时候就有人要问了,为什么交换机不能使用冗余设计来消灭单点故障

这是因为交换机中MAC地址表大小是有限的,当交换机的地址表中没找到对应的MAC地址的时候,就会进行全网广播,然而当形成环路的时候,广播操作就会一直在交换机之间发生,然后无限死循环,造成全网瘫痪。所以,为了避免这种情况的发生,二层网络物理上不能有环路。

所以我们回到前面,我们就可以用路由器来将一个个小网络连接起来

png6

下一步是将我们网络中的消息发送至目标网络。为此,我们将通过互联网服务提供商(ISP)连接至互联网。ISP 是管理特殊路由器的公司,这些路由器相互连接,并能访问其他 ISP 的路由器。因此,来自我们网络的消息将通过 ISP 网络的网络传输至目标网络。整个互联网正是由这样的网络基础设施构成的。

png7

ARP:通过 IP 找到 MAC 地址

即使知道要把数据交给默认网关,主机还需要知道网关的 MAC 地址。

因为在局域网里,数据链路层真正转发的是 MAC 帧。

主机会发送 ARP 请求:

谁是 192.168.1.1?请告诉 192.168.1.100

路由器回复:

192.168.1.1 的 MAC 地址是 aa:bb:cc:dd:ee:ff

之后,本机会把数据封装成以太网帧,发给网关的 MAC 地址。

这里要注意一个重要点:

IP 地址用于跨网络寻址,MAC 地址用于同一个局域网内的下一跳转发。

这一阶段主要对应:

网络层次 协议 / 概念
数据链路层 ARP、MAC、以太网帧

TCP 三次握手:建立可靠连接

在大多数情况下,一个HTTP请求会对应一个TCP连接。HTTP是基于TCP协议的,它使用TCP来传输HTTP请求和响应数据。

HTTP 1.0 和HTTP 2.0都基于TCP,而HTTP 3.0基于UDP

TCP 三次握手过程如下:

客户端 -> 服务器:SYN
服务器 -> 客户端:SYN + ACK
客户端 -> 服务器:ACK

三次握手的目的:

  1. 确认双方都能发送和接收数据
  2. 协商初始序列号
  3. 建立可靠传输连接

TCP 提供的能力包括:

能力 说明
可靠传输 丢包后可以重传
有序传输 接收方按顺序交付数据
流量控制 防止发送方把接收方打爆
拥塞控制 避免把网络链路打爆
端口复用 用端口区分不同应用进程

这一阶段主要对应:

网络层次 协议
传输层 TCP

TLS 握手:HTTPS 为什么安全

如果 URL 是 https://,TCP 连接建立后,还不能直接发送 HTTP 明文请求。

浏览器和服务器还要进行 TLS 握手。

TLS 握手主要做几件事:

  1. 协商 TLS 版本
  2. 协商加密套件
  3. 服务器发送证书
  4. 浏览器验证证书是否可信
  5. 双方协商出会话密钥
  6. 后续 HTTP 数据使用会话密钥加密传输

证书验证主要是为了确认:

我访问的真的是 www.example.com,而不是中间人伪造的网站。

TLS 解决的问题包括:

问题 TLS 的作用
窃听 加密传输内容
篡改 校验数据完整性
冒充 通过证书验证服务器身份

TLS 通常被认为位于应用层和传输层之间,也可以理解为 HTTPS 的安全基础。

关于TCP和TLS我以前的TLS Poison 攻击学习中都有提到过

数据是如何被一层层封装的

浏览器生成 HTTP 请求后,数据不会直接裸奔到网络上。

它会被一层层封装:

HTTP 数据
  ↓ 加 TCP 头
TCP Segment
  ↓ 加 IP 头
IP Packet
  ↓ 加 Ethernet 头和尾
Ethernet Frame
  ↓ 转成电信号 / 光信号 / 无线电波
物理介质上传输

接收方则反过来一层层拆包:

Ethernet Frame
  ↓ 去掉以太网头尾
IP Packet
  ↓ 去掉 IP 头
TCP Segment
  ↓ 去掉 TCP 头
HTTP 数据

每一层只关心自己的职责:

层次 关注点
应用层 传什么业务数据
传输层 进程到进程,可靠性,端口
网络层 主机到主机,IP 和路由
数据链路层 相邻节点之间,MAC 和帧
物理层 比特如何在介质上传输

路由器在中间做了什么

数据包从你的电脑到服务器,通常会经过多个路由器。

每个路由器主要做这些事:

  1. 收到数据帧
  2. 拆掉当前链路层头部
  3. 查看 IP 包的目标地址
  4. 查询路由表
  5. 找到下一跳
  6. 重新封装新的链路层帧
  7. 转发出去

一个很重要的点:

源 IP 和目标 IP 通常在传输过程中不变,但每一跳的源 MAC 和目标 MAC 都会变化。

例如:

电脑 -> 家用路由器
源 MAC:电脑 MAC
目标 MAC:路由器 MAC

路由器 -> 下一跳运营商设备
源 MAC:路由器出口 MAC
目标 MAC:下一跳设备 MAC

IP 负责端到端,MAC 负责下一跳。

服务器处理请求

服务器收到 HTTP 请求后,可能经历:

Nginx / Apache / Caddy
  ↓
反向代理
  ↓
后端应用服务
  ↓
缓存 / 数据库
  ↓
生成响应

例如访问一个动态页面时,后端可能会:

  1. 解析请求路径和参数
  2. 校验 Cookie 或 Token
  3. 查询 Redis 缓存
  4. 查询 MySQL / PostgreSQL
  5. 渲染 HTML 或返回 JSON
  6. 交给 Web 服务器返回给浏览器

如果是静态资源,比如图片、CSS、JS,服务器可能直接从磁盘或 CDN 返回。

浏览器解析并渲染页面

浏览器收到 HTML 后,会开始渲染页面。

大致流程:

  1. 解析 HTML,构建 DOM 树
  2. 解析 CSS,构建 CSSOM 树
  3. 合并 DOM 和 CSSOM,生成渲染树
  4. Layout,计算元素位置和大小
  5. Paint,绘制像素
  6. Composite,合成图层并显示

如果 HTML 中引用了 CSS、JS、图片、字体等资源:

<link rel="stylesheet" href="/style.css">
<script src="/main.js"></script>
<img src="/logo.png">

浏览器还会继续发起新的网络请求。

这些请求可能会:

  • 复用已有 TCP/TLS 连接
  • 使用缓存
  • 重新 DNS 查询
  • 走 CDN
  • 使用 HTTP/2 多路复用
  • 使用 HTTP/3 over QUIC

用这个过程串起网络分层

现在回头看,输入网址这件事正好把网络分层串起来了。

网络层次 在这个过程中的体现
应用层 DNS、HTTP、HTTPS
传输层 TCP、UDP、端口、可靠传输
网络层 IP、路由、跨网段转发
数据链路层 MAC、ARP、以太网帧
物理层 网线、光纤、Wi-Fi 信号

如果用 OSI 七层模型表示:

OSI 七层 对应例子
应用层 HTTP、DNS
表示层 TLS、编码、压缩
会话层 会话状态、连接管理
传输层 TCP、UDP
网络层 IP、路由
数据链路层 Ethernet、MAC、ARP
物理层 电信号、光信号、无线电波

总流程图

输入 URL
  ↓
浏览器解析 URL
  ↓
DNS 查询域名对应 IP
  ↓
判断目标是否在同一网段
  ↓
ARP 获取下一跳 MAC 地址
  ↓
TCP 三次握手
  ↓
TLS 握手
  ↓
发送 HTTP 请求
  ↓
服务器处理请求
  ↓
返回 HTTP 响应
  ↓
数据逐层拆包
  ↓
浏览器解析并渲染页面

总结

输入网址并按下回车,看起来只是一个简单动作,但背后串起了计算机网络的大部分核心知识。

DNS 负责把域名变成 IP,IP 和路由负责把数据送到目标网络,ARP 和 MAC 负责局域网内的下一跳转发,TCP 负责可靠连接,TLS 负责安全加密,HTTP 负责应用层语义,浏览器最终负责解析和渲染页面。

如果把这些知识孤立地背,很容易混乱;但如果沿着“一次网页访问”的路径去看,每一层为什么存在、解决什么问题,就会清楚很多。

参考

互联网是如何工作的?

Licensed under CC BY-NC-SA 4.0
Build by Oight
使用 Hugo 构建
主题 Stack 由 Jimmy 设计