Amazon web services NGINX:客户端证书

Amazon web services NGINX:客户端证书,amazon-web-services,ssl,nginx,aws-api-gateway,Amazon Web Services,Ssl,Nginx,Aws Api Gateway,我的环境 我有AWS API网关和弹性Beanstalk。我想在主机端使用客户端证书验证(Elastic Beanstalk)。Elastic Beanstalk由负载均衡器(ELB)和EC2组成,其中包含NGINX和我的Ruby on Rails应用程序。我已经在API网关上生成了客户端证书。当前流量为: API网关发送请求 此请求通过弹性负载平衡器(TCP端口80)发送到端口80(TCP)上的EC2实例 在EC2实例中,我在Docker中运行NGINX。NGINX容器侦听端口443,该端口绑

我的环境

我有AWS API网关和弹性Beanstalk。我想在主机端使用客户端证书验证(Elastic Beanstalk)。Elastic Beanstalk由负载均衡器(ELB)和EC2组成,其中包含NGINX和我的Ruby on Rails应用程序。我已经在API网关上生成了客户端证书。当前流量为:

  • API网关发送请求
  • 此请求通过弹性负载平衡器(TCP端口80)发送到端口80(TCP)上的EC2实例
  • 在EC2实例中,我在Docker中运行NGINX。NGINX容器侦听端口443,该端口绑定到主机的端口80
  • API网关->(TCP 80)ELB(TCP 80)->(端口80)主机->(端口443)NGINX容器

    我的问题

    我使用以下nginx.conf,尝试进行客户端证书验证:

    user  root;
    
    error_log  /var/log/app-nginx-error.log debug;
    pid        /var/run/app-nginx.pid;
    
    events {
        worker_connections  8096;
        multi_accept        on;
        use                 epoll;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for" "$ssl_client_cert"';
    
        access_log /var/log/app-nginx-access.log  main;
    
        sendfile           on;
        tcp_nopush         on;
        tcp_nodelay        on;
        keepalive_timeout  10;
    
        upstream appserver {
          server unix:///var/run/puma.sock;
        }
    
        server {
          listen 443 default_server;
          root /var/www/public;
          client_max_body_size  16m;
    
          ssl_trusted_certificate /etc/nginx/ssl/api-gateway.pem;
          ssl_client_certificate /etc/nginx/ssl/api-gateway.pem;
          ssl_verify_client on;
    
          ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
          ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
          ssl_prefer_server_ciphers on;
    
          if ($ssl_client_verify = FAILED) {
            return 495;
          }
    
          if ($ssl_client_verify = NONE) {
            return 402;
          }
    
          if ($ssl_client_verify != SUCCESS) {
            return 403;
          }
    
          location ^~ /assets/ {
            gzip_static on;
            expires max;
            add_header Cache-Control public;
          }
    
          try_files $uri/index.html $uri @appserver;
          location @appserver {
            proxy_set_header  Host $host;
            proxy_set_header  X-Real-IP $remote_addr;
            proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header  X-Forwarded-Host $server_name;
            proxy_set_header  Client-IP $remote_addr;
            proxy_pass        http://appserver;
            proxy_set_header X-Client-Verify $ssl_client_verify;
          }
    
          access_log    /var/log/app-nginx-access.log;
          error_log     /var/log/app-nginx-error.log debug;
          error_page    500 502 503 504 /500.html;
        }
    }
    
    但是,当我使用API网关发送证书测试它时,它总是返回403-它来自以下块:

     if ($ssl_client_verify != SUCCESS) {
        return 403;
      }
    
    对我来说奇怪的是,它并没有进入任何前面的if语句,其中包含FAILED或NONE

    如果我删除:

     ssl_verify_client on;
    
    它还涉及:

     if ($ssl_client_verify != SUCCESS) {
        return 403;
      }
    
    如果我再次打开ssl\u verify\u client并删除此If语句:

     if ($ssl_client_verify != SUCCESS) {
        return 403;
      }
    
    所有内容都是向前传递的-无论我发送的请求是否带有证书,都没有关系

    我的问题

  • 我的nginx.conf可以吗?(也许我把一些东西和TCP/HTTP混在一起了?)
  • 是否有任何方法可以获得NGINX的更多细节(是否有任何证书?),ssl\u verify\u client的结果是什么,以及任何有助于检测问题的方法

  • 我在这里可能会大错特错,但看起来像是你的设置

    “API网关->(TCP 80)ELB(TCP 80)->(端口80)主机->(端口443)NGINX容器”

    也许应该

    API网关->(TCP 80)ELB(TCP443)->(端口443)NGINX容器->(端口80)主机

    也就是说,nginx应该位于应用程序的前面,而不是后面

    在配置文件中,看起来您实际上并没有将nginx的443端口代理到应用程序的80端口。你在某处丢失了一张代理通行证或类似的证件


    您还提到docker,您使用的是多容器环境还是单容器环境?如果是前者,您应该(可以?)在dockrun.aws.json文件中指定nginx应用程序端口映射。

    我已经对其进行了一些测试。我的问题是我没有设置“ssl开启”和服务器证书。没有它,我会得到空的$ssl\u client\u verify-我用条件:if($ssl\u client\u verify=”“)检查它。我在运行multicontainer,nginx也在运行container。然后它通过我的应用程序将流量传递到另一个容器。@nicq那么你让它工作了吗?如果是的话,如果你发布了你的配置/设置,以防其他人遇到类似的问题,那就太好了。我已经在本地进行了测试,但我将在EB上进行测试。然后我会发布完整的答案“应该设置什么和哪里”:api网关、elb、eb和nginx。@nicq当你说,
    我没有设置“ssl on”;和服务器证书时,
    我相信,你需要从证书颁发机构购买ssl证书,并在nginx配置中使用密钥和证书文件?如果错了,请纠正我。@NishutoshSharma,你是对的。您需要从可信提供商处购买SSL证书(这意味着某些SSL证书可能无法工作-例如,Let's Encrypt将无法工作)。您可以使用AWS证书,而不是购买新证书,但前提是您拥有在AWS上注册的域。