计算机网络学习笔记

从协议栈到抓包实战,系统理解网络通信的底层原理和常见面试考点。


1 · 网络模型

1.1 OSI 七层模型

层 作用 协议/设备
应用层 用户交互接口 HTTP、FTP、DNS、SMTP
表示层 数据格式、加密压缩 SSL/TLS、JPEG
会话层 会话管理 RPC
传输层 端到端通信 TCP、UDP
网络层 寻址与路由 IP、ICMP、OSPF、路由器
数据链路层 相邻节点传输 Ethernet、ARP、交换机
物理层 比特流传输 网线、光纤、集线器

1.2 TCP/IP 四层模型

更贴近实际实现:

应用层(HTTP / DNS / FTP) 传输层(TCP / UDP) 网络层(IP / ICMP) 网络接口层(Ethernet / Wi-Fi)

1.3 数据封装

发送方从上到下逐层加头部,接收方从下到上逐层拆头部。

每一层的数据单位不同:

  • 应用层:消息(Message)
  • 传输层:段(Segment)
  • 网络层:数据报(Datagram)
  • 数据链路层:帧(Frame)
  • 物理层:比特(Bit)

2 · IP 协议与子网划分

2.1 IPv4 地址

32 位,点分十进制表示,如 192.168.1.1。

分类地址:

  • A 类:1.0.0.0 ~ 126.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 类:保留

私有地址:

  • 10.0.0.0/8
  • 172.16.0.0/12
  • 192.168.0.0/16

2.2 CIDR

CIDR(无类别域间路由)用 /n 表示前 n 位是网络号。

例如 192.168.1.0/24:

  • 网络号:192.168.1
  • 主机号:0 ~ 255
  • 可用主机:192.168.1.1 ~ 192.168.1.254

2.3 子网划分

借主机位作为子网位。

例如 192.168.1.0/24 划分成 4 个子网:

  • 每个子网需要 2 位子网位(2² = 4)
  • 新掩码 /26
  • 每个子网 64 个地址

2.4 ICMP

用于网络诊断:

  • ping:Echo Request / Echo Reply
  • traceroute:利用 TTL 超时或端口不可达
  • Destination Unreachable、Time Exceeded

3 · TCP 与 UDP

3.1 TCP 特性

  • 面向连接:通信前先三次握手建立连接
  • 可靠传输:确认号、超时重传
  • 有序:序列号保证数据顺序
  • 流量控制:滑动窗口防止发送方压垮接收方
  • 拥塞控制:慢启动、拥塞避免、快重传、快恢复

3.2 三次握手

图 1 \xb7 TCP 三次握手

为什么是三次?

防止历史连接请求被服务端接受。如果只握手两次,客户端已经断开的旧 SYN 到达服务端,服务端会建立半连接。

3.3 四次挥手

客户端最后发送 ACK 后进入 TIME_WAIT 状态,等待 2MSL(Maximum Segment Lifetime)。

为什么需要 TIME_WAIT?

  1. 确保最后的 ACK 被对方收到,如果没收到,对方会重发 FIN。
  2. 等待网络中残留的报文段消失,避免影响下一个连接。

3.4 TCP 可靠传输机制

  • 序列号:标识每个字节的位置
  • 确认号:期望收到的下一个字节序号
  • 超时重传:RTT 动态估计,超时未确认则重传
  • 滑动窗口:允许连续发送多个数据包再统一确认
  • 拥塞窗口(cwnd):根据网络拥塞情况动态调整

3.5 UDP

  • 无连接、不可靠、不保证顺序
  • 头部只有 8 字节,开销小
  • 支持广播和组播
特性 TCP UDP
连接 面向连接 无连接
可靠 是 否
有序 是 否
开销 大 小
速度 慢 快
应用 HTTP、FTP、SMTP DNS、视频流、游戏

4 · HTTP/HTTPS

4.1 HTTP 版本演进

HTTP/1.0:每次请求新建 TCP 连接,效率低。

HTTP/1.1:

  • 持久连接(Keep-Alive)
  • 管道化(Pipeline,但很少用)
  • Host 头支持虚拟主机
  • 缓存控制:Cache-Control、ETag、Last-Modified

HTTP/2:

  • 二进制分帧
  • 多路复用:一个 TCP 连接上并发多个请求
  • 头部压缩(HPACK)
  • 服务器推送

HTTP/3:

  • 基于 QUIC(UDP)
  • 解决 HTTP/2 的 TCP 队头阻塞问题

4.2 HTTPS 握手

客户端 -> 服务端:ClientHello(支持的加密套件、随机数) 服务端 -> 客户端:ServerHello(选定加密套件、随机数)、证书 客户端 -> 服务端:验证证书、生成预主密钥、用服务端公钥加密发送 服务端 -> 客户端:解密得到预主密钥 双方 -> 生成会话密钥 后续通信 -> 对称加密

