【HAProxy08】企业级反向代理HAProxy高级功能之自定义日志格式与IP透传

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
相关推荐
Linux运维日记11 分钟前
k8s1.31版本最新版本集群使用容器镜像仓库Harbor
linux·docker·云原生·容器·kubernetes
嚯——哈哈18 分钟前
轻量云服务器:入门级云计算的最佳选择
运维·服务器·云计算
我是唐青枫20 分钟前
Linux dnf 包管理工具使用教程
linux·运维·服务器
嚯——哈哈44 分钟前
从入门到精通:解析如何使用亚马逊云服务器(AWS EC2)
运维·服务器·aws
编程修仙1 小时前
Collections工具类
linux·windows·python
芝麻团坚果2 小时前
对subprocess启动的子进程使用VSCode python debugger
linux·ide·python·subprocess·vscode debugger
Elastic 中国社区官方博客2 小时前
Elasticsearch 中的热点以及如何使用 AutoOps 解决它们
大数据·运维·elasticsearch·搜索引擎·全文检索
写点什么啦2 小时前
[debug]不同的window连接ubuntu的vscode后无法正常加载kernel
linux·vscode·ubuntu·debug
wellnw2 小时前
[ubuntu]编译共享内存读取出现read.c:(.text+0x1a): undefined reference to `shm_open‘问题解决方案
linux·ubuntu
不爱学习的YY酱2 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统