带有$remote_addr的Nginx代理传递

ef1yzkbh  于 2022-11-02  发布在  Nginx
关注(0)|答案(7)|浏览(173)

我尝试在proxy_pass上包含$remote_addr或$http_remote_addr,但没有成功。
重写规则起作用

location ^~ /freegeoip/ {  
  rewrite ^ http://freegeoip.net/json/$remote_addr last;
}

没有$remote_addr的proxy_pass可以工作,但freegoip无法读取x-Real-IP

location ^~ /freegeoip/ {
  proxy_pass http://freegeoip.net/json/;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header Host $host;
}

然后,我将ip添加到请求的末尾,如下所示:

location ^~ /freegeoip/ {
  proxy_pass http://freegeoip.net/json/$remote_addr;
}

但是nginx报告了此错误:未定义解析程序来解析freegeoip.net

a11xaf1n

a11xaf1n1#

如果proxy_pass语句中没有变量,则它将在启动或重新加载期间使用“gethostbyaddr”系统调用,并将永久缓存该值.
如果有任何变数,例如使用下列其中一项:

set $originaddr http://origin.example.com;
proxy_pass $originaddr;

# or even

proxy_pass http://origin.example.com$request_uri;

然后nginx将使用一个内置的解析器,并且“resolver”指令 * 必须 * 存在。“resolver”可能是一个用词不当;可以把它想象成“内置解析器将使用哪个DNS服务器”。2从nginx 1.1.9开始,内置解析器将接受DNS TTL值。3在此之前,它使用的是一个固定值5分钟。

y0u0uwnf

y0u0uwnf2#

nginx在运行时而不是在配置时解析域名似乎有点奇怪(因为域名是硬编码的)。在location块中添加一个resolver声明通常可以修复运行时遇到的dns问题。因此,您的location块可能如下所示:

location ^~ /freegeoip/ {
  #use google as dns
  resolver 8.8.8.8;
  proxy_pass http://freegeoip.net/json/$remote_addr;
}

这个解决方案是基于我不久前读过的一篇文章-Proxy pass and resolver。值得一读。

aiazj4mn

aiazj4mn3#

如果有人仍然遇到问题,* 对我来说,将proxy_pass主机移到一个单独的上游有助于 *,所以我想出了这样的方法

upstream backend-server {
  server backend.service.consul;
}

server {
  listen       80;
  server_name  frontend.test.me;

  location ~/api(.*)$  {
    proxy_pass http://backend-server$1;
  }
  location / {
    # this works mystically! backend doesn't...
    proxy_pass http://frontend.service.consul/;
  }
}
gwo2fgha

gwo2fgha4#

另一种方法是,您可以在proxy_pass中提供您的主机ip地址和port编号,而不是主机URL,如下所示:

您的验证码:proxy_pass http://freegeoip.net/json/;
更新的代码proxy_pass http://10.45.45.10:2290/json/;

vbkedwbf

vbkedwbf5#

你也可以在proxy_pass uri中提到你的nginx server port。这为我解决了这个问题。

56lgkhnf

56lgkhnf6#

尝试使用dig / nslookup来确定这仍然是nginx的问题。在我的例子中,问题是我的nginx和根dns之间的一个dns服务器不尊重小到1秒的TTL值。
Nginx不会在Docker中重新解析DNS名称

fhity93d

fhity93d7#

所以你想这样做:

location ^~ /freegeoip/ {
  proxy_pass http://freegeoip.net/json/$remote_addr;
}

但是作为Chris Cogdon的pointed out,它失败了,因为在运行时,nginx没有解析域名,因此proxy_pass需要一个解析器(另请参见proxy_pass docs)。
看起来可行的方法(虽然可能是黑客!)是在启动时触发nginx解析域名并缓存。
因此,请更改config以包含一个不带任何变量的位置(对于同一主机)(以及您的位置 * 带 * 变量):

location = /freegeoip/this-location-is-just-a-hack {
  # A dummy location. Use any path, but keep the hostname.
  proxy_pass http://freegeoip.net/this-path-need-not-exist;
}

location ^~ /freegeoip/ {
  proxy_pass http://freegeoip.net/json/$remote_addr;
}

现在将在启动时解析主机(并且其缓存值将在运行时用于第二个位置)。您可以通过更改主机名来验证此启动解析行为(freegeoip.net)到不存在的东西,当您运行nginx -tnginx -s reload时,将出现紧急错误([emerg] host not found in upstream)。当然,您可以通过忽略任何resolver,命中您的location块,并在日志中观察到没有错误,来验证缓存的值是否在运行时使用。

相关问题