Skip to content

Nginx如果透过代理获取真实IP地址

# 环境
client_ip:10.10.10.1

proxy_server_1:10.10.10.16
proxy_server_2:10.10.10.17

web_server:10.10.10.18

使用X-Forwarded-For+realip模块

使用realip模块可以解决该问题。

查看nginx的编译参数:nginx -V(默认是安装了realip模块的)

  • set_real_ip_from:表示从何处获取真实IP,只认可自己信赖的IP,可以是网段,也可以设置多个。
  • real_ip_header:表示从哪个header属性中获取真实IP。
  • real_ip_recursive:递归检索真实IP,如果从X-Forwarded-For中获取,则需要递归检索;如果中X-Real-IP中获取,无需递归。

Nginx配置

# proxy_server_1的nginx配置
location / {
    proxy_pass http://10.10.10.17;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# proxy_server_2的nginx配置
location / {
    proxy_pass http://10.10.10.18;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# web_server的nginx配置,在server中新增
set_real_ip_from 10.10.10.16;
set_real_ip_from 10.10.10.17;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

使用浏览器正常访问,默认不改变日志格式的情况下,我们来看3台server的日志情况。

# proxy_server_1的日志
10.10.10.1 - - [25/Jun/2019:20:49:03 -0400] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "-"

# proxy_server_2的日志
10.10.10.16 - - [25/Jun/2019:20:49:03 -0400] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "10.10.10.1"

# web_server的日志
10.10.10.1 - - [25/Jun/2019:20:49:03 -0400] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "10.10.10.1, 10.10.10.16"

这个时候的remote_addr就是用户的真实IP,添加XFF头访问,我们来看3台server的日志情况。

# proxy_server_1的日志
10.10.10.1 - - [25/Jun/2019:20:59:10 -0400] "GET / HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1"

# proxy_server_2的日志
10.10.10.16 - - [25/Jun/2019:20:59:10 -0400] "GET / HTTP/1.0" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1, 10.10.10.1"

# web_server的日志
10.10.10.1 - - [25/Jun/2019:20:59:10 -0400] "GET / HTTP/1.0" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1, 10.10.10.1, 10.10.10.16"

可以看到用户自己配置的XFF头并没有被识别为真实的IP。

使用X-Forwarded-For+安全设置

在第一个代理处处理用户传递的XFF,达到忽略用户传递的XFF值的效果。

配置nginx

# proxy_server_1的nginx配置
location / {
    proxy_pass http://10.10.10.17;
    proxy_set_header X-Forwarded-For $remote_addr;
}

# proxy_server_2的nginx配置
location / {
    proxy_pass http://10.10.10.18;
}

# web_server不做任何配置

使用浏览器正常访问,默认不改变日志格式的情况下,我们来看3台server的日志情况

# proxy_server_1的日志
10.10.10.1 - - [25/Jun/2019:21:17:42 -0400] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "-"

# proxy_server_2的日志
10.10.10.16 - - [25/Jun/2019:21:17:42 -0400] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "10.10.10.1"

# web_server的日志
10.10.10.17 - - [25/Jun/2019:21:17:42 -0400] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "10.10.10.1"

这个时候http_x_forwarded_for就是代表用户真实IP,添加XFF头访问,我们来看3台server的日志情况。

# proxy_server_1的日志
10.10.10.1 - - [25/Jun/2019:21:19:51 -0400] "GET / HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1"

# proxy_server_2的日志
10.10.10.16 - - [25/Jun/2019:21:19:51 -0400] "GET / HTTP/1.0" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "10.10.10.1"

# web_server的日志
10.10.10.17 - - [25/Jun/2019:21:19:51 -0400] "GET / HTTP/1.0" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "10.10.10.1"

使用X-Real-IP

配置Nginx

# proxy_server_1的nginx配置
location / {
    proxy_pass http://10.10.10.17;
    proxy_set_header X-Real-IP $remote_addr;
}

# proxy_server_2的nginx配置
location / {
    proxy_pass http://10.10.10.18;
}

# 两台proxy_server与web_server的日志第一个字段由$http_x_real_ip 替换 $remote_addr 
log_format  main  '$http_x_real_ip - $remote_user

使用浏览器正常访问,我们来看3台server的日志情况

# proxy_server_1的日志
- - - [25/Jun/2019:21:33:47 -0400] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "-"

# proxy_server_2的日志
10.10.10.1 - - [25/Jun/2019:21:41:59 -0400] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "-"

# web_server的日志
10.10.10.1 - - [25/Jun/2019:21:33:47 -0400] "GET / HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "-"

这个时候web_server的http_x_real_ip就是代表用户真实IP,添加XFF头访问,我们来看3台server的日志情况。

# proxy_server_1的日志
- - - [25/Jun/2019:21:34:24 -0400] "GET / HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1"

# proxy_server_2的日志
10.10.10.1 - - [25/Jun/2019:21:42:26 -0400] "GET / HTTP/1.0" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1"

# web_server的日志
10.10.10.1 - - [25/Jun/2019:21:34:24 -0400] "GET / HTTP/1.0" 200 15 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" "192.168.1.1"

与未配置XFF一致。

参考资料

Nginx多级反向代理下的IP透传

Nginx 之 X-Forwarded-For 中首个IP一定真实吗?