577 lines
14 KiB
Markdown
577 lines
14 KiB
Markdown
---
|
||
tags: [network, tools, whistle, packet-capture, proxy]
|
||
create time: 2026-04-17 12:20
|
||
---
|
||
|
||
# 网络抓包
|
||
|
||
## 概述
|
||
|
||
网络抓包是调试和分析网络请求的核心技术。本文档以 whistle 支持的抓包功能为核心,介绍网络请求的抓取、分析、修改和重放方法。
|
||
|
||
理论性的协议分析内容请参考 [[CS/NET/网络协议分析基础]]。
|
||
|
||
## 正文
|
||
|
||
### 代理状态下的网络请求流程
|
||
|
||
在配置代理后,网络请求会经过代理服务器转发。以下是完整的请求流程:
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Client as 客户端 (浏览器/应用)
|
||
participant Proxy as 代理服务器 (Whistle)
|
||
participant Target as 目标服务器
|
||
|
||
%% 1. 客户端发起请求
|
||
Client->>Proxy: ✅ 1. 发起 HTTP/HTTPS 请求
|
||
Note over Client,Proxy: URL: https://api.example.com/data<br/>Method: GET<br/>Headers: {...}
|
||
|
||
%% 2. 代理接收并解析
|
||
Proxy->>Proxy: 🔍 2. 接收请求并解析
|
||
Note over Proxy: 检查规则匹配<br/>- 规则: reqHeaders?<br/>- 规则: resBody?<br/>- 规则: 映射?
|
||
|
||
%% 分支: 是否有转发规则
|
||
alt 有转发规则
|
||
Proxy->>Proxy: 📝 3. 应用转发规则
|
||
Note over Proxy: 执行修改操作<br/>- 修改请求头<br/>- 替换域名<br/>- 重写路径
|
||
end
|
||
|
||
%% 分支: HTTPS 请求
|
||
alt HTTPS 请求
|
||
Proxy->>Proxy: 🔒 4. SSL/TLS 握手
|
||
Note over Proxy: - 代理充当中间人<br/>- 使用自签名证书<br/>- 解密请求内容
|
||
end
|
||
|
||
%% 3. 代理转发请求
|
||
Proxy->>Target: ⬆️ 5. 转发请求到目标服务器
|
||
Note over Proxy,Target: 处理后的请求<br/>Header + Body
|
||
|
||
%% 4. 目标服务器处理
|
||
Target->>Target: ⚙️ 6. 处理请求
|
||
Note over Target: 业务逻辑处理<br/>生成响应数据
|
||
|
||
%% 5. 目标服务器返回响应
|
||
Target-->>Proxy: ⬇️ 7. 返回响应
|
||
Note over Target,Proxy: Status: 200<br/>Headers: {...}<br/>Body: {...}
|
||
|
||
%% 6. 代理接收并记录
|
||
Proxy->>Proxy: 💾 8. 接收并记录响应
|
||
Note over Proxy: - 记录到抓包列表<br/>- 计算耗时<br/>- 保存完整信息
|
||
|
||
%% 分支: 是否有响应修改规则
|
||
alt 有响应修改规则
|
||
Proxy->>Proxy: 🎭 9. 应用响应规则
|
||
Note over Proxy: - 修改响应头<br/>- 替换响应体<br/>- 修改状态码<br/>- Mock 数据
|
||
end
|
||
|
||
%% 7. 代理转发响应
|
||
Proxy-->>Client: ✅ 10. 返回响应给客户端
|
||
Note over Proxy,Client: 最终的响应数据<br/>Client 可以正常处理
|
||
|
||
%% 循环: 请求重放
|
||
rect rgba(0, 255, 0, 0.1)
|
||
Client->>Proxy: 🔄 11. 重放请求 (可选)
|
||
Proxy->>Client: 📤 12. 返回重放结果
|
||
Note over Client,Proxy: 复现 Bug<br/>接口调试<br/>压力测试
|
||
end
|
||
```
|
||
|
||
**流程说明:**
|
||
|
||
1. **请求发起**: 客户端(浏览器或应用)向配置的代理服务器发送请求
|
||
2. **代理解析**: 代理服务器接收请求,解析 URL、方法、头部等信息
|
||
3. **规则匹配**: 代理检查配置的转发规则,包括请求/响应修改、域名映射等
|
||
4. **HTTPS 处理**: 对于 HTTPS 请求,代理通过中间人模式解密和重新加密请求
|
||
5. **转发请求**: 代理将处理后的请求转发到目标服务器
|
||
6. **响应处理**: 目标服务器处理请求并返回响应
|
||
7. **记录数据**: 代理记录完整的请求/响应信息到抓包列表
|
||
8. **应用规则**: 如果配置了响应修改规则,代理会修改响应内容
|
||
9. **返回响应**: 代理将最终响应返回给客户端
|
||
10. **请求重放**: 可以对已记录的请求进行重放,用于调试和测试
|
||
|
||
**Whistle 的核心作用:**
|
||
- 🔍 **可见性**: 记录所有经过代理的请求
|
||
- 🎭 **可控性**: 可以修改和重放请求
|
||
- 🔄 **灵活性**: 支持域名映射和数据 Mock
|
||
- 📊 **调试性**: 提供详细的请求/响应分析
|
||
|
||
### Whistle 工具介绍
|
||
|
||
#### 为什么选择 Whistle
|
||
|
||
Whistle 是一款基于 HTTP 代理的跨平台调试工具,相比传统抓包工具具有以下优势:
|
||
|
||
- 跨平台支持 (Windows, Mac, Linux)
|
||
- 内置抓包功能,支持 HTTP/HTTPS
|
||
- 便捷的请求修改和重放
|
||
- 支持域名映射、远程调试
|
||
- 界面友好,操作简单
|
||
- 支持插件扩展
|
||
- 配置灵活,规则强大
|
||
|
||
#### 安装与启动
|
||
|
||
```bash
|
||
# 全局安装
|
||
npm install -g whistle
|
||
|
||
# 启动服务
|
||
w2 start
|
||
|
||
# 启动指定端口
|
||
w2 start -p 8899
|
||
|
||
# 停止服务
|
||
w2 stop
|
||
|
||
# 重启服务
|
||
w2 restart
|
||
```
|
||
|
||
![[Pasted image 20260417125039.png]]
|
||
![[Pasted image 20260417125713.png]]
|
||
**访问界面:**
|
||
- 默认地址: http://127.0.0.1:8899
|
||
- 默认账号: whistle (首次安装无密码)
|
||
|
||
#### 代理配置
|
||
|
||
**命令行配置:**
|
||
```bash
|
||
# Mac/Linux
|
||
export http_proxy=http://127.0.0.1:8899
|
||
export https_proxy=http://127.0.0.1:8899
|
||
|
||
# Windows
|
||
set http_proxy=http://127.0.0.1:8899
|
||
set https_proxy=http://127.0.0.1:8899
|
||
```
|
||
|
||
**系统代理配置:**
|
||
1. 打开系统网络设置
|
||
2. 配置 HTTP/HTTPS 代理为 127.0.0.1:8899
|
||
3. 应用并保存
|
||
|
||
**手机代理配置:**
|
||
1. 确保手机和电脑在同一局域网
|
||
2. 查看电脑 IP 地址 (如 192.168.1.100)
|
||
3. 手机 WiFi 设置中配置代理:
|
||
- 服务器: 192.168.1.100
|
||
- 端口: 8899
|
||
4. 浏览器访问 https://rootca.pro 安装信任证书
|
||
|
||
### 核心功能
|
||
|
||
#### 1. 抓包查看
|
||
|
||
**功能特性:**
|
||
- 显示所有 HTTP/HTTPS 请求
|
||
- 显示请求/响应头和内容
|
||
- 支持 WebSocket 抓包
|
||
- 支持长连接和断点续传
|
||
- 按域名、状态码、方式筛选
|
||
|
||
**界面说明:**
|
||
- **请求列表**: 显示所有请求的摘要信息 (URL、方法、状态码、耗时)
|
||
- **请求详情**: 点击请求查看完整信息 (请求头、响应头、请求体、响应体)
|
||
- **时间线**: 显示请求的时间顺序和耗时
|
||
- **统计**: 显示请求总数、成功数、失败数等统计信息
|
||
|
||
#### 2. 请求修改
|
||
|
||
**修改方法:**
|
||
|
||
1. **Values 方式 (规则面板)**:
|
||
```
|
||
# 修改请求头
|
||
example.com reqHeaders://{test}
|
||
|
||
# 在 Values 中定义变量
|
||
test:
|
||
x-custom-header: custom-value
|
||
x-another-header: another-value
|
||
```
|
||
|
||
2. **正则匹配修改**:
|
||
```
|
||
# 修改所有匹配的请求
|
||
/^https:\/\/example\.com\/(.*)/ reqHeaders://{test}
|
||
```
|
||
|
||
3. **修改请求体**:
|
||
```
|
||
example.com reqBody://{test-body}
|
||
|
||
# Values
|
||
test-body:
|
||
{"modified": "data"}
|
||
```
|
||
|
||
4. **修改响应**:
|
||
```
|
||
# 修改响应头
|
||
example.com resHeaders://{test-res}
|
||
|
||
# 修改响应体
|
||
example.com resBody://{test-body}
|
||
|
||
# 修改响应状态码
|
||
example.com statusCode://404
|
||
```
|
||
|
||
#### 3. 请求重放
|
||
|
||
**功能作用:**
|
||
- 复现问题 bug
|
||
- 压力测试
|
||
- 接口调试
|
||
- 自动化脚本测试
|
||
|
||
**操作步骤:**
|
||
1. 在请求列表中选择要重放的请求
|
||
2. 点击"重放"按钮
|
||
3. 选择重放次数
|
||
4. 开始重放
|
||
|
||
**批量重放:**
|
||
- 支持选中多个请求批量重放
|
||
- 支持导出请求列表为脚本
|
||
- 支持自定义重放间隔
|
||
|
||
#### 4. 域名映射
|
||
|
||
**本地开发映射:**
|
||
```
|
||
# 映射到本地服务
|
||
api.example.com 127.0.0.1:3000
|
||
|
||
# 映射到远程服务
|
||
api.example.com www.test-api.com
|
||
|
||
# 路径映射
|
||
example.com/api local.path/to/api
|
||
```
|
||
|
||
**多环境切换:**
|
||
```
|
||
# 开发环境
|
||
dev.example.com api-dev.example.com
|
||
|
||
# 测试环境
|
||
test.example.com api-test.example.com
|
||
|
||
# 生产环境
|
||
prod.example.com api.example.com
|
||
```
|
||
|
||
#### 5. 接口 Mock
|
||
|
||
**数据 Mock:**
|
||
```
|
||
# Mock 接口响应
|
||
api.example.com/user/info resBody://{mock-user}
|
||
|
||
# Values 中定义 Mock 数据
|
||
mock-user:
|
||
{
|
||
"code": 200,
|
||
"data": {
|
||
"name": "测试用户",
|
||
"age": 25,
|
||
"avatar": "https://example.com/avatar.png"
|
||
},
|
||
"message": "success"
|
||
}
|
||
```
|
||
|
||
**Mock 模板:**
|
||
```
|
||
# 文件 Mock
|
||
api.example.com/list resBody://{./mock/list.json}
|
||
|
||
# 使用 mockjs 语法
|
||
api.example.com/list resBody://{./mock/list.js}
|
||
```
|
||
|
||
### 高级用法
|
||
|
||
#### 1. Bypass 跳过代理
|
||
|
||
**配置跳过规则:**
|
||
```
|
||
# 跳过特定域名
|
||
www.google.com bypass://*
|
||
|
||
# 跳过 IP 地址
|
||
192.168.1.100 bypass://*
|
||
|
||
# 跳过本地地址
|
||
192.168.* bypass://*
|
||
10.* bypass://*
|
||
```
|
||
|
||
#### 2. 插件使用
|
||
|
||
**常用插件:**
|
||
```
|
||
# 安装插件
|
||
w2 install whot
|
||
|
||
# 使用插件
|
||
example.com whot://
|
||
|
||
# 查看插件
|
||
w2 list
|
||
```
|
||
|
||
#### 3. WebSocket 调试
|
||
|
||
**WebSocket 抓包:**
|
||
1. 在网络列表中找到 WebSocket 请求
|
||
2. 点击查看连接详情
|
||
3. 实时查看发送和接收的消息
|
||
4. 支持文本和二进制消息
|
||
|
||
#### 4. HTTPS 处理
|
||
|
||
**自签名证书概念:**
|
||
|
||
**什么是自签名证书?**
|
||
|
||
自签名证书是指不由受信任的证书颁发机构(CA,如 DigiCert、Let's Encrypt 等)签发的 SSL/TLS 证书,而是由服务器自己生成并签名的证书。
|
||
|
||
**与传统证书的区别:**
|
||
|
||
| 特性 | 受信任证书 | 自签名证书 |
|
||
|------|------------|------------|
|
||
| **签发者** | 受信任的 CA 机构 | 服务器自己 |
|
||
| **浏览器信任** | ✅ 自动信任 | ❌ 警告不安全 |
|
||
| **成本** | 付费(免费付费都有) | 免费 |
|
||
| **验证流程** | CA 验证身份 | 无验证 |
|
||
| **适用场景** | 生产环境、对外服务 | 开发测试、内网代理 |
|
||
|
||
**为什么代理抓包需要自签名证书?**
|
||
|
||
在 HTTPS 抓包中,代理服务器使用自签名证书的原理:
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
subgraph 正常HTTPS流程
|
||
A1[客户端] -->|建立加密连接| B1[目标服务器]
|
||
B1 -->|发送官方证书<br>由CA签发| A1
|
||
A1 -->|验证CA信任| B1
|
||
end
|
||
|
||
subgraph 代理抓包流程
|
||
A2[客户端] -->|建立加密连接| B2[代理服务器]
|
||
B2 -->|发送自签名证书<br>代理自己签发| A2
|
||
A2 -->|❓ 证书无效?|
|
||
A2 -->|⚠️ 需要手动信任| C{是否信任代理证书}
|
||
C -->|是| B2
|
||
C -->|否| D[连接失败]
|
||
|
||
B2 -->|解密查看内容| E[代理检查内容<br/>应用修改规则]
|
||
E -->|重新加密| B2
|
||
B2 -->|转发到真实服务器| F[目标服务器]
|
||
F -->|响应| B2
|
||
B2 -->|返回给客户端| A2
|
||
end
|
||
```
|
||
|
||
**代理使用自签名证书的原因:**
|
||
|
||
1. **中间人攻击(MITM)的本质**:
|
||
- HTTPS 的目的是防止中间人攻击
|
||
- 代理抓包本质上就是"合法的中间人"
|
||
- 需要解密 HTTPS 流量才能查看和修改
|
||
|
||
2. **无法动态生成官方证书**:
|
||
- 代理无法为每个域名申请真实证书
|
||
- 代理需要处理成千上万个不同域名的请求
|
||
- 自签名证书是最灵活的解决方案
|
||
|
||
3. **时间成本和工作效率**:
|
||
- 为每个抓包域名单独申请证书不现实
|
||
- 自签名证书可以立即生成和使用
|
||
|
||
**Whistle 证书工作原理:**
|
||
|
||
```
|
||
1. 用户访问 https://api.example.com
|
||
↓
|
||
2. Whistle 拦截请求
|
||
↓
|
||
3. Whistle 为 api.example.com 动态生成自签名证书
|
||
(证书上的域名是 api.example.com)
|
||
↓
|
||
4. Whistle 将此证书发送给浏览器
|
||
↓
|
||
5. 浏览器识别出这不是受信任的 CA 签发的证书
|
||
(因为根证书不在浏览器信任列表中)
|
||
↓
|
||
6. 如果用户手动导入了 Whistle 的根证书并信任
|
||
↓
|
||
7. 浏览器信任该证书,连接建立成功
|
||
↓
|
||
8. Whistle 可以解密并查看 HTTPS 内容
|
||
```
|
||
|
||
**信任证书:**
|
||
1. 访问 https://rootca.pro 下载证书
|
||
2. 安装到系统信任根证书
|
||
3. 移动端需要额外配置
|
||
|
||
**SSL Pinning 绕过:**
|
||
- 开发环境可以关闭 SSL Pinning
|
||
- 使用测试证书配置
|
||
- 使用移动端调试工具 (如 Frida)
|
||
|
||
### 实践场景
|
||
|
||
#### 场景 1: 前端开发调试
|
||
|
||
**需求:**
|
||
- 查看接口请求和响应
|
||
- 修改接口数据进行测试
|
||
- Mock 接口用于前端开发
|
||
|
||
**配置:**
|
||
```
|
||
# 查看接口日志
|
||
api.example.com log://
|
||
|
||
# 修改接口响应
|
||
api.example.com resBody://{mock-data}
|
||
|
||
# 映射到本地服务
|
||
api.example.com 127.0.0.1:8080
|
||
```
|
||
|
||
#### 场景 2: 移动端开发调试
|
||
|
||
**需求:**
|
||
- 抓取手机应用的网络请求
|
||
- 查看和修改接口数据
|
||
- 解决跨域问题
|
||
|
||
**配置:**
|
||
```
|
||
# 启用 CORS
|
||
api.example.com resCors:// *
|
||
|
||
# 允许所有域
|
||
api.example.com reqHeaders://{test}
|
||
|
||
test:
|
||
Access-Control-Allow-Origin: *
|
||
Access-Control-Allow-Credentials: true
|
||
```
|
||
|
||
#### 场景 3: 接口测试和压测
|
||
|
||
**需求:**
|
||
- 重复某接口的请求
|
||
- 测试并发请求
|
||
- 验证接口性能
|
||
|
||
**操作:**
|
||
1. 选择目标接口
|
||
2. 点击"重放" → "多次重放"
|
||
3. 设置重放次数和间隔
|
||
4. 查看结果和统计
|
||
|
||
#### 场景 4: 问题复现
|
||
|
||
**需求:**
|
||
- 在本地复现线上问题
|
||
- 使用线上数据调试
|
||
- 分离前端和后端问题
|
||
|
||
**配置:**
|
||
```
|
||
# 使用线上接口,本地前端
|
||
localhost:8080/api online.example.com/api
|
||
|
||
# 使用本地接口,线上前端
|
||
www.example.com/api 127.0.0.1:8080/api
|
||
```
|
||
|
||
### 常见问题
|
||
|
||
#### 1. 抓不到 HTTPS 请求
|
||
|
||
**解决方法:**
|
||
- 确认已安装并信任根证书
|
||
- 检查系统代理是否配置正确
|
||
- 重启浏览器和应用
|
||
- 清除浏览器缓存
|
||
|
||
#### 2. 证书不信任
|
||
|
||
**解决方法:**
|
||
- Windows: 安装到"受信任的根证书颁发机构"
|
||
- Mac: 安装钥匙串并设置为"始终信任"
|
||
- 移动端: 进入设置 → 通用 → 关于本机 → 证书信任设置
|
||
|
||
#### 3. 代理配置后无法上网
|
||
|
||
**解决方法:**
|
||
- 检查 whistle 是否启动
|
||
- 确认代理地址和端口正确
|
||
- 检查防火墙设置
|
||
- 尝试使用 bypass:// 规则
|
||
|
||
#### 4. 规则不生效
|
||
|
||
**排查步骤:**
|
||
1. 检查规则语法是否正确
|
||
2. 确认规则没有冲突
|
||
3. 查看规则优先级
|
||
4. 使用 log:// 查看匹配情况
|
||
|
||
### 最佳实践
|
||
|
||
#### 1. 规则组织
|
||
|
||
```
|
||
# 按功能分类
|
||
# ----- 本地开发 -----
|
||
api-dev.example.com 127.0.0.1:3000
|
||
static-dev.example.com 127.0.0.1:8080
|
||
|
||
# ----- 测试环境 -----
|
||
api-test.example.com test-api.example.com
|
||
|
||
# ----- Mock 数据 -----
|
||
api.example.com/user resBody://{./mock/user.json}
|
||
api.example.com/list resBody://{./mock/list.json}
|
||
|
||
# ----- 特殊规则 -----
|
||
google.com bypass://*
|
||
```
|
||
|
||
#### 2. 性能优化
|
||
|
||
- 及时清理过多的抓包记录
|
||
- 使用过滤器只关注相关请求
|
||
- 对于高流量场景使用 bypass:// 规则
|
||
|
||
#### 3. 安全建议
|
||
|
||
- 不要在公共WiFi下使用代理抓包
|
||
- 及时清理缓存中的敏感信息
|
||
- 不要在生产环境使用长时间的代理
|
||
- 定期备份重要的配置和规则
|
||
|
||
## 关联笔记
|
||
|
||
- [[CS/NET/网络协议分析基础]]
|
||
- [[CS/SECURITY/网络安全基础]]
|
||
- [[DEV/DEBUG/调试技巧总结]]
|
||
|
||
## 参考资源
|
||
|
||
- Whistle 官方文档: https://wproxy.org/whistle/
|
||
- Whistle GitHub: https://github.com/avwo/whistle
|