XingPiaoLiang's

Back

What happens when#

今天来详看一下「当你在浏览器输入栏中输入 www.google.com 会发生什么?」世纪经典面试问题的答案,当然这篇文章主要聚焦于计算机网络部分的故事,在这之前还存在着包括硬件驱动等故事,具体 参看

Parse URL#

URL(Uniform Resource Locator)统一资源定位符。在浏览器输入框内部收到输入的内容后,首先需要判断输入内容是否是一个 URL 还是一个搜索项。

URL 包含着以下信息,在浏览器中:

  • protocol “http”
  • Resource ”/”

如果浏览器没有在输入的目标文字中检测到有效的「协议」和「域名」,那么目标文字就会被直接转入到默认的搜索引擎中。在大部分情况下,如果直接使用默认的搜索引擎,浏览器会自动在搜索结果中的 URL 中附加一些特定的信息,包括用于标识这样的搜索请求来自哪一个浏览器等等。

在 chrome 浏览器中输入 erasernoob 搜索,对应的 URL 如下: https://www.google.com/search?q=erasernoob&oq=erasernoob&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIGCAEQRRhBMgwIAhAAGAgYChgNGB4yDQgDEAAYhgMYgAQYigUyBggEEEUYPDIGCAUQRRg8MgYIBhBFGDwyBggHEEUYQdIBCDU2ODNqMGo3qAIAsAIA&sourceid=chrome&ie=UTF-8

  • sourceid:代表地址栏的来源浏览器
  • gs_lcrp:代表着 chrome 浏览器添加的搜索上下文参数
  • oq: original query 记录了用户输入的原始内容
  • q: query 记录最终的搜索参数(包括根据 google 建议补全)

Convert non-ASCII Unicode characters in the hostname#

  • 浏览器检查 域名中是否存在不是 ASCII 码的符号 A-Z a-z 0-9 - .

**早期,互联网的设计是基于 ASCII 编码的,所以只支持上述的符号。**所以 DNS 智能识别 ASCII 字符,所以如果有一个域名包括了非 ASCII 码,那么就需要通过 PunyCode 的编码方式转换为合法的 ASCII 码。

PunyCode: Punycode 把非 ASCII 字符转换为数字表示,然后用一种特殊算法压缩成只包含 ASCII 的字符。它保留了原始 ASCII 的部分,只“翻译”非 ASCII 的部分。 你好.com -> xn--6qq79v.com PunyCode 翻译过后域名以 xn-- 开头,代表着这是 PunyCode 编码之后的域名

Check HSTS list#

浏览器开始通过查 「预加载 HSTS 列表」 (preloaded HSTS (HTTP Strict Transport Security) list),如果目标网站在这个列表中,那么浏览器就直接通过 HTTPS 方式请求服务器。如果网站不在列表中,那么第一个请求就使用 HTTP 方式。

为什么要使用 HSTS list?#

预加载 HSTS 列表,其中包含着所有浏览器之前保存过的需要用 HTTPS 访问的所有网站。HSTS 是一个 HTTP 安全机制,服务器需要通过响应头设置告诉浏览器:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
lua

告知浏览器,之后的一整年(max-age 以秒为单位)都要使用 HTTPS 访问我。所以这样的问题就是,第一次请求还是得用 HTTP 的方式请求,还是会存在着被攻击的风险,所以干脆这样维护一个预加载的列表,增强安全性。

