Nginx - 如何访问客户端证书的主题备用名称 (SAN) 字段

joe*_*eoj 7 nginx client-certificates ssl-certificate x509

我有一个 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";
}
}
Run Code Online (Sandbox Code Playgroud)

使用作为ngx_http_ssl_module模块一部分公开的嵌入式变量,我可以访问 DN(专有名称),因此可以访问 CN 等,但我似乎无法访问 SAN。

是否有一些我缺少的嵌入式 var/其他模块/通用 Nginx foo?我可以访问原始证书,那么是否可以手动解码并提取它?

我真的宁愿在 Nginx 层执行此操作,而不是将证书传递到应用程序层并在那里执行。

非常感谢任何帮助。

js.*_*js. 11

您可以使用 Nginx-builtin map提取它们,例如对于 CN:

map $ssl_client_s_dn $ssl_client_s_dn_cn {
    default "";
    ~,CN=(?<CN>[^,]+) $CN;
}
Run Code Online (Sandbox Code Playgroud)

  • @js。它位于 nginx.conf 中的哪里?然后我如何将它作为标头传递到后端服务器? (3认同)
  • 自 nginx 版本 1.11.6 以来,$ssl_client_s_dn 的格式已更改为使用逗号而不是斜杠。(https://serverfault.com/q/829754)。上面的版本反映了这一点,但是有很多使用旧格式 ~/CN=(?&lt;CN&gt;[^/]+) $CN; 的例子。您很容易忽略斜杠而不是现在正确的逗号。至少我花了相当长的时间才发现我的配置错误。 (2认同)
  • 如果只有 CN 礼物,这将会失败。 (2认同)
  • 这不会获取 SAN。上面的代码只会给出 CN (2认同)

小智 5

我不是 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, ':'))
Run Code Online (Sandbox Code Playgroud)


mik*_*ero 3

您可以通过 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=([^/]+)")
Run Code Online (Sandbox Code Playgroud)