题 使逆转录时nginx传递上游的主机名


我用主机名运行几个docker容器:

web1.local web2.local web3.local

通过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:header中上游服务器组的名称?


71
2018-05-23 20:46




我认为你不能。为什么不设置后端服务器以响应main或example.com?并不是说后端不知道是谁 它 是。反之亦然:proxy_set_header Host $ host;将使用原始请求中的主机名替换从上游返回的任何Host变量。 - Andrew Domaszek
正确的做法是修复应用程序。 - Michael Hampton♦


答案:


实际上你可以通过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;
  }
}

88
2018-05-24 08:10



proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for;似乎更好 - sivann
@pavel:得到了它。实际上我也做了一些研究和一些测试。似乎没有直接的方法来满足您的要求。因此,即使是“混蛋”解决方案也是一种解决方案。我不想问你为什么要这样做。我很确定你有理由。 :-) - Jens Bradler
@JensBradler你似乎比我更专业,你能告诉我你对我的解决方案的看法吗?我想这样做,因为我从我的ISP上的两个帐户运行了两个我的网站副本: site1.myisp.com 和 site2.myisp.com 他们只回应他们各自的名字。我现在拥有自己的域名,我想使用我的ISP网站来平衡我的服务器。这不是一个好理由吗?非常感谢你 ;) - ncenerar
@ncenerar您可以这样做,但这会带来单点故障:负载均衡器。如果这是用于负载平衡(非冗余),您还可以将基于DNS的负载平衡与DNS故障转移结合使用。 - Jens Bradler
这个答案反映了 官方博客的建议。 - Bernard Rosset


我有同样的问题,我终于通过使用两级代理解决了它。以下是您可以如何处理您的情况(我认为):

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

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


21
2017-08-20 15:20



我最初使用Lua方法,但现在完全切换到HAProxy,它允许使用标准配置完成我想要的操作。 - pavel_karoukin


因此,从阅读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;
        }
}

2
2018-05-24 13:39





我们将上游addr作为单独的标头传递给你

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;
    add_header       X-Upstream      $upstream_addr;
  }
}

如果你试过怎么办?

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

2
2018-04-26 17:49





虽然目标似乎合乎逻辑, nginx不会更改Host:标头以匹配上游。相反,它会对待 upstream 像a这样的域名 CNAME 在DNS中 - 作为获取IP地址的一种方式。

在选择上游之前,请求标头(和主体)是固定的。如果发现特定上游没有响应,则上游可以在请求中间改变,但请求不会改变。


1
2018-06-23 01:06