web-dev-qa-db-ja.com

SSLバックエンドを備えたAWSELBは、SSLストリーム内にプロキシプロトコルを追加します

これは http://thread.gmane.org/gmane.comp.web.haproxy/27737 にも投稿されていることに注意してください。

このアーキテクチャを構成しようとしています。

  • 事前設定された証明書を使用してSSLを終了するELB。 (これは要件です。制限されたユーザーのみがエンドユーザー証明書にアクセスできるためです)
  • ELBはSSLを使用してHAproxyバックエンドに接続します(これも要件です)
  • ELBは、 http://amzn.to/1YajEG で説明されているようにプロキシヘッダーを送信します

  • 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で「チェーン」構成を行いました。1つは純粋なTCP)でSSLターミネーションを実行し、もう1つはプロキシプロトコルを「抽出」して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ストリームの外部に配置することは可能ですか?それについての情報は見つかりませんでした。
  • そうでない場合。 1つのフロントエンドを使用するようにHAProxyの動作を変更して、SSLストリーム内からproxy-protocolヘッダーを読み取ることは可能ですか?
  • そうでない場合は、上記のように構成を「チェーン」するためのより良い方法がありますか。

ありがとうございました!

2
Keymon

これがあなたの質問1の情報です。以下のURLをチェックしてください。

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

テーブルの最後の行で略奪しますTCP/SSLロードバランサー(2番目のテーブル)。それはあなたの場合です。そしてそれは明確に言う

プロキシプロトコルヘッダーをサポートしていません。

したがって、質問2の場合、答えはノーです。

そして、申し訳ありませんが、質問3と4についてこれ以上のサポートを提供することはできません(実際、私の経験に基づいて、質問4については、あなたのやり方で十分だと思います。たぶん私の経験では不十分です; P)

1
Bruce

私もこの問題に遭遇しました。ただし、内部ロードバランサーではHAプロキシではなくnginxを使用しています。

解決策は似ていますが、投稿する価値があると思います。

#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暗号化を有効にできます。必要に応じて、WebSocketまたはhttps、あるいは単純なTCPをプロキシできます。

0
user272845