mod_log_config无法记录SSL握手原始信息,仅能在TLS握手成功后记录mod_ssl提供的会话级变量,如%{SSL_PROTOCOL}x、%{SSL_CIPHER}x等,且必须启用mod_ssl并使用正确的%{}x语法,错误写成%{}e将导致字段为空。

mod_log_config 本身不能记录 SSL 握手过程中的原始信息(比如 ClientHello 内容、SNI、ALPN),但它可以在 TLS 握手成功、HTTP 请求进入处理流程后,记录由 mod_ssl 提供的会话级变量——前提是 Apache 已启用 mod_ssl,且连接未在握手阶段失败。
必须确认 mod_ssl 已启用并完成握手
只有 TLS 握手成功后,%{SSL_PROTOCOL}x 和 %{SSL_CIPHER}x 等变量才可用。若客户端使用 TLS 1.0 连接而你已用 SSLProtocol all -TLSv1 -TLSv1.1 禁用该版本,请求根本不会到达日志模块,对应字段将为空或被跳过。
- 检查是否加载了
mod_ssl:httpd -M | grep ssl或查看LoadModule ssl_module modules/mod_ssl.so - 确保虚拟主机中启用了 SSL:
SSLEngine on - 不要依赖“握手前”日志——
mod_log_config没有这个能力
正确使用 %{...}x 语法记录 SSL 会话信息
%{...}x 是 mod_ssl 专用于日志的扩展语法,不是普通环境变量访问方式(%{...}e 无效)。常见可记录项包括:
-
%{SSL_PROTOCOL}x→ 实际协商协议,如TLSv1.2或TLSv1.3 -
%{SSL_CIPHER}x→ 加密套件名,如ECDHE-RSA-AES128-GCM-SHA256 -
%{SSL_CIPHER_USEKEYSIZE}x→ 实际对称密钥位数,如128 -
%{SSL_SECURE_RENEG}x→ 是否启用安全重协商(secure/unsafe) -
%{SSL_CLIENT_VERIFY}x→ 客户端证书验证结果(SUCCESS/NONE/FAILED:xxx)
示例配置:
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
注意 TLS 1.3 下 SSL_CIPHER 的行为差异
TLS 1.3 的加密套件与密钥交换机制已解耦,%{SSL_CIPHER}x 在 TLS 1.3 连接中仍会返回套件名(如 TLS_AES_256_GCM_SHA384),但它的语义和 TLS 1.2 不同:不再包含密钥交换算法(如 ECDHE),也不再反映签名算法或证书类型。
- 如果你依赖
%{SSL_CIPHER}x做客户端兼容性分析(比如判断是否用了 RSA 密钥交换),TLS 1.3 场景下该字段已失去这部分含义 - 无法通过
%{SSL_CIPHER}x区分是 ECDSA 还是 RSA 证书——需结合%{SSL_SERVER_S_DN_CN}x或其他证书字段 - 若需区分 TLS 版本+套件组合,建议额外记录
%{SSL_PROTOCOL}x并做联合解析,而非只看 cipher 字段
别把 %{...}x 当成通用环境变量来用
很多人误写成 %{SSL_PROTOCOL}e 或 %{SSL_CIPHER}e,这是错的——e 表示环境变量(environment),而 SSL 会话变量是 x(ssl extension)。Apache 会静默忽略错误语法,对应位置输出 -,日志里看着像“没数据”,实际是配置写错了。
- 正确写法只有
%{SSL_PROTOCOL}x、%{SSL_CIPHER}x等带x后缀的形式 - 所有 SSL 相关日志变量都以
x结尾,没有例外 - 调试时可用
LogLevel debug+SSLOptions +StdEnvVars查看实际注入的环境变量,但日志中仍必须用x访问
真正想审计握手失败原因(比如 ALPN 不匹配、SNI 为空、证书链不全),得换工具:tcpdump 抓包解密、OpenSSL s_server -debug 模拟、或部署专用 TLS 代理。mod_log_config 只管“活下来的连接”。


















