Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to proxy http_x_ssl_client_s_dn header?

Tags:

nginx

proxy

I want to proxy the request header 'HTTP_X_SSL_CLIENT_S_DN' through nginx.

Here is our server network structure.

[front server:443] <---> [nginx proxy:8004] <---> [application server:8008]
(client cert auth)

When I tried it two servers([front server] and [application server]), it worked properly. The header 'HTTP_X_SSL_CLIENT_S_DN' was passed to application server.

Then adding the server [nginx proxy], the header 'HTTP_X_SSL_CLIENT_S_DN' was not passed to application server.

My nginx config is below.

server {
    listen   8004;
    index index.html;

    location / {
        proxy_pass_header Server;
        proxy_pass_header X-Scheme;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://app-server/;

# TODO: to proxy 'HTTP_X_SSL_CLIENT_S_DN'
# failed settings
#        proxy_pass_request_headers on; # not worked (default: on)
#        proxy_pass_header X-SSL-Client-S-DN; # none
#        proxy_pass_header X_SSL_CLIENT_S_DN; # none
#        proxy_pass_header HTTP_X_SSL_CLIENT_S_DN; # none
#        proxy_pass_header HTTP-X-SSL-CLIENT-S-DN; # none
#        proxy_set_header X-SSL-Client-S-DN $ssl_client_s_dn; # none
#        proxy_set_header X_SSL_Client_S_DN $x_ssl_client_s_dn; # none
#        proxy_set_header X-SSL-Client-S-DN $http_ssl_client_s_dn; # none
#        proxy_set_header X-SSL-Client-S-DN $http_x_ssl_client_s_dn; # none
    }
}

upstream app-server {
    server 127.0.0.1:8008;
}

Any help appliciated.

like image 479
superdaigo Avatar asked Aug 07 '12 07:08

superdaigo


2 Answers

First and foremost, make sure you have nginx.conf configured to verify client certificates! I had exact same problem you described.

server {
  # ...
  ssl_client_certificate /srv/ssl/self.crt;
  ssl_verify_depth     1;
  ssl_verify_client    on;
  # ...
  location @app { # I'm using nginx+unicorn, don't blindly copy this!  :)
    # ...
    proxy_set_header X-SSL-Client-Serial $ssl_client_serial;
    proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
    proxy_set_header X-SSL-Client-S-DN   $ssl_client_s_dn;
    # ...
}

To test this out, you will need a separate client key and a certificate that has been signed using the root authority certificate. The client credentials start with "me" and my root authority credentials start with "self" in the following commands.

  1. Generate a private key for the client.

    openssl genrsa -out me.key 1024
    
  2. Make a request for the self-CA to sign.

    openssl req -new -key me.key -out me.csr
    
  3. Sign the request using the self-CA to create a certificate.

    openssl x509 -req -days 365 -in me.csr -CA self.crt -CAkey self.key -set_serial 01 -out me.crt
    
  4. Try out your new key.

    curl -v -s -k --key me.key --cert me.crt https://fort-awesome-o
    
  5. Extra credit: generate a certificate that can be imported into your browser.

    openssl pkcs12 -export -in me.crt -inkey me.key -certfile self.crt -out me.p12
    

I have a simple Sinatra web app that dumps the HTTP environment and I see the following:

"HTTP_X_SSL_CLIENT_SERIAL"=>"01", "HTTP_X_SSL_CLIENT_VERIFY"=>"SUCCESS", "HTTP_X_SSL_CLIENT_S_DN"=>"/C=US/ST=Maryland/L=Annapolis/O=Fort Kickass/CN=Jonathan Morton/[email protected]"

like image 186
Jon M. Avatar answered Nov 12 '22 06:11

Jon M.


I had the same problem with nginx as proxy deleted the X_REQUESTED_WITH field from the request. Per default nginx marks headers with underscores as invalid and ignores invalid headers.

You can use nginx directives to either allow underscores in headers with underscores_in_headers on; or don't ignore invalid header with ignore_invalid_headers off;.

In my concrete case I used python requests as client, django as server and nginx as proxy and solved my problem in which I renamed X_REQUESTED_WITH to X-REQUESTED-WITH. (Django automatically adds 'HTTP_' to the start of x-header names before making the header available in request.META.)

import requests
headers = {'X-REQUESTED-WITH':'XMLHttpRequest'}
r = requests.post(url, data=payload, headers=headers)
like image 32
elim Avatar answered Nov 12 '22 05:11

elim