我试图将
$remote_addr
或 $http_remote_addr
包含在我的 proxy_pass
上,但没有成功。重写规则有效:
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
报告此错误:
no resolver defined to resolve freegeoip.net
如果
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 分钟的固定值。
nginx 在运行时而不是在配置时解析域名失败(因为域名是硬编码的),这似乎有点奇怪。向位置块添加
resolver
声明通常可以修复运行时遇到的 dns 问题。所以你的位置块可能看起来像:
location ^~ /freegeoip/ {
#use google as dns
resolver 8.8.8.8;
proxy_pass http://freegeoip.net/json/$remote_addr;
}
这个解决方案基于我不久前读过的一篇文章 - 代理传递和解析器。值得一读。
如果有人仍然遇到麻烦,对我来说,将 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/;
}
}
ip
地址和
port
号码,而不是
URL
中的主机
proxy_pass
,如下所示:
您的代码:
proxy_pass http://freegeoip.net/json/;
更新代码
proxy_pass http://10.45.45.10:2290/json/;
location ^~ /freegeoip/ {
proxy_pass http://freegeoip.net/json/$remote_addr;
}
但正如 Chris Cogdon 指出,它会失败,因为在运行时,nginx 没有解析域名,因此 proxy_pass
需要解析器(另请参阅proxy_pass 文档)。 似乎有效的方法(尽管可能是黑客!)是触发 nginx 在启动时解析域名并缓存它。
因此,更改配置以包含不带任何变量的位置(针对同一主机)(以及您的位置
和变量):
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 -t
或
nginx -s reload
时,您将遇到紧急错误 (
[emerg] host not found in upstream
)。当然,您可以通过省略任何
resolver
、点击
location
块并观察日志中没有错误来验证缓存的值是否在运行时使用。
server port
中提及您的 nginx
proxy_pass uri
。这为我解决了这个问题。
proxy_pass http://backend-server;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Host $host;