如何取得nginx做反向代理时的真实IP?

1.编译
对于client->nginxreverseproxy->apache,
要想在程序中取得真实的IP,在执行nginx的configure时,必须指定参数“--with-http_realip_module”,示例:
./configure--prefix=/data/nginx--with-http_realip_module--with-stream--with-pcre=/tmp/X/pcre-8.32--with-openssl=/tmp/X/openssl-1.0.2a
参数说明:
--prefix=指定安装目录,也就是makeinstall后程序文件等的存放目录
--with-http_realip_module使得程序可以通过环境变量HTTP_X_REAL_IP取得真实的客户端IP地址
--with-stream表示启用TCP代理
--with-pcre=指定依赖的pcre,注意为pcre源代码解压后的目录路径,而不是安装路径
--with-openssl=指定依赖的openssl,注意为openssl源代码解压后的目录路径,而不是安装路径
另外,最简单的确认方法是使用nm命令查看nginx程序文件,看看是否有包含real相关的符号,对于版本nginx-1.9.4,可以发现存在“0809c54btngx_http_realip”。
2.程序代码
测试程序代码(后续测试基于它):
//g++-g-ohello.cgihello.cpp
#include<stdio.h>
#include<stdlib.h>
intmain()
{
printf("Content-Type:text/html;charset=utf-8\r\n\r\n");
printf("<p>HTTP_X_FORWARDED_FOR:%s\n",getenv("HTTP_X_FORWARDED_FOR"));
printf("<p>HTTP_X_REAL_IP:%s\n",getenv("HTTP_X_REAL_IP"));
printf("<p>REMOTE_ADDR:%s\n",getenv("REMOTE_ADDR"));
printf("<p>");
return0;
}
测试是在nginx自带配置文件nginx.conf上进行的修改:
proxy_set_header可以添加在nginx.conf的http段,也可以是server段,还可以是location段,一级一级间是继承和覆盖关系。
3.相关配置
示例:
location/{
#roothtml;
#indexindex.htmlindex.htm;
proxy_passhttp://20.61.28.11:80;
proxy_redirectoff;
proxy_set_headerHost$host;
proxy_set_headerX-Real-IP$remote_addr;#这个是必须的
proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;
}
X-Forwarded-For和X-Real-IP的区别是,如果请求时已带了X-Forwarded-For,则nginx追加方式,这样可以通过它显示转发的轨迹。
当然请求时完全可以构造假的X-Forwarded-For,在配置文件打开了X-Real-IP及编译指定了--with-http_realip_module时,环境变量HTTP_X_REAL_IP总是为真实的客户端IP。
如果是:
client->nginxreverseproxy(A)->nginxreverseproxy(B)->apache
HTTP_X_REAL_IP又会是什么了?
4.测试1
假设如下部署:
client(10.6.81.39)->nginx(10.6.223.44:8080)->nginx(10.6.208.101:8080)->apache(10.6.208.101:80)
?A
假设nginx(10.6.223.44:8080)的配置均为(在nginx默认配置上的修改部分):
server{
listen8080;
server_name10.6.223.44;
location/{
#roothtml;
#indexindex.htmlindex.htm;
proxy_passhttp://10.6.208.101:8080;
proxy_redirectoff;
proxy_set_headerHost$host;
proxy_set_headerX-Real-IP$remote_addr;
proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;
}
假设nginx(10.6.208.101:8080)的配置均为(在nginx默认配置上的修改部分):
server{
listen8080;
server_name10.6.208.101;
location/{
#roothtml;
#indexindex.htmlindex.htm;
proxy_passhttp://10.6.208.101:80;
proxy_redirectoff;
proxy_set_headerHost$host;
proxy_set_headerX-Real-IP$remote_addr;
proxy_set_headerX-Forwarded-For$proxy_add_x_forwarded_for;
}