让 nginx 在反向代理时传递上游的主机名

让 nginx 在反向代理时传递上游的主机名

我运行了几个带有主机名的docker容器:

web1.本地 web2.本地 web3.本地

nginx 根据主机名完成对这些的路由。我在这个设置前面有一个代理(在连接到互联网的不同机器上),我将上游定义为:

    upstream main {
      server web1.local:80;
      server web2.local:80;
      server web3.local:80;
    }

以及实际的虚拟主机描述:

    server {
      listen 80;
      server_name example.com;
      location / {
        proxy_pass http://main;
      }
    }

现在,由于容器接收主机名“main”而不是“web1.local”,因此它们无法正确响应请求。

问题:在代理请求时,如何告诉 nginx 在 Host: 标头中传递上游服务器的名称而不是上游服务器组的名称?

答案1

实际上您可以通过 proxy_set_header 来实现这一点。

更多详细信息请见此处:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header或者在这里查看示例用例:https://stackoverflow.com/questions/12847771/configure-nginx-with-proxy-pass

我已将动态方法纳入您上面发布的配置中:

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            $host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

以下是静态主机名的示例:

server {
  listen 80;
  server_name example.com;
  location / {
    proxy_pass       http://main;
    proxy_set_header Host            www.example.com;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

答案2

我遇到了同样的问题,最后通过使用两级代理解决了这个问题。以下是您可以针对您的情况采取的措施(我认为):

server {
  listen      8001 default_server;
  server_name web1.example.com;
  location / {
    proxy_pass       http://web1.local:80;
    proxy_set_header Host web1.local:80;
  }
}

server {
  listen      8002 default_server;
  server_name web2.example.com;
  location / {
    proxy_pass       http://web2.local:80;
    proxy_set_header Host web2.local:80;
  }
}

server {
  listen      8003 default_server;
  server_name web3.example.com;
  location / {
    proxy_pass       http://web3.local:80;
    proxy_set_header Host web3.local:80;
  }
}

upstream main {
  server 127.0.0.1:8001;
  server 127.0.0.1:8002;
  server 127.0.0.1:8003;
}

server {
  listen      80;
  server_name example.com;
  location / {
    proxy_pass http://main;
  }
}

如您所见,诀窍是创建一个响应特定端口的本地服务器,该服务器将通过重写每个服务器的正确主机来代理服务器。然后,您可以在上游使用此本地服务器,并最终在实际代理中使用该上游。

答案3

虽然这个目标看起来合乎逻辑,nginx 不会更改 Host: 标头来匹配上游。相反,它将upstream域名视为CNAMEDNS 中的 - 作为获取 IP 地址的一种方式。

在选择上游之前,请求标头(和主体)是固定的。如果发现某个上游无响应,上游可能会在请求中途更改,但请求不会更改。

答案4

因此,通过阅读 nginx 的所有文档(我无法真正解析上游模块的代码 =(),我想出了这个混蛋的解决方案。不幸的是,这个解决方案不会跟踪失败的主机,而只是随机选择一个并将请求重定向到它。所以我必须设置某种监控以确保所有后端都在运行。

server {
        listen 80;
        server_name example.com;
        resolver 127.0.0.1;

        location / {
                set $upstream "";
                rewrite_by_lua '
                        local upstreams = {
                                "http://web1.dokku.localdomain",
                                "http://web2.dokku.localdomain",
                                "http://web3.dokku.localdomain",
                                "http://web4.dokku.localdomain"
                        }
                        ngx.var.upstream = upstreams[ math.random( #upstreams ) ] 
                ';
                proxy_pass $upstream;
        }
}

相关内容