计算机网络学习笔记
从协议栈到抓包实战,系统理解网络通信的底层原理和常见面试考点。
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 三次握手

为什么是三次?
防止历史连接请求被服务端接受。如果只握手两次,客户端已经断开的旧 SYN 到达服务端,服务端会建立半连接。
3.3 四次挥手
客户端最后发送 ACK 后进入 TIME_WAIT 状态,等待 2MSL(Maximum Segment Lifetime)。
为什么需要 TIME_WAIT?
- 确保最后的 ACK 被对方收到,如果没收到,对方会重发 FIN。
- 等待网络中残留的报文段消失,避免影响下一个连接。
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:
- 浏览器缓存
- 操作系统缓存
- hosts 文件
- 本地 DNS 服务器(ISP 提供)
- 根 DNS 服务器
- 顶级域 DNS 服务器(.com)
- 权威 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 三次握手
- 过滤
tcp.port == 80
- 找到 SYN → SYN+ACK → ACK 三个包
- 右键 → Follow → TCP Stream,查看完整通信
7.3 排查问题
- 重传过多:
tcp.analysis.retransmission
- RST 包:连接被异常关闭
- 零窗口:接收方缓存满了,发送方暂停
- 乱序:网络抖动导致包到达顺序不一致
7.4 HTTPS 解密
设置环境变量:
export SSLKEYLOGFILE=/tmp/sslkeys.log
然后在 Wireshark 中配置这个文件,就能解密 Chrome/Firefox 的 TLS 流量。