nginx - Nginx 与 Apache 代理通行证
问题描述
我正在尝试将我的 apache 配置转换为 nginx。对于 apache,我有以下内容:
<VirtualHost *:443>
ServerName loc.goout.net
<Location />
ProxyPass http://localhost:8080/ retry=0
ProxyPreserveHost On
</Location>
<Location /i/>
ProxyPass https://dev.goout.net/i/ retry=0
ProxyPreserveHost Off
</Location>
...
像这样,如果我获取:
https://loc.goout.net/i/user/606456_001_min.jpg
它正确地从以下位置获取内容:
https://dev.goout.net/i/user/606456_001_min.jpg
所以对于 nginx,我正在尝试这个:
server {
listen 443 ssl;
server_name loc.goout.net;
proxy_buffering off;
proxy_ssl_session_reuse off;
proxy_redirect off;
proxy_set_header Host dev.goout.net;
location /i/ {
proxy_pass https://dev.goout.net:443;
}
但是当我获取内容时,我总是会得到502
.
在 nginx 日志中,我看到以下内容:
[error] 7#7: *5 no live upstreams while connecting to upstream, client: 127.0.0.1, server: loc.goout.net, request: "GET /i/user/606456_001_min.jpg HTTP/1.1", upstream: "https://dev.goout.net/i/user/606456_001_min.jpg", host: "loc.goout.net"
请注意链接:https ://dev.goout.net/i/user/606456_001_min.jpg - 它工作正常。在我看来,它仍然没有与 SSL 连接。我还尝试将上游部分定义为:
upstream backend {
server dev.goout.net:443;
}
但它没有任何效果。
请注意,服务器位于 CloudFlare 网关后面,我希望它不会阻止正确的连接,但我想这在 apache 中也不起作用。
解决方案
tl;dr:根据http://nginx.org/r/proxy_ssl_server_name,SNI在 Nginx 中默认关闭,但 Cloudflare 需要。
在 Cloudflare 之上拥有自制代理通常不是最好的主意——它应该是相反的。
但是,您忽略的是发出请求所产生的实际错误消息curl -v localhost:3227/i/user/606456_001_min.jpg
- 当然它与 TLS 相关:
2018/07/07 23:18:39 [error] 33345#33345: *3 SSL_do_handshake() failed (SSL: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure) while SSL handshaking to upstream, client: 127.0.0.1, server: loc.goout.net, request: "GET /i/user/606456_001_min.jpg HTTP/1.1", upstream: "https://[2400:cb00:2048:1::6818:7303]:443/i/user/606456_001_min.jpg", host: "localhost:3227"
这是因为 nginx 并不是真的打算用来通过 窃取别人的网站proxy_pass
,因此,Cloudflare 确实需要的一些功能在 nginx 中默认关闭以供一般使用;具体来说,这是SNI, TLS 的服务器名称指示扩展,这在这里有所不同。
根据http://nginx.org/r/proxy_ssl_server_name,在您的确切配置中添加额外proxy_ssl_server_name on;
内容确实可以解决问题(我自己对此进行了测试 - 它有效) - 请注意,这需要 nginx 1.7.0 或更高版本。
+ proxy_ssl_server_name on; # SNI is off by default
此外,请注意,您还必须确保在运行时更新域名解析,因为默认情况下,只有在加载或重新加载配置时才会解析;您可以使用在您的http://nginx.org/r/proxy_pass中使用变量的技巧来使其适当地更新主机的分辨率,但这也需要您使用http://nginx.org/ r/resolver指令指定用于 DNS 解析的服务器(在运行时,加载配置后),因此,您的 MVP 将是:
location /i/ {
resolver 1dot1dot1dot1.cloudflare-dns.com.;
proxy_ssl_server_name on; # SNI is off by default
proxy_pass https://dev.goout.net:443$request_uri;
}
推荐阅读
- python - Python - 需要使用 python 包而不使用 pip/命令提示符安装
- spring-cloud-stream - Spring Cloud Stream函数问题——StreamBridge多次调用消费者
- autodesk-forge - 模型衍生 API 404 回复
- reactjs - 引导卡在反应中没有水平排列
- android - 使用坐标和地址打开谷歌地图导航方向
- recaptcha - 在 recaptcha 中验证服务器端用户响应的目的是什么?
- c# - c#:命名空间的问题
- wordpress - 在 WPAllimport 中使用 PHP 从一个字段中提取维度
- iteration - reduce是如何定义的(使用foreach)
- c# - 如果对象没有终结器,GC.SuppressFinalize() 是否有效?