【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 \ \]:请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络 \[ header \ \]:使用自定义的首部名称,而非"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
相关推荐
没有bug.的程序员4 小时前
单体 → 微服务演进路径:一个真实电商项目的渐进式转型
jvm·微服务·云原生·架构·电商·gc调优
Xの哲學4 小时前
Linux流量控制: 内核队列的深度剖析
linux·服务器·算法·架构·边缘计算
tuokuac4 小时前
docker中nginx配置报错解决
linux·运维·服务器
Zeku5 小时前
20251129 - 详细解析Linux的mmap(内存映射)
linux·驱动开发·嵌入式软件·linux应用开发
Joren的学习记录6 小时前
【Linux运维大神系列】docker详解(四)
linux·运维·docker
rain bye bye6 小时前
calibre lvs rule 的更改(添加器件)
lvs
老王熬夜敲代码6 小时前
网络中数据传输的具体过程
linux·网络·笔记
Elastic 中国社区官方博客7 小时前
让我们把这个 expense 工具从 n8n 迁移到 Elastic One Workflow
大数据·运维·elasticsearch·搜索引擎·ai·信息可视化·全文检索
世转神风-7 小时前
linux使用终端打开当前文件夹界面
linux
( •̀∀•́ )9207 小时前
GitHub Actions SSH 部署密钥
运维·ssh·github