为什么用对称加密传输数据?

非对称加密计算量大,对称加密快。所以只用它交换对称密钥,之后用对称密钥通信。

4.3 常见状态码

码 含义
200 OK
301 永久重定向
302 临时重定向
304 Not Modified(缓存命中)
400 Bad Request
401 Unauthorized(未认证)
403 Forbidden(无权限)
404 Not Found
500 Internal Server Error
502 Bad Gateway
503 Service Unavailable

5 · DNS / CDN / 负载均衡

5.1 DNS 解析流程

浏览器访问 www.example.com:

  1. 浏览器缓存
  2. 操作系统缓存
  3. hosts 文件
  4. 本地 DNS 服务器(ISP 提供)
  5. 根 DNS 服务器
  6. 顶级域 DNS 服务器(.com)
  7. 权威 DNS 服务器(example.com)

递归查询 vs 迭代查询:

  • 客户端 → 本地 DNS:递归(我只要答案,你负责跑完全程)
  • 本地 DNS → 根/顶级域/权威:迭代(每一步只返回"下一步去问谁")
TIP

📌 域名解析的本质是一次"分级问路":根服务器不知道 www.example.com 的 IP,它只知道 .com 谁管;.com 不知道具体主机,只知道 example.com 的权威 NS 是谁。真正持有 A 记录的只有权威 DNS——也就是你在域名商或 DNS 服务商(Cloudflare、DNSPod)后台改的那一份。所以改解析只在权威 DNS 生效,其余各级都是缓存。

5.2 常见 DNS 记录类型

类型 作用 值示例
A 域名 → IPv4 1.2.3.4
AAAA 域名 → IPv6 2400:xx::1
CNAME 域名 → 另一个域名(别名) xxx.cdn.example.net
NS 指定该域由哪台权威 DNS 负责 ns1.dnspod.net
MX 邮件服务器(带优先级) 10 mx.example.com
TXT 任意文本,用于域名归属校验、SPF/DKIM v=spf1 ...
SRV 指定服务的主机+端口 _sip._tcp 0 5 5060 host
CAA 限定哪些 CA 可以为该域签证书 0 issue "letsencrypt.org"

几条必须记住的规则:

  • 根域(example.com 本身)不能用 CNAME,只能用 A/AAAA。用 CNAME 会和该域必须存在的 NS/SOA 记录冲突。想让根域指向 CDN,只能用服务商的 ALIAS / CNAME 扁平化(伪记录)。
  • CNAME 不能与同名的其他记录共存,www 有了 CNAME 就不能再加 A 记录。
  • @ 表示根域,* 是泛解析(*.example.com 全部落到同一 IP,方便多子域/多租户)。

5.3 TTL 与解析生效时间

TTL(Time To Live,单位秒)告诉各级缓存"这条记录可以缓存多久"。

dig www.example.com          # 看 ANSWER 段里的 TTL 倒计时
dig +trace www.example.com   # 从根开始完整跟踪解析路径
dig @8.8.8.8 www.example.com # 指定 DNS 服务器查(绕过本地缓存)
dig NS example.com           # 看权威 DNS 是谁
nslookup www.example.com     # Windows 常用
TIP

📌 为什么改了解析"没生效"?因为链路上全是缓存:浏览器缓存 → 系统 DNS 缓存 → 本地/公共 DNS 缓存,最长按旧 TTL 保留。换 IP 的正确做法是:先把 TTL 调低(如 60s),等旧 TTL 过期后再改 IP,割接完成再调回 600s。查"权威是否已更新"要用 dig @权威NS 域名,别看本地结果。

ipconfig /flushdns              # Windows 清本地 DNS 缓存
sudo resolvectl flush-caches    # Linux systemd-resolved

5.4 域名绑定到服务器:完整链路

从买域名到 https://example.com 能打开,要跑通四段:

① 域名注册/实名 → ② DNS 解析到服务器公网 IP(A 记录) ↓ ③ 服务器放行 80/443 + Nginx server_name 匹配域名 ↓ ④ 申请证书开 HTTPS,80 跳 443

② DNS 侧:在 DNS 服务商加记录

主机记录 类型 值 说明
@ A 服务器公网 IP 根域
www A / CNAME IP 或 example.com 常见做 301 到根域
api A 服务器公网 IP 子域指同一台机

③ 服务器侧:一个 IP 靠 server_name 区分多站点

server {                       # 默认兜底:未匹配任何域名的请求(含直接用 IP 访问)
    listen 80 default_server;
    server_name _;
    return 444;                # 直接断开,避免站点被野域名解析蹭流量
}

