Nginx 与 Apache 代理通行证

标签 nginx

我正在尝试将我的 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:SNI 在 nginx 中默认关闭,根据 http://nginx.org/r/proxy_ssl_server_name ,但 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, Server Name Indication extension to 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

此外,请注意,您还必须确保在运行时更新域名解析,因为默认情况下,只有在加载或重新加载配置时才会解析;您可以在 trick 中使用变量的 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;
}

关于Nginx 与 Apache 代理通行证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51023227/

相关文章:

nginx - 在 nginx 日志中看到保持事件状态的错误

ssl - Google Cloud Load Balancer - 502 - 非托管实例组未通过健康检查

node.js - Nginx 反向代理 服务 Node.js 应用程序静态文件

php - nginx 从 https 排除路径

caching - 如何有选择地清除 Sinatra + Nginx + Phusion Passenger 的缓存?

docker - 获取 : unknown directive "js_import" when njs used with Nginx

node.js - 如何设置 Node.js 和 Express(MERN 堆栈)

python - Laravel 应用程序使用 Symfony 在 LEMP 堆栈上执行 Python 脚本 - 权限被拒绝

linux - 在我自己的域上运行 docker shiny app

amazon-web-services - 如何避免使用Nginx配置进行AWS ELB健康检查的基本身份验证