问题描述
获取客户端真实网络地址,有时候让人头疼。尤其是多种中间件联合使用时,层层相套,而且大家又使用不同的规范,将客户端的真实 IP 地址保存在不同的请求头中。
在这篇笔记中,我们将尝试寻找一种通用的方案,该方案可以让我们方便地定位到客户端的真实 IP 地址。
该笔记将记录:在 Nginx 中,调试并获取客户端真实网络地址(IP Address)的相关方法。
解决方案
第一步、查看客户端的网络地址
客户端的真实网络地址是通过 HTTP 请求头传递的(除了 Proxy 协议,因为我们用的不多,所以这里未讨论该协议)
所以,我们打印所有的与网络地址有关的变量及请求头(至少是我们知道的),这样我们就能知道各种地址信息:
log_format client_ip_address '[$time_local] Host="$http_host", '
'Forwarded="$http_forwarded", '
'X-Forwarded-For="$http_x_forwarded_for", '
'X-Forwarded-Host="$http_x_forwarded_host", '
'X-Forwarded-Proto="$http_x_forwarded_proto", '
'X-REAL-IP="$http_x_real_ip", '
'realip_remote_addr="$realip_remote_addr", '
'remote_addr="$remote_addr", '
'server_addr="$server_addr", '
'upstream_addr="$upstream_addr", ' ;
server {
...
access_log /var/log/nginx/client-ip-address.log client_ip_address;
...
}
在这些地址中,如果没有出现客户端的真实网络地址,那多半表示上游下来的请求存在问题。需要修改上游服务,以传递客户端真实网络地址。
第二步、设置请求头,以传递真实地址
如果客户端的真实网络地址出现在这些字段中,那么我们需要将该地址传递给下游服务器。
这样要根据下游服务器的要求进行设置,比如下游服务器从 X-Forwarded-For 中读取客户端真实网络地址,那我们这里的 Nginx 就要设置:
# proxy_set_header X-Forwarded-For <the variable containing real_ip_address>
# 比如,如下配置行
proxy_set_header X-Forwarded-For $remote_addr;
注意事项,在 RFC 中,没有 X-Real-IP 字段的描述,该字段可能是 Web Server 自定义的字段。如果下游服务器从 X-Real-IP 中读取客户端真实网络地址,那我们就要设置 X-Real-IP 字段。
相关链接
与代理有关的 HTTP 字段
参考文献
Alphabetical index of variables