$ssl_client_fingerprint才是唯一指纹,$ssl_client_s_dn因字段顺序不固定、转义问题及缺乏唯一性无法直接用作唯一标识;应优先使用40字符SHA-1指纹,并结合解析后的CN/serialNumber与验证状态等构建审计依据。
直接用 $ssl_client_s_dn 记录客户端身份并不等于获得“唯一指纹”——它只是可读的字符串,字段顺序不固定、易被转义、不能直接用于去重或匹配。真正可用的唯一指纹是 $ssl_client_fingerprint,而 $ssl_client_s_dn 的价值在于结合解析后提取结构化标识(如 CN、serialNumber),再与指纹联合使用,才能构建可靠审计依据。
该变量输出的是证书主题 DN 的标准字符串表示,例如:"CN=device-001,OU=IoT,O=Corp,L=Beijing,ST=BJ,C=CN"
但它存在几个关键限制:
OU=Dev,CN=app-01)这是最简、最稳、最隐私友好的方式。只要客户端在 TLS 握手阶段发送了证书(无论是否通过验证),该变量就生成一个 40 字符的 SHA-1 指纹,例如:a1b2c3d4e5f678901234567890abcdef12345678
$ssl_client_verify 判断是否有效(SUCCESS / FAILED / NONE)若业务强依赖 CN、OU 或 serialNumber,应使用 map 指令做正则预处理,避免硬切分:
map $ssl_client_s_dn $client_cn { ~CN=([^,]+) $1; default "-";}map $ssl_client_s_dn $client_serial { ~serialNumber=([^,]+) $1; default "-";}
注意:
~OU=([^,]+)(?:,|$) 这类模式,兼容字段位置变化X-Client-CN 头给后端单靠一个变量不够,建议在 log_format 中同时记录:
fingerprint="$ssl_client_fingerprint" —— 唯一证书指纹dn="$ssl_client_s_dn" —— 原始 DN(供人工核查)verify="$ssl_client_verify" —— 验证状态(排除吊销、过期等异常)issuer="$ssl_client_i_dn" —— 签发者 DN,防止私有 CA 滥用proto="$ssl_protocol" cipher="$ssl_cipher" —— TLS 协议与加密套件,评估客户端安全性这样一条日志就能支撑设备识别、异常行为追踪、合规性检查三类审计场景。