具有 SSL 后端的 AWS ELB 在 SSL 流内添加了代理协议

具有 SSL 后端的 AWS ELB 在 SSL 流内添加了代理协议

请注意,这也已发布在http://thread.gmane.org/gmane.comp.web.haproxy/27737

我们正在尝试配置这种架构:

  • ELB 终止 SSL,使用预配置的证书。(这是必需的,因为只有受限制的人才能访问最终用户证书)
  • ELB 使用 SSL 连接到 HAproxy 后端(也是要求)
  • ELB 发送代理标头,具体说明如下http://amzn.to/1YajEG3

  • HAproxy 在 443 中监听 SSL

  • HAProxy 用于进行一些 HTTP 转换(修改标头等)。

一旦 ELB 配置为 SSL + Proxy 协议,我们就尝试通过在 HTTPS 前端的绑定中添加 accept-proxy 来配置 HAProxy:

frontend https-in
    mode http
    # Note, I truncated this line because the maillist 80 chars limitations
    bind :443 accept-proxy ssl crt \
     /var/vcap/jobs/haproxy/config/cert.pem \
     no-sslv3 ciphers ...
    ...

但它失败了:Received something which does not look like a PROXY protocol header

故障排除我发现 ELB 在 SSL 流内部发送 PROXY 标头。例如,我运行 openssl 作为服务器:

$ openssl s_server -accept 443 -cert cert.pem
...

ACCEPT
bad gethostbyaddr
-----BEGIN SSL SESSION PARAMETERS-----
MFUCAQECAgMDBAIAnwQABDBsAWD78V/tz9KhYw4R/kpL5YPBxfF1qcmzxlclNDuz
0KWw9aGojVogjtBkH/zZOLWhBgIEVyoquqIEAgIBLKQGBAQBAAAA
-----END SSL SESSION PARAMETERS-----
Shared
ciphers:...
CIPHER is DHE-RSA-AES256-GCM-SHA384
Secure Renegotiation IS supported
PROXY TCP4 80.194.77.90 192.168.6.14 39220 443
GET / HTTP/1.1
User-Agent: curl/7.35.0
Host: something.com
Accept: */*

因此我在 haproxy 中做了一个“链式”配置,一个使用纯 TCP 进行 SSL 终止,另一个“提取”代理协议并进行 HTTP 转换:

listen https-in
    mode tcp
    bind :443 ssl crt /var/vcap/jobs/haproxy/config/cert.pem no-sslv3
ciphers ...
    server http 127.0.0.1:8081

frontend http-in-from-ssl
    mode http
    bind :8081 accept-proxy
    option httplog
    option forwardfor
    reqadd X-Forwarded-Proto:\ https
    default_backend http-routers

并且有效!

我的问题是:

  • 这是正常且预料之中的吗?我找不到任何相关信息。
  • 是否可以更改 ELB 行为以将代理协议标头放在 SSL 流之外?我没有找到有关此内容的任何信息。
  • 如果没有的话,是否可以更改 HAProxy 的行为以使用一个前端,但从 SSL 流内部读取代理协议标头?
  • 如果没有的话,有没有更好的方法来“链接”配置,就像我上面做的那样。

谢谢你!

答案1

这是针对您的问题 1 的信息,请查看下面的 URL。

http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/using-elb-listenerconfig-quickref.html

桌子最后一排的战利品TCP/SSL 负载均衡器(第二张表)。这只是你的情况。它明确地说

不支持代理协议标头。

因此对于你的问题2,答案是否定的。

并且很抱歉我无法为您的问题3和4提供更多帮助。(实际上,根据我的经验,对于问题4,我认为您的方法已经足够好了。也许我的经验还不够;P)

答案2

我也遇到了这个问题。但是,我在内部负载均衡器上使用 nginx 而不是 HA-proxy。

解决方案类似,但我认为值得发布:

#nginx.conf

user  nginx;
worker_processes  1;

error_log  /dev/stderr debug;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}

stream {
    upstream stream_backend {
        server 127.0.0.1:500;
    }

    server{
        listen 443 ssl;
        proxy_pass stream_backend;

        ssl_certificate /certs/local/public.crt;
        ssl_certificate_key /certs/local/private.key;
        ssl_protocols TLSv1.2;
        ssl_ciphers HIGH:!aNULL:!MD5;
    }
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '[$host] $remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /dev/stdout  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  60;

    #gzip  on;
    server {
        listen 8000;
        location /elb-status {
        keepalive_timeout 0;    # Disable HTTP keepalive

            access_log off;
            return 200;
        }
    }

    map $http_upgrade $connection_upgrade {
        default upgrade;
        '' close;
    }

    server {
        listen 80 proxy_protocol;
        server_name test-nginx.corp.com;

        location / {
            keepalive_timeout 0;    # Disable HTTP keepalive
            return 301 https://$host$request_uri;
        }
    }

    upstream nginx-test-stack {
        server 10.42.111.6:80;
    }

    server {
        listen 127.0.0.1:500 proxy_protocol;
        server_name test-nginx.corp.com;
        real_ip_header proxy_protocol;

        location / {
            proxy_pass http://nginx-test-stack;
        }

    }
}

这样我就可以为任何 TCP 连接启用 E2E 加密。如果需要,我可以代理 websockets 或 https,或者直接使用 TCP

相关内容