Nginx proxy_pass 与 $remote_addr

Posted

技术标签:

【中文标题】Nginx proxy_pass 与 $remote_addr【英文标题】:Nginx proxy_pass with $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块的时候出现的? 当我请求网址时 【参考方案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。值得一读。

【讨论】:

不要使用可公开访问的 DNS 服务器,例如 8.8.8.8。 To prevent DNS spoofing, it is recommended configuring DNS servers in a properly secured trusted local network. 这应该是公认的答案,因为它涵盖了其他情况,如 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

【讨论】:

以上是关于Nginx proxy_pass 与 $remote_addr的主要内容,如果未能解决你的问题,请参考以下文章

Nginx 每个位置/将重写的 uri 传递给 proxy_pass

[转帖]Nginx rewrite 规则 与 proxy_pass 实现

windows服务器nginx配置 使用proxy_pass windows server2008 配置vue与python后端 端口放行

nginx 反向代理 proxy_pass 及对比nginx与haproxy反向代理服务器功能性能的优劣

nginx 之 proxy_pass各种用法

Nginx配置proxy_pass末尾有参数与无参数的区别