本页定位 · Computer Networks

你写的每个接口、每次 fetch、每个 502 报错,背后都是一套网络协议在跑。不懂网络,排障全靠猜。本页以"一次请求从浏览器到服务器再回来"为主线,把 TCP/IP 分层、HTTP 全家桶、DNS/CDN、负载均衡、网络安全和诊断工具讲成人话。学完你至少能:看懂抓包、说清"为什么慢"、定位"卡在哪一层"、写出一个说得过去的 HTTPS/Nginx 配置。基线:HTTP/2 已成主流、HTTP/3(QUIC) 加速普及、TLS 1.3 是默认。

阅读建议:别死记协议字段,抓住"为什么这么设计"——每个机制都是为了解决某个真实痛点(可靠、安全、快、可扩展)。每章末尾的 .trap 是我踩过或常见的新手坑,重点看。配合 系统设计 一页,网络知识会立刻变成架构里的具体决策。

1

TCP/IP 模型:数据是怎么一层层"穿上衣服"又"脱掉"的

Layering · TCP Handshake · Flow & Congestion Control · UDP

复杂系统靠分层解耦。网络也如此:把"怎么发比特""怎么找路""怎么保证可靠""怎么表达业务"拆成不同的层,每层只管自己的事。实战中最常用的是TCP/IP 四层模型,理论教学里常对照 OSI 七层。

分层模型:OSI 七层 vs TCP/IP 四层

为什么要有"层"?一句话:把复杂问题切成小块,每层独立演进、独立排障。你改 HTTP 不用动网卡驱动,换光纤不用改应用代码。下面把教科书里的 OSI 和工程里的 TCP/IP 对照起来看,别被两套名词搞晕。

OSI 层TCP/IP 对应干啥代表协议 / 设备
应用层应用层业务数据(网页/邮件/接口)HTTP、DNS、WebSocket
表示层加密、压缩、编码TLS、gzip
会话层会话维护(多并入应用层)
传输层传输层端到端可靠/不可靠传输TCP、UDP
网络层网络层寻址与路由(找路)IP、路由器
链路层链路/物理层相邻节点怎么传帧以太网、交换机
物理层怎么传比特(电压/光)网线、光纤、Wi-Fi

论分层的"封装"思想

发送时,每层给数据加自己的"头"(Header),像套娃:应用数据 → 加 TCP 头 → 加 IP 头 → 加以太网头,到达对端再一层层拆开。这个"加头/拆头"过程叫封装与解封装。理解它,你抓包时看到的一堆协议层才算"对上了号"。

三次握手:连接是怎么"握"出来的

TCP 是面向连接的——真正传数据前,双方要先确认"能发也能收"。这就是三次握手。很多人死记"SYN/SYN-ACK/ACK",但要知道每个包在干什么。

客户端 --SYN(seq=x)---------> 服务端 # 1. 我想连你,带上我的初始序号 x 客户端 <--SYN(seq=y),ACK(x+1)-- 服务端 # 2. 收到,我也想连,确认你的 x,带上我的 y 客户端 --ACK(y+1)-----------> 服务端 # 3. 确认收到你的 y,连接建立,开始传数据
为什么是三次而不是两次

两次握手无法确认客户端的接收能力,还可能建起一条基于"过期连接请求"的脏连接。三次让双方在传数据前都确认"彼此能发也能收",并同步了初始序号。顺便说:握手不传业务数据,第三次 ACK 之后才能发。这也是 SYN Flood 攻击能打瘫服务器的原因——半连接占满队列。

四次挥手:连接是怎么"体面分手"的

建立要三次,断开却要四次,因为 TCP 是全双工——两个方向的数据流独立关闭。被动方收到 FIN 后,可能还有数据要发,所以 ACK 和自己的 FIN 不能合并。

客户端 --FIN---------> 服务端 # 1. 我没数据要发了,请求关闭(主动方→被动方) 客户端 <--ACK--------- 服务端 # 2. 收到,先回确认(但被动方可能还在发数据) 客户端 <--FIN--------- 服务端 # 3. 被动方数据也发完了,它也发 FIN 客户端 --ACK---------> 服务端 # 4. 确认,进入 TIME_WAIT

论TIME_WAIT 不是 bug,是保险

主动方发完最后一个 ACK 不会立刻消失,而是进 TIME_WAIT 等 2×MSL(报文最大存活时间,通常 60s)。目的是:① 确保最后一个 ACK 真到了(丢了被动方会重发 FIN);② 让网络上残留的旧报文过期,不复用到新连接。代价是高并发短连接下 TIME_WAIT 堆积,可用 tcp_tw_reuse / 连接池缓解,但别轻易关掉它。

可靠性机制:序号、确认与重传

IP 层本身"尽力而为"——丢包、乱序、重复它全不管。TCP 在传输层把可靠性补上,核心三件套:

  • 序号(Sequence):给每个字节编号,接收方能重组、去重。
  • 确认(ACK):收到后回"我期待的下一个序号",捎带在反向数据里(累计确认)。
  • 重传:超时没收到 ACK,或收到三个重复 ACK(快速重传),就重发。
丢包情况TCP 反应
单个包丢了,后续包到了收到 3 个重复 ACK → 快速重传(不等超时)
整段都没回 ACK超时重传(RTO 随历史 RTT 动态估算)
包乱序到达接收端缓存,按序号重组后上交

