ca证书不匹配是最常见原因,需验证服务端ca路径存在且可读、内容有效,并确保客户端(dbeaver/jdbc/命令行)正确加载对应证书,同时检查jvm tls版本兼容性及缓存问题。

MySQL客户端连接报“SSL handshake failed”时,CA证书不匹配是最常见原因
不是所有SSL握手失败都该关SSL,很多情况只是客户端没拿到服务端信任的CA证书。比如连阿里云RDS、腾讯云CDB或自建MySQL 8.0+启用require_secure_transport=on后,客户端若没配sslTrustCertificate或用错证书文件,就会在TLS协商阶段直接中断——错误日志里常出现javax.net.ssl.SSLHandshakeException或SSL_connect_error。
确认服务端实际加载的CA证书路径和内容
别只看my.cnf里写了ssl_ca = /path/to/ca.pem,得验证这个文件真实存在、可读、且内容有效:
- 登录MySQL执行:
SHOW VARIABLES LIKE 'ssl_ca';,拿到路径 - 在服务器上检查文件权限:
ls -l /path/to/ca.pem,确保MySQL进程用户(如mysql)有读权限 - 用OpenSSL验证证书是否能被正确解析:
openssl x509 -in /path/to/ca.pem -text -noout,输出应含Subject:和有效期,不能报unable to load certificate - 云数据库用户注意:AWS/Aliyun/RDS提供的CA证书是独立下载的,不是服务端自签名的,必须用控制台下载的
RDS-Global-Bundle.pem或aliyun-rds-ca-cert.pem,不能用mysql_ssl_rsa_setup生成的本地证书
DBeaver、JDBC、命令行工具分别怎么填CA证书
同一份CA证书,在不同客户端里加载方式差异很大,填错位置等于没配:
-
DBeaver:编辑连接 → “Driver properties” → 找到
sslTrustCertificate,值填绝对路径(如/home/user/certs/aliyun-rds-ca-cert.pem),不要填相对路径或URL;同时确保useSSL设为true,sslMode设为REQUIRED -
JDBC URL:必须显式指定
trustCertificateKeyStoreUrl和trustCertificateKeyStorePassword,例如:jdbc:mysql://xxx:3306/db?sslMode=REQUIRED&trustCertificateKeyStoreUrl=file:/tmp/rds-ca.pem&trustCertificateKeyStorePassword=changeit;注意changeit是Java默认JKS密码,若用PEM需先转JKS,或改用sslTrustCertificate参数(部分驱动支持) -
mysql命令行:用
--ssl-ca=/path/to/ca.pem,不能只写--ssl-mode=VERIFY_CA却不指定CA路径,否则会静默降级为PREFERRED
CA证书更新后,客户端缓存和JVM TLS协议支持也要同步检查
换了新CA证书,不代表问题立刻解决——旧证书可能还被JVM或驱动缓存,或者JDK根本不支持服务端要求的TLS版本:
- Java应用启动时加JVM参数强制刷新信任库:
-Djavax.net.ssl.trustStore=/dev/null -Djavax.net.ssl.trustStoreType=JKS(慎用,仅调试),或更稳妥地把CA导入JVM默认cacerts:keytool -importcert -alias rds-ca -file rds-ca.pem -keystore $JAVA_HOME/jre/lib/security/cacerts - 确认JDK支持TLSv1.2+:
java -cp . TestTLS(TestTLS类里调用SSLContext.getDefault().getSupportedSSLParameters().getProtocols()),OpenJDK 8u252+才默认启用TLSv1.2,低于此版本需手动加-Dhttps.protocols=TLSv1.2 - DBeaver底层用的是自带JRE,不是系统JDK,所以改系统
cacerts无效;要进DBeaver安装目录找jre/lib/security/cacerts,或在DBeaver.ini里加-Djavax.net.ssl.trustStore=...
CA证书本身没问题,不代表它就能被客户端正确加载——路径写错、格式不兼容、JVM未识别、驱动参数混用,任何一个环节断掉,握手都会在第一个数据包就失败。排查时优先抓包看ClientHello里有没有发送CertificateVerify,比反复改配置更直接。











