一台主机上具有多个客户端证书的Nginx

时间:2019-05-28 14:04:54

标签: authentication nginx kubernetes

我想使用nginx 1.15.12作为tls终止和身份验证的代理。如果显示了有效的客户端证书,则nginx服务器将转发到相应的后端系统(在本例中为localhost:8080)。当前配置针对每个请求执行此操作。

很遗憾,无法在每个位置{}块配置一个证书。可以创建多个服务器块,每个服务器块都检查另一个证书,但是我还要求只通过一个端口接收请求。

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

理想情况下,我想实现以下目标: (对除“ / blabla”以外的任何路径“ /”的请求应使用cert1进行检查,如果“ / blabla”匹配,则应使用另一个密钥来检查客户端证书。

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

我在kubernetes集群上,但是出于某些原因,这里没有选择使用入口身份验证机制。理想的结果是一种为nginx中的同一服务器块配置不同路径,使用不同证书的方法。

谢谢!

1 个答案:

答案 0 :(得分:1)

我想SNI是答案。 通过ssl握手中的协议,具有一个IP和一个端口的服务器可以提供多个certificates

但是据我了解,两台服务器的server_name属性必须不同。不知道顶级域名和二级域名是否需要这样做,或者仅通过路径即可做到这一点。

SNI扩展了TLS的握手协议。这样,在ssl握手期间建立连接之前,服务器可以知道要使用什么certificate

较新的nginx版本默认应启用SNI。可以检查:nginx -V

看看this如何构造nginx.conf