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

不幸的是,我不是一个系统pipe理员,而是遇到了一个让我头撞墙的问题。

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

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

SSL握手到上游,客户端:ipaddress1,服务器:example.com,请求:“GET / proxiedpath / proxiedpage”时,SSL_do_handshake()失败(SSL:错误:14094438:SSL例程:SSL3_READ_BYTES:tlsv1警报内部错误:SSL警报编号80) HTTP / 1.1“,上游:”https:// ipaddress2:443 / proxiedpath / proxiedpage“,主机:”e​​xample.com“

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

我在这一点上探索的另外几点:

  • 当我切换到新的免费Heroku SSL,我改变了我们的app.example.com DNSlogging指向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中configuration如下:

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

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

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

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

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

这导致我到了proxy_ssl_server_name指令:

http://nginx.org/r/proxy_ssl_server_name

通过在您的配置中设置为“on”,您可以使用SNI代理上游主机。

感谢所有提出建议的人!

作为其他人的一个注意事项Heroku强加的相关条件是HOST字段必须匹配自定义域名。

所以除了proxy_ssl_server_name之外,你还可以设置一行:

 proxy_set_header Host mycustomdomain.com; 

当然,这只适用于传入服务器的主机字段与服务器所在的域不同的情况。

你得到的具体错误是:

SSL证书错误

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