抓包代理
# 抓包代理
tcpdump 抓包过滤、mitmproxy 中间人代理、Charles/Whistle、Python 脚本拦截修改 HTTPS 请求。
# 一、tcpdump——命令行抓包
# 抓包原理
tcpdump 利用 libpcap(Packet Capture Library)将网卡设为混杂模式(Promiscuous Mode),拦截所有经过的数据包——不仅发给本机的,也包括同网段的广播包。过滤条件在内核层面应用(BPF - Berkeley Packet Filter),未被过滤的包才从内核态拷贝到用户态——这也是为什么"加过滤比不加快 100 倍"——不加过滤意味着所有包都要拷贝。
tcpdump 需要 root 权限(或
CAP_NET_RAWcapability),因为需要访问原始套接字。
# 1.1 基础过滤
#!/bin/bash
# ===== 必须加过滤——否则输出爆炸 =====
# 按主机
tcpdump -i eth0 host 192.168.1.10 -nn -c 50
# 按端口
tcpdump -i any port 80 -nn -c 30
# 按协议
tcpdump -i eth0 tcp -nn -c 20
# 组合过滤器
tcpdump -i eth0 'host 192.168.1.10 and port 443' -nn
# -nn = 不解析主机名和端口名——省去每次 DNS 查询和 /etc/services 查找
# -c = 抓 N 个包后停止
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.2 实用场景速查
#!/bin/bash
# ===== 抓 HTTP 请求头(只看 GET/POST 等)=====
# 技巧:使用 BPF 字节偏移匹配 "GET " 这 4 个字节
# TCP 头偏移计算:ip[0]&0xf = IP 头长度(32位为单位)
# tcp[12:1]&0xf0>>2 = TCP 头长度(32位为单位)
# tcp[((ip[0]&0xf)<<2):4] = TCP payload 的前 4 字节
tcpdump -i eth0 -A -s 0 'tcp port 80 and (tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420)' -c 10
# 0x47455420 = "GET " 的十六进制
# ===== 抓 DNS 请求 =====
tcpdump -i any -nn 'udp port 53' -c 20
# ===== 只看 SYN 包(谁在建立连接——可用于检测端口扫描)=====
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0'
# ===== 保存为 pcap 文件(供 Wireshark 离线分析)=====
tcpdump -i eth0 -w capture.pcap port 443 -c 200
# ===== 读取 pcap =====
tcpdump -r capture.pcap -nn | head -30
tcpdump -r capture.pcap -A port 80 # -A 以 ASCII 显示 HTTP 内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1.3 实战:快速抓包分析脚本
#!/bin/bash
# 抓取 80/443 端口流量并做简要分析
OUTFILE="/tmp/capture_$(date +%H%M%S).pcap"
echo "抓包 30 秒(80/443 端口)→ $OUTFILE"
timeout 30 tcpdump -i any -nn -w "$OUTFILE" 'port 80 or port 443' 2>/dev/null
echo ""
echo "===== 连接摘要 ====="
tcpdump -r "$OUTFILE" -nn 2>/dev/null | awk '{print $3" → "$5}' | sort | uniq -c | sort -rn | head -20
echo ""
echo "===== HTTP Hosts ====="
tcpdump -r "$OUTFILE" -A 2>/dev/null | grep -oP '(?<=Host: )\S+' | sort | uniq -c | sort -rn | head -10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 二、mitmproxy——HTTPS 中间人代理
# MITM 原理
TLS 的设计目标是防止中间人窃听,而 mitmproxy 作为"合法的中间人"之所以能解密 HTTPS,是因为它做了以下操作:
- 客户端发起 CONNECT 请求到代理
- 代理动态生成该域名的自签名证书(用 mitmproxy 自己的 CA 签发)
- 将此证书返回给客户端——客户端必须信任 mitmproxy 的 CA 证书,否则会报证书错误
- 代理与服务端之间走真正的 TLS——所以 mitmproxy 能同时看到明文和密文
安装 CA 证书是安全前提:如果不安装 — 只有
curl -k能通过。安装后,mitmproxy 可以解密任何 HTTPS 流量——仅在测试设备上使用!
# 安装
pip install mitmproxy
# 启动方式
mitmproxy -p 8080 # 命令行 TUI
mitmweb -p 8080 # Web 界面(推荐)→ http://localhost:8081
mitmdump -p 8080 # 非交互模式(适合 CI/Automation)
1
2
3
4
5
6
7
2
3
4
5
6
7
# 2.1 Python 脚本拦截修改请求
mitmproxy 的插件系统让你用 Python 脚本动态拦截、修改、Mock HTTP 流量——request 钩子在前端,response 钩子在返回路径:
#!/usr/bin/env python3
"""mitmproxy 脚本——拦截并修改请求/响应
用法:mitmproxy -s this_script.py -p 8080
"""
from mitmproxy import http
def request(flow: http.HTTPFlow):
"""拦截请求——在发送到服务端之前"""
# 修改 Header
flow.request.headers["X-Custom"] = "injected-by-mitmproxy"
# 阻止无关请求(如埋点)
if "analytics.example.com" in flow.request.pretty_host:
flow.response = http.Response.make(204)
# Mock API--直接返回假响应,不真的请求服务端
if flow.request.pretty_url.endswith("/api/status"):
flow.response = http.Response.make(
200, b'{"status":"ok","mode":"mocked"}',
{"Content-Type": "application/json"}
)
def response(flow: http.HTTPFlow):
"""拦截响应——在返回客户端之前"""
# 注入调试脚本到 HTML
if "text/html" in flow.response.headers.get("content-type", ""):
flow.response.text = flow.response.text.replace(
"</body>",
"<script>console.log('mitmproxy injected')</script></body>"
)
# 改写状态码
if flow.request.pretty_url.endswith("/legacy-api"):
flow.response.status_code = 200
# 删除暴露技术栈的 Header
flow.response.headers.pop("X-Powered-By", None)
flow.response.headers.pop("Server", None)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 2.2 mitmdump——非交互容器友好
# 无 UI——适合服务器/CI 流水线
mitmdump -s mock_api.py -p 8888 --set block_global=false
# 流量录制——保存所有请求/响应到文件
mitmdump -w traffic.flow -p 8080
# 流量回放——重放录制的流量做回归测试
mitmdump -n -r traffic.flow
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 三、Charles / Whistle——GUI 抓包工具
# ===== Charles——macOS/Windows HTTPS 代理 =====
# 核心功能:Map Remote(URL 重定向到另一个 URL)、Map Local(用本地文件替换远程响应)、
# Rewrite(正则替换请求/响应)、Breakpoints(修改请求体)、Throttle(模拟弱网)
# 手机抓包流程:Proxy Settings(8888) → Install CA → 手机设代理 → 装证书 → 开始
# ===== Whistle——Node.js 跨平台抓包(推荐前端开发者)=====
npm install -g whistle
w2 start -p 8899 # 浏览器打开 http://localhost:8899
# 手机:下载证书 → rootca.pro
# Whistle Rules 示例:
# 本地 Mock 接口
# api.example.com/api/status resBody://{mock.json}
# 注入自定义 JS 到页面
# example.com js://{inject.js}
# 修改响应头
# api.example.com resHeaders://{headers.txt}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 四、实战:开发调试三件套
#!/bin/bash
# ===== 场景 1:调试 H5 移动端 HTTPS 请求(Whistle 最佳)=====
# w2 start → 手机设代理 → 访问 rootca.pro 装证书 → whistle 界面查看
# ===== 场景 2:服务器上排查 API 调用异常(tcpdump 抓包离线分析)=====
# tcpdump -i eth0 -w debug.pcap 'host api.example.com' &
# curl https://api.example.com/endpoint
# kill %1
# scp debug.pcap local: && Wireshark 打开分析
# Wireshark 里:Statistics → Flow Graph 看 TCP 交互时序;Follow → TLS Stream 看解密内容
# ===== 场景 3:前端联调 Mock 后端接口(mitmdump)=====
cat > mock_script.py << 'PYEOF'
from mitmproxy import http
def request(flow):
# 把 /api/users 接口的响应换成假数据——联调期间无需真实后端
if flow.request.pretty_url.endswith("/api/users"):
flow.response = http.Response.make(
200, b'[{"id":1,"name":"Mock User"}]',
{"Content-Type": "application/json"}
)
PYEOF
# mitmdump -s mock_script.py -p 8888
# curl -x http://localhost:8888 https://api.example.com/api/users
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
上次更新: 2026/06/17, 12:47:39