基于openresty反向代理、dns劫持、实现对http请求、响应内容抓包
基于NGINX反向代理、dns劫持、实现对http请求、响应内容抓包
- 基于 NGINX 反向代理 + DNS 劫持,实现对 HTTP/HTTPS 请求与响应内容的抓包分析
- 背景
- 整体架构
- 步骤详解
- 1. 准备工作
- (1)申请域名与 SSL 证书
- (2)部署 OpenResty
- 2. 配置 Nginx 主文件(`nginx.conf`)
- 3. 配置反向代理站点(`conf.d/app.conf`)
- 4. DNS 劫持(让客户端流量指向代理)
- 5. 测试与验证
- 发送测试请求
- 查看日志
- 注意事项与安全提醒
- 总结
基于 NGINX 反向代理 + DNS 劫持,实现对 HTTP/HTTPS 请求与响应内容的抓包分析
作者:林鹤霄
环境:OpenResty(Nginx + Lua) + 自定义域名 + SSL 证书
适用场景:调试第三方接口、安全审计、中间人日志记录、教学演示等
背景
在日常开发或运维中,我们经常需要查看某个 Web 应用发出或接收的完整 HTTP 请求和响应内容,尤其是当目标服务是黑盒(如 SaaS 平台、校园一卡通系统等)时。传统抓包工具(如 Wireshark、Fiddler)在 HTTPS 场景下配置复杂,且难以自动化记录。
本文将介绍一种 基于 OpenResty(Nginx + Lua)反向代理 + DNS 劫持 的轻量级方案,无需修改客户端代码,即可透明捕获并记录:
- URL 参数(
$args) - 请求体(Request Body,如 JSON、Form)
- 响应体(Response Body)
- 客户端 IP、User-Agent、状态码等元数据
整体架构
下面方案是,有办法拿到a.b.cn的https证书。
[Client] │▼
(DNS 查询 a.b.cn → 指向本地服务器 IP)│▼
[OpenResty 代理服务器]├── 拦截 HTTPS 请求(443 端口)├── 使用有效 SSL 证书终止 TLS├── 通过 Lua 读取 $request_body├── 通过 body_filter_by_lua 拦截响应流└── 将完整请求/响应写入 JSON 格式日志│▼
[真实后端服务: https://a.b.cn]
💡 关键点:客户端以为自己在访问
a.b.cn,实际流量被代理到a.b.cn,全程无感知。
步骤详解
1. 准备工作
(1)申请域名与 SSL 证书
- 域名:
b.cn(主域),子域a.b.cn - 使用 Let’s Encrypt 或其他 CA 申请证书,得到:
b.pem(证书链)b.key(私钥)
📌 证书必须与
server_name匹配,否则浏览器会报不安全。
(2)部署 OpenResty
# 示例路径
/usr/local/openresty/nginx/
├── conf/
│ ├── nginx.conf
│ └── conf.d/
│ ├── app.conf # 反向代理配置
│ └── ssl/
│ ├── b.cn.pem
│ └── b.cn.key
2. 配置 Nginx 主文件(nginx.conf)
user nginx;
worker_processes auto;error_log /var/log/openresty/error.log notice;
pid /var/run/openresty.pid;events {worker_connections 1024;
}http {include mime.types;default_type application/octet-stream;# 标准日志格式(可选)log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';# 【核心】JSON 格式日志,包含请求体和响应体log_format full_log escape=json'{''"time": "$time_iso8601",''"client": "$remote_addr",''"method": "$request_method",''"url": "$request_uri",''"args": "$args",''"request_body": "$request_body",''"status": $status,''"resp_body": "$resp_body"''}';# 缓冲区设置(必须!否则无法捕获 body)client_body_buffer_size 128k;proxy_buffering on;proxy_buffer_size 64k;proxy_buffers 8 64k; # 总缓冲 512kproxy_busy_buffers_size 128k; # 必须 < (8-1)*64k# 【关键】使用 full_log 记录完整内容access_log /var/log/openresty/access.log full_log;sendfile on;keepalive_timeout 65;# 加载站点配置(注意路径正确!)include /usr/local/openresty/nginx/conf/conf.d/*.conf;
}
⚠️ 常见错误:
- 忘记定义
log_format main→ 启动失败proxy_busy_buffers_size超限 → 启动失败include路径嵌套(如conf.d/conf.d/)→ 配置未加载
3. 配置反向代理站点(conf.d/app.conf)
server {listen 443 ssl;server_name a.b.cn; # 客户端访问的域名ssl_certificate /usr/local/openresty/nginx/conf/conf.d/ssl/b.cn.pem;ssl_certificate_key /usr/local/openresty/nginx/conf/conf.d/ssl/b.cn.key;ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;ssl_prefer_server_ciphers off;location / {# 【关键1】启用请求体读取lua_need_request_body on;# 【关键2】拦截响应体(防止日志爆炸,限制长度)set $resp_body "";body_filter_by_lua_block {local chunk = ngx.arg[1]if chunk thenif not ngx.ctx.resp_body thenngx.ctx.resp_body = ""end-- 最多记录 2KB 响应if string.len(ngx.ctx.resp_body) < 2048 thenngx.ctx.resp_body = ngx.ctx.resp_body .. chunkendendif ngx.arg[2] then -- 最后一块ngx.var.resp_body = ngx.ctx.resp_body or ""end}# 添加自定义请求头(可选)# proxy_set_header X-TEST-TAG "1";# 反向代理到真实后端proxy_pass https://a.b.cn/;}
}
4. DNS 劫持(让客户端流量指向代理)
在客户端(或内网 DNS 服务器)上,将 a.b.cn 解析到你的 OpenResty 服务器 IP:
# Linux / macOS: /etc/hosts
192.168.10.100 a.b.cn# Windows: C:\Windows\System32\drivers\etc\hosts
192.168.10.100 a.b.cn
🔒 若用于生产环境,请使用权威 DNS 或内网 DNS 服务器进行解析劫持。
5. 测试与验证
发送测试请求
curl -k -X POST https://a.b.cn/login \-H "Content-Type: application/json" \-d '{"username":"test","password":"secret123"}'
查看日志
tail -f /var/log/openresty/access.log
输出示例(JSON 格式):
{"time": "2025-11-07T16:45:22+08:00","client": "192.168.1.50","method": "POST","url": "/login","args": "","request_body": "{\"username\":\"test\",\"password\":\"secret123\"}","status": 200,"resp_body": "{\"code\":200,\"msg\":\"success\",\"data\":{\"token\":\"abc...\"}}"
}
✅ 成功捕获:
- 请求方法、URL、参数
- 完整的请求体(明文 JSON)
- 后端返回的响应体(截断版)
注意事项与安全提醒
- 性能开销:捕获 body 会增加内存和 CPU 消耗,建议仅在调试环境启用。
- 敏感信息:日志中可能包含密码、token 等,务必:
- 限制日志访问权限(
chmod 600) - 定期清理或脱敏
- 限制日志访问权限(
- HTTPS 限制:此方案依赖你拥有目标域名的合法证书。若用于非自有域名,属于中间人攻击(MITM),仅限授权测试。
- 大响应体:
body_filter_by_lua中务必限制长度,避免 OOM。 - 无a.b.cn的https证书: 如果没办法拿到
a.b.cn的https证书,本地服务ip暴露的域名可以不是a.b.cn,可以是自已的域名,比如:d.e.cn。之后在nginx拿到响应之后对响应内容修改,比如:proxy_cookie_domain a.b.cn d.e.cn;
总结
通过 OpenResty + Lua + DNS 劫持,我们构建了一个轻量、灵活、可编程的 HTTP 抓包平台。相比传统抓包工具,它具备以下优势:
- ✅ 支持 HTTPS(只需证书)
- ✅ 自动化日志记录(JSON 格式,便于分析)
- ✅ 无需客户端安装代理
- ✅ 可扩展(如加入告警、过滤、转发等逻辑)
此方案特别适合:
- 调试第三方 API 行为
- 监控内部系统调用链
- 安全团队进行流量审计
- 教学环境中演示 HTTP 协议细节
说明:
Android修改hosts,可自行百度寻找相关app。