流量控制:别把对方"灌爆"

发送方不能一股脑狂发,接收方缓冲区可能已满。滑动窗口(Sliding Window)就是接收方告诉发送方"我还能收多少"的机制——窗口大小在 TCP 头里随 ACK 通告,动态变化。

# 接收方通告窗口(rwnd)随处理速度变化 服务端 ACK: ack=1001, win=4096 # 我现在能收 [1001, 1001+4096) 服务端 ACK: ack=3001, win=1024 # 应用读得慢,窗口缩小,发送方减速 服务端 ACK: ack=3001, win=0 # 窗口为 0 = 暂停!发送方只能发"窗口探测"

论流量控制 vs 拥塞控制:别混了

流量控制管"接收方能不能收"(端到端,靠窗口);拥塞控制管"网络扛不扛得住"(整条链路,靠拥塞窗口 cwnd)。两者叠加,发送方实际窗口 = min(rwnd, cwnd)。一个是怕压垮对端,一个是怕压垮网络。

拥塞控制:全网一起"踩刹车"

如果每个人都按自己窗口狂发,网络会整体拥堵、大面积丢包、全面减速——拥塞崩溃。TCP 用一套"试探+退让"算法避免它:

阶段/算法行为直觉
慢启动 Slow Startcwnd 从 1 开始指数增长先试探网络能扛多少
拥塞避免到阈值后改线性增长接近极限就谨慎加
快重传 + 快恢复3 个重复 ACK → 减半 cwnd,不回到慢启动轻度丢包,温和退让
超时cwnd 直接归 1,重新慢启动严重丢包,狠踩刹车
新手最常误解的"慢启动"

"慢启动"名字吓人,其实一点不慢——它是指数涨,几个 RTT 就到很大。真正慢的是触发超时后的"归一再涨"。所以系统设计里强调"长连接复用":每次新建 TCP 都要经历慢启动,短连接密集时吞吐量上不去。

UDP:当"快"比"可靠"重要

不是所有场景都要可靠。视频通话、游戏、DNS 查询、直播——丢了重传反而更糟(你不在乎 30ms 前的那一帧)。UDP 没有握手、没有重传、没有连接,发完就忘,延迟极低。

维度TCPUDP
连接有(三次握手)无
可靠是(确认/重传)否
顺序保证不保证
头部开销20 字节起8 字节
典型用途网页、接口、文件音视频、游戏、DNS、QUIC
# 用 dig 看一次真实的 UDP DNS 查询(默认 53/UDP) dig +stats +noall +answer example.com ;; Query time: 8 msec # 一次 UDP 往返的典型时延,HTTP/3 也借它做传输
2

HTTP 家族:从 1.1 到 3,页面是怎么变快的

HTTP/1.1 · HTTPS/TLS · HTTP/2 Multiplexing · HTTP/3 QUIC

HTTP 是应用层协议里你打交道最多的。它持续进化的核心动力就一个:让页面更快、更安全。这一章把 1.1 → HTTPS → 2 → 3 的来龙去脉讲清楚,让你选型时心里有数。

HTTP 是什么:请求/响应模型

HTTP 是无状态的"请求-响应"协议:客户端发一个请求报文,服务端回一个响应报文,两者结构清晰。理解报文长什么样,才会调接口、看日志。

# 一个典型 GET 请求报文(简化) GET /api/user/1 HTTP/1.1 Host: api.example.com Authorization: Bearer <token> Accept: application/json # 服务端响应 HTTP/1.1 200 OK Content-Type: application/json Content-Length: 38 {"id":1, "name":"MJ"}

论"无状态"意味着什么

每个请求自带全部上下文,服务器不记得"上一个请求是谁"。登录态只能靠 Cookie / Token / 请求里带状态来传递。这正是为什么分布式下要做"会话保持"或把状态外置到 Redis——见系统设计的会话保持一节。

HTTP/1.1:长连接与队头阻塞

1.0 时代每请求都要新建 TCP(慢启动、握手开销),1.1 用 Connection: keep-alive 让一条连接复用多次。但它有个硬伤——队头阻塞(Head-of-line Blocking):同一连接里,前一个响应没回来,后面的请求只能排队。

HTTP/1.1 优化作用遗留问题
keep-alive 长连接省去重复握手仍受队头阻塞
管线化 pipelining请求可连续发响应仍须按序,几乎没人用
浏览器开 6 个并发连接缓解阻塞连接数爆炸、慢启动重复
别慌,1.1 仍是现实主力

虽然 2/3 在普及,但大量内部服务、老网关还是 1.1。懂得它的局限,才能解释"为什么我页面 100 个请求加载很慢"——多半是队头阻塞 + 并发连接数被浏览器限制。

HTTPS 与 TLS:给 HTTP 穿盔甲

裸 HTTP 明文传输,谁在中间都能看、能改。HTTPS = HTTP + TLS,在 TCP 之上加了一层加密。TLS 1.3 现在是主流,握手从 2-RTT 降到 1-RTT(甚至 0-RTT 恢复)。

# 用 curl 看站点用了什么协议/加密套件 curl -v https://example.com 2>&1 | grep -i "SSL\|TLS\|http" # 典型输出:SSL connection using TLSv1.3 / cipher TLS_AES_256_GCM

TLS 握手细节:证书链与密钥协商

