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