haproxy 透传 用户真实IP

文章目录

      • haproxy 透传 用户真实IP
        • 原理
        • IP透传
          • 四层IP透传
          • 七层IP透传
          • 总结:

haproxy 透传 用户真实IP

原理

haproxy 透传 用户真实IP_第1张图片

L4:四层负载 (IP+PORT转发)

​ 在四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据。

L7:七层代理 (协议+内容交换)

​ 七层负载均衡服务器起了一个反向代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问webserver要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握手与此台webserver建立TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用。

tcpdump tcp -i eth0   -nn port ! 22 -w dump-tcp.pcap -v

可以抓包验证

IP透传

四层IP透传

web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。

例子

环境

机器 service ip
阿里云 ECS nginx 172.16.122.180 (vpc,ww.wandu.ink)
虚拟机 1 haproxy 192.168.1.101
运行虚拟机的笔记本 谷歌浏览器 192.168.0.1
虚拟机5 curl 浏览器 192.168.1.105

haproxy的配置

listen web_prot_http_nodes
        bind 192.168.1.101:80
        mode tcp
        server web1  ww.wandu.ink:80 send-proxy check inter 3000 fall 3 rise 5

nginx 的配置

定义log_format 主要是记录 tcp_xf、 xff 对应的 proxy_protocol_addr、 $http_x_forwarded_for的值

log_format access_json '{"@timestamp":"$time_iso8601",'

                                '"host":"$server_addr",'

                                '"clientip":"$remote_addr",'

                                '"size":$body_bytes_sent'

                                '"responsetime":$request_time,'

                                '"upstreamtime":"$upstream_response_time",'

                                '"upstreamhost":"$upstream_addr",'

                                '"http_host":"$host",'

                                '"uri":"$uri",'

                                '"domain":"$host",'

                                '"xff":"$http_x_forwarded_for",'

                                '"referer":"$http_referer",'

                                '"tcp_xff":"$proxy_protocol_addr",'

                                '"http_user_agent":"$http_user_agent",'

                                '"status":"$status"}';

nginx server 的配置

server {
    listen 80 proxy_protocol ;
    server_name ww.wandu.ink;
    access_log /data/nginx/logs/ww-wandu-com_access.log  access_json;
    root /data/nginx;
    index  index.html;
}

验证

当 访问 192.168.1.101 时, 可以跳到 ww.wandu.ink 的首页

root@aly-01:~# tail -f /data/nginx/logs/www-wandu-com_access.log 

下面是ww.wandu.ink 的日志记录 ,其中tcp_xff 取到的192.168.0.1 为vmware nat 网卡地址

浏览器访问

mark

curl命令访问 ,可以取到用户真实私网IP

mark

七层IP透传

HAProxy配置

defaults
option forwardfor

或者:
option forwardfor header X-Forwarded-xxx #自定义传递IP参数,后端web服务器写X-Forwarded-xxx,如果写option forwardfor则后端服务器web格式为X-Forwarded-For

例子

server ip
haproxy 192.168.1.101
apache2 192.168.1.103
apache2 192.168.1.104
listen web_host
 bind 192.168.1.101:80
 mode http
option forwardfor
 log global
 balance random
 server web1 192.168.1.103:80 weight 1 check inter 3000 fall 2 rise 5
 server web2 192.168.1.104:80 weight 1 check inter 3000 fall 2 rise 5

apache 的格式设置

LogFormat "%{X-Forwarded-For}i  %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined

验证: 当用浏览器(不是虚拟机内的浏览器,而是笔记本的浏览器)时取到的是NAT网卡地址,用curl 时得到的是客户端IP地址

haproxy 透传 用户真实IP_第2张图片

当nginx 做为后端服务器时

listen web_host
 bind 192.168.1.101:80
 mode http
 option forwardfor
 log global
 server web1 ww.wandu.ink:80 weight 1 check inter 3000 fall 2 rise 5

nginx server listen 80 就行;

haproxy 透传 用户真实IP_第3张图片

总结:

由于我们的haproxy(192.168.1.101)无论7或4层,都是配置了和用户(192.168.1.105)网段在一起了,所以可以得到真实的内网地址,但是生产中haproxy 是配置和后端服务器在一个网络环境内,所以只能拿到remote_adrr ,就是公网出口的地址了(打马赛克的部分),好比在上面的实验中,若是用虚拟外的浏览器访问,只能拿到 NAT网卡地址一样,是不可能透传用户的私网地址的。

你可能感兴趣的:(负载均衡)