我正在尝试通过 Nginx 反向代理设置负载均衡器。我的应用程序使用客户端证书来验证客户端。我希望我的反向代理将客户端证书转发到我的后端服务器。我已将此行添加到我的反向代理的配置中,以将客户端证书信息存储在自定义 HTTP 标头中:
proxy_set_header X-SSL-CERT $ssl_client_cert
但是,$ssl_client_cert
使用多行来存储证书,而我的后端 nginx 服务器无法将其正确识别为一个 HTTP 标头。实现转发客户端证书的最佳方法是什么?
该问题在 2013 年就已在该论坛上提出,但至今尚未找到真正的解决方案:https://forum.nginx.org/read.php?2,236546,236546
谢谢!
答案1
所以我找到了一个解决方案。我删除证书中的所有换行符,并将它们作为单个 HTTP 标头从代理发送到后端,类似于此处的解释:
https://forum.nginx.org/read.php?2,236546,236546
在我的后端,我通过每 64 个字符添加一个换行符来重建证书。反向代理的更新代码如下,最多 26 行:
map $ssl_client_raw_cert $a {
"~^(-.*-\n)(?<st>[^\n]+)\n((?<b>[^\n]+)\n)?((?<c>[^\n]+)\n)?((?<d>[^\n]+)\n)?((?<e>[^\n]+)\n)?((?<f>[^\n]+)\n)?((?<g>[^\n]+)\n)?((?<h>[^\n]+)\n)?((?<i>[^\n]+)\n)?((?<j>[^\n]+)\n)?((?<k>[^\n]+)\n)?((?<l>[^\n]+)\n)?((?<m>[^\n]+)\n)?((?<n>[^\n]+)\n)?((?<o>[^\n]+)\n)?((?<p>[^\n]+)\n)?((?<q>[^\n]+)\n)?((?<r>[^\n]+)\n)?((?<s>[^\n]+)\n)?((?<t>[^\n]+)\n)?((?<v>[^\n]+)\n)?((?<u>[^\n]+)\n)?((?<w>[^\n]+)\n)?((?<x>[^\n]+)\n)?((?<y>[^\n]+)\n)?((?<z>[^\n]+)\n)?(-.*-)$" $st;
}
server {
location / {
proxy_set_header X-cert $a$b$c$d$e$f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$v$u$w$x$y$z;
proxy_pass http://localhost:8000;
}
}
(请注意,我删除了以数字开头的变量)虽然这个解决方案并不理想,但目前对我来说还算有效。另一个解决方案是仅发送证书的 DN 信息,该信息只有一行。目前这对我来说还行不通,因为我没有将每个 DN 存储在数据库中。
答案2
看起来较新版本的 nginx 已将变量中的所有内容更改\n
为。如果您不想应用该转换,则可以使用变量。\t
$ssl_client_cert
$ssl_client_raw_cert
看:http://nginx.org/en/docs/http/ngx_http_ssl_module.html#variables
答案3
我相信这是解决原始问题的方法:
proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
根据文档:
$ssl_client_escaped_cert 以 PEM 格式(urlencoded)返回已建立的 SSL 连接(1.13.5)的客户端证书;
答案4
这是对我有用的 LUA 解决方案:
set_by_lua $client_cert "return ngx.var.ssl_client_raw_cert and ngx.var.ssl_client_raw_cert:gsub('\\n',' ') or nil";
proxy_set_header X-SSL-CERT $client_cert;
另外,如果您使用 Ubuntu,nginx-extra 默认具有 LUA 插件,因此无需额外配置: https://stackoverflow.com/questions/22193852/running-lua-in-nginx-config