TLS 握手干三件事:① 身份认证(证书确认对方真是它声称的服务器,防中间人);② 协商密钥(双方生成只有彼此知道的对称密钥);③ 加密传输(之后所有数据用该密钥加密)。

# TLS 1.3 简化握手(1-RTT) ClientHello ──> 服务端 # 支持的加密套件、密钥交换参数 <── ServerHello + 证书 + 密钥参数 # 双方各自算出相同的"会话密钥",证书验真后开始加密应用数据

论证书链:为什么"信任"能传递

浏览器内置一批根 CA(信任锚)。服务器出示的证书由中间 CA 签发,中间 CA 又由根 CA 签发,形成证书链。浏览器沿链向上验证,直到命中某个信任的根,就相信"这证书是真的"。所以证书过期/域名不匹配/链不完整都会报错——不是浏览器矫情,是信任断了。

证书报错别忽略

浏览器红标"证书不受信任"通常是域名不匹配、证书过期、或公司内网自建 CA 未信任。不该点"继续"绕过——它可能正是中间人攻击的信号。内网自签证书请先把根 CA 装进系统/浏览器信任库。

HTTP/2:多路复用把队头阻塞打散

HTTP/2 在同一 TCP 连接上开多个流(Stream),每个流独立收发,互不阻塞;再配头部压缩(HPACK)和二进制帧,把 1.1 的痛点基本解决。一个连接并发几十个请求不再排队。

# 验证站点是否支持 h2 curl -I --http2 https://example.com | head -1 # 或看响应头:HTTP/2 200 # 多路复用示意:一条 TCP 上同时跑 stream1/stream2/stream3 # [stream1:data][stream2:headers][stream3:data][stream1:data]...

论HTTP/2 没根除的"底层阻塞"

多路复用只解决应用层队头阻塞。底层还是一条 TCP,一旦这个 TCP 丢了一个包,所有流都得等它重传——这叫 TCP 层队头阻塞。弱网(高丢包)下 HTTP/2 反而可能不如 1.1 的多连接。这就是 HTTP/3 要解决的。

HTTP/3:把传输层换成 QUIC(基于 UDP)

HTTP/3 不再跑在 TCP 上,而是跑在 QUIC 上——QUIC 自己用 UDP 实现可靠、拥塞控制,并且每个流独立:一个流丢包只阻塞自己,不影响别的流。还内置 TLS 1.3、连接迁移(换 IP 不断线)。

版本传输层队头阻塞握手 RTT
HTTP/1.1TCP应用层有TCP+TLS 多次
HTTP/2TCP仅 TCP 层TCP+TLS 多次
HTTP/3QUIC/UDP无(流独立)1-RTT(恢复 0-RTT)
QUIC 也有代价

UDP 常被企业防火墙/中间设备"另眼相看"甚至丢弃;QUIC 加密了更多头部,给运营商做按流限速/观测带来困难;服务端 CPU 开销略高。所以现实是渐进部署:支持就升 3,不支持回落 2/1.1。Nginx/Envoy 都已支持。

该用哪个版本:选型与降级

结论很朴素:能上 2 就上 2,面向公网弱网优先试 3,内部服务 1.1 也够用。关键是配置好 TLS 1.3、开启压缩与连接复用,并让服务端优雅协商降级。

# Nginx 同时开启 h2 与 h3(alt-svc 告知客户端可升级) listen 443 ssl; http2 on; add_header Alt-Svc 'h3=":443"; ma=86400'; # 告诉浏览器:我也支持 HTTP/3
3

DNS 与 CDN:先"找人",再把内容"搬到家门口"

DNS Resolution · Recursive/Authoritative · Edge Cache

你输 example.com,浏览器第一件事不是发请求,而是问 DNS"这名字对应哪个 IP"。这一查通常走 UDP 53,是打开网页的第一道时延。CDN 则更进一步:把内容缓存到离用户最近的边缘节点,让用户"就近取货"。

DNS 是什么:域名到 IP 的电话簿

人记名字,机器认 IP。DNS 就是这套"名字→IP"的分布式数据库。它分层、去中心化:根 → 顶级域(.com) → 权威服务器,逐级往下查。

# 追一条解析的完整链路(从根到权威) dig +trace example.com # . → com. → example.com. 的 NS → 最终 A 记录 IP

完整的解析流程:递归与迭代

你本机只问"本地 DNS(递归解析器)",后面的脏活累活它替你干:向根、向 .com、向权威服务器一级级迭代查询,最后把 IP 还给你。

你的浏览器 → 本地 DNS(递归) 本地 DNS → 根服务器: .com 在哪? → 返回 .com 的 NS 本地 DNS → .com 服务器: example.com 在哪? → 返回权威 NS + IP 本地 DNS → 权威服务器: example.com 的 A? → 返回 93.184.x.x 本地 DNS → 你的浏览器: 缓存并返回 IP

论为什么设计成"递归 + 迭代"混合

如果每台客户端都去问根,根会被打爆。递归让本地 DNS 替你跑全流程(你只问一次);迭代让根/顶级域只指路、不代查,把负载分散到各级。这个分工是 DNS 能扛住全球查询量的关键。

递归解析器 vs 权威服务器

两类角色别搞混:递归解析器(你运营商给的,或 8.8.8.8 / 1.1.1.1)负责"替你查到底"并缓存;权威服务器是你域名真正注册、由它持有解析记录的地方(如域名注册商/Cloudflare)。

