【问题标题】:Nginx proxy_pass with $remote_addrNginx proxy_pass 与 $remote_addr
【发布时间】:2013-07-15 04:09:05
【问题描述】:

我试图在我的 proxy_pass 中包含 $remote_addr 或 $http_remote_addr 但没有成功。

重写规则有效

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

没有 $remote_addr 的 proxy_pass 有效,但 freegeoip 不读取 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

【问题讨论】:

  • 这个错误是重启nginx的时候出现的,还是http请求命中location块的时候出现的?
  • 当我请求网址时

标签: nginx proxypass


【解决方案1】:

如果 proxy_pass 语句中没有变量,那么它将在启动或重新加载期间使用“gethostbyaddr”系统调用并永久缓存该值。

如果有任何变量,例如使用以下任一:

set $originaddr http://origin.example.com;
proxy_pass $originaddr;
# or even
proxy_pass http://origin.example.com$request_uri;

然后 nginx 将使用内置的解析器,并且“解析器”指令必须存在。 “解析器”可能是用词不当;将其视为“内置解析器将使用什么 DNS 服务器”。从 nginx 1.1.9 开始,内置解析器将支持 DNS TTL 值。在此之前,它使用 5 分钟的固定值。

【讨论】:

  • 这是一个非常更有用且内容丰富的答案。谢谢。
  • 关键是proxy_pass值中存在的任何变量,感谢正确的答案和解释。
  • 一些参考?
  • 有趣的事实:docker 容器的默认名称服务器位于127.0.0.11,请参阅cat /etc/resolv.conf
  • 如果它正在运行 kubernetes,我应该将解析器设置为什么?没有 resolv.conf 文件。
【解决方案2】:

nginx 在运行时而不是在配置时解析域名似乎有点奇怪(因为域名是硬编码的)。向 location 块添加 resolver 声明通常可以修复运行时遇到的 dns 问题。所以你的位置块可能看起来像:

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

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

【讨论】:

  • 这应该是公认的答案,因为它涵盖了其他情况,如 args、remote_addr 等
  • 这对最新的稳定版 nginx/1.10.3 仍然有效。因此,resolver 指令需要与 proxy_pass 动态指令结合使用,例如proxy_pass http://$host;。虽然这个工作没有解析器:server { listen 80; server_name myurl.com; location / {return 303 https://$host$request_uri;} }
  • 就我而言(Google Cloud),我使用内部名称服务器 169.254.169.254 通过主机名解析租户中的其他实例。
【解决方案3】:

如果有人仍然遇到问题,对我来说,它帮助将 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/;
  }
}

【讨论】:

  • 如果您的代理 URI 没有更改,这是更简单的答案,并且无需添加额外的解析器步骤!
【解决方案4】:

您还可以在 proxy_pass uri 中提及您的 nginx server port。这为我解决了这个问题。

【讨论】:

    【解决方案5】:

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

    您的代码: proxy_pass http://freegeoip.net/json/;

    更新代码 proxy_pass http://10.45.45.10:2290/json/;

    【讨论】:

      【解决方案6】:

      尝试使用 dig / nslookup 确保这仍然是 nginx 问题。 在我的情况下,问题是我的 nginx 和根 dns 之间的一个 dns 服务器不遵守小至 1 秒的 TTL 值。

      Nginx does not re-resolve DNS names in Docker

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-03-29
        • 2019-01-22
        • 2012-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多