飘在云端

啊!那蓝真天,白真云!

· 前端 · · 777次浏览

后端获取 nginx 反向代理后的客户端真实IP

测试环境:nginx version: nginx/1.21.0
场景:现在有 2个 网站 A(1.0z.gs) 和 B(2.0z.gs),A 网站对外提供 WEB 服务,A 网站反向代理到 B 网站获取内容,对用户透明无感知,用户访问 A 网站实际上是看到 B 网站的内容。
现在网站 A 的 nginx 日志能记录到访问的客户端真实 IP,但是 B 网站只能记录到 使用反向代理的 A 网站的服务器 IP,如何让 B 网站也能获取到 A 网站记录的客户端真实 IP?
在 A 网站的 nginx 配置文件 server 段,增加如下内容:

#获取真实ip
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
# NginxHttpRealIpModule
set_real_ip_from 上级反向代理服务器IP;   
real_ip_header X-Real-IP;
real_ip_recursive on;

然后修改 Nginx 的配置文件,在 http 段添加 如下内容:

#格式化时间 格式 为数字 年-月-日 时:分:秒,仅记录真实用户 IP
log_format realip 
'$remote_addr [$fmt_localtime] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"';
# 格式化时间为
map $host $fmt_localtime {
    default '';
}

log_by_lua_block {
   ngx.var.fmt_localtime = ngx.localtime();
}

修改 B 网站的 nginx 配置段落中关于 日志记录的部分,使用之前配置好的 格式化时间 样式:

access_log  /logs/nginx/2.0z.gs.log realip;

修改实际提供内容的B网站:

# 获取真实 IP
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# NginxHttpRealIpModule
set_real_ip_from 反向代理服务器自身IP;
real_ip_header X-Real-IP;

重启nginx,注意是 重启 nginx,而不是热重载配置,即执行 systemctl restart nginx,而不是 nginx -s reload
访问 1.0z.gs(A网站),此时 2.0z.gs(B网站) 日志能记录到真实 IP 了,并且自动过滤掉上级反向代理IP,仅保留真实IP,输出如下:

1.2.3.4 [2021-11-21 01:16:22] "GET /abc HTTP/1.1" 301 162 "-" "testUA"
1.2.3.4 [2021-11-21 01:16:22] "GET /abc/ HTTP/1.1" 200 5313 "-" "testUA"
1.2.3.4 [2021-11-21 01:16:26] "GET /abc/?test=realip HTTP/2.0" 200 2872 "-" "testUA"
1.2.3.4 [2021-11-21 01:17:24] "GET /abc/?type=realip HTTP/1.1" 403 146 "-" "-"

参考:

nginx 真实IP模块 http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
nginx 多层反向代理套娃 http://blog.chinaunix.net/uid-26479545-id-4814716.html
nginx 格式化时间为年月日 时分秒:https://developer.aliyun.com/article/69512
nginx 格式化日志:https://www.jb51.net/article/137191.htm
评论 (0条)