ZAP经zScaler企业代理访问HTTPS时连接重置问题求助
ZAP在ZScaler企业代理后无法建立HTTPS连接,提示Connection reset
在ZScaler企业代理后方使用ZAP工具时,HTTP流量可正常传输,但访问HTTPS网站时触发java.net.SocketException: Connection reset错误,curl通过同一代理访问HTTPS网站则完全正常。
ZAP错误日志
ZAP Error [java.net.SocketException]: Connection reset Stack Trace: java.net.SocketException: Connection reset at java.base/sun.nio.ch.NioSocketImpl.implRead(NioSocketImpl.java:323) at java.base/sun.nio.ch.NioSocketImpl.read(NioSocketImpl.java:350) at java.base/sun.nio.ch.NioSocketImpl$1.read(NioSocketImpl.java:803) at java.base/java.net.Socket$SocketInputStream.read(Socket.java:966) at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:484) at java.base/sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:478) at java.base/sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:160) at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:111) at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1510) at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1425) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:455) at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:426) at org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.executeHandshake(SSLConnectionSocketFactory.java:303) at org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:275) at org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:251) at org.zaproxy.addon.network.internal.client.apachev5.SslConnectionSocketFactory.connectSocket(SslConnectionSocketFactory.java:195) at org.apache.hc.client5.http.impl.io.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:181) at org.apache.hc.client5.http.impl.io.ZapHttpClientConnectionOperator.connect(ZapHttpClientConnectionOperator.java:95) at org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:433) at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.connectEndpoint(InternalExecRuntime.java:159) at org.apache.hc.client5.http.impl.classic.InternalExecRuntime.connectEndpoint(InternalExecRuntime.java:169) at org.apache.hc.client5.http.impl.classic.ConnectExec.execute(ConnectExec.java:146) at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at org.apache.hc.client5.http.impl.classic.ProtocolExec.execute(ProtocolExec.java:192) at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at org.apache.hc.client5.http.impl.classic.ZapHttpRequestRetryExec.execute(ZapHttpRequestRetryExec.java:81) at org.apache.hc.client5.http.impl.classic.ExecChainElement.execute(ExecChainElement.java:51) at org.apache.hc.client5.http.impl.classic.ZapInternalHttpClient.doExecute(ZapInternalHttpClient.java:158) at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:245) at org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(CloseableHttpClient.java:188) at org.zaproxy.addon.network.internal.client.apachev5.HttpSenderApache.sendImpl0(HttpSenderApache.java:394) at org.zaproxy.addon.network.internal.client.apachev5.HttpSenderApache.sendImpl(HttpSenderApache.java:297) at org.zaproxy.addon.network.internal.client.apachev5.HttpSenderApache.sendImpl(HttpSenderApache.java:103) at org.zaproxy.addon.network.internal.client.BaseHttpSender.sendAuthenticated(BaseHttpSender.java:298) at org.zaproxy.addon.network.internal.client.BaseHttpSender.sendNoRedirections(BaseHttpSender.java:266) at org.zaproxy.addon.network.internal.client.BaseHttpSender.send(BaseHttpSender.java:222) at org.zaproxy.addon.network.internal.client.BaseHttpSender.sendAndReceive(BaseHttpSender.java:193) at org.zaproxy.addon.network.internal.client.BaseHttpSender.sendAndReceive(BaseHttpSender.java:57) at org.parosproxy.paros.network.HttpSender.sendAndReceive(HttpSender.java:303) at org.zaproxy.addon.network.internal.server.http.handlers.HttpSenderHandler.handleMessage(HttpSenderHandler.java:77) at org.zaproxy.addon.network.internal.server.http.MainServerHandler.notifyMessageHandlers(MainServerHandler.java:133) at org.zaproxy.addon.network.internal.server.http.MainServerHandler.processMessage(MainServerHandler.java:115) at org.zaproxy.addon.network.internal.server.http.LocalServerHandler.processMessage(LocalServerHandler.java:63) at org.zaproxy.addon.network.internal.server.http.MainServerHandler.process(MainServerHandler.java:84) at org.zaproxy.addon.network.internal.server.http.MainServerHandler.channelRead0(MainServerHandler.java:73) at org.zaproxy.addon.network.internal.server.http.MainServerHandler.channelRead0(MainServerHandler.java:38) at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.access$600(AbstractChannelHandlerContext.java:61) at io.netty.channel.AbstractChannelHandlerContext$7.run(AbstractChannelHandlerContext.java:370) at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) at io.netty.util.concurrent.DefaultEventExecutor.run(DefaultEventExecutor.java:66) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:833)
curl正常访问日志
C:\Users\ORI17635>curl -v https://google.de * Uses proxy env variable all_proxy == 'http://165.225.72.40:80' * Trying 165.225.72.40:80... * Connected to 165.225.72.40 (165.225.72.40) port 80 (#0) * allocate connect buffer * Establish HTTP proxy tunnel to google.de:443 > CONNECT google.de:443 HTTP/1.1 > Host: google.de:443 > User-Agent: curl/8.0.1 > Proxy-Connection: Keep-Alive > < HTTP/1.1 200 Connection Established < Proxy-Agent: Zscaler/6.2 < * CONNECT phase completed * CONNECT tunnel established, response 200 * schannel: disabled automatic use of client certificate * ALPN: offers http/1.1 * ALPN: server accepted http/1.1 * using HTTP/1.1 > GET / HTTP/1.1 > Host: google.de > User-Agent: curl/8.0.1 > Accept: */* > < HTTP/1.1 301 Moved Permanently < Location: https://www.google.de/ < Content-Type: text/html; charset=UTF-8 < Content-Security-Policy-Report-Only: object-src 'none';base-uri 'self';script-src 'nonce-aSS9KPWBUfr_W55RxLWlGw' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp < Date: Mon, 17 Jul 2023 21:27:35 GMT < Expires: Mon, 17 Jul 2023 21:27:35 GMT < Cache-Control: private, max-age=2592000 < Server: gws < Content-Length: 219 < X-XSS-Protection: 0 < X-Frame-Options: SAMEORIGIN ...
已尝试导入自签名根证书,但推测问题可能出在ZAP生成的中间证书中组织单元(OU)固定为"Zed Attack Proxy Project",导致ZScaler拦截了连接。
解决方案
1. 自定义ZAP证书的OU字段
ZAP允许修改生成证书的组织单元信息,步骤如下:
- 打开ZAP,进入 工具 -> 选项 -> 动态SSL证书
- 点击 生成 按钮旁的 高级 选项
- 在证书生成对话框中,将**组织单元(OU)**修改为符合企业安全策略的名称(如企业内部标识)
- 重新生成根证书,导出后导入系统信任存储,同时确保ZScaler代理信任该证书
2. 配置ZAP使用ZScaler的根证书
若企业要求必须使用ZScaler证书代理,可让ZAP直接使用其根证书解密流量:
- 从ZScaler管理员处获取企业根证书(通常为.pem格式)
- 在ZAP的 工具 -> 选项 -> 动态SSL证书 中,点击 导入 选择ZScaler根证书
- 确保ZAP代理配置指向ZScaler地址,且系统已信任ZScaler证书
3. 对齐ZAP与curl的CONNECT请求头部
对比curl的请求头部,确保ZAP发送的CONNECT请求包含必要字段:
- 在ZAP的 工具 -> 选项 -> 网络 -> HTTP客户端 中,添加自定义头部
Proxy-Connection: Keep-Alive - 可将ZAP的User-Agent修改为与curl一致的值(如
curl/8.0.1)测试是否因UA被拦截
4. 禁用ZAP的SSL会话复用
部分企业代理对SSL会话复用支持存在问题,尝试禁用该功能:
- 进入ZAP的 工具 -> 选项 -> 网络 -> SSL
- 取消勾选 启用SSL会话复用,重启ZAP后测试连接
内容的提问来源于stack exchange,提问作者maurizio
相关产品推荐
相关产品推荐

