title: Nginx with multiple client certificates on one host
body: <p>I want to use nginx 1.15.12 as a proxy for tls termination and authentication. If a valid client certificate is shown, the nginx server will forward to the respective backend system (localhost:8080 in this case) The current configuration does that for every request.</p>
  
  <p>Unfortunately it is not possible to configure one certificate per location{} block. Multiple server blocks could be created, which each check for another certificate, but I have also the requirement to just receive requests via one port.</p>
  
  <pre class="lang-sh prettyprint-override"><code>nginx.conf: |
      events {
        worker_connections  1024;  ## Default: 1024
      }
  
      http{
        # password file to be moved to seperate folder?
        ssl_password_file /etc/nginx/certs/global.pass;
        server {
          listen 8443;
          ssl on;
          server_name *.blabla.domain.com;
          error_log stderr debug;
  
          # server certificate
          ssl_certificate     /etc/nginx/certs/server.crt;
          ssl_certificate_key /etc/nginx/certs/server.key;
  
          # CA certificate for mutual TLS
          ssl_client_certificate /etc/nginx/certs/ca.crt;
          proxy_ssl_trusted_certificate /etc/nginx/certs/ca.crt;
  
          # need to validate client certificate(if this flag optional it won't
          # validate client certificates)
          ssl_verify_client on;
  
          location / {
            # remote ip and forwarding ip
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  
            # certificate verification information
            # if the client certificate verified against CA, the header VERIFIED
            # will have the value of 'SUCCESS' and 'NONE' otherwise
            proxy_set_header VERIFIED $ssl_client_verify;
  
            # client certificate information(DN)
            proxy_set_header DN $ssl_client_s_dn;
            proxy_pass http://localhost:8080/;
          }
        }
      }
  </code></pre>
  
  <p>Ideally I would like to achieve something like that:
  (requests to any path "/" except "/blabla" should be checked with cert1, if "/blabla" is matching, another key should be used to check the client certificate.</p>
  
  <pre class="lang-sh prettyprint-override"><code>nginx.conf: |
      events {
        worker_connections  1024;  ## Default: 1024
      }
  
      http{
        # password file to be moved to seperate folder?
        ssl_password_file /etc/nginx/certs/global.pass;
        server {
          listen 8443;
          ssl on;
          server_name *.blabla.domain.com;
          error_log stderr debug;
  
          # server certificate
          ssl_certificate     /etc/nginx/certs/server.crt;
          ssl_certificate_key /etc/nginx/certs/server.key;
  
          # CA certificate for mutual TLS
          ssl_client_certificate /etc/nginx/certs/ca.crt;
          proxy_ssl_trusted_certificate /etc/nginx/certs/ca.crt;
  
          # need to validate client certificate(if this flag optional it won't
          # validate client certificates)
          ssl_verify_client on;
  
          location / {
            # remote ip and forwarding ip
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  
            # certificate verification information
            # if the client certificate verified against CA, the header VERIFIED
            # will have the value of 'SUCCESS' and 'NONE' otherwise
            proxy_set_header VERIFIED $ssl_client_verify;
  
            # client certificate information(DN)
            proxy_set_header DN $ssl_client_s_dn;
            proxy_pass http://localhost:8080/;
          }
  
          location /blabla {
            # Basically do the same like above, but use another ca.crt for checking the client cert.
          }
        }
      }
  </code></pre>
  
  <p>Im on a kubernetes cluster but using ingress auth mechanisms is no option here for reasons. Ideal result would be a way to configure different path, with different certificates for the same server block in nginx.</p>
  
  <p>Thank you!</p>
  
  <p>Edit:
  The following nginx.conf can be used to check different certificates within nginx. Therefore 2 independent <code>server{}</code> blocks are needed with a different <code>server_name</code>. The URI /blabla can now only be accessed via blabla-api.blabla.domain.com. </p>
  
  <pre><code>events {
        worker_connections  1024;  ## Default: 1024
      }
      http{
        server_names_hash_bucket_size 128;
        server {
          listen 8443;
          ssl on;
          server_name *.blabla.domain.com;
          error_log stderr debug;
          # password file (passphrase) for secret keys
          ssl_password_file /etc/nginx/certs/global.pass;
          # server certificate
          ssl_certificate     /etc/nginx/certs/server.crt;
          ssl_certificate_key /etc/nginx/certs/server.key;
          # CA certificate for mutual TLS
          ssl_client_certificate /etc/nginx/certs/ca.crt;
          proxy_ssl_trusted_certificate /etc/nginx/certs/ca.crt;
          # need to validate client certificate(if this flag optional it won't
          # validate client certificates)
          ssl_verify_client on;
  
          location / {
            # remote ip and forwarding ip
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # certificate verification information
            # if the client certificate verified against CA, the header VERIFIED
            # will have the value of 'SUCCESS' and 'NONE' otherwise
            proxy_set_header VERIFIED $ssl_client_verify;
            # client certificate information(DN)
            proxy_set_header DN $ssl_client_s_dn;
            proxy_pass http://localhost:8080/;
          }
          location /blabla {
            return 403 "authorized user is not allowed to access /blabla";
          }
  
        }
        server {
          listen 8443;
          ssl on;
          server_name blabla-api.blabla.domain.com;
          error_log stderr debug;
          # password file (passphrase) for secret keys
          ssl_password_file /etc/nginx/certs/global-support.pass;
          # server certificate
          ssl_certificate     /etc/nginx/certs/server-support.crt;
          ssl_certificate_key /etc/nginx/certs/server-support.key;
          # CA certificate for mutual TLS
          ssl_client_certificate /etc/nginx/certs/ca-support.crt;
          proxy_ssl_trusted_certificate /etc/nginx/certs/ca-support.crt;
          # need to validate client certificate(if this flag optional it won't
          # validate client certificates)
          ssl_verify_client on;
  
          location /blabla {
            # remote ip and forwarding ip
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # certificate verification information
            # if the client certificate verified against CA, the header VERIFIED
            # will have the value of 'SUCCESS' and 'NONE' otherwise
            proxy_set_header VERIFIED $ssl_client_verify;
            # client certificate information(DN)
            proxy_set_header DN $ssl_client_s_dn;
            proxy_pass http://localhost:8080/blabla;
          }
        }
      }
  </code></pre>