角色谁拥有职责
递归解析器ISP / 公共 DNS替客户端迭代查询 + 缓存结果
权威服务器域名持有者返回该域名的真实记录
根 / TLDICANN / 注册局指路到对应权威

记录类型:A / AAAA / CNAME / MX / TXT

DNS 不只是"名字→IPv4"。不同记录类型承载不同信息,配错一类就会出怪问题。

# 常见记录一览 example.com. A 93.184.216.34 # IPv4 地址 example.com. AAAA 2606:2800:... # IPv6 地址 www.example.com CNAME example.com. # 别名,指向另一个域名(不能和 MX 同名的根用) example.com. MX 10 mail.example. # 邮件服务器 example.com. TXT "v=spf1 include:..." # 文本,常用于 SPF/域名校验
CNAME 的坑

CNAME 是"别名",DNS 规则规定:一个名字一旦是 CNAME,就不能再有其他记录(包括它自己根域的 MX、TXT)。所以根域 example.com 通常不能直接 CNAME 到 CDN,要用"ALIAS/CNAME 扁平化"或 ANAME。新手把根域设成 CNAME,邮件/校验全失效。

TTL 与缓存:为什么改 DNS 不立刻生效

每条记录带一个 TTL(生存时间,秒),告诉解析器"这个值能缓存多久"。你改了 A 记录,旧 IP 可能还在别人缓存里,要等 TTL 过期才更新。所以——

  • 上线前临时把 TTL 调小(如 60s),改完再调大,避免切换生效慢。
  • 紧急切换 IP 时,TTL 大 = 全球生效慢,要有心理预期。

CDN:把内容推到边缘

CDN(内容分发网络)在全球部署边缘节点,把静态资源(图片、JS、视频)缓存到离用户最近的地方。用户不再跨半个地球打你的源站,延迟和源站压力都骤降。

# 用户 -> 最近的边缘节点(命中缓存直接返回) # 未命中 -> 回源(Origin Pull) 取一次,再缓存下来 # 验证是否命中 CDN 缓存 curl -I https://cdn.example.com/logo.png | grep -i "x-cache\|cf-cache" # 例:x-cache: HIT 表示边缘命中;MISS 表示回源了

CDN 缓存策略与回源

缓存什么、缓存多久、怎么刷新,是 CDN 配置的精髓。常见策略:

策略做法注意
按文件类型图片/JS 长缓存,HTML 短缓存HTML 长缓存会导致发版看不到
文件名哈希main.a1b2c3.js 带指纹可放心长缓存,发版即新名
回源超时/重试边缘回源失败走兜底源站挂了返回 stale-while-rerror

论CDN 也参与"安全"

现代 CDN(Cloudflare 等)还能做 DDoS 清洗、WAF、TLS 卸载。它既是加速器,也是第一道防护墙——这也是为什么很多站把 80/443 只暴露给 CDN,源站藏 behind。详见第五章安全。

4

负载均衡与反向代理:流量怎么被"分摊"和"改写"

L4 / L7 · Nginx / Envoy · Session Affinity

单机扛不住,就上多台;多台就得有人在前面对外"一个门面",内部把流量分匀——这就是负载均衡。它常常和反向代理合体:不仅转发,还做 TLS 卸载、缓存、限流、改写。

为什么需要负载均衡

单台服务器有容量上限,且一挂全挂。负载均衡(LB)把流量分摊到多台健康后端,既提升吞吐,又通过"健康检查 + 剔除故障节点"实现高可用。它是系统设计里"横向扩展"的物理落地。

# 经典拓扑 用户 → [负载均衡器] → 后端1 ├→ 后端2 └→ 后端3 # 某后端挂了,LB 自动摘掉

L4 vs L7:在哪一层做决策

负载均衡按"看多深"分代:L4(传输层)只看 IP+端口,转发快、不解析内容;L7(应用层)能看 URL、Header、Cookie,可做更聪明的路由(如把 /api 和 /static 分到不同集群)。

维度L4 负载均衡L7 负载均衡
决策依据IP、端口、TCP 连接URL、Host、Header、Cookie
性能极高(不拆应用层)略低(要解析内容)
典型LVS、云厂商 NLBNginx、Envoy、云 ALB
能做的均匀分摊按路径路由、重写、限流、WAF

调度算法:轮询 / 加权 / 最少连接 / 一致性哈希

流量怎么分?不同算法适用不同场景:

  • 轮询(Round Robin):依次分配,简单但忽略机器差异。
  • 加权轮询:强机器多分,照顾异构集群。
  • 最少连接:发给当前连接最少的节点,更均衡。
  • 一致性哈希:同个用户/IP 总落到同一节点,扩缩容时只影响少量 key——适合有状态/缓存场景。

论一致性哈希为什么是"扩容友好"的

普通取模 hash(key) % N 在加一台机器时,几乎全部 key 重新映射,引发缓存雪崩。一致性哈希把节点和数据都放到一个哈希环上,新增节点只"抢走"环上相邻的一小段,影响最小。Redis 集群、分库分表都在用这招。

反向代理:不只是转发

正向代理是"替客户端出门"(你公司内网翻墙用的那种);反向代理是"替服务器接客"——客户端以为在跟它聊,其实它背后是一群后端。反向代理顺手能干很多事:

