Jetty SSL配置有效性验证及握手失败问题排查求助
问题情况
Jetty启动后日志显示SSL连接器已正常启动:
jetty9[31330]: 2023-06-13 16:45:40.260:INFO:oejs.AbstractConnector:main: Started ServerConnector@7668d560{SSL,[ssl, alpn, h2, http/1.1]}{0.0.0.0:8443}
但使用Insomnia发送HTTPS GET请求时触发SSL_ERROR,Jetty连接日志显示连接刚建立即关闭:
16:47:38.179:qtp1715998167-27 OPENED ALPNServerConnection@b2904c::DecryptedEndPoint@3499d391{:54855<->:8443,OPEN,fill=-,flush=-,to=1/30000}
16:47:38.212:qtp1715998167-15 CLOSED ALPNServerConnection@b2904c::DecryptedEndPoint@3499d391{:54855<->:8443,CLOSED,fill=-,flush=-,to=31/30000}
16:47:38.212:qtp1715998167-15 CLOSED SslConnection@d0b4ffc::SocketChannelEndPoint@297abdf1{/:54855<->:8443,CLOSED,fill=-,flush=-,to=0/30000}{io=1/1,kio=-1,kro=-1}->SslConnection@d0b4ffc{NOT_HANDSHAKING,eio=-1/-1,di=-1,fill=IDLE,flush=IDLE}~>DecryptedEndPoint@3499d391{/:54855<->:8443,CLOSED,fill=-,flush=-,to=31/30000}=>ALPNServerConnection@b2904c
执行keytool -printcert -sslserver 0.0.0.0:8443 -v返回握手失败,无法获取证书:
java.lang.Exception: No certificate from the SSL server
at java.base/sun.security.tools.keytool.Main.doPrintCert(Main.java:2736)
at java.base/sun.security.tools.keytool.Main.doCommands(Main.java:1238)
at java.base/sun.security.tools.keytool.Main.run(Main.java:397)
at java.base/sun.security.tools.keytool.Main.main(Main.java:390)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
...(省略后续堆栈信息)
但通过sudo keytool -list -v -keystore etc/keystore检查本地密钥库,确认已存在对应SSL证书条目,问题出在哪里?
可能的问题点及排查步骤
1. Jetty加载的密钥库路径不正确
你检查的etc/keystore未必是Jetty实际使用的文件,尤其是配置相对路径时,需以Jetty启动时的工作目录为基准:
- 打开Jetty的SSL配置文件(如
jetty-ssl.xml或start.ini),核对keystorePath参数,确认路径为绝对路径,或相对Jetty启动目录的路径无误。 - 启动Jetty时添加
-Djavax.net.debug=ssl,handshake参数,输出SSL调试日志,查看Jetty实际加载的密钥库路径及证书读取状态。
2. 密钥库密码与Jetty配置不匹配
即使密钥库存在证书,若Jetty配置的keystorePassword或keyPassword错误,会导致无法读取证书,直接触发握手失败:
- 验证密钥库密码:执行
keytool -list -keystore etc/keystore,输入密码确认能正常列出条目,再与Jetty配置中的密码核对。 - 注意证书条目是否设置了独立的密钥密码,若有则必须在Jetty配置中指定
keyPassword,且与该密码一致。
3. 证书链不完整或格式不兼容
- 检查密钥库中的证书是否包含完整链:从服务器证书到中间CA再到根CA,缺失中间证书会导致客户端无法信任服务器,握手失败。
- 确认证书格式为Jetty支持的类型(JKS或PKCS12),若使用PKCS12,需在Jetty配置中添加
keystoreType=PKCS12。
4. SSL协议/密码套件不兼容
客户端(Insomnia)支持的SSL协议或密码套件与Jetty配置不匹配,会导致协商失败:
- 查看Jetty配置中
sslContextFactory的设置,确认启用的协议(如protocols=TLSv1.2,TLSv1.3)和密码套件是否被客户端支持。 - 使用
openssl s_client -connect 0.0.0.0:8443命令测试,可直观查看协议协商结果及错误信息,比keytool更清晰。
5. ALPN配置异常
日志显示使用了ALPNServerConnection,若ALPN配置错误(尤其在HTTP/2场景下),会导致握手失败:
- 核对Jetty的ALPN依赖:Java 9+版本ALPN已内置,但需确保Jetty版本与JDK版本兼容;Java 8及以下需手动添加ALPN扩展库。
- 可暂时禁用HTTP/2,仅启用HTTP/1.1,测试是否能正常握手,排除ALPN相关问题。
6. 端口绑定或防火墙拦截
虽然日志显示连接器监听0.0.0.0:8443,但可能存在端口复用或防火墙拦截,导致客户端连接未到达Jetty:
- 执行
netstat -tulpn | grep 8443确认Jetty进程确实在监听该端口。 - 本地使用
curl -k https://localhost:8443测试(-k跳过证书验证),若本地也失败则问题在服务器端;若本地成功则排查网络/防火墙问题。
内容的提问来源于stack exchange,提问作者Garros JP

