Nginx reverse proxy pass through client certificate

http-headershttpsnginxreverse-proxyssl

I'm trying to set up a load balancer via an Nginx reverse proxy. My application uses client certificates to authenticate clients. I would like my reverse proxy to forward the client certificate to my back-end servers. I have added this line to my reverse proxy's configuration to store the client certificate information in a custom HTTP header:

proxy_set_header X-SSL-CERT $ssl_client_cert

However, $ssl_client_cert uses multiple lines to store the certificate, and my back-end nginx server does not recognize this properly as one HTTP header. What is the best way to achieve forward my client certificates?

This question has been asked in 2013 on this forum, but so far no real solution: https://forum.nginx.org/read.php?2,236546,236546

Thanks!

Best Answer

So I have found a solution. I remove all newlines in the certificate and send them as a single HTTP Header from the proxy to the back-end, similar as explained here:

https://forum.nginx.org/read.php?2,236546,236546

In my back-end I reconstruct the certificate by adding a newline every 64 characters. The updated code for the reverse proxy is the following and works up to 26 lines:

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;
   }
}

(note that I have removed the variable starting with a number) While this solution is not ideal, it works for me at this moment. Another solution would be to only send the certificate's DN info, which is a single line. This does not work for me at this time, as I have not stored every DN in my database.