You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Jetty ProxyServlet处理SSL的CONNECT请求

我来帮你捋捋嵌入式Jetty的AsyncMiddlemanServlet在HTTPS环境下踩的坑,毕竟我之前也折腾过类似的场景😉

嵌入式Jetty AsyncMiddlemanServlet HTTPS代理问题排查与解决

1. 先把HTTPS端点的基础配置拉满

很多时候HTTPS代理卡壳,根源是Jetty本身的SSL上下文没配置对。你得给Server或者Connector绑定正确的SslContextFactory,不管用自签证书还是内部CA签发的证书都不能偷懒:

// 配置服务器端SSL上下文
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("/path/to/your/keystore.jks");
sslContextFactory.setKeyStorePassword("your-keystore-pass");
// 重点:如果后端HTTPS服务用的是自签/内部CA证书,必须把它加到信任库
sslContextFactory.setTrustStorePath("/path/to/your/truststore.jks");
sslContextFactory.setTrustStorePassword("your-truststore-pass");

// 把SSL上下文绑定到HTTPS连接器
ServerConnector sslConnector = new ServerConnector(
    server,
    new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
    new HttpConnectionFactory(new HttpConfiguration())
);
sslConnector.setPort(443);
server.addConnector(sslConnector);

要是后端证书没被信任,Jetty连握手都通不过,更别说代理了。

2. 给AsyncMiddlemanServlet的内部HttpClient补SSL配置

AsyncMiddlemanServlet是靠内部HttpClient去请求后端服务的,很多人只配置了服务器端的SSL,忘了给这个客户端也配,结果后端HTTPS请求直接失败。你可以重写newHttpClient()方法补全:

@Override
protected HttpClient newHttpClient() throws Exception {
    HttpClient httpClient = super.newHttpClient();
    // 配置客户端SSL上下文,和服务器端信任库保持一致就行
    SslContextFactory.Client clientSslContext = new SslContextFactory.Client();
    clientSslContext.setTrustStorePath("/path/to/your/truststore.jks");
    clientSslContext.setTrustStorePassword("your-truststore-pass");
    httpClient.setSslContextFactory(clientSslContext);
    return httpClient;
}

这一步是HTTPS代理能正常转发请求的核心,别漏了!

3. 修正HTTPS转发的逻辑细节

当代理收到HTTPS请求时,要确保转发给后端的也是HTTPS协议,别不小心转成HTTP了。可以重写rewriteTarget()方法做校验:

@Override
protected String rewriteTarget(HttpServletRequest request) {
    String originalTarget = super.rewriteTarget(request);
    // 根据你的实际场景调整,比如把HTTP目标强制转成HTTPS
    if (originalTarget.startsWith("http://")) {
        return originalTarget.replaceFirst("http://", "https://");
    }
    return originalTarget;
}

另外记得给后端传递X-Forwarded-Proto: https头部,避免后端服务因为识别不到原始协议而跳转到HTTP。

4. 开DEBUG日志抓问题

要是还是卡壳,直接开Jetty的DEBUG日志,重点看SSL握手和HttpClient请求的细节:

// 代码里临时开DEBUG日志
org.eclipse.jetty.util.log.Log.getRootLogger().setLevel(Level.DEBUG);

或者启动时加参数:
-Dorg.eclipse.jetty.LEVEL=DEBUG
日志里能直接看到是SSL握手失败(比如证书不被信任)、URL转发错误,还是异步处理超时,比瞎猜高效多了。

5. 适配老旧服务器的兼容性

你提到是给老旧服务器做代理,那得考虑后端HTTPS服务的SSL协议版本和加密套件是否和Jetty兼容。Jetty 9.4默认禁用了TLSv1.0这类旧协议,如果后端只支持旧协议,得手动开启:

sslContextFactory.setIncludeProtocols("TLSv1.0", "TLSv1.1", "TLSv1.2");
// 按需添加后端支持的加密套件
sslContextFactory.setIncludeCipherSuites("SSL_RSA_WITH_3DES_EDE_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");

这一步要权衡安全性,毕竟旧协议有漏洞,但内部环境下可以临时妥协。


内容的提问来源于stack exchange,提问作者Chris Bartlett

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:06:58