我有一个Nginx服务器,客户端使用包含特定CN和SAN的客户端证书发出请求。我希望能够提取该客户端证书的CN(通用名称)和SAN(主题备用名称)字段。
粗略的示例配置:
server {
listen 443 ssl;
ssl_client_certificate /etc/nginx/certs/client.crt;
ssl_verify_client on; #400 if request without valid cert
location / {
root /usr/share/nginx/html;
}
location /auth_test {
# do something with the CN and SAN.
# tried these embedded vars so far, to no avail
return 200 "
$ssl_client_s_dn
$ssl_server_name
$ssl_client_escaped_cert
$ssl_client_cert
$ssl_client_raw_cert";
}
}
使用作为ngx_http_ssl_module模块的一部分公开的嵌入变量,我可以访问DN(专有名称),因此访问CN等,但我似乎无法访问SAN。
是否有一些嵌入式var /其他模块/一般Nginx foo我缺少?我可以访问原始证书,因此可以手动解码并提取它吗?
我宁愿在Nginx层执行此操作,而不是将证书传递到应用程序层并在那里执行。
任何帮助非常感谢。
您可以通过OpenResty + Lua-OpenSSL来完成它并解析原始证书以获取它。
请参阅:https://github.com/Seb35/nginx-ssl-variables/blob/master/COMPATIBILITY.md#ssl_client_s_dn_x509
像这样:
local varibleName = string.match(require("openssl").x509.read(ngx.var.ssl_client_raw_cert):issuer():oneline(),"/C=([^/]+)")
您可以使用Nginx-builtin map提取它们,例如对于CN:
map $ssl_client_s_dn $ssl_client_s_dn_cn {
default "";
~,CN=(?<CN>[^,]+) $CN;
}
我不是lua专家,但这就是我的工作:
local openssl = require('openssl')
dnsNames = {}
for k,v in pairs(openssl.x509.read(ngx.var.ssl_client_raw_cert):extensions()) do
for k1,v1 in pairs(v:info()) do
if(type(v1)=='table') then
for k2,v2 in pairs(v1) do
if(type(v2)=='table') then
for k3,v3 in pairs(v2) do
if(k3=='dNSName') then
table.insert(dnsNames, v3:toprint())
end
end
end
end
end
end
end
ngx.say(table.concat(dnsNames, ':'))