# 反向代理常见附加价值 TLS 卸载 # 在代理处解密,后端跑明文 HTTP,省 CPU 动静分离 # 静态资源代理直接返回,动态转发后端 限流/熔断 # 在入口挡住超额流量 统一入口 # 多服务共用一个域名/端口

Nginx 配置实战

Nginx 是事实标准的 L7 反向代理。一个最小可用配置长这样:

# nginx.conf 片段:反向代理 + 负载均衡 upstream app_cluster { least_conn; # 最少连接调度 server 10.0.0.1:8080 weight=2; server 10.0.0.2:8080; server 10.0.0.3:8080 backup; # 备用机,主力都挂才上 } server { listen 443 ssl; location /api/ { proxy_pass http://app_cluster; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 把真实 IP 透传给后端 } }
后端拿到的 IP 全是代理的

不配 X-Real-IP / X-Forwarded-For,后端日志里客户端 IP 全是 LB 的地址,限流、审计、风控全错。务必在代理处透传真实 IP,后端读取对应 Header。

Envoy 与服务网格

当服务变多,Nginx 这种"中心代理"不够用了。Envoy 是边车(sidecar)模式的数据面:每个服务旁挂一个 Envoy,统一做 mTLS、重试、熔断、可观测。配合 Istio 等控制面,就是"服务网格"。它的优势是能力下沉到每个服务边,不用改业务代码。

# Envoy 核心概念(伪配置):listener 接、cluster 转、route 路由 static_resources: listeners: [{ address: 0.0.0.0:8080, filter_chains: [http] }] clusters: [{ name: app, hosts: [10.0.0.1:8080, 10.0.0.2:8080] }]

会话保持:Sticky Session

如果后端把登录状态存在自己内存里(没外置到 Redis),那同一个用户的请求必须总打到同一台,否则"刷新就掉登录"。这就是会话保持(Session Affinity):LB 按 Cookie 或 IP 把用户粘到固定节点。

# Nginx 用 cookie 做粘性(ip_hash 也可,但 NAT 下不准) upstream app { sticky cookie srv_id expires=1h; # 首次分配并种 cookie,之后按它路由 server 10.0.0.1:8080; server 10.0.0.2:8080; }

论会话保持是"补丁",不是"正解"

粘性会带来问题:某节点挂了,粘它的用户全掉线;扩容时负载不均。更好的做法是无状态化——把会话放 Redis/JWT,后端随便哪台都能处理。系统设计里讲"把状态外置",正是为干掉粘性。

5

网络安全:握手、证书与那些"看不见的攻击"

TLS Chain · MITM · DDoS · Hardening

网络是开放信道,意味着别人也能听、能插嘴、能冒充。这一章讲清"信任怎么建立"(证书链)、"常见的刀在哪"(中间人、DDoS、Web 攻击),以及"怎么防"。安全不是事后加的,是设计时就得想。

威胁模型:你要防谁

先想清楚对手是谁,才知道防什么:窃听者(想看内容)、篡改者(想改内容)、冒充者(想假装成你)、拒绝服务者(想让你瘫)。TLS 解决前三者,DDoS 防护解决后者。

威胁目标对应防护
窃听读明文TLS 加密
篡改改内容TLS 完整性校验
冒充伪装成服务端证书 + 域名校验
拒绝服务打瘫服务限速、清洗、冗余

证书链与信任锚

前面 TLS 握手提过:浏览器内置根 CA,服务器证书由中间 CA 签发。验证时沿"叶子证书 → 中间 CA → 根 CA"向上,任一环断裂就报不安全。

# 查看服务器证书链是否完整 openssl s_client -connect example.com:443 -servername example.com # 输出里应看到:证书链(leaf→中间)、Verify return code: 0 (ok) # 常见错误:0 (unable to verify) = 链没配全或系统不信任该根
证书链"少中间"是高发事故

很多同学只在服务端配了叶子证书,忘了把中间证书一起发。老浏览器自带根、能补中间,新客户端/移动端常常直接报错。用 openssl 验证链完整是上线前的必做项。

中间人攻击 MITM

MITM:攻击者插在你和服务器中间,假装是服务器(对你)、假装是你(对服务器),两边 TLS 各自建立,于是它能看能改。公共 Wi-Fi 下尤其危险。

论为什么"忽略证书错误"等于开门

证书校验正是识别 MITM 的机制。一旦你点"继续访问(风险)",就等于关掉了这层识别,攻击者可以毫无阻碍地中转你的流量。开发自签证书请走正道:把自签根 CA 加入信任库,而不是全局忽略证书错误。

DDoS:分布式拒绝服务

DDoS 不是"黑进系统",而是用海量肉鸡把你的带宽/连接/CPU 打满,正常用户进不来。分几类:

  • volumetric(流量型):UDP/ICMP 洪流塞满带宽。靠运营商/云清洗。
  • 协议型:SYN Flood 占满半连接队列。靠 SYN Cookie、LB 防护。
  • 应用型:海量真实 HTTP 请求打慢接口。靠限流、缓存、WAF。
# Nginx 层面对单 IP 限连/限速,缓解应用型 DDoS limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; server { location /api/ { limit_req zone=one burst=20 nodelay; # 超了直接 503,保护后端 } }

常见 Web 攻击与防护

