$ssl_protocol 是 Nginx 记录实际协商 TLS 版本的只读变量,用于真实审计而非仅依赖配置;需通过 log_format 记录、grep 筛查 TLSv1.0/1.1、结合 UA/IP 定位来源,并用 if 指令拦截或升级 OpenSSL 加固。

$ssl_protocol 是 Nginx 内置的只读变量,代表当前 HTTPS 连接实际协商并启用的 TLS 协议版本(如 TLSv1.2 或 TLSv1.3)。它不反映配置支持的协议范围,而是真实连接所用的协议——这正是审计合规性的黄金依据。
为什么必须用 $ssl_protocol 而非配置检查?
仅看 ssl_protocols TLSv1.2 TLSv1.3; 配置不能说明问题:客户端可能因兼容性降级到 TLSv1.0,或服务端未正确禁用旧协议导致漏洞暴露。$ssl_protocol 记录的是“实际发生”的协议,是真实攻击面的快照。
- PCI DSS、等保2.0、Azure 安全基准等强制要求禁用 TLSv1.0 和 TLSv1.1
- 若日志中持续出现
TLSv1.0,说明仍有老旧客户端(如 WinXP IE6)或恶意扫描器在连接 - 即使你已配置 TLSv1.3,若日志里没有
TLSv1.3字样,说明客户端不支持或中间设备拦截了协商过程
如何在日志中稳定捕获 $ssl_protocol
无需模块或代理,只需两步:
- 在
http块中定义含该变量的日志格式:log_format tls_audit '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $ssl_protocol $ssl_cipher'; - 将该格式应用到 access_log:
access_log /var/log/nginx/access.log tls_audit; - 执行
nginx -t && nginx -s reload生效
之后每条 HTTPS 请求日志末尾都会追加类似 TLSv1.2 或 -(明文 HTTP 请求时为空)。
快速识别不合规协议连接
直接用命令行筛查,高效定位风险:
- 查 TLSv1.0/TLSv1.1:
grep -E 'TLSv1\.0|TLSv1\.1' /var/log/nginx/access.log - 查协议缺失(即非 HTTPS 请求):
awk '$12 == "-" {print}' /var/log/nginx/access.log(假设 $ssl_protocol 是第12字段) - 统计各协议占比(辅助决策是否可全面关闭旧协议):
awk '{print $12}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
发现后怎么闭环处理?
记录只是起点,关键在响应:
- 结合
$remote_addr和$http_user_agent判断来源:是嵌入式设备、爬虫,还是真实用户? - 若某 IP 段集中出现 TLSv1.0,检查是否因 SNI 不支持导致降级;若为扫描器,可配合 geoip 或 rate-limit 封控
- 确认业务影响后,在 Nginx 中主动拦截:
if ($ssl_protocol ~ "^TLSv1\.0|TLSv1\.1$") { return 426 Upgrade Required; } - 最终加固:显式声明
ssl_protocols TLSv1.2 TLSv1.3;,并确保 OpenSSL 库版本 ≥1.1.1(支持 TLSv1.3)











