AWS ELB -> 带有自签名证书的 HTTPS 后端服务器

Posted

技术标签:

【中文标题】AWS ELB -> 带有自签名证书的 HTTPS 后端服务器【英文标题】:AWS ELB -> Backend Server over HTTPS with Self-Signed Certificate 【发布时间】:2016-07-10 23:37:22 【问题描述】:

我已经有 HTTPS 来终止我的 AWS ELB 上的外部 HTTPS 连接。我现在正在尝试使用带有自签名证书的 HTTPS 来保护我的 ELB 和我在 EC2 上的后端 nginx 服务器之间的连接。我关注了the documentation,但是通过 HTTPS 访问服务器会导致 408 HTTP 超时。我似乎无法获得任何调试信息来确定失败的地方。

我已确认安全组允许 ELB 和 EC2 上的 NGINX 之间的连接。 我已经确认 VPC 允许在 ELB 和 EC2 节点之间路由流量(HTTP 也可以正常工作)。 我已确认 EC2 节点上的 HTTPS 侦听器正在运行(我可以直接点击它而无需前往 ELB。 我创建了一个 PublicKeyPolicyType 类型的 ELB 策略,并关联了我的公钥。 我创建了一个类型为 BackendServerAuthenticationPolicyType 的 ELB 策略,并将其与 PublicKeyPolicyType 相关联。 我已将 BackendServerAuthenticationPolicyType 与 ELB 相关联。 我已确保 SSLNegotiationPolicyType 支持我在 NGINX 配置中指定的算法和密码。 我在 NGINX 访问日志中看到 HTTP 请求,但没有看到 HTTPS 请求。

我有什么方法可以获得任何额外的诊断信息来测试这个吗?

这是我的 ELB 配置:

$ aws elb describe-load-balancers --load-balancer-name <MY-ELB-NAME>


    "LoadBalancerDescriptions": [
        
            "Subnets": [
                "<REDACTED>",
                "<REDACTED>",
                "<REDACTED>"
            ],
            "CanonicalHostedZoneNameID": "<REDACTED>",
            "VPCId": "<REDACTED>",
            "ListenerDescriptions": [
                
                    "Listener": 
                        "InstancePort": 80,
                        "LoadBalancerPort": 80,
                        "Protocol": "HTTP",
                        "InstanceProtocol": "HTTP"
                    ,
                    "PolicyNames": []
                ,
                
                    "Listener": 
                        "InstancePort": 443,
                        "SSLCertificateId": "<REDACTED>",
                        "LoadBalancerPort": 443,
                        "Protocol": "HTTPS",
                        "InstanceProtocol": "HTTPS"
                    ,
                    "PolicyNames": [
                        "ELBSecurityPolicy-2015-05"
                    ]
                
            ],
            "HealthCheck": 
                "HealthyThreshold": 2,
                "Interval": 30,
                "Target": "HTTP:80/health",
                "Timeout": 10,
                "UnhealthyThreshold": 2
            ,
            "BackendServerDescriptions": [
                
                    "InstancePort": 443,
                    "PolicyNames": [
                        "MyBackendServerAuthenticationPolicy"
                    ]
                
            ],
            "Instances": [
                
                    "InstanceId": "<REDACTED>"
                
            ],
            "DNSName": "<REDACTED>.us-west-2.elb.amazonaws.com",
            "SecurityGroups": [
                "<GROUP_ID>"
            ],
            "Policies": 
                "LBCookieStickinessPolicies": [],
                "AppCookieStickinessPolicies": [],
                "OtherPolicies": [
                    "ELBSecurityPolicy-2015-05",
                    "MyBackendServerAuthenticationPolicy",
                    "MyPublicKeyPolicy"
                ]
            ,
            "LoadBalancerName": "<MY-ELB-NAME>",
            "CreatedTime": "2016-03-23T20:58:49.490Z",
            "AvailabilityZones": [
                "us-west-2a",
                "us-west-2b",
                "us-west-2c"
            ],
            "Scheme": "internal",
            "SourceSecurityGroup": 
                "OwnerAlias": "<REDACTED>",
                "GroupName": "<GROUP_NAME>"
            
        
    ]

这是我的 ELB 政策:

$ aws elb describe-load-balancer-policies --load-balancer-name <MY-ELB-NAME>

    "PolicyDescriptions": [
        
            "PolicyAttributeDescriptions": [
                
                    "AttributeName": "Reference-Security-Policy",
                    "AttributeValue": "ELBSecurityPolicy-2015-05"
                ,
                ...
                
                    "AttributeName": "Protocol-TLSv1.2",
                    "AttributeValue": "true"
                ,
                ...
                
                    "AttributeName": "ECDHE-RSA-AES128-GCM-SHA256",
                    "AttributeValue": "true"
                ,
                ...
            ],
            "PolicyName": "ELBSecurityPolicy-2015-05",
            "PolicyTypeName": "SSLNegotiationPolicyType"
        ,
        
            "PolicyAttributeDescriptions": [
                
                    "AttributeName": "PublicKeyPolicyName",
                    "AttributeValue": "MyPublicKeyPolicy"
                
            ],
            "PolicyName": "MyBackendServerAuthenticationPolicy",
            "PolicyTypeName": "BackendServerAuthenticationPolicyType"
        ,
        
            "PolicyAttributeDescriptions": [
                
                    "AttributeName": "PublicKey",
                    "AttributeValue": "<REDACTED>"
                
            ],
            "PolicyName": "MyPublicKeyPolicy",
            "PolicyTypeName": "PublicKeyPolicyType"
        
    ]

这是我的 NGINX 配置:

worker_processes 10;
worker_rlimit_nofile 8192;
events 
  worker_connections  4096;


error_log syslog:server=unix:/dev/log error;
pid       logs/nginx.pid;

http 
  default_type  application/octet-stream;

  log_subrequest on;
  access_log syslog:server=unix:/dev/log,severity=debug extended;

  tcp_nodelay    on;
  tcp_nopush     on;

  server_tokens off;

  upstream api 
    server localhost:8080;
  

  server 
    listen 80 default_server;
    listen [::]:80 default_server;

    location / 
      # Redirect all other HTTP requests to HTTPS with a 301 Moved Permanently response.
      return 301 https://$host$request_uri;
    
  

  server 
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /path/to/ssl.crt;
    ssl_certificate_key /path/to/ssl.key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;ECDHE

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # modern configuration. tweak to your needs.
    # See: https://mozilla.github.io/server-side-tls/ssl-config-generator/
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains;";

    # Our main location to proxy everything else to the upstream
    # server, but with the added logic for enforcing HTTPS.
    location / 
      proxy_http_version 1.1;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
      proxy_next_upstream error;

      proxy_pass http://api;
    
  

我正在使用以下命令生成密钥/证书:

$ openssl genrsa \
  -out /path/to/ssl.key 2048
$ openssl req \
  -sha256 \
  -new \
  -key /path/to/ssl.key \
  -out /path/to/ssl.csr
$ openssl x509 \
  -req \
  -days 365 \
  -in /path/to/ssl.csr \
  -signkey /path/to/ssl.key \
  -out /path/to/ssl.crt
$ openssl dhparam -out /path/to/dhparam.pem 2048

【问题讨论】:

您这样做是出于合规性原因(PCI/HIPAA/等),还是仅仅因为您认为需要它? ELB 和 Web 服务器之间的网络流量将包含在您的 VPC 中,因此只有当攻击者获得对您 VPC 中服务器的访问权限时,它才会受到损害。除非您对“动态加密”有法律要求,否则通常认为 SSL 到 ELB 已经足够好。 是的,我们有对通过网络传输的流量进行加密的法律要求,这是一个很好的做法。 监听器的Instance Protocol 设置是否设置为HTTPS(在控制台中)? HTTPS 和 443 需要在该屏幕的左侧和右侧设置,右侧默认为 HTTP ...我不知道如果不是这样会导致 408。 @Michael-sqlbot 抱歉,我应该发布我的 ELB 侦听器设置。我会用该信息更新我的问题。要回答您的问题,是的,实例协议设置为 HTTPS,并且在后端实例上转发到 443。 感谢您提出的非常详尽的问题。它帮助我弄清楚了如何设置经典负载均衡器以及如何在我的目标 EC2 实例上创建自签名证书以及如何去做。给您的问题:您的 NGINX 配置文件中的 location / 部分包含所有代理规则是什么?这对负载均衡器有必要吗?我的 EC2 实例的 NGINX 配置文件中没有这样的部分。不确定我是否应该添加它。 【参考方案1】:

在 NGINX 配置中添加一些非 EC DHE 密码为我解决了这个问题。我已经在 nginx.conf 的 HTTPS 监听器中切换到以下配置:

  # intermediate configuration. tweak to your needs.
  ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';

我想放弃所有非 EC DHE 密码,只支持 ECDHE。我怀疑这可以解决问题,因为我正在生成 RSA 密钥/证书而不是 EC 密钥/证书。如果有人知道我如何正确生成 EC 密钥/证书,然后正确提取 EC 公钥以上传到 AWS,请改进我的回答。我尝试生成 EC 密钥/证书,但当我尝试创建 ELB 公钥策略时,AWS 将其报告为无效公钥。

【讨论】:

您能否更新您的帖子以包含您用于创建和上传 EC 密钥/证书的说明/命令,以及尝试上传该 EC 密钥时从 AWS 返回的确切错误/响应/证书? 这对我有用。我以前使用 nginx 的“Mozilla 现代”SSL 配置,切换到“中级”后一切正常。所有现代密码都以“ECDHE-”开头,而中间密码包括一些“DHE-”、“AES128-”、“AES256-”和“EDH-”。我还没有深入了解实际使用的是哪些 AWS ELB。 谢谢 - 遇到同样的问题,需要密码。

以上是关于AWS ELB -> 带有自签名证书的 HTTPS 后端服务器的主要内容,如果未能解决你的问题,请参考以下文章

我可以使用 AWS 自己的 ELB 证书进行 HTTPS/SSL 连接吗?

如何在aws elb上安装godaddy ssl证书?

自签名证书在 AWS Route53 域上引发 404 not found 错误

如何将自签名证书分配给 AWS 弹性 beantalk 应用程序

如何在 AWS EC2 和 ELB 上使用 Godaddy 注册的域实现 SSL 证书

带有自签名证书的 InternetOpenUrl