HAProxy 高级功能
介绍 HAProxy 高级配置及实用案例
自定义日志格式
log global 开启日志功能,默认只会在记录下面格式的日志
[root@haproxy ~]#tail /var/log/haproxy.log
Apr 9 19:38:46 localhost haproxy[60049]: Connect from 172.16.0.200:54628 to
172.16.0.100:80 (web_prot_http_nodes/HTTP)
option httplog 可以采用 http 格式记录下来,并且可以使用相关指令将特定信息记录在haproxy的日志 中
但一般不建议开启,这会加重 HAProxy 负载
配置选项
log global #开启记录日志,默认不开启
option httplog #开启记录httplog日志格式选项
capture cookie <name> len <length> #捕获请求和响应报文中的 cookie及值的长度,将之记录到日志
capture request header <name> len <length> #捕获请求报文中指定的首部内容和长度并记录日志
capture response header <name> len <length> #捕获响应报文中指定的内容和长度首部并记录日志
#示例:
log global
option httplog
capture request header Host len 256
capture request header User-Agent len 512
capture request header Referer len 15
capture request header X-Forwarded-For len 15
同时开启日志功能log global和option httplog,记录日志格式如下
[root@haproxy ~]#vim /etc/haproxy/haproxy.cfg
listen www.web01.com
balance roundrobin
bind 172.16.1.211:80
mode http
log global
option httplog
capture request header Host len 256
capture request header User-Agent len 512
capture request header Referer len 15
capture request header X-Forwarded-For len 15
cookie WEBSRV insert nocache indirect
server 10.0.0.52 10.0.0.52:80 check inter 3000 fall 3 rise 5 cookie web01
server 10.0.0.53 10.0.0.53:80 check inter 3000 fall 3 rise 5 cookie web02
[root@haproxy ~]#tail -f /var/log/haproxy.log
Nov 12 17:31:05 haproxy haproxy[13087]: 172.16.1.51:55028 [12/Nov/2024:17:31:05.806] www.web01.com www.web01.com/10.0.0.52 0/0/1/1/2 200 228 - - --VN 1/1/0/0/0 0/0 {172.16.1.211|curl/7.29.0||} "GET / HTTP/1.1"
配置示例
listen web_host
bind 10.0.0.7:80
mode http
balance roundrobin
log global #开启日志功能
option httplog #开启httplog日志格式选项
capture request header User-Agent len 512 #记录日志信息,记录User-Agent首部值的前512个字符
capture request header Host len 256 #记录日志信息,记录Host首部值
cookie SERVER-COOKIE insert indirect nocache
server web1 10.0.0.17:80 cookie web1 check inter 3000 fall 3 rise 5
server web2 10.0.0.27:80 cookie web2 check inter 3000 fall 3 rise 5
验证日志格式
[root@haproxy ~]#tail -f /var/log/haproxy.log
Nov 12 17:31:05 haproxy haproxy[13087]: 172.16.1.51:55028 [12/Nov/2024:17:31:05.806] www.web01.com www.web01.com/10.0.0.52 0/0/1/1/2 200 228 - - --VN 1/1/0/0/0 0/0 {172.16.1.211|curl/7.29.0||} "GET / HTTP/1.1"
IP透传
web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场 景。
Layer 4 与 Layer 7
四层:IP+PORT转发
七层:协议+内容交换
四层负载
在LVS 传统的四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡
设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立
TCP连接并发送数据,而四层负载自身不参与建立连接
而和LVS不同,haproxy是伪四层负载均衡,因为haproxy 需要分别和前端客户端及后端服务器建立连接
七层代理
七层负载均衡服务器起了一个反向代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问Web Server要先与七层负载设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡;然后七层负载均衡再根据设置的均衡规则选择特定的 Web Server,然后通过三次握手与此台 Web Server建立TCP连接,然后Web Server把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发送给client;所以,七层负载均衡设备起到了代理服务器的作用,七层代理需要和Client和后端服务器分别建立连接
[root@haproxy ~]#tcpdump tcp -i eth0 -nn port ! 22 -w dump-tcp.pcap -v
[root@haproxy ~]#tcpdump tcp -i eth1 -nn port ! 22 -w dump-tcp2.pcap -v
四层IP透传
#haproxy 配置:
listen web_http_nodes
bind
172.16.0.100:80 #因下面wangxiaochun.com的站点建立在阿里云有防火墙,此处必须用80
端口,如无防火墙可以使用其它端口
mode tcp
#不支持http协议
balance roundrobin
server web1 www.wangxiaochun.com:80 send-proxy check inter 3000 fall 3
rise 5 #添加send-proxy
访问
#nginx 配置:在访问日志中通过变量$proxy_protocol_addr 记录透传过来的客户端IP
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request"
"$proxy_protocol_addr"'
server {
listen
80 proxy_protocol; #启用此项,将无法直接访问此网站,只能通过四层代理
server_name www.wangxiaochun.com;
......
抓包可以看到 continuation 信息中带有客户端的源IP
范例: nginx 开启四层日志功能
#nginx在开启proxy_protocol前
[root@internet ~]#curl 172.16.0.100
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@VM_0_10_centos ~]# tail -f /apps/nginx/logs/nginx.access.log
111.199.187.69 - - [09/Apr/2020:20:48:51 +0800] "PROXY TCP4 10.0.0.7 58.87.87.99
35948 80" sendfileon
111.199.187.69 - - [09/Apr/2020:20:48:54 +0800] "PROXY TCP4 10.0.0.7 58.87.87.99
35952 80" sendfileon
111.199.187.69 - - [09/Apr/2020:20:48:57 +0800] "PROXY TCP4 10.0.0.7 58.87.87.99
35954 80" sendfileon
......
#在nginx服务器上开启日志格式和proxy_protocal
[root@VM_0_10_centos ~]# vim /apps/nginx/conf/nginx.conf
http {
.......
log_format main '$remote_addr - $remote_user [$time_local] "$request"
"$proxy_protocol_addr"'
sendfile on;
keepalive_timeout 65;
client_max_body_size 100m;
server {
listen
80 default_server proxy_protocol ;
#nginx在开启proxy_protocol后,可以看客户端真实源IP
[root@VM_0_10_centos ~]# tail -f /apps/nginx/logs/nginx.access.log
111.199.187.69 - - [09/Apr/2020:20:52:52 +0800] "GET / HTTP/1.1"
"172.16.0.200"sendfileon
七层IP透传
当haproxy工作在七层的时候,也可以透传客户端真实IP至后端服务器
HAProxy配置
在由haproxy发往后端主机的请求报文中添加"X-Forwarded-For"首部,其值为前端客户端的地址;用于 向后端主发送真实的客户端IP
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
[ except <network> ]:请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
[ header <name> ]:使用自定义的首部名称,而非"X-Forwarded-For",示例:X-client
[ if-none ] 如果没有首部才添加首部,如果有使用默认值
范例:
#haproxy 配置
defaults
#此为默认值,首部字段默认为:X-Forwarded-For
option forwardfor
#或者自定义首部,如:X-client
option forwardfor except 127.0.0.0/8 header X-client
#listen配置
listen web_host
bind 10.0.0.7:80
mode http #一定是http模式,tcp 模式不会传递客户端IP
log global
balance random
server web1 10.0.0.17:80 weight 1 check inter 3000 fall 2 rise 5
server web2 10.0.0.27:80 weight 1 check inter 3000 fall 2 rise 5
报文修改
新版
2.1版本以上用下面指令http-request和http-response代替
官方文档:参看2.4的帮助文档
http://cbonte.github.io/haproxy-dconv/2.4/configuration.html#4-http-request
http://cbonte.github.io/haproxy-dconv/2.4/configuration.html#4-http-response
配置说明:
#修改请求host首部,默认host首部会保留客户端原首部haproxy不会修改
http-request set-header host www.wangxiaochun.com
#添加向后端服务器发送的请求报文首部
http-request add-header <name> <fmt> [ { if | unless } <condition> ]
#示例:http-request add-header X-Haproxy-Current-Date %T
#删除向后端服务器发送的请求报文首部
http-request del-header <name> [ { if | unless } <condition> ]
#修改响应首部
http-response set-header server wangserver
#添加向客户端发送的响应报文首部
http-response add-header <name> <fmt> [ { if | unless } <condition> ]
#删除向客户端发送的响应报文首部
http-response del-header <name>
#示例:http-response del-header Server
范例: 添加向后端服务器发送的请求报文首部
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
#haproxy 配置
defaults
#此为默认值,首部字段默认为:X-Forwarded-For
option forwardfor
listen www.web01.com
balance roundrobin
bind 172.16.1.211:80
mode http
log global
cookie WEBSRV insert nocache indirect
http-request add-header X-Haproxy-Current-Date %T
server 10.0.0.52 10.0.0.52:80 check inter 3000 fall 3 rise 5 cookie web01
server 10.0.0.53 10.0.0.53:80 check inter 3000 fall 3 rise 5 cookie web02
[root@haproxy ~]#systemctl restart haproxy.service
[root@web01 ~]#vim /apps/nginx/conf/nginx.conf
log_format main '"$proxy_add_x_forwarded_for" - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_For" "$http_x_Haproxy_Current_Date" ';
[root@master-db ~]#curl -b /root/cookie.txt 172.16.1.211
[root@web01 ~]#tail -f /apps/nginx/logs/access.log
"172.16.1.51, 10.0.0.211" - - [12/Nov/2024:13:36:57 +0800] "GET / HTTP/1.1" 200 29 "-" "curl/7.29.0" "172.16.1.51" "12/Nov/2024:05:36:57 +0000"
范例: 修改向后端服务器的请求首部user-agent
[root@haproxy ~]#vim /etc/haproxy/haproxy.cfg
#注意:先删除再添加才能修改,反之将删除此首部
listen www.web01.com
balance roundrobin
bind 172.16.1.211:80
mode http
log global
cookie WEBSRV insert nocache indirect
http-request add-header X-Haproxy-Current-Date %T
http-request set-header user-agent test-browser
#http-request set-header user-agent test-browser #可以替代上面两条
server 10.0.0.52 10.0.0.52:80 check inter 3000 fall 3 rise 5 cookie web01
server 10.0.0.53 10.0.0.53:80 check inter 3000 fall 3 rise 5 cookie web02
[root@haproxy ~]#systemctl restart haproxy.service
[root@master-db ~]#curl -b /root/cookie.txt 172.16.1.211
[root@web01 ~]#tail -f /apps/nginx/logs/access.log
"172.16.1.51, 10.0.0.211" - - [12/Nov/2024:13:44:13 +0800] "GET / HTTP/1.1" 200 29 "-" "test-browser" "172.16.1.51" "12/Nov/2024:05:44:13 +0000"
范例: 添加向客户端发送的响应报文首部
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen www.web01.com
balance roundrobin
bind 172.16.1.211:80
mode http
log global
cookie WEBSRV insert nocache indirect
http-response add-header X-via haproxy-zhang
server 10.0.0.52 10.0.0.52:80 check inter 3000 fall 3 rise 5 cookie web01
server 10.0.0.53 10.0.0.53:80 check inter 3000 fall 3 rise 5 cookie web02
[root@haproxy ~]#systemctl restart haproxy.service
[root@master-db ~]#curl -b /root/cookie.txt 172.16.1.211 -i
HTTP/1.1 200 OK
server: nginx/1.22.1
date: Tue, 12 Nov 2024 05:51:30 GMT
content-type: text/html
content-length: 29
last-modified: Tue, 05 Nov 2024 14:33:04 GMT
etag: "672a2ca0-1d"
accept-ranges: bytes
x-via: haproxy-zhang
nginx 10.0.0.52 WEBSITE v3.0
范例: 修改向客户端发送的响应报文首部,实现自定义Server首部
[root@haproxy ~]#vim /etc/haproxy/conf.d/test.cfg
listen www.web01.com
balance roundrobin
bind 172.16.1.211:80
mode http
log global
cookie WEBSRV insert nocache indirect
http-response del-header X-via haproxy-zhang
http-response add-header X-via haproxy-zhang #注意和上面指令的前后顺序
http-response set-header X-via haproxy-zhang #可以替代上面两条
server 10.0.0.52 10.0.0.52:80 check inter 3000 fall 3 rise 5 cookie web01
server 10.0.0.53 10.0.0.53:80 check inter 3000 fall 3 rise 5 cookie web02
[root@master-db ~]#curl -b /root/cookie.txt 172.16.1.211 -i
HTTP/1.1 200 OK
server: nginx/1.22.1
date: Tue, 12 Nov 2024 05:51:30 GMT
content-type: text/html
content-length: 29
last-modified: Tue, 05 Nov 2024 14:33:04 GMT
etag: "672a2ca0-1d"
accept-ranges: bytes
x-via: haproxy-zhang
nginx 10.0.0.52 WEBSITE v3.0