即便传输加密,应用层仍有经典漏洞,必须懂:

攻击原理防护
XSS注入脚本到页面,偷 Cookie/钓鱼输入输出转义、CSP、HttpOnly Cookie
CSRF借用户身份发非本意请求CSRF Token、SameSite Cookie
SQL 注入拼 SQL 被执行预编译/参数化查询,永拼字符串
中间人截获明文/伪造证书全站 HTTPS + HSTS
SQL 注入至今仍是头号漏洞

永远用参数化查询(Prepared Statement),别用字符串拼接 SQL。一句 "SELECT * FROM u WHERE name='"+name+"'" 就能被 ' OR '1'='1 打穿。ORM 默认帮你做了,但手写 SQL 时千万别松懈。

加密基础:对称 / 非对称 / 哈希

TLS 背后是三套原语的组合:

# 对称加密:一把钥匙加解密,快,但钥匙怎么安全给对方? AES-256-GCM # 握手后传数据用的就是它 # 非对称加密:公钥加密、私钥解密(或反过来签名) RSA / ECC # 握手时用来安全协商出"对称密钥" # 哈希:单向摘要,验完整性、存密码 SHA-256 # 证书指纹、密码加盐哈希都用它

论为什么不全用非对称加密

非对称慢几十上百倍。所以现实是混合:用非对称(RSA/ECC)在握手时安全地协商出一把对称密钥,之后海量数据都用这把对称密钥(AES)加密。各取所长——非对称管"安全交换",对称管"高效传输"。

防御纵深:WAF / 限流 / 零信任

安全没有银弹,靠纵深防御:边界有 WAF 拦恶意请求,入口有限流挡突发,内网用 mTLS 让服务间也得认证(零信任:不默认内网可信),再加日志审计和定期演练。

# HSTS:告诉浏览器"以后只准 HTTPS 访问我" add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; # 防 SSL Strip(把 https 降级成 http 的攻击)的第一道闸
6

网络诊断:把"卡在哪"说清楚

ping · curl · traceroute · tcpdump / Wireshark

线上出问题,不能靠"重启试试"。这一章给你一套逐层定位的工具箱:ping/traceroute 看通不通、curl 看 HTTP 全过程、tcpdump/Wireshark 抓原始包。目标是把"网不好"变成"第 3 跳丢了 20% 包"。

排障方法论:分层定位

别一上来瞎试。按 OSI/TCP-IP 从下往上剥:

# 一张排障 Checklist 链路层 网线/Wi-Fi 通?网卡 up? 网络层 ping 通?traceroute 第几跳开始丢? 传输层 端口能连?telnet/nc 试 TCP 应用层 curl 看 HTTP 状态/耗时;dig 看 DNS # 每层一个工具,定位到"哪层"再深挖

论先证伪,再归因

别凭感觉下结论"是 DNS 的问题"。用证据一步步排除:DNS 解析快 → 不是它;ping 通 → 网络层 OK;telnet 端口通 → 传输层 OK;只剩应用层。这种"排除法"比拍脑袋靠谱一万倍。

ping 与 traceroute:连通性与路径

ping 看网络层通不通、延迟多少、丢包率;traceroute(Windows 叫 tracert)看路径上每一跳的延迟,定位"从哪开始慢/丢"。

# ping:看丢包与 RTT ping -c 20 example.com # 20 packets transmitted, 2 received, 90% packet loss ← 丢包报警 # traceroute:看每一跳延迟,定位瓶颈跳 traceroute example.com # 第 9 跳突然 * * * 或延迟从 20ms 跳到 200ms → 瓶颈在那
traceroute 出现 * 不一定是挂了

很多路由器默认不回应 ICMP(防探测/省 CPU),所以中间跳显示 * * * 但后面跳又正常,是常见现象,不代表断。真断的特征是某一跳之后全部变 *。

curl -v:看清 HTTP 全过程

curl -v 把 DNS 解析、TCP 连接、TLS 握手、请求/响应头全打出来,是排查"接口为什么慢/为什么 4xx"的利器。

# -w 还能精确输出各阶段耗时(秒) curl -o /dev/null -s -w "dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n" https://example.com # dns 大 → DNS 慢;tls 大 → 握手慢;ttfb 大 → 服务端处理慢

论把"慢"拆成时间切片

time_namelookup(DNS)、time_connect(TCP)、time_appconnect(TLS)、time_starttransfer(首字节 TTFB)、time_total(总耗时)。哪一截长就治哪截——DNS 慢加缓存,TLS 慢看是否每次重连,TTFB 慢查服务端/DB。分而治之,别笼统说"网不好"。

tcpdump:命令行抓包

抓包是"看原始协议字段"的终极手段。tcpdump 在服务端无界面环境尤其好用,能按端口/主机/协议过滤。

# 抓 443 端口、主机 example.com 的包,存文件用 Wireshark 细看 tcpdump -i any -n host example.com and port 443 -w cap.pcap # 或实时看 TCP 握手:SYN / SYN-ACK / ACK 一目了然 tcpdump -i any -n 'tcp[tcpflags] & (tcp-syn|tcp-ack) != 0' host example.com

Wireshark:图形化分析

Wireshark 把 pcap 做成可点的树状结构,能跟完一次完整 TLS 握手、看每个 TCP 重传、分析"为什么首字节慢"。新手最该做的:抓一次自己访问 https 站点的包,跟着看三次握手 → TLS → HTTP。

