Heroku的Nginx反向代理失败了SSL握手

Bar*_*art 17 ssl configuration reverse-proxy nginx heroku

不幸的是,我不是一个系统管理员并且遇到了一个让我头撞墙的问题.

简短的故事是我在EC2(Ubuntu 14.04.4 LTS)上运行Nginx,以(a)托管我公司的营销网站(https://example.com,顺便提一下是Wordpress)和(b)作为反向运行对于某些路径,在Heroku(https:// app.example.com)上运行的Rails应用程序的代理.我们对example.com和app.example.com使用相同的SSL证书.所有这些都运行了8-10个月,但我最近从Heroku的付费SSL插件切换到新的免费SSL产品,现在我们的反向代理被打破了.

在检查Nginx错误日志时,我看到以下内容:

SSL_do_handshake()失败(SSL:错误:14094438:SSL例程:SSL3_READ_BYTES:tlsv1警报内部错误:SSL警报号80)当SSL握手到上游时,客户端:ipaddress1,server:example.com,请求:"GET/proxiedpath/proxiedpage HTTP/1.1",上游:"https:// ipaddress2:443/proxiedpath/proxiedpage",主持人:"example.com"

我试图寻找一些额外的指导 - 我已经升级了Nginx(1.10.1)和OpenSSL(1.0.2h)而没有运气.我怀疑这个问题可能是由于Heroku在新的免费SSL功能(https://devcenter.heroku.com/articles/ssl-beta)中使用了SNI ,但是无法确定为什么这可能是个问题.

关于这一点我的探索还有几点:

  • 当我切换到新的免费Heroku SSL时,我按照文档的指示将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地址与上面日志错误消息("ipaddress2")中引用的IP地址不同.事实上,"ipaddress2"在整个日志中并不一致 - 它似乎经常变化.我再也不知道我不知道什么......在Heroku的一边负载平衡?

最后,我的Nginx反向代理在nginx.conf中配置如下:

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/;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

非常感谢任何帮助 - 非常感谢!

Bar*_*art 30

我今天能够解决这个问题,并希望发布解决方案以防其他人遇到同样的问题.

事实证明,这个问题毕竟与SNI有关.我在nginx.org上找到了这张票:

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

这让我进入了proxy_ssl_server_name指令:

http://nginx.org/r/proxy_ssl_server_name

通过在配置中设置为"on",您将能够使用SNI代理上游主机.

感谢所有评论建议的人!

  • 在这种情况下,nginx 日志显示的具体 OpenSSL 错误是“SSL: error:14094410:SSLroutines:ssl3_read_bytes:sslv3alert handshake failure:SSL Alert number 40”,其中“alert number 40”是关键部分,翻译为“this”可能是 SNI 主机,并且握手没有尝试 SNI`,请参阅 [this](https://github.com/openssl/openssl/issues/7147) 了解更多信息。`proxy_ssl_server_name on` 应该可以帮助您继续。 (3认同)
  • 上帝保佑你亲爱的...你救了我! (3认同)
  • 感谢您的回答。我以为找到这个答案很容易,但Google却不这么认为 (2认同)
  • 你救了我的命。添加了“proxy_ssl_server_name on”,它对我有用!谢谢 (2认同)

Nad*_*iam 10

请尝试添加proxy_ssl_server_name on

location ^~ /proxiedpath/ {
    proxy_ssl_server_name on;
 }
Run Code Online (Sandbox Code Playgroud)


Jas*_*son 9

作为其他说明,Heroku施加的一个相关条件是HOST字段必须与自定义域名匹配。

因此,除了proxy_ssl_server_name您之外,您可能还需要设置以下行:

proxy_set_header Host mycustomdomain.com;
Run Code Online (Sandbox Code Playgroud)

当然,这仅在输入服务器的主机字段与服务器所在的域不同时才适用。

您得到的特定错误是:

SSL证书错误

SSL连接,其证书和/或包含的HTTP请求之间的信息冲突。