接口调试新姿势
开了 SSL 抓包,有些网站反而打不开?把域名加进「跳过 SSL 代理」
已经设好了系统代理,证书也信任了,SSL 代理同样开着。
大部分 HTTPS 请求都能正常出现在抓包列表里,甚至可以直接看到请求头、请求体和响应内容。
但偏偏有几个网站打不开了。
日志里可能出现这样的错误:
PROXY_TO_SERVER_REQUEST_ERROR: Error [ERR_TLS_CERT_ALTNAME_INVALID]:
Hostname/IP does not match certificate's altnames:
Host: admin.shop-example.com. is not in the cert's altnames:
DNS:*.cdn-host.cn, DNS:cdn-host.cn
浏览器表现为页面加载失败,抓包列表里的请求也中断。
但把系统代理关掉,或者关闭 SSL 代理之后,网站又恢复正常。
这时候,问题通常不是 DevPeek 根证书没有安装。
真正发生的是:DevPeek 连接源站时,源站返回的证书与当前 Host 不匹配。
这种情况下,最简单的办法不是关闭整个 SSL 抓包,而是在 SSL 代理配置里排除这个域名,让它走 HTTPS 隧道。
本文就来看看这条错误到底意味着什么,以及为什么 Include / Exclude 两份名单需要同时存在。
适合什么情况?
如果你遇到的是下面这种情况,这篇文章正适合你:
- 已经配置好系统代理和 DevPeek CA
- 大部分 HTTPS 都可以正常抓包
- 只有少数网站开启 SSL 代理后无法访问
- 日志中出现
ERR_TLS_CERT_ALTNAME_INVALID - 报错里的 Host 和证书 SAN 看起来完全不是一个域名
- 希望只放过这些特殊域名,而不是关闭整个 SSL 抓包
如果你还没有成功抓到第一个 HTTPS 请求,可以先看:
先看懂这条错误
例如:
Host: admin.shop-example.com.
is not in the cert's altnames:
DNS:*.cdn-host.cn
DNS:cdn-host.cn
这里最值得注意的是两部分。
你想访问的 Host:
admin.shop-example.com
源站实际返回的证书:
*.cdn-host.cn
cdn-host.cn
证书的 SAN(Subject Alternative Name)里没有 admin.shop-example.com。
因此,Node 在连接源站时进行 TLS 证书主机名校验,发现:我正在连接 admin.shop-example.com,但你给我的证书是 *.cdn-host.cn。
于是连接失败。这就是 ERR_TLS_CERT_ALTNAME_INVALID。
这不是「没装 DevPeek 证书」
这是最容易搞混的地方。
如果 DevPeek CA 没有被浏览器或设备信任,通常看到的是类似:
NET::ERR_CERT_AUTHORITY_INVALID
也就是:这个证书的颁发者,我不信任。
而本文讨论的是另一种情况:ERR_TLS_CERT_ALTNAME_INVALID。
它关注的是:证书里的域名,与当前连接的 Host 对不上。
所以,如果你看到 Host 是 admin.shop-example.com,证书却是 DNS:*.cdn-host.cn,继续重装 DevPeek CA 通常没有意义。
为什么只开 SSL 代理时会出问题?
理解这个问题,关键是知道 SSL 代理实际上发生了什么。
普通 HTTPS 代理连接大致是:
浏览器
│
│ CONNECT
▼
DevPeek
│
│ TCP 隧道
▼
源站
TLS 握手仍然由浏览器直接与源站完成。DevPeek 只是把连接「穿过去」。所以浏览器 ↔ 源站之间的 TLS 证书由浏览器自己验证。
而开启 SSL 代理之后,情况变成了两段 TLS:
浏览器
│
│ TLS
▼
DevPeek
│
│ TLS
▼
源站
第一段:浏览器 ↔ DevPeek。DevPeek 会动态生成对应域名的证书,并使用 DevPeek CA 签发。
第二段:DevPeek ↔ 源站。DevPeek 作为 TLS 客户端连接真实网站,并验证源站返回的证书。
因此,本文的错误发生在第二段。
为什么 CDN、WAF 特别容易碰到这种情况?
实际网络环境里,一个 IP 往往并不只服务一个网站。
例如 admin.shop-example.com、api.shop-example.com、cdn-host.cn、static.cdn-host.cn 可能最终都经过同一个 CDN、WAF 或反向代理。
正常情况下,服务器会根据 TLS 握手中的 SNI 选择正确的证书。
但如果代理链、客户端、CDN 配置或者 Host / SNI 处理存在异常,就可能出现:请求的 Host 是 admin.shop-example.com,源站返回 *.cdn-host.cn。
这时候浏览器直连可能正常,但经过 SSL 中间人代理之后出现证书主机名错误。
另外,如果你看到 Host 写成 admin.shop-example.com.,末尾多了一个 .,也值得留意。这是 FQDN 的合法写法,本身并不代表错误,但某些客户端、代理或 CDN 在处理这种形式时可能存在兼容性问题。
为什么不能「失败之后自动变成隧道」?
你可能会想到一个很自然的方案:DevPeek 第一次尝试 SSL 代理失败了,那就自动改成普通 CONNECT 隧道不就行了?
问题在于,到了这里已经晚了。
SSL 代理建立的是浏览器 ↔ DevPeek 的 TLS 连接。浏览器的 ClientHello 已经交给 DevPeek 处理,DevPeek 也已经开始作为中间人连接源站。
如果这时候源站证书校验失败,原来的 CONNECT 已经不能简单地「倒退」回透明隧道。因此,隧道通常需要在建立连接之前就决定。
这也是为什么 Fiddler、Charles 等代理工具同样提供「哪些 Host 做 SSL 代理、哪些 Host 跳过」的配置,而不是等证书校验失败之后再自动降级。Charles 把这两份名单叫 Include / Exclude。
DevPeek 怎么处理?
DevPeek 把 SSL 代理范围拆成两份名单:
SSL 代理这些主机,也就是 Include。默认 *,代表所有符合条件的 HTTPS Host 都允许进行 SSL 代理。
跳过 SSL 代理(隧道),也就是 Exclude。这里列出的 Host 不做 SSL 中间人代理,而是直接建立 HTTPS 隧道。
最终规则可以简单理解为:
做 SSL 代理
= SSL 已开启
&& 命中 Include
&& 未命中 Exclude
Include 和 Exclude 同时命中时,Exclude 优先。
这与参数转换里的加解密规则无关。
在 SSL 代理配置里排除这个域名
打开 DevPeek 的 SSL 代理配置。
上面是 SSL 代理这些主机,下面是 跳过 SSL 代理(隧道)。
例如现在 Include 是 *,而 admin.shop-example.com 开启 SSL 代理时出现 ERR_TLS_CERT_ALTNAME_INVALID,那么可以在 Exclude 中加入:
admin.shop-example.com
如果这个站点的一整个子域都存在类似问题,也可以使用:
*.shop-example.com
保存之后,后续建立的连接会按照新规则处理。已经建立的 CONNECT 不会自动变成隧道,因此修改配置后刷新页面,必要时清掉旧连接再测试。
完成标准: 该站能打开,抓包列表里对应 HTTPS 是隧道;其它仍在 Include 内的域名继续做 SSL 代理。
Include / Exclude 怎么配?
规则支持通配符,例如 *、*.example.com、*api*、api.example.com。
几个典型情况:
| Include | Exclude | 访问 Host | 结果 |
|---|---|---|---|
* |
*.shop-example.com |
admin.shop-example.com |
隧道 |
* |
*.shop-example.com |
api.other.com |
SSL 代理 |
*.example.com |
api.example.com |
api.example.com |
隧道 |
api.example.com |
*.example.com |
api.example.com |
隧道 |
核心原则只有一个:排除优先。 因此即使一个 Host 同时命中 Include 和 Exclude,也会走隧道。
排除名单里加入 *,则相当于把所有 HTTPS 都排除掉,也就是全部走隧道。DevPeek 会在保存前进行确认,避免误操作导致整个 SSL 抓包突然「消失」。
一个容易忽略的点:不能按 URL Path 排除
例如你可能想写 https://api.example.com/login,或者 api.example.com/v1/*。
但 SSL 代理的决定发生在 HTTPS CONNECT 阶段。此时代理还没有看到 /v1/login 这样的 HTTP URL Path。
因此 SSL 代理排除只能根据 Host 等连接级信息进行匹配。也就是说:api.example.com 可以,但 api.example.com/v1/login 不是一条 SSL 代理 Host 规则。
不要把三个问题混在一起
遇到 HTTPS 抓包异常时,可以先用下面这张表快速判断:
| 现象 | 更可能是什么问题 |
|---|---|
浏览器提示「不受信任的颁发者」/ NET::ERR_CERT_AUTHORITY_INVALID |
DevPeek CA 没有正确安装或信任 |
| Host 是 A,源站证书 SAN 却是完全不同的域名;直连正常,SSL 代理才失败 | 源站证书 / SNI / 代理链兼容问题 |
| 关闭 SSL 代理后该站仍然提示证书错误 | 源站自己的证书就存在问题 |
| HTTPS 已经成功拆开,但 JSON 中仍然是密文 | 参数转换 / 加解密规则 |
尤其注意最后一种:HTTPS 已经是明文 HTTP 了,JSON 里面还是 { "data": "7a3f..." }。这不是 SSL 代理的问题,这是应用层的参数加密,可以交给 参数转换 处理。
那么,什么时候应该跳过 SSL 代理?
通常有三类情况。
1. 源站证书与 Host 存在兼容问题
例如本文的 ERR_TLS_CERT_ALTNAME_INVALID。直接把问题域加入 Exclude,让它恢复成普通 HTTPS 隧道。
2. 这个站点本来就不需要抓明文
例如 *.google-analytics.com、*.example-cdn.com。这些流量只是背景请求,你并不关心它的 HTTPS 内容。把它们排除,可以减少抓包噪声。
3. 某些客户端使用了证书固定等机制
如果某个应用不适合被中间人代理,或者你根本不需要查看它的 HTTPS 明文,也可以让对应 Host 直接走隧道。
这里要注意:跳过 SSL 代理并不是「解决证书固定」,而是选择不对这部分流量进行 SSL 中间人代理。
不要为了几个网站关闭整个 SSL 代理
这是最重要的使用建议。
如果只有 admin.shop-example.com 有问题,没有必要把整个 SSL 代理关掉。也没有必要为了绕过一个站点的源站证书问题,就关闭全局的源站证书校验。后者相当于让代理不再认真验证自己连接的真实源站。
正确的思路应该是:
大部分域名
↓
SSL 代理
↓
需要明文抓包
少数特殊域名
↓
跳过 SSL 代理
↓
HTTPS 隧道
两种模式可以在同一套代理配置里长期共存。
最终可以记住这一句话
如果:直连正常 + 开启 SSL 代理后某个站点失败 + Host 与源站证书 SAN 不匹配,那么优先检查 「跳过 SSL 代理(隧道)」,而不是重新安装 CA,也不是关闭整个 SSL 抓包。
最终的判断逻辑就是:
Include
│
├── 未命中 → 不做 SSL 代理
│
└── 命中
│
├── Exclude 命中 → 隧道
│
└── Exclude 未命中 → SSL 代理
这样既可以保持大部分 HTTPS 的明文抓包,也不会因为少数特殊站点把整个代理配置关掉。
下一步
如果你需要继续处理接口调试,可以沿着同一条代理链继续往下:
- 参数转换:处理 AES、Base64 等参数编解码
- 转发规则:接口已经迁移,前端还没发版?直接改到新服务
- Mock:不改后端,直接模拟接口响应
- 抓包界面与请求详情:查看和分析 HTTP / HTTPS / WebSocket 流量
如果只是想解决本文这个问题,通常只需要:找到出问题的 Host → 在 SSL 代理配置里排除它 → 刷新连接。
下一篇
《待整理:代理链上的断点、重发与协作》——继续聊接口联调中那些容易被代理工具「卡住」的细节。
如果你也遇到过「一开 SSL 代理,个别网站反而打不开」,欢迎 下载 DevPeek 试试在 SSL 代理配置中增加一条排除规则,也可以到 GitHub Discussions 交流你遇到的证书、CDN 或代理兼容问题。