# 过滤表达式速查 tcp.flags.syn==1 and tcp.flags.ack==0 # 只看 SYN(建连起点) tls.handshake # 只看 TLS 握手 http.response.code >= 400 # 只看出错响应 tcp.analysis.retransmission # 只看重传(丢包证据)
抓不到包?先确认"听对网卡/方向"

-i any 听所有网卡;容器/诺基环境可能流量走 docker0/lo。还有本地回环(127.0.0.1)在部分系统上 tcpdump 抓不到,要用 tcpdump -i lo。方向错了,抓一晚上也是空的。

延迟与丢包排查清单

把常见症状对应到动作,形成肌肉记忆:

症状第一反应
完全连不上ping 通?防火墙/安全组?端口监听?
时好时坏ping 看丢包率;traceroute 找抖动跳
首次慢、后续快多半 DNS / TLS 握手慢,或没连复用
大文件慢看带宽、TCP 窗口、是否开压缩
仅某地区慢CDN/路由问题,换节点或查骨干

真实案例:一次"很慢"的定位

假设用户报"打开后台很慢"。按本章方法走一遍:

# 1) 先量化:是整体慢还是接口慢 curl -w "ttfb=%{time_starttransfer}" https://admin.example.com # 2) ttfb 很大 → 服务端问题,但先排除网络: ping admin.example.com # RTT 正常,网络 OK # 3) 抓包看握手:发现每次请求都重新 TCP+TLS 握手 tcpdump ... | grep SYN # 没复用连接! # 4) 根因:前端没开 keep-alive / 用了短连接池 # 5) 修:连接池复用 + 上 HTTP/2 → 慢消失

论证据链要闭环

现象 → 量化(curl 各阶段)→ 缩小层级(网络 OK、应用层)→ 抓包取证(无连接复用)→ 假设(短连接)→ 修复 → 复测验证。每一步有证据,避免"我觉得是 XX 所以调了一下"——这是工程师和"重启侠"的区别。

结
本页要点

网络靠分层解耦:应用(HTTP/DNS)→传输(TCP/UDP)→网络(IP)→链路。TCP 用三次握手建连、四次挥手分手、序号/确认/重传保可靠,滑动窗口做流量控制、拥塞控制(慢启动/拥塞避免/快重传)防网络崩溃,二者取小决定实际窗口。HTTP/1.1 有队头阻塞,HTTPS(TLS 1.3) 用证书链认证+协商对称密钥加密,HTTP/2 多路复用缓解应用层阻塞,HTTP/3(QUIC/UDP) 从根上消除 TCP 队头阻塞。DNS 用递归+迭代解析、TTL 控缓存;CDN 把内容推到边缘。负载均衡 L4/L7 分摊流量,Nginx/Envoy 做反向代理与会话保持。安全靠证书链防 MITM、限流/清洗挡 DDoS、参数化查询防注入。诊断按层逐段定位,用 curl 时间切片、tcpdump/Wireshark 抓包把"慢"量化。

一句话记忆:网络里没有"魔法",只有"权衡"——要可靠就牺牲一点速度(TCP),要快就接受可能丢(UDP),要安全就多一次握手(TLS),要扩展就多一层代理(LB)。看懂权衡,你就看懂了网络。

自测 · 看你是否真懂

1.为什么 TCP 连接是"三次握手"而不是两次?四次挥手又是为什么?

查看答案

两次握手无法确认双方收发能力,且可能建起基于过期请求的脏连接;三次在传数据前让双方都确认"能发能收"并同步序号。挥手要四次是因为 TCP 全双工,被动方收到 FIN 后可能还有数据要发,所以 ACK 与自己的 FIN 不能合并,分两步走。

2.流量控制和拥塞控制有什么区别?为什么说实际发送窗口是两者取小?

查看答案

流量控制(rwnd)保证"接收方缓冲不溢出",端到端靠窗口通告;拥塞控制(cwnd)保证"网络不被压垮",靠慢启动/拥塞避免等算法。发送方实际窗口 = min(rwnd, cwnd),既怕压垮对端也怕压垮网络。

3.HTTP/2 和 HTTP/3 分别怎么解决"队头阻塞"?为什么 2 没根除?

查看答案

HTTP/2 在应用层做多路复用,一个 TCP 上并发多流,缓解但没根除——底层 TCP 丢一个包,所有流都得等它重传(TCP 层队头阻塞)。HTTP/3 把传输层换成基于 UDP 的 QUIC,每个流独立,一个流丢包只阻塞自己,从根上消除。

4.为什么改了 DNS 的 A 记录,有些用户要等很久才生效?TTL 在这起什么作用?

查看答案

每条 DNS 记录带 TTL(秒),告诉递归解析器"这个值能缓存多久"。改记录后,旧 IP 还在别人缓存里,要等 TTL 过期才去重新查。所以紧急切换前应先把 TTL 调小(如 60s),改完再调大。

5.反向代理(如 Nginx)除了转发,还该做什么?漏掉 X-Real-IP 会怎样?

查看答案

还能做 TLS 卸载、动静分离、限流、统一入口、会话保持。若不在代理处透传 X-Real-IP/X-Forwarded-For,后端日志里客户端 IP 全是 LB 的地址,导致限流、审计、风控、按 IP 定位全部出错。

