Forum: NGINX Problem with proxy_set_header $ssl_client_cert

Posted by jstrybis (Guest)
on 2013-02-24 15:41
(Received via mailing list)
Hello,

I am having an issue while verifying client SSL certificates. Everything
works fine until I attempt to forward the cert onto the upstream.

Once I add a line similar to the following in my location block, all
requests become an error 400 Bad Request.
> proxy_set_header X-SSL-Client_Cert $ssl_client_cert;
(I've also tried $ssl_client_raw_cert, but the docs say 
"[$ssl_client_cert]
is intended for the use in the proxy_set_header directive;"

Here is my entire location block:
  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-SSL-Client-Cert $ssl_client_cert;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn;
  }

Originally I was using add_header X-SSL-Client-Cert in the server block,
which did not throw a 400, but my upstream app was not seeing the 
header.

Once I remove the proxy_set_header line, the server works as expected:
requests with a valid cert get passed through while unauthenticated 
requests
get a 403. (This is done by checking $ssl_client_verify).

Am I missing something obvious? Any help would be very appreciated. 
Thank
you.

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,236546,236546#msg-236546
Posted by Maxim Dounin (Guest)
on 2013-02-24 19:01
(Received via mailing list)
Hello!

On Sun, Feb 24, 2013 at 09:41:38AM -0500, jstrybis wrote:

>
> Originally I was using add_header X-SSL-Client-Cert in the server block,
> which did not throw a 400, but my upstream app was not seeing the header.
>
> Once I remove the proxy_set_header line, the server works as expected:
> requests with a valid cert get passed through while unauthenticated requests
> get a 403. (This is done by checking $ssl_client_verify).
>
> Am I missing something obvious? Any help would be very appreciated. Thank
> you.

The $ssl_client_cert variable abuses header continuation, and this
doesn't work with many http servers (including nginx itself).
There should be more portable way to pass client certificate to an
upstream server.

--
Maxim Dounin
http://nginx.com/support.html
Posted by Lynoure (Guest)
on 2013-02-25 15:38
(Received via mailing list)
> The $ssl_client_cert variable abuses header continuation, and this
> doesn't work with many http servers (including nginx itself).

Noticed that with spray-can.

> There should be more portable way to pass client certificate to an
> upstream server.

Is there already, or is there one in plans? Any known workarounds? 
Encoding
and decoding the $ssl_client_cert somehow? (I'm really new to nginx.)

--
Lynoure Braakman

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,236546,236581#msg-236581
Posted by Sergey Budnevitch (Guest)
on 2013-02-25 21:58
(Received via mailing list)
On 25  Feb2013, at 18:37 , Lynoure <nginx-forum@nginx.us> wrote:

>> The $ssl_client_cert variable abuses header continuation, and this
>> doesn't work with many http servers (including nginx itself).
>
> Noticed that with spray-can.
>
>> There should be more portable way to pass client certificate to an
>> upstream server.
>
> Is there already, or is there one in plans? Any known workarounds? Encoding
> and decoding the $ssl_client_cert somehow? (I'm really new to nginx.)

You could hack ngx_ssl_get_certificate() function to get certificate in 
one line,
or there is an ugly, but possible way to remove limited number of 
newline
characters from variable with map directive:

map $ssl_client_raw_cert $a {
"~^(-.*-\n)(?<1st>[^\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)?(-.*-)$" 
$1st;
}

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

Example works for up to 26 line certificate, you could extend it to 
reasonable number of lines.
Posted by jstrybis (Guest)
on 2013-02-25 23:00
(Received via mailing list)
Thanks for your reply. My application does not require the entire
certificate, so I am just forwarding $ssl_client_s_dn in a custom header
without any problems.

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,236546,236599#msg-236599
Posted by Lynoure (Guest)
on 2013-02-26 12:28
(Received via mailing list)
Thank you Sergey, this workaround suffices for us for now.

Posted at Nginx Forum: 
http://forum.nginx.org/read.php?2,236546,236618#msg-236618
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.