apache mod_ssl不支持logformat式自定义ssl日志,但可通过loglevel info ssl:debug将tls握手细节(如client hello、sni、密码套件)输出至error_log以排查“ssl handshake failed”;成功连接可用%{ssl_protocol}x等字段记录于访问日志;关键线索包括“no shared cipher”“unknown protocol”及openssl错误码。
apache 的 mod_ssl 本身不支持像 logformat 那样自由定义 ssl 日志字段的格式,但可以通过启用详细日志级别和使用特定环境变量,把关键 tls 握手信息输出到错误日志中,用于定位“ssl handshake failed”这类问题。
开启 SSL 调试日志
默认情况下,错误日志只记录简略失败信息。要看到握手过程细节,必须提升日志级别:
- 在 Apache 主配置(如
httpd.conf或虚拟主机配置)中设置:LogLevel info ssl:debug - 重启 Apache 后,
error_log会输出 Client Hello 的协议版本、SNI 域名、支持的密码套件列表等前序信息,这对判断“no shared cipher”或“unknown protocol”非常关键 - 注意:debug 级别会产生大量日志,排查完毕建议调回
warn或error,避免磁盘被占满
在访问日志中记录协商结果
虽然握手失败本身不会进访问日志(连接未建立),但成功 HTTPS 请求的协议与加密信息可辅助对比分析:
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
- 定义含 SSL 字段的日志格式,例如:
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{SSL_PROTOCOL}x %{SSL_CIPHER}x" ssl_combined - 在虚拟主机中启用:
CustomLog logs/ssl_access.log ssl_combined - 有效字段包括:
%{SSL_PROTOCOL}x(如 TLSv1.2)、%{SSL_CIPHER}x(如 ECDHE-RSA-AES256-GCM-SHA384)、%{SSL_CLIENT_VERIFY}x(双向认证时用)
重点盯住错误日志里的关键线索
真正定位握手失败,90% 的依据来自 error_log 中的几类高信息量条目,而非泛泛的“SSL handshake failed”:
-
SSL_do_handshake() failed或SSL_accept() failed:服务端在接收 Client Hello 阶段就出错,常见于私钥不匹配、证书加载失败或 OpenSSL 初始化异常 -
no shared cipher:客户端与服务器支持的加密套件无交集,需检查SSLCipherSuite配置是否过于严格,或客户端太旧(如仅支持 SSLv3) -
unknown protocol:TLS 版本不兼容,比如客户端发 TLS 1.3 Hello,而 Apache 配置了SSLProtocol -all +TLSv1.2 -
bad certificate或certificate verify failed:证书过期、链不完整(漏中间证书)、私钥与证书不匹配、或 OCSP 响应超时 - OpenSSL 错误码(如
error:1408A0C1):最精准的线索,可用命令openssl errstr 1408A0C1直接查含义
验证证书与密钥是否真正匹配
很多“bad certificate”错误其实源于私钥和证书不配对,光看文件名一致没用:
- 提取证书公钥模数并 MD5:
openssl x509 -noout -modulus -in cert.pem | openssl md5 - 提取私钥模数并 MD5:
openssl rsa -noout -modulus -in key.pem | openssl md5 - 两行输出必须完全相同;不同说明不是一对,必须重新生成或核对
- 检查证书有效期:
openssl x509 -in cert.pem -noout -dates - 验证证书链(尤其 Let’s Encrypt):
openssl verify -CAfile fullchain.pem cert.pem,返回 OK 才算完整