6.用 curl 怎么判断"慢"是 DNS 慢、TLS 慢还是服务端慢?

查看答案

用 curl -w 输出时间切片:time_namelookup 大=DNS 慢;time_connect 大=TCP 慢;time_appconnect 大=TLS 握手慢;time_starttransfer(TTFB) 大=服务端处理慢。分而治之,别笼统说"网不好"。

下一步往哪走

路学完网络之后

① 配合 Linux:去 tech-linux 看 iptables/ss/tcpdump 实操,理论落地成命令。

② 配合系统设计:下一页讲 CDN、负载均衡、超时重试的工程化权衡,是网络知识的直接应用。

③ 抓一次真实包:用 Wireshark 跟完一次 HTTPS 握手,比读十遍都直观;再用 curl 时间切片给自己网站的接口做个体检。

补

国密算法 SM2 / SM3 / SM4 与合规

Chinese National Crypto

国密(商用密码)是国家密码管理局标准,等保、金融、政务合规常常硬性要求。搞国内业务,这几个字母迟早要碰。

三者分别是什么

一句话:SM2 管"签名/密钥交换"(非对称),SM3 管"摘要"(哈希),SM4 管"加密"(对称)。别记混角色。

论定位与对标

SM2:椭圆曲线非对称算法(公钥加密+数字签名),256 位,对标 ECDSA/RSA,用于密钥交换、签名验签。SM3:密码杂凑(哈希)算法,256 位输出,对标 SHA-256。SM4:分组对称加密,128 位分组、128 位密钥,对标 AES,用于数据传输/存储加密。注意 SM1 也是对称但不公开。

算法类型 / 位数 / 对标 / 用途
SM2非对称 / 256 位 / 对标 ECDSA·RSA / 签名验签、密钥交换
SM3哈希 / 256 位输出 / 对标 SHA-256 / 摘要、完整性
SM4对称 / 128 位分组·128 位密钥 / 对标 AES / 传输与存储加密
常见坑

国密 ≠ 只用 SM4 替代 AES 就够了。合规往往要求"SM2 签名 + SM3 摘要 + SM4 加密"整套组合,且需合规的实现库(如国密 SDK);自研容易踩标准错(曲线参数、填充方式)。

自测

Q1. SM2 / SM3 / SM4 分别对应哪种密码学原语?

参考答案

非对称 / 哈希 / 对称。

动手片段:用 gmssl 跑通 SM3 / SM4

下面基于纯 Python 国密库 gmssl(pip install gmssl);方法名随版本可能微调,运行前以所装版本的官方文档为准。

# SM3:256 位摘要,对标 SHA-256 from gmssl import sm3, sm4 from gmssl.func import bytes_to_list digest = sm3.sm3_hash(bytes_to_list(b"hello guomi")) print("SM3:", digest) # 十六进制字符串 # SM4:128 位分组 / 128 位密钥的对称分组密码(CBC 模式) key = b"0123456789abcdef" # 必须正好 16 字节 iv = b"fedcba9876543210" # CBC 需要 16 字节 IV data = b"secret-plaintext0" # 长度需为 16 的倍数(不足做 PKCS7 填充) crypt = sm4.CryptSM4() crypt.set_key(key, sm4.SM4_ENCRYPT) ct = crypt.crypt_cbc(iv, data) # 模式由 set_key 决定 crypt2 = sm4.CryptSM4() crypt2.set_key(key, sm4.SM4_DECRYPT) print("解密:", crypt2.crypt_cbc(iv, ct))
补

渗透测试基础:授权攻击找漏洞

Penetration Testing

渗透测试就是"在授权范围内,雇人模拟黑客打你自己的系统",目的是合法地找出漏洞并修掉——和真黑客的唯一区别是有书面授权、不造成真实损害。

流程与视角

标准流程:信息收集(recon) → 扫描(漏洞/端口) → 利用(exploit) → 后渗透(权限维持/横向移动,受范围限制) → 报告(风险评级+修复)。

论测试视角与常见漏洞

视角分黑盒(无内部信息)、白盒(给源码/架构)、灰盒(部分信息)。常见漏洞:SQL 注入、XSS、SSRF、越权(水平/垂直)、弱口令、反序列化、敏感信息泄露。合规上,等保 2.0、ISO 27001、PCI-DSS 常要求定期渗透测试。

视角说明
黑盒无内部信息,模拟外部攻击者
白盒提供源码/架构,更深层查逻辑漏洞
灰盒部分信息,介于两者之间
常见坑

渗透测试必须书面授权,越权扫描、未授权测试可能违法。报告要可复现,并给出修复优先级(如 CVSS 评分),别只丢一摞漏洞名。

自测

Q1. 黑盒与白盒区别?

参考答案

黑盒无内部信息、模拟外部攻击者;白盒提供源码/架构、可更深层查逻辑漏洞。

动手片段:只对你的授权目标跑

下面都是"看自己家"的命令。对不属于你、未书面授权的目标执行,可能违法。

# 端口 / 服务指纹(对本机) nmap -sV -p 1-1000 localhost # Web 漏洞扫描(对自己的站点) nikto -h http://localhost:8080 # 看响应头与安全字段(对自己的站点) curl -sI https://your-own-domain.example # 本机开放监听(授权主机) ss -tulnp | grep LISTEN