3. HTTP/HTTPS 协议分析:请求方法、状态码、Cookie、HTTPS 握手与证书解密
HTTP 和 HTTPS 是网络世界里最常用的协议。你想想看,我们每天刷网页、看视频、调 API,底层跑的都是它。但 Wireshark 里抓到的 HTTP 包,你真的看透了吗?
我个人习惯,分析 HTTP 问题从来不看应用日志,直接看原始报文。为什么?因为日志可能被框架“美化”过,而报文不会骗人。这一章,我们就来把 HTTP/HTTPS 的底裤扒干净。
3.1 请求方法:不只是 GET 和 POST
很多人觉得请求方法就 GET 和 POST 两种。其实 HTTP/1.1 定义了 8 种方法,但实际常用的就 5 个。
| 方法 | 幂等 | 安全 | 常见场景 |
|---|---|---|---|
| GET | 是 | 是 | 获取资源,参数在 URL 里 |
| POST | 否 | 否 | 提交数据,参数在 Body 里 |
| PUT | 是 | 否 | 上传/替换资源 |
| DELETE | 是 | 否 | 删除资源 |
| PATCH | 否 | 否 | 部分更新资源 |
避坑指南:我曾经排查过一个诡异问题,客户端反复重试请求,导致数据库插入了大量重复订单。一看报文,用的是 POST 请求。POST 不幂等,重试就会出问题。如果换成 PUT,就不会有这种事了。
在 Wireshark 里怎么看请求方法?很简单。抓包后,找到 HTTP 请求包,看 Request Method 字段。或者直接过滤:http.request.method == "POST"。
3.2 状态码:服务器在说什么悄悄话
状态码是服务器给你的“暗号”。我见过不少开发,看到 500 就慌,看到 404 就骂前端。其实每个状态码背后都有故事。
常见的几类状态码:
- 1xx:信息提示。比如 101 Switching Protocols,WebSocket 升级时会出现。
- 2xx:成功。200 OK 最常见,201 Created 表示资源创建成功。
- 3xx:重定向。301 永久重定向,302 临时重定向。我遇到过 CDN 配置错误,导致 301 循环跳转,浏览器直接报错。
- 4xx:客户端错误。400 Bad Request 通常是参数格式不对,401 未认证,403 禁止访问,404 找不到资源。
- 5xx:服务端错误。500 内部错误,502 Bad Gateway,503 服务不可用。
重点:304 Not Modified 是个特殊状态码。它告诉客户端:“你缓存的内容还能用,别重新下载了。” 这在优化页面加载速度时非常有用。我在做性能优化时,经常检查 304 的比例,如果太低,说明缓存策略有问题。
Wireshark 过滤状态码:http.response.code == 404。想快速定位所有错误响应?用 http.response.code >= 400。
3.3 Cookie:无状态协议里的“小纸条”
HTTP 本身是无状态的。服务器怎么记住你是谁?靠 Cookie。说白了,就是服务器在你浏览器里贴了一张“小纸条”,下次你来的时候,浏览器会自动带上它。
Cookie 的结构很简单:name=value,后面跟着一堆属性。
| 属性 | 含义 | 示例 |
|---|---|---|
| Domain | 指定哪些域名可以访问该 Cookie | .example.com |
| Path | 指定哪些路径可以访问 | / |
| Expires/Max-Age | 过期时间 | Session(会话级)或具体时间 |
| Secure | 仅通过 HTTPS 传输 | 有/无 |
| HttpOnly | 禁止 JavaScript 访问 | 有/无 |
| SameSite | 防止 CSRF 攻击 | Strict/Lax/None |
注意:我曾经遇到一个线上故障,用户登录后频繁掉线。抓包一看,服务器返回的 Cookie 没有设置 Domain 属性,浏览器默认把它绑定到了子域名上。用户从主站跳到子站,Cookie 就丢了。嗯,这种坑,不抓包根本发现不了。
Wireshark 里看 Cookie:请求包里的 Cookie 字段,响应包里的 Set-Cookie 字段。过滤:http.cookie 或 http.set_cookie。
3.4 HTTPS 握手:TLS 的“三次握手”升级版
HTTPS 就是在 HTTP 外面套了一层 TLS。握手过程比 TCP 三次握手复杂得多。我把它拆成四个阶段:
- Client Hello:客户端告诉服务器,我支持哪些 TLS 版本、加密套件。
- Server Hello + 证书:服务器选一个加密套件,把证书发给客户端。
- 密钥交换:客户端验证证书,生成预主密钥,用服务器公钥加密后发过去。
- 握手完成:双方用预主密钥生成会话密钥,之后所有数据都对称加密。
个人经验:我排查过一个 HTTPS 慢的问题。抓包发现,TLS 握手阶段,客户端发完 Client Hello 后,等了 2 秒才收到 Server Hello。一看,服务器证书链太长,中间证书没配好。去掉多余的中间证书后,握手时间降到了 200 毫秒。
3.5 证书解密:让 HTTPS 不再“黑盒”
HTTPS 加密后,Wireshark 只能看到一堆乱码。怎么解密?两种方法:
- 方法一:使用私钥。如果你有服务器的私钥,可以直接导入 Wireshark。路径:Edit → Preferences → Protocols → TLS → RSA keys list。
- 方法二:使用 SSLKEYLOGFILE。这是我最推荐的方法。设置环境变量
SSLKEYLOGFILE,指向一个文件。浏览器会把会话密钥写进去。Wireshark 读取这个文件,就能解密。
操作步骤:
- 关闭所有浏览器实例。
- 设置环境变量:
export SSLKEYLOGFILE=/tmp/sslkeys.log(Linux/macOS)或set SSLKEYLOGFILE=C:\sslkeys.log(Windows)。 - 启动浏览器,访问目标网站。
- Wireshark 中配置:Edit → Preferences → Protocols → TLS → (Pre)-Master-Secret log filename,选择刚才的文件。
- 抓包,现在 HTTPS 内容一目了然。
注意:私钥解密只适用于传统 RSA 密钥交换。现在很多服务器用 ECDHE,私钥解密不管用了。SSLKEYLOGFILE 方法通用,支持所有密钥交换算法。我曾经用私钥解密折腾了半天没成功,换成 SSLKEYLOGFILE 后,一分钟搞定。
解密后,你就能看到 HTTP 请求的完整内容了。包括请求头、响应体、Cookie 等等。这对于调试 API、分析恶意流量、排查性能问题,都非常有用。
嗯,这一章的内容就到这里。HTTP/HTTPS 看似简单,但里面的细节很多。下次你遇到网络问题,别急着看日志,先抓个包看看。报文不会骗你。