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后端 端口放行