目录
3.1.2、$proxy_add_x_forwarded_for
一、什么是IP透传
公司生产环境中,系统的架构一般都不会直接让用户访问服务端,中间可能会经过一个甚至多个转发层(F5,citrix,HAproxy,nginx等等)
这也就会出现一个问题,经过一次或者多次转发之后,服务端如何能获取到用户的真实IP
用户的真实IP在经过层层转发之后,还能传递到服务端,这就是IP透传
二、nginx的IP透传场景
2.1、nginx作为proxy:传递真实IP
nginx作为负载均衡、反向代理,需要IP透传来将用户真实IP传递够后端服务
当用户直接访问服务端的时候,服务端看到的客户端IP是真实的用户IP,这没有任何问题,如下图:
但当用户访问服务端是通过nginx转发的,那么服务端看到的客户端IP是nginx的IP,就无法获取用户真实的IP,如下图:
这时就需要IP透传,让服务端获取到真实的用户侧的IP,如下图
2.2、nginx作为web服务端:获取真实IP
nginx作为web服务端的时候,如果前面有一个或者多个转发层,这个时候nginx的日志字段remote_addr的IP就不是用户真实IP,对于日志分析,或者安全审计等都无法接受
这个时候我们就需要通过IP透传手段,让nginx将用户真实IP在日志中打印出来
如果不做IP透传,nginx web前端服务打印的日志,远端IP都是前一层proxy的IP,毫无意义,如下图
四层转发的话,通过转发层开启proxy protocol协议,则nginx侧可以通过开启proxy protocol获取用户真实IP并在日志中打印出来
七层则可以通过传递X-Forwarded-For值,在nginx端获取并在日志打印出来
3、NG七层配置
七层转发将客户端真实IP透传给后端服务,就是将客户端真实IP赋值给X-Forwarded-For放入请求头,传递给后端
标准格式如下:
X-Forwarded-For: client1, proxy1, proxy2
从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个。
将用户真实IP通过请求头X-Forwarded-For给到后端
3.1、作为proxy:透传IP给到后端
3.1.1、$http_x_forwarded_for
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
$http_x_forwarded_for 就是请求头中的X-Forwarded-For
3.1.2、$proxy_add_x_forwarded_for
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
$proxy_add_x_forwarded_for 包含了请求头中的X-Forwarded-For以及$remote_addr(逗号分开)
如果访问NG请求中没有设置X-Forwarded-For,那么$proxy_add_x_forwarded_for最后被设置的值就等于$remote_addr
3.1.3、$proxy_protocol_addr
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
这个需要nginx前一层(用户端或者前一个proxy)开启proxy protocol协议
3.2、作为web服务器,打印真实IP到日志
log_format json '{"remote_addr":"$remote_addr",'
'"http_x_forwarded_for":"$http_x_forwarded_for"}';
remote_addr是前一个节点(proxy)IP
http_x_forwarded_for:是用户真实 IP
4、NG四层配置
注意nginx编译时需要加上stream模块及stream_realip_module模块;一个用来四层负载,一个用来获取客户端真实IP
4.1、作为proxy:透传IP给到后端
stream {
server {
listen 12345;
proxy_pass 1.1.1.1:8080;
proxy_protocol on;
}
}
4.2、作为web服务器,打印真实IP到日志
需要前侧的proxy开启PP协议(proxy protocol)
stream {
log_format acc_log '$proxy_protocol_addr';
server {
listen 12345 proxy_protocol;
proxy_pass 1.1.1.1:8080;
}
}