关于亚马逊网络服务:AWS ELB -> 带有自签名证书的基于 HTTPS 的后端服务器

AWS ELB -> Backend Server over HTTPS with Self-Signed Certificate

我已经使用 HTTPS 来终止我的 AWS ELB 上的外部 HTTPS 连接。我现在正在尝试使用带有自签名证书的 HTTPS 来保护我的 ELB 和 EC2 上的后端 NGINX 服务器之间的连接。我遵循了文档,但通过 HTTPS 访问服务器会导致 408 HTTP 超时。我似乎无法获得任何调试信息来确定哪里出错了。

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

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

这是我的 ELB 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
$ 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 政策:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
$ 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 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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;
    }
  }
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ 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


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

1
2
  # 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 将其报告为无效公钥。