X-Forwarded-For
我们常常使用 Nginx 作为 Web 站点的反向代理服务器,如下图所示,我们可以通过 Nginx 的内置变量 $remote_addr
来获取客户端访问的 IP。
当我们的 Web 站点接入 CDN 或者 WAF 后,$remote_addr
却是 CDN 或者 WAF 的 IP,因为 CDN 获取 WAF 这里也充当了一个反向代理服务器。为了解决这个问题,RFC 7239(Forwarded HTTP Extension)标准中定义了 X-Forwareded-For,X-Forwareded-For 放在 HTTP Header 中,格式如下:
X-Forwarded-For: client1, proxy1, proxy2
其中的值通过一个 逗号+空格 把多个IP地址区分开, 最左边(client1)是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。一般来说,CDN 或者 WAF 的厂商均会准守这个协议,所以你接入 CDN 或者 WAF 后的 X-Forwarded-For 的值是 client1, CDN_IP/WAF_IP
,所以,我们可以通过解析 X-Forwarded-For 来获取真正的客户端访问 IP。
ngx_http_realip_module
而 ngx_http_realip
模块的作用是当你的 nginx 服务器位于一个反向代理后面时,去获取客户端真实访问的 IP。这个模块默认没有编译到 Nginx 中,需要在编译时通过 --with-http_realip_module
开启。
这个模块的相关配置如下:
set_real_ip_from 192.168.1.0/24;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
-
set_real_ip_from:
address | CIDR | unix:
, 定义信任地址(trusted address),配合后续的real_ip_recursive
使用。 -
real_ip_header:
field | X-Real-IP | X-Forwarded-For | proxy_protocol
, 默认值是X-Real-IP
, 定义真实的 IP 在请求头中的字段名。 -
real_ip_recursive:
on | off
, 默认值是off
,如果是off
,则使用real_ip_header
请求头中匹配信任地址(trusted address)中最后一个作为客户端请求的真实 IP;如果是on
, 则取匹配的前一个值作为客户端真实 IP。
ngx_http_realip
模块将用获取到的客户端真实 IP 作为 Nginx 内置变量 $remote_addr
的值。这样你又能通过 $remote_addr
得到你客户端访问的真实 IP 了。
另外,除了使用 ngx_http_realip
模块,你也可以通过 Lua 脚本去解析 X-Forwarded-For
,从而获取真实的 IP。
网友评论