web-dev-qa-db-ja.com

HerokuへのNginxリバースプロキシがSSLハンドシェイクに失敗する

残念ながら、システム管理者はそれほど多くないので、頭を壁にぶつけてしまうという問題に遭遇しました。

短い話は、EC2(Ubuntu 14.04.4 LTS)でNginxを実行して、(a)私の会社のマーケティングサイトをホストする( https://example.com 、これはWordpressです) (b)特定のパスに対して、Heroku(https:// app.example.com)で実行されているRailsアプリのリバースプロキシとして機能します。両方の例で同じSSL証明書を使用します。 comとapp.example.com。これらはすべて8〜10か月間は問題なく機能していましたが、最近、Herokuの有料SSLアドオンから新しい無料のSSLサービスに切り替えたため、リバースプロキシが壊れています。

Nginxエラーログを確認すると、次のように表示されます。

SSL_do_handshake()が失敗しました(SSL:error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error:SSL alert number 80)while SSL handshakeing up up、client:ipaddress1、server:example.com、request: "GET/proxiedpath/proxiedpage HTTP/1.1 "、アップストリーム:" https:// ipaddress2:443/proxiedpath/proxiedpage "、ホスト:" example.com "

いくつかの追加のガイダンスを探してみました-Nginx(1.10.1)とOpenSSL(1.0.2h)を運よくアップグレードしました。この問題は、Herokuが新しい無料のSSL機能でSNIを使用しているためであると思われます( https://devcenter.heroku.com/articles/ssl-beta )。しかし、これが問題になる理由を判断してください。

このポイントへの私の探求に関するいくつかの追加ポイント:

  • 新しい無料のHeroku SSLに切り替えたとき、docsの指示に従って、app.example.com DNSレコードをapp.example.com.herokudns.comを指すように変更しました。アプリケーションは通常app.example.comからアクセスでき、app.example.comとapp.example.com.herokudns.comでnslookupを実行すると、同じIPアドレスが返されます。しかしながら...

  • Nslookupまたはapp.example.com.herokudns.comから返されたIPアドレスからアプリケーションにアクセスできません。これは正常で予想されることではないかと思いますが、これがなぜなのかを正確に言うのは十分ではありません。そして...

  • Nslookupから返されるIPアドレスは、上記のログのエラーメッセージで参照されているIPアドレス(「ipaddress2」)とは異なります。実際、「ipaddress2」はログ全体で一貫していません-定期的に変更されるようです。繰り返しますが、私が知らないことを知るのに十分ではありません... Heroku側の負荷分散ですか?

最後に、nginx.confでNginxリバースプロキシを次のように構成します。

http {

    client_max_body_size 500M;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    server_names_hash_bucket_size 64;

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

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_disable "msie6";

    server {

        listen 443 default_server;
        server_name example.com;

        root /usr/share/nginx/html;
        index index.php index.html index.htm;

        ssl on;
        ssl_certificate mycompanycert.crt;
        ssl_certificate_key mycompanykey.key;

        ssl_session_timeout 5m;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
        ssl_prefer_server_ciphers on;

        error_page 404 /404.html;
        error_page 500 502 503 504 /50x.html;

        location / {
            try_files $uri $uri/ /index.php?q=$uri&$args;
        }

        location ^~ /proxiedpath/ {
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-Proto https;
            proxy_pass https://app.example.com/proxiedpath/;
        }

    }

}

どんな助けも大歓迎です-どうもありがとう!

17
Bart

私は今日これを解決することができ、他の人が同じ問題に遭遇した場合に備えて解決策を投稿したかった。

結局のところ、問題はSNIに関連していたことがわかります。私はnginx.orgでこのチケットを見つけました:

https://trac.nginx.org/nginx/ticket/229

Proxy_ssl_server_nameディレクティブに私を導いた:

http://nginx.org/r/proxy_ssl_server_name

構成で「オン」に設定することにより、SNIを使用してアップストリームホストにプロキシできます。

提案をコメントしてくれたすべての人に感謝します!

28
Bart

他の人への注意として、Herokuが課す関連条件は、ホストフィールドがカスタムドメイン名と一致する必要があるということです。

したがって、proxy_ssl_server_nameに加えて、次のような行を設定することもできます。

proxy_set_header Host mycustomdomain.com;

もちろん、これはサーバーに着信するホストフィールドがサーバーが存在するドメインと異なる場合にのみ適用されます。

特定のエラーは次のとおりです。

SSL証明書エラー

SSL接続、その証明書、および/または含まれているHTTP要求の間に矛盾する情報があります。

7
Jason Axelson