apache http server 本身不支持 mod_ssl 日志格式自由定制,但可通过 ssl 日志指令和环境变量将 tls 握手信息输出至访问日志或错误日志以辅助排障;关键字段如 %{ssl_protocol}x、%{ssl_cipher}x 等需配合 logformat 使用;握手失败日志默认仅记录在 error_log 中,需设 loglevel ssl:debug 并关注“no shared cipher”等关键词;java 侧需同步检查 tls 版本、加密套件兼容性、证书链及系统时间。

Apache HTTP Server 本身不提供 mod_ssl 的日志格式自定义能力(比如像 LogFormat 那样自由组合 SSL 字段),但可以通过启用特定的 SSL 日志指令和环境变量,将关键握手信息输出到访问日志或错误日志中,辅助排查 TLS 握手失败问题。
SSL 相关日志指令与常用字段
Apache 的 mod_ssl 提供了若干内置日志变量,需配合 LogFormat 和 %{...}x 语法使用。这些变量只在 HTTPS 请求上下文中有效(即仅对启用 SSL 的虚拟主机生效):
-
%{SSL_PROTOCOL}x:协商使用的 TLS 协议版本(如TLSv1.2、TLSv1.3) -
%{SSL_CIPHER}x:协商成功的加密套件(如ECDHE-ECDSA-AES128-GCM-SHA256) -
%{SSL_SECURE_RENEG}x:是否启用安全重协商(on/off) -
%{SSL_CLIENT_VERIFY}x:客户端证书验证结果(NONE、SUCCESS、FAILED:xxx) -
%{SSL_CLIENT_S_DN}x:客户端证书主题 DN(常用于双向认证调试) -
%{SSL_SERVER_S_DN_OU}x等:服务端证书组织单位等字段(支持细粒度提取)
示例日志格式定义(加入主配置或虚拟主机内):
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %{SSL_PROTOCOL}x %{SSL_CIPHER}x %{SSL_CLIENT_VERIFY}x" ssl_combined
再在 CustomLog 中启用:
CustomLog logs/ssl_access.log ssl_combined
定位握手异常的核心日志位置
SSL 握手失败通常**不会出现在访问日志中**(因为连接未建立成功),而会记录在 错误日志(error_log) 中,且默认级别可能不够详细。需主动提升日志级别并关注以下线索:
- 确保
LogLevel至少设为info,推荐调试时临时设为debug(注意性能与磁盘空间):LogLevel info ssl:debug - 常见握手失败关键词:
SSL_do_handshake failed、SSL_accept failed、no shared cipher、unknown protocol、bad certificate、certificate verify failed - 重点检查前后几行:错误行本身往往只显示“失败”,但前序日志常含 Client Hello 的协议版本、SNI 域名、支持的密码套件列表;后续日志可能有证书加载失败、私钥不匹配、OCSP 响应超时等根因
Java 应用侧关联排查要点
若 Apache 作为反向代理(如通过 mod_proxy_http 或 mod_jk)对接 Java 后端,握手异常可能源于两端 TLS 配置不兼容。需同步检查:
- Java 客户端(如 HttpClient、OkHttp)是否禁用了旧协议(如 JDK 8u251+ 默认禁用 TLSv1/TLSv1.1),而 Apache 仍强制要求?
- Java 服务端(如 Tomcat 的
Connector)是否启用了不兼容的 TLS 版本或加密套件?可对比双方openssl s_client -connect host:port -tls1_2输出的 Supported Ciphers - 证书链完整性:Java 的 TrustStore 是否包含 Apache 所用证书的全部中间 CA?可用
keytool -list -v -keystore cacerts验证 - 时间同步:Java 进程所在系统时间偏差超过 5 分钟,会导致证书“尚未生效”或“已过期”误判
快速验证与最小化复现建议
不要依赖单一日志。建议组合使用以下方法交叉验证:
- 用
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com -debug -msg模拟握手,观察 Client Hello / Server Hello 交换细节 - 开启 Wireshark 抓包(过滤
ssl.handshake),直接查看 Alert 报文内容(如handshake_failure、protocol_version) - 临时在 Apache 中添加
SSLOptions +StdEnvVars,并在 CGI/PHP 脚本中打印$_SERVER['SSL_PROTOCOL']等变量,确认运行时实际协商结果 - 检查 Apache 是否启用了
SSLStrictSNIVHostCheck on,且 SNI 域名与证书 Subject Alternative Name 不匹配
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