DNS Lookup#

  • 浏览器首先检测目标域名是否在缓存中,chrome://net-internals/#dns 输入来查看 chrome 浏览器的 dns 缓存。
  • 如果不在缓存中,那么浏览器调用 gethostbyname 库函数来完成查询
  • gethostsname 库函数查看目标域名的地址是否存在在本地的 hosts 文件中,不同的操作系统该文件位置不同。如果不在,那么就通过会像 DNS 服务器发送一条 DNS 查询解析请求(Linux 的 /etc/hosts 或 Windows 的 C:\Windows\System32\drivers\etc\hosts
  • DNS 服务器由操作系统配置在网络协议栈(network stack)中,这通常包括本地路由器和 ISP 的缓存 DNS 服务器(这样可以加速 DNS 解析,不用每次都去根域名服务器或者权威服务器进行访问)
  • 如果发现 DNS 服务器的 IP 地址和本机在一个子网中,此时 OS 转入到局域网请求流程,通过 ARP(Address Resolution Protocol)协议查询到 DNS 服务器的 MAC 地址,通过 MAC 地址直接将 DNS 请求包发给目标 DNS 服务器
  • 若不在一个子网中,那么通过 ARP 协议查询到默认网关的 MAC 地址,将 DNS 请求包发给默认网关

经过 ARP Process 之后,此时要么拿到了 DNS 服务器的 IP 或者是默认网关的 IP,紧接着就可以继续 DNS 查询请求:

  • DNS 客户端通过 UDP 53 端口向 DNS 服务器建立 socket 连接发送请求包,如果请求包太大就会使用 TCP
  • 如果没有找到,那么 DNS 服务器就会递归的向上层服务器请求,直到抵达授权 DNS 服务器 (SOA)

Opening of a socket#

浏览器一收到目标 IP 地址,便会带着目标 IP 以及目标端口(Http 默认为 80, Https 默认为443)z后调用系统库函数 socket 然后请求使用一个 TCP 套接字流:

  • 首先,第一个请求被传递到传输层,在这里请求被封装成 TCP segment,然后目标端口被加入请求头部,源端口由 OS 随机决定
  • segment 被送到网络层,在这里会在被加上一个 IP 头部,其中包含着目标 IP 以及本机的源 IP
  • 接下来 packet 抵达链路层,在这里加上一个包含着本机的 MAC 以及默认网关的 MAC 的帧头,如上文所说,如果不知道默认网关的 MAC 那么就需要通过 ARP 广播请求到。 到这个时候,请求包 packet 就准备好被 Ethernet, WiFi, Cellular data network 三者其中之一方式传送转发了。

对于大部分家庭网络或者小型企业网络,请求包首先会从电脑出发,通过本地网络之后,然后通过一个现代的调制解调器(MOdulator/DEModulator),将数字信号(0/1)转换为模拟信号,这样可以在电话线路等上传播,在线路的另一端会有另外一个调制解调器,相反的,它会将模拟信号转换成原有数字信号将请求包继续向前传播,到达下一个网络节点

现在比较现代的网络大多都直接和以太网相连接,所以请求包数据保持着数字信号一路向前,直接被传向下一个网络节点。

整体上看,数据通过抵达本地子网的路由器,之后继续前往自治系统(AS)的边界路由器,穿越其他自治系统,最终达到目标服务器。

在路上的每一跳(经过的路由器)都会对请求包进行拆封,根据目标 IP 地址,决定下一跳需要将请求包送往哪里。其中 TTLnetwork congestion 都会造成包的丢失。

在上面的请求接收过程中,TCP的连接建立会发生很多次,TCP connection flow :

  • 客户端选择一个 ISN (Initial Sequence Number),并设置好 SYN 位,代表正在设置 ISN 位,需要和服务器建立连接
  • 如果服务器目前可以接收当前的连接,接收 SYN
    • 设置自身的 ISN 位
    • 设置 SYN 位,代表其正在设置 ISN 位
    • 将接收到的 ISN 位 + 1,并将得到的数字设置在 ACK 字段,并设置 ACK 位,代表确认收到客户端的的数据
  • 客户端确认连接并发送数据包
    • 客户端将 ISN + 1
    • 将服务器发送的 ISN + 1 并设置在 ACK 字段
    • 设置 ACK 位,代表确认收到
  • 数据开始阐述
    • 当一方收到了 N 字节数据,那么 SEQ 字段就加上 N
    • 当另一端收到了相应的数据包,就返回一个 ACK 请求确认包,ACK = 上一次收到的数据包的最后一个序列号
  • 关闭连接
    • 关闭者设置 FIN 位,发送 FIN 请求包
    • 接收者收到 FIN 请求包,设置 FIN 位,设置 ACK,发送 FIN 请求包
    • 关闭者确认收到接收者发出的 FIN 请求包, 设置 ACK

TLS(Transport Layer Security) handshake#

TLS

  1. 客户端发起握手(ClientHello)

客户端发送 ClientHello 消息,包含: - 支持的 TLS 版本(如 TLS 1.2 / 1.3) - 支持的密码套件(Cipher Suites) - 客户端随机数(Client Random) - 支持的扩展(如 SNI、ALPN) - (TLS 1.3)密钥共享(KeyShare)参数

  1. 服务器响应握手(ServerHello)

服务器返回 ServerHello 消息,包含: - 选择的 TLS 版本 - 选定的密码套件 - 服务器随机数(Server Random) - (TLS 1.3)服务器的 KeyShare 参数

  1. (TLS 1.2)发送服务器证书及密钥交换信息

    • Certificate: 服务器发送数字证书(含公钥)
    • ServerKeyExchange: 若非 RSA,需要发送 Diffie - Hellman 参数
    • CertificateRequest: 可选,要求客户端发送证书
    • ServerHelloDone: 握手阶段结束标志(TLS 1.2)
  2. 客户端处理服务器消息

    • 验证服务器证书的合法性(通过 CA 链)
    • 生成预主密钥(Pre - Master Secret)
    • 加密发送给服务器(或使用 DH 完成共享)
  3. 生成会话密钥

    • 双方使用:
    • Pre - Master Secret
    • Client Random
    • Server Random
    • 计算出会话密钥(Master Secret)
    • 再派生出加密/解密所需的对称密钥和 MAC 密钥
  4. 握手完成

客户端发送: - ChangeCipherSpec: 通知服务器将启用加密通信 - Finished: 加密的握手完成校验信息

服务器发送: - ChangeCipherSpec - Finished

HTML CSS 渲染#

What happens when..(network)
https://astro-pure.js.org/blog/what-happens-when
Author erasernoob
Published at June 12, 2025
Comment seems to stuck. Try to refresh?✨