调试线上或测试环境的接口时,最头疼的情况莫过于:请求先经过Nginx转发,再走HTTPS加密,到了客户端这边只剩一个错误码,中间到底发生了什么完全看不到。Charles作为一款老牌的抓包工具,配合Nginx可以做多层代理转发,把请求链路完整地暴露出来。这篇文章把整套配置过程拆开讲清楚,包括证书安装、SSL Proxying设置、Nginx侧的代理配置,以及几个高频踩坑点的处理办法。

一、抓包前先理解整个链路结构
在动手配置之前,有必要先弄清楚数据在链路里是怎么流动的。典型的场景是这样的:客户端(浏览器、手机App或者本机的curl)把请求发给Charles,Charles作为正向代理拦截请求,再决定把请求转发到哪里。如果目标是一个经过Nginx反代的域名,Charles会把请求原样转发给Nginx,Nginx再转发给真正的上游服务。
整条链路可以简化为:客户端 → Charles → Nginx → 上游应用。Charles在这个链条里充当中间人的角色。对于HTTP请求,Charles可以直接看到明文;但一旦是HTTPS,Charles就必须用自己的根证书给客户端动态签发一张证书,才能完成中间人解密。这就是为什么抓HTTPS包之前,必须先在客户端安装并信任Charles的根证书,否则客户端会直接报证书错误,连接都建立不起来。
另外要注意区分两个方向:如果你是想抓客户端发出去的请求,Charles用默认的正向代理模式就够了;如果你是想在Nginx服务器侧观察进出流量,则需要把Nginx配置成向上游走Charles代理,两者配置方式完全不同,后面分别说明。
二、Charles证书安装与SSL Proxying配置
首先确保电脑上已经安装了Charles,启动后它会默认监听8888端口。打开菜单栏的Help菜单,选择SSL Proxying,再选择Install Charles Root Certificate,系统会弹出证书安装界面。以Windows为例,安装时证书存储位置要选本地计算机,并且手动指定放到受信任的根证书颁发机构这个存储里,只装到个人存储是没用的。macOS用户则需要在钥匙串访问中找到Charles的证书,双击进入信任设置,把安全套接字层那一项改为始终信任。
手机端安装证书的做法类似。保证手机和电脑在同一局域网内,在手机浏览器访问chls.pro/ssl下载描述文件(iOS)或证书文件(Android)。iOS需要在设置中手动安装描述文件,然后到关于本机的证书信任设置里手动开启对该证书的完全信任。Android 7以上的版本,由于系统默认不信任用户安装的证书,普通App抓HTTPS会失败,这种情况要么让App在manifest里声明信任用户证书(仅限自己开发的App),要么用低于7的系统或模拟器测试。
证书装好后,还需要开启SSL代理白名单。在Charles的Proxy菜单里打开SSL Proxying Settings,勾选Enable SSL Proxying,然后在Include列表中添加要抓的域名,端口填443。这里建议只加需要调试的域名,不要直接用星号匹配所有地址,一是减少干扰,二是避免部分有证书校验的App因为中间人证书而触发风控。配置完成后,重启Charles使设置生效。
三、Nginx侧的两种典型配置方式
第一种也是最常见的情况:Nginx只是被抓包链路经过的一环,本身不需要改任何配置。比如本地开发时用Nginx起了个反向代理,监听80端口转发到本地的Node或Java服务,此时只要让客户端的流量走Charles,Charles再访问Nginx即可。这种场景Nginx配置保持原样,示例如下:
server {
listen 80;
server_name dev.local;
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}客户端侧把系统代理指向Charles所在机器的8888端口,Charles的SSL Proxying里加上dev.local,就能在Charles里看到完整请求了。如果Nginx前面还有HTTPS,把proxy_pass换成https协议头并配置相应的SSL证书即可,抓包逻辑不受影响。
第二种情况是服务器侧抓包:你想观察Nginx转发给上游服务的请求内容。这时可以把Charles部署在一台机器上,让Nginx通过它上网。Nginx原生不支持给proxy_pass指定代理服务器,需要借助Lua模块或者改用域名指向的方式。更实用的替代方案是用环境变量配合curl在服务器上测试,或者直接在Nginx里把上游地址指向Charles所在机器:
location /api/ {
# 将上游指向运行Charles的机器,由Charles解密后再转发
proxy_pass https://charles-host:443;
proxy_set_header Host real-api.example-ipipp.com;
}这种做法本质是让Charles充当HTTPS的终结点,它收到请求后根据Host头再转发到真实目标。注意Charles需要开启外部代理或Map Remote功能来决定转发目的地,配置时要把Host头原样带上,否则后端路由会出问题。
四、常见问题排查
抓不到包是最先遇到的问题。先确认客户端代理设置是否指向Charles的IP和8888端口,注意手机上填的必须是电脑的局域网IP而不是127.0.0.1。其次检查Charles的Proxy Settings里是否勾选了透明代理或者访问控制列表(Access Control List),默认情况下Charles只允许本机连接,其他设备连不上时需要把手机所在网段加进白名单。防火墙也要放行8888端口。
证书相关的问题通常表现为客户端报SSL错误或者Charles里显示unknown字样的乱码请求。乱码说明HTTPS没有被解密,检查三点:证书是否安装到受信任的根证书存储、SSL Proxying的Include列表是否覆盖了目标域名和端口、请求是否真的走了443以外的端口(有些接口走8443,白名单里要单独加)。浏览器端如果用的是Firefox,它有独立的证书库,需要在Firefox的证书管理器里单独导入Charles的证书。
还有一个容易忽略的坑:Nginx开启了HTTP严格转发或者WebSocket支持时,Charles对WebSocket的展示在Structure面板里是单独分类的,别在普通请求列表里找不到就以为没抓到。另外部分App做了证书锁定(SSL Pinning),这类请求在Charles里会直接连接失败,属于客户端主动拒绝了中间人证书,只能通过修改App或使用其他手段绕过,配置层面解决不了。
把这套环境搭好之后,请求头、请求体、响应内容都能以明文形式查看,还支持断点修改请求、限速模拟弱网、Map Local做本地Mock,排查接口问题的效率会提升不少。建议在测试环境长期保留这套配置,生产环境注意仅在排查故障时临时开启,用完及时关闭,避免安全风险。
Nginx抓包Charles抓包配置HTTPS抓包修改时间:2026-09-12 22:10:39