server {
    listen 80;
    server_name example.com www.example.com;
    location / { proxy_pass http://127.0.0.1:3000; }
}
TIP

📌 一个 IP 怎么承载多个域名?靠 HTTP/1.1 的 Host 头(呼应 4.1):TCP 只认 IP+端口,Nginx 拿到请求后读 Host 再匹配 server_name 选中对应 server 块。HTTPS 下客户端在 TLS 握手的 ClientHello 里通过 SNI 扩展提前明文告知域名,Nginx 才能选对证书——这也是运营商/防火墙能按域名封锁 HTTPS 的原因。

④ 证书:证书绑定的是域名而不是 IP,且签发前域名必须已解析到本机、80 端口外网可达(ACME HTTP-01 验证)。若域名还没解析或在国内需备案,可用 DNS-01 验证(加一条 TXT 记录)来签发,还能签泛域名 *.example.com。

5.5 域名打不开的排查顺序

① dig 域名 解析结果对不对(拿到的是不是你的 IP) ② dig @权威NS 域名 权威已更新但本地是旧的 → 缓存问题,等 TTL ③ ping / telnet IP 80 服务器网络与端口通不通(安全组 + ufw 都要放行) ④ curl -H 'Host: 域名' http://IP/ 绕过 DNS 直连,验证 Nginx 匹配是否正确 ⑤ nginx -t / error.log server_name 拼写、重复 server 块、证书路径 ⑥ curl -vI https://域名 看证书 CN/SAN 是否包含该域名、是否过期

常见坑:

  • 云服务器安全组没放行 80/443(比本机防火墙更容易被忘)。
  • 解析填了内网 IP 或旧机器 IP。
  • sites-enabled/ 里存在重复 server_name,后加载的块覆盖前者(见 部署文档)。
  • 国内主机绑定域名未备案,80/443 被拦截,表现为"解析正常但访问超时"。
  • 证书只签了 example.com,访问 www.example.com 报 NET::ERR_CERT_COMMON_NAME_INVALID。

5.6 CDN

内容分发网络:把静态资源缓存到离用户最近的节点。

  • 用户请求 cdn.example.com/image.jpg
  • DNS 返回最近的 CDN 节点 IP
  • 节点命中则直接返回,未命中回源站拉取

回源 vs 命中:

  • 命中:CDN 节点有缓存
  • 回源:CDN 节点没有,向源站请求

5.7 负载均衡

四层负载均衡(L4):

  • 基于 IP + 端口转发
  • 不解析 HTTP 内容
  • 工具:LVS、Nginx stream

七层负载均衡(L7):

  • 基于 URL、Header、Cookie 转发
  • 可以做限流、重写、鉴权
  • 工具:Nginx、HAProxy、Traefik

负载均衡算法:

  • 轮询
  • 加权轮询
  • 最少连接
  • 一致性哈希(相同请求打到同一台机器)

6 · NAT / VPN / 代理

6.1 NAT

网络地址转换:把私有 IP 转成公网 IP。

类型:

  • 静态 NAT:一对一
  • 动态 NAT:从地址池动态分配
  • PAT(端口地址转换):多对一,用端口号区分

6.2 VPN

虚拟专用网络:在公网上建立加密隧道。

协议:

  • IPSec
  • OpenVPN
  • WireGuard(新一代,简洁高效)

场景:

  • 远程办公访问公司内网
  • 跨地域机房内网互通

6.3 代理

  • 正向代理:代理客户端,隐藏客户端身份
  • 反向代理:代理服务端,隐藏真实服务器
  • 透明代理:客户端无感知

Nginx 通常做反向代理:

server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://backend;
    }
}

7 · Wireshark 抓包实战

7.1 基本使用

捕获过滤器(在抓包前过滤,BPF 语法):

tcp port 80 and host 192.168.1.1

显示过滤器(抓包后过滤):

ip.addr == 192.168.1.1 http.request.method == "GET" tcp.flags.syn == 1 and tcp.flags.ack == 0

7.2 分析 TCP 三次握手

  1. 过滤 tcp.port == 80
  2. 找到 SYN → SYN+ACK → ACK 三个包
  3. 右键 → Follow → TCP Stream,查看完整通信

7.3 排查问题

  • 重传过多:tcp.analysis.retransmission
  • RST 包:连接被异常关闭
  • 零窗口:接收方缓存满了,发送方暂停
  • 乱序:网络抖动导致包到达顺序不一致

7.4 HTTPS 解密

设置环境变量:

export SSLKEYLOGFILE=/tmp/sslkeys.log

然后在 Wireshark 中配置这个文件,就能解密 Chrome/Firefox 的 TLS 流量。