当前位置: 首页 > news >正文

Haproxy七层代理及配置

1.1.什么是负载均衡
负载均衡:Load Balance,简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均衡将特定的业务(web服务、网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了 公司业务的并发处理能力、保证了业务的高可用性、方便了业务后期的水平动态扩展。
1.2.为什么用负载均衡
Web服务器的动态水平扩展-->对用户无感知
增加业务并发访问及处理能力-->解决单服务器瓶颈问题
节约公网IP地址-->降低IT支出成本
隐藏内部服务器IP-->提高内部服务器安全性
配置简单-->固定格式的配置文件
功能丰富-->支持四层和七层,支持动态下线主机
性能较强-->并发数万甚至数十万
1.3.2.四层负载均衡
1.通过ip+port决定负载均衡的去向。
2.对流量请求进行NAT处理,转发至后台服务器。
3.记录tcpudp流量分别是由哪台服务器处理,后续该请求连接的流量都通过该服务器处理。
4.支持四层的软件
      lvs:重量级四层负载均衡器。
      Nginx:轻量级四层负载均衡器,可缓存。(nginx四层是通过upstream模块)
      Haproxy:模拟四层转发。
1.3.3.七层负载均衡
1.通过虚拟ur|或主机ip进行流量识别,根据应用层信息进行解析,决定是否需要进行负载均衡。
2.代理后台服务器与客户端建立连接,如nginx可代理前后端,与前端客户端tcp连接,与后端服务器建立
tcp连接,
3.支持7层代理的软件:
       Nginx:基于http协议(nginx七层是通过proxy_pass)
       Haproxy:七层代理,会话保持、标记、路径转移等。
1.3.4 四层和七层的区别
所谓的四到七层负载均衡,就是在对后台的服务器进行负载均衡时,依据四层的信息或七层的信息来决 定怎么样转发流量
四层的负载均衡,就是通过发布三层的IP地址(VIP),然后加四层的端口号,来决定哪些流量需要做负载均衡,对需要处理的流量进行NAT处理,转发至后台服务器,并记录下这个TCP或者UDP的流量是由哪 台服务器处理的,后续这个连接的所有流量都同样转发到同一台服务器处理。
七层的负载均衡,就是在四层的基础上(没有四层是绝对不可能有七层的),再考虑应用层的特征,比 如同一个Web服务器的负载均衡,除了根据VIP80端口辨别是否需要处理的流量,还可根据七层的 URL、浏览器类别、语言来决定是否要进行负载均衡。
1.分层位置:四层负载均衡在传输层及以下,七层负载均衡在应用层及以下
2.性能 :四层负载均衡架构无需解析报文消息内容,在网络吞吐量与处理能力上较高:七层可支持解析应用 层报文消息内容,识别URLCookieHTTP header等信息。
3.原理 :四层负载均衡是基于ip+port;七层是基于虚拟的URL或主机IP等。
4.功能类比:四层负载均衡类似于路由器;七层类似于代理服务器。
5.安全性:四层负载均衡无法识别DDoS攻击;七层可防御SYN Cookie/Flood攻击。
.haproxy简介
HAProxy是法国开发者 威利塔罗(Willy Tarreau) 2000年使用C语言开发的一个开源软件
是一款具备高并发(万级以上)、高性能的TCPHTTP负载均衡器
支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计
企业版网站:https://www.haproxy.com
社区版网站:http://www.haproxy.org
githubhttps://github.com/haprox
企业版本和社区版功能对比
.haproxy的安装和服务信息
3.1.实验环境
3.2.软件安装
安装软件包:haproxy ~]# dnf install haproxy -y
查看版本
[root@haproxy ~]# haproxy -v
HAProxy version 2.4.22-f8e3218 2023/02/14 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs: http://www.haproxy.org/bugs/bugs-2.4.22.html
Running on: Linux 5.14.0-427.13.1.el9_4.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 10
10:29:16 EDT 2024 x86_64
haproxy软件基本信息
软件安装包: haproxy-2.4.22-3.el9_3.x86_64.rpm
启动文件: /lib/systemd/system/haproxy.service
主配置目录: /etc/haproxy/
主配置文件: /etc/haproxy/haproxy.cfg
子配置目录: /etc/haproxy/conf.d
3.3.haproxy的基本配置信息
官方文档:http://cbonte.github.io/haproxy-dconv/
HAProxy 的配置文件haproxy.cfg由两大部分组成,分别是:
global:全局配置段
              进程及安全配置相关的参数
              性能调整相关参数
              Debug参数
proxies:代理配置段
                defaults:为frontend, backend, listen提供默认配置
                frontend:前端,相当于nginx中的server {}
                backend:后端,相当于nginx中的upstream {}
                listen:同时拥有前端和后端配置,配置简单,生产推荐使用
   
环境准备
vim /etc/haproxy/haproxy.cfg
# 前端配置
frontend webclusterbind *:80mode httpuse_backend webcluster-host  # 指定使用的后端集群# 后端配置
backend webcluster-hostbalance roundrobin  # 负载均衡算法server web1 172.25.254.10:80server web2 172.25.254.20:80

合并配置方法(listen方式)

listen webclusterbind *:80  # 监听所有IP的80端口mode httpbalance roundrobinserver web1 172.25.254.10:80 check inter 2 fall 3 rise 5 weight 2server web2 172.25.254.20:80 check inter 2 fall 3 rise 5 weight 1
重启服务
systemctl restart haproxy.service

webserver1和webserver2

测试

global配置

实验:

1.设置脚本的的行数,避免太多看不清楚及出错

vim ~/.vimrc   

set ts=4 ai sw=4

2.    mode http  七层         mode tcp 四层

实验1.编写haproxy的配置文件访问服务端内容实现负载均衡

(在vim /etc/haproxy/haproxy.conf中的两种写法)

测试结果

实验2.日志的配置
定义全局的syslog服务器;日志服务器需要开启UDP协议,
最多可以定义两个

在配置文件中查看local2

在日志文件添加

vim etc/rsyslog.conf

实验3.多进程和socket文件的配置
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...(上略)...
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 100000
user haproxy
group haproxy
daemon# turn on stats unix soxket
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1  
# 启用多sock文件
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2
nbproc 2  # 启用多进程
cpu-map 1 0  # 进程与CPU核心绑定,防止CPU抖动降低系统消耗
cpu-map 2 1  # 2表示第二个进程,1表示第二个CPU核心
...(下略)...

启动多线程
haproxy ~]# vim /etc/haproxy/haproxy.cfg
...省略上方配置...
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 100000
user haproxy
group haproxy
daemon# turn on stats unix socket
stats socket /var/lib/haproxy/haproxy.sock1 mode 600 level admin process 1
# 启用多个sock文件
stats socket /var/lib/haproxy/haproxy.sock2 mode 600 level admin process 2#nbproc 2
#cpu-map 1 0
#cpu-map 2 1
nbthread 2  # 启用多线程模式
...省略下方配置...

注意: 多线程和多进程之间的不能同时使用会互斥

未开启多线程
haproxy ~]# cat /proc/xxxx(haproxy子进程id)/status
...上面内容省略...
Threads: 1
...下面内容省略...
开启后
haproxy ~]# cat /proc/xxxx(haproxy子进程id)/status
...上面内容省略...
Threads: 2
...下面内容省略...

proxies配置

server

#针对一个server配置
check #对指定real进行健康状态检查,如果不加此设置,默认不开启检查,只有check后面没
有其它配置也可以启用检查功能
#默认对相应的后端服务器IP和端口,利用TCP连接进行周期性健康性检查,注意必须指定
端口才能实现健康性检查
addr <IP> #可指定的健康状态监测IP,可以是专门的数据网段,减少业务网络的流量
port <num> #指定的健康状态监测端口
inter <num> #健康状态检查间隔时间,默认2000 ms
fall <num> #后端服务器从线上转为线下的检查的连续失效次数,默认为3代码示例:
测试效果:
rise <num> #后端服务器从下线恢复上线的检查的连续有效次数,默认为2
weight <weight> #默认为1,最大值为256,0(状态为蓝色)表示不参与负载均衡,但仍接受持久连接
backup #将后端服务器标记为备份状态,只在所有非备份主机down机时提供服务,类似Sorry
Server
disabled #将后端服务器标记为不可用状态,即维护状态,除了持久模式
#将不再接受连接,状态为深黄色,优雅下线,不再接受新用户的请求
redirect prefix http://www.baidu.com/ #将请求临时(302)重定向至其它URL,只适用于http模

maxconn <maxconn> #当前后端server的最大并发连接数

实验:

weight

haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...backend lee-webserver-80-RSmode httpserver web1 192.168.0.101:80 check inter 3s fall 3 rise 5server web2 192.168.0.102:80 check inter 3s fall 3 rise 5...上面内容省略...

backend

首先下载httpd,再配置文件中设置端口号为8080

注意:此时此刻要注意要关闭web1和web2的内容

disabled   ----代表下线了

redirect prefix http://www.baidu.com/        ---重定向网页

maxconn <maxconn>


socat工具
对服务器动态权重和其它状态可以利用 socat工具进行调整,Socat 是 Linux 下的一个多功能的网络工具,名字来由是Socket CAT,相当于netCAT的增强版.Socat 的主要特点就是在两个数据流之间建立双向通道,且支持众多协议和链接方式。如 IP、TCP、 UDP、IPv6、Socket文件等。

下载软件socat

单进程

#查看haproxy状态
[root@haproxy ~]# echo "show info" | socat stdio /var/lib/haproxy/stats
Name: HAProxy
Version: 2.4.22-f8e3218
Release_date: 2023/02/14
Nbthread: 1
Nbproc: 1
Process_num: 1
Pid: 33542
Uptime: 0d 0h03m43s
Uptime_sec: 223
Memmax_MB: 0
PoolAlloc_MB: 0
#查看集群状态
[root@haproxy ~]# echo "show servers state" | socat stdio /var/lib/haproxy/stats
1
# be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight
srv_iweight srv_time_since_last_change srv_check_status srv_check_result
srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id
srv_fqdn srv_port srvrecord srv_use_ssl srv_check_port srv_check_addr
srv_agent_addr srv_agent_port
2 webcluster 1 web1 172.25.254.20 2 0 2 2 188 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
2 webcluster 2 web2 172.25.254.30 2 0 1 1 188 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
4 static 1 static 127.0.0.1 0 0 1 1 187 8 2 0 6 0 0 0 - 4331 - 0 0 - - 0
5 app 1 app1 127.0.0.1 0 0 1 1 187 8 2 0 6 0 0 0 - 5001 - 0 0 - - 0
5 app 2 app2 127.0.0.1 0 0 1 1 187 8 2 0 6 0 0 0 - 5002 - 0 0 - - 0
5 app 3 app3 127.0.0.1 0 0 1 1 186 8 2 0 6 0 0 0 - 5003 - 0 0 - - 0
5 app 4 app4 127.0.0.1 0 0 1 1 186 8 2 0 6 0 0 0 - 5004 - 0 0 - - 0
#查看集群权重
[root@haproxy ~]# echo get weight webcluster/web1 | socat stdio
/var/lib/haproxy/stats
2 (initial 2)
[root@haproxy ~]# echo get weight webcluster/web2 | socat stdio
/var/lib/haproxy/stats
1 (initial 1)
#设置权重
[root@haproxy ~]# echo "set weight webcluster/web1 1 " | socat stdio
/var/lib/haproxy/stats
[root@haproxy ~]# echo "set weight webcluster/web1 2 " | socat stdio
/var/lib/haproxy/stats
#下线后端服务器
[root@haproxy ~]# echo "disable server webcluster/web1 " | socat stdio
/var/lib/haproxy/stats
#上线后端服务器
[root@haproxy ~]# echo "enable server webcluster/web1 " | socat stdio
/var/lib/haproxy/stats

多进程

.haproxy的算法

HAProxy通过固定参数 balance 指明对后端服务器的调度算法

balance参数可以配置在listen或backend选项中。

HAProxy的调度算法分为静态和动态调度算法

有些算法可以根据参数在静态和动态算法中相互转换。

4.1 静态算法
静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、连接数和响应速度等,且无法实时修改权重(只能为0和1,不支持其它值),只能靠重启HAProxy生效。

4.1.1 static-rr:基于权重的轮询调度
不支持运行时利用socat进行权重的动态调整(只支持0和1,不支持其它值)
不支持端服务器慢启动
其后端主机数量没有限制,相当于LVS中的 wrr\

注意:慢启动是指在服务器刚刚启动上不会把他所应该承担的访问压力全部给它,而是先给一部分,当没问题后在给一部分

4.1.2 first

根据服务器在列表中的位置,自上而下进行调度

其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务

其会忽略服务器的权重设置

不支持用socat进行动态修改权重,可以设置0和1,可以设置其它值但无效

示例:

测试效果:

4.2 动态算法
动态算法

基于后端服务器状态进行调度适当调整,
新请求将优先调度至当前负载较低的服务器
权重可以在haproxy运行时动态调整无需重启


4.2.1 roundrobin
1. 基于权重的轮询动态调度算法,

2. 支持权重的运行时调整,不同于lvs中的rr轮训模式,

3. HAProxy中的roundrobin支持慢启动(新加的服务器会逐渐增加转发数),

4. 其每个后端backend中最多支持4095个real server,

5. 支持对real server权重动态调整,

6. roundrobin为默认调度算法,此算法使用广泛

示例:

动态调整权重 :

4.2.2 leastconn
  • leastconn加权的最少连接的动态
  • 支持权重的运行时调整和慢启动,即:根据当前连接最少的后端服务器而非权重进行优先调度(新客户端连接)
  • 比较适合长连接的场景使用,比如:MySQL等场景。

示例:

4.3 其他算法
其它算法即可作为静态算法,又可以通过选项成为动态算法
4.3.1 source
源地址hash,基于用户源地址hash并将请求转发到后端服务器,后续同一个源地址请求将被转发至同一个后端web服务器。此方式当后端服务器数据量发生变化时,会导致很多用户的请求转发至新的后端服务器,默认为静态方式,但是可以通过hash-type支持的选项更改这个算法一般是在不插入Cookie的TCP模式下使用,也可给拒绝会话cookie的客户提供最好的会话粘性,适用于session会话保持但不支持cookie和缓存的场景源地址有两种转发客户端请求到后端服务器的服务器选取计算方式,分别是取模法和一致性hash

示例:

测试:

注意:如果访问客户端时一个家庭,那么所有的家庭的访问流量都会被定向到一台服务器,这时source算法的缺陷

4.3.1.1 map-base 取模法
map-based:取模法,对source地址进行hash计算,再基于服务器总权重的取模,最终结果决定将此请求转发至对应的后端服务器。
此方法是静态的,即不支持在线调整权重,不支持慢启动,可实现对后端服务器均衡调度。
缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因总权重发生变化而导致调度结果整体改变。
hash-type 指定的默值为此算法。

注意:所谓取模运算,就是计算两个数相除之后的余数, 10%7=3, 7%4=3
map-based 算法:基于权重取模, hash(source_ip)% 所有后端服务器相加的总权重

取模法配置示例:

4.3.1.2 一致性hash
一致性哈希,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动hash(o)mod n
该hash算法是动态的,支持使用 socat等工具进行在线权重调整,支持慢启动
算法:

hash环偏斜问题

hash对象

Hash对象到后端服务器的映射关系:

一致性hash示意图

后端服务器在线与离线的调度方式

一致性 hash 配置示例

4.3.2 uri
基于对用户请求的URI的左半部分或整个uri做hash,再将hash结果对总权重进行取模后,根据最终结果将请求转发到后端指定服务器,适用于后端是缓存服务器场景

默认是静态算法,也可以通过hash-type指定map-based和consistent,来定义使用取模法还是一致性hash

注意:此算法基于应用层,所以只支持 mode http ,不支持 mode tcp

4.3.2.1 uri 取模法配置示例

4.3.2.2 uri 一致性hash配置示例

4.3.2.3 访问测试

访问不同的uri,确认可以将用户同样的请求转发至相同的服务器

4.3.3 url_param
url_param对用户请求的url中的 params 部分中的一个参数key对应的value值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器,后端搜索同一个数据会被调度到同一个服务器,多用与电商

通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个real server

如果无没key,将按roundrobin算法

4.3.3.1 url_param取模法配置示例

4.3.3.2 url_param一致性hash配置示例

4.3.3.3 测试访问

4.3.4 hdr
针对用户每个http头部(header)请求中的指定信息做hash,
此处由 name 指定的http首部将会被取出并做hash计算,
然后由服务器总权重取模以后派发至某挑出的服务器,如果无有效值,则会使用默认的轮询调度。


4.3.4.1 hdr取模法配置示例

4.3.4.2 一致性hash配置示例

4.3.4.3 测试访问

4.3.6 算法总结

4.3.7 各算法使用场景

五、高级功能及配置
5.1 基于cookie的会话保持
cookie value:为当前server指定cookie值,实现基于cookie的会话黏性,相对于基于 source 地址hash调度算法对客户端的粒度更精准,但同时也加大了haproxy负载,目前此模式使用较少, 已经被session共享服务器代替

注意:不支持 tcp mode,使用 http mode

5.1.1 配置选项

5.1.2 配置示例

5.1.3 验证cookie信息

通过命令行验证:

[root@client ~]# curl -i 172.25.254.100
HTTP/1.1 200 OK
server: nginx/1.20.1
date: Sun, 11 Aug 2024 07:33:11 GMT
content-type: text/html
content-length: 26
last-modified: Sun, 11 Aug 2024 07:31:22 GMT
etag: "66b868ca-1a"
accept-ranges: bytes
set-cookie: WEBCOOKIE=check; path=/
cache-control: private

RS server - 192.168.0.102

#curl访问时指定cookie
[root@client ~]# curl -b WEBCOOKIE=web1 172.25.254.100
RS1 server - 192.168.0.101
[root@client ~]# curl -b WEBCOOKIE=web2 172.25.254.100
RS2 server - 192.168.0.102

[root@client ~]# curl -vb WEBCOOKIE=web1 172.25.254.100
*   Trying 172.25.254.100:80...
* Connected to 172.25.254.100 (172.25.254.100) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.25.254.100
> User-Agent: curl/7.76.1
> Accept: */*
> Cookie: WEBCOOKIE=web1

* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< date: Sun, 11 Aug 2024 07:34:49 GMT
< server: Apache/2.4.57 (Red Hat Enterprise Linux)
< last-modified: Sun, 11 Aug 2024 07:32:11 GMT
< etag: "1a-61f635fe882c7"
< accept-ranges: bytes
< content-length: 26
< content-type: text/html; charset=UTF-8
< set-cookie: WEBCOOKIE=check; path=/
< cache-control: private

RS server - 192.168.0.101
* Connection #0 to host 172.25.254.100 left intact

5.2 HAProxy状态页

通过web界面,显示当前HAProxy的运行状态

5.2.1 状态页配置项

5.2.2 启用状态页

5.2.3 登录状态页

#pid为当前pid号,process为当前进程号,nbproc和nbthread为一共多少进程和每个进程多少个线程
pid = 27134 (process #1, nbproc = 1, nbthread = 1)

#启动了多长时间
uptime = 0d 0h00m04s

#系统资源限制:内存/最大打开文件数/
system limits: memmax = unlimited; ulimit-n = 200029

#最大socket连接数/单进程最大连接数/最大管道数maxpipes
maxsock = 200029; maxconn = 100000; maxpipes = 0

#当前连接数/当前管道数/当前连接速率
current conns = 2; current pipes = 0/0; conn rate = 2/sec; bit rate = 0.000 kbps

#运行的任务/当前空闲率
Running tasks: 1/14; idle = 100 %

active UP: #在线服务器
backup UP: #标记为backup的服务器
active UP, going down: #监测未通过正在进入down过程
backup UP, going down: #备份服务器正在进入down过程
active DOWN, going up: #down的服务器正在进入up过程
backup DOWN, going up: #备份服务器正在进入up过程
active or backup DOWN: #在线的服务器或者是backup的服务器已经转换成了down状态
not checked: #标记为不监测的服务器

#active或者backup服务器人为下线的
active or backup DOWN for maintenance (MAINT)

#active或者backup被人为软下线(人为将weight改成0)
active or backup SOFT STOPPED for maintenance

5.2.4 backend server信息

5.3 IP透传

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

5.3.2 四层IP透传

#未开启透传的四层代理
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...

listen webserver_80
bind 172.25.254.100:80
mode tcp
balance roundrobin
server webserver1 192.168.0.101:80 weight 1 check inter 3s fall 3 rise 5

...上面内容省略...

#正常的nginx配置
[root@server1 ~]# vim /etc/nginx/nginx.conf
...内容省略...

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
...内容省略...
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
...内容省略...
}
}

#在访问haproxy后查看nginx日志
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
192.168.0.10 - - [10/Jul/2024:15:21:00 +0800] "GET / HTTP/1.1"200 18 "-"
"curl/7.29.0" "-"192.168.0.10 - - [10/Jul/2024:15:26:11 +0800] "GET /
HTTP/1.1"200 18 "-" "curl/7.29.0" "-"
在此日志中是无法看到真实访问源地址的

开启四层透传

#nginx 配置:在访问日志中通过变量$proxy_protocol_addr 记录透传过来的客户端IP
[root@rs1 ~]# vim /etc/nginx/nginx.conf
...内容省略...

http {
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
' "$proxy_protocol_addr"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
...内容省略...
server {
listen 80 proxy_protocol; #启用此项,将无法直接访问此网站,只能通过四层代理
访问
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
...内容省略...
}
}
#修改haproxy
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...

listen webserver_80
bind 172.25.254.100:80
mode tcp
balance roundrobin
server webserver1 192.168.0.101:80 send-proxy weight 1 check inter 3s fall 3 rise 5

...上面内容省略...

#查看日志内容
[root@server1 ~]# tail -n 3 /var/log/nginx/access.log
192.168.0.10 - - [10/Jul/2024:15:21:00 +0800] "GET / HTTP/1.1"200 18 "-" "curl/7.29.0" "-"
192.168.0.10 - - [10/Jul/2024:15:26:11 +0800] "GET / HTTP/1.1"200 18 "-" "curl/7.29.0" "-"
192.168.0.10 - - [10/Jul/2024:15:41:56 +0800] "GET / HTTP/1.1" "172.25.254.10"200 18 "-" "curl/7.29.0"

5.3.3 七层IP透传
当haproxy工作在七层的时候,也可以透传客户端真实IP至后端服务器

5.3.3.1 HAProxy配置
在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For"首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP

示例:

5.3.3.2 web服务器日志格式配置

配置web服务器,记录负载均衡透传的客户端IP地址

#apache 配置:
LogFormat "%{X-Forwarded-For}i %a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

#nginx 日志格式:
$proxy_add_x_forwarded_for: 包括客户端IP和中间经过的所有代理的IP
$http_x_forwarded_For: 只有客户端IP

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';

#查看日志如下:
[root@server1 ~]# tail -n 3 /var/log/nginx/access.log
"172.25.254.10, 192.168.0.10" 192.168.0.10 - - [10/Jul/2024:16:15:00 +0800] "GET / HTTP/1.1"200 18 "-" "curl/7.29.0" "172.25.254.10"
[root@server2 ~]# tail -n 3 /etc/httpd/logs/access_log
172.25.254.10 192.168.0.10 - - [11/Jul/2024:00:15:00 +0800] "GET / HTTP/1.1" 200 27 "-" "curl/7.29.0"

5.4 ACL
访问控制列表ACL,Access Control Lists)

是一种基于包过滤的访问控制技术

它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配)即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃。

示例:

5.4.1 ACL配置选项

5.4.1.1 ACL-Name 名称

5.4.1.2 ACL-criterion 匹配规范

定义 ACL 匹配规范,即:判断条件

hdr string,提取在一个HTTP请求报文的首部
hdr([<name> [,<occ>]]):完全匹配字符串,header的指定信息,<occ> 表示在多值中使用的值的出现次数
hdr_beg([<name> [,<occ>]]):前缀匹配,header中指定匹配内容的begin
hdr_end([<name> [,<occ>]]):后缀匹配,header中指定匹配内容end
hdr_dom([<name> [,<occ>]]):域匹配,header中的dom(host)
hdr_dir([<name> [,<occ>]]):路径匹配,header的uri路径
hdr_len([<name> [,<occ>]]):长度匹配,header的长度匹配
hdr_reg([<name> [,<occ>]]):正则表达式匹配,自定义表达式(regex)模糊匹配
hdr_sub([<name> [,<occ>]]):子串匹配,header中的uri模糊匹配 模糊匹配c 报文中a/b/c也会匹配

#示例:
hdr(<string>) 用于测试请求头部首部指定内容

hdr_dom(host) 请求的host名称,如 www.timinglee.org
hdr_beg(host) 请求的host开头,如 www. img. video. download. ftp.
hdr_end(host) 请求的host结尾,如 .com .net .cn

#示例:
acl bad_agent hdr_sub(User-Agent) -i curl wget
http-request deny if bad_agent

#有些功能是类似的,比如以下几个都是匹配用户请求报文中host的开头是不是www
acl short_form hdr_beg(host) www.
acl alternate1 hdr_beg(host) -m beg www.
acl alternate2 hdr_dom(host) -m beg www.
acl alternate3 hdr(host) -m beg www.

base : string
#返回第一个主机头和请求的路径部分的连接,该请求从主机名开始,并在问号之前结束,对虚拟主机有用
<scheme>://<user>:<password>@#<host>:<port>/<path>;<params>#?<query>#<frag>
base : exact string match
base_beg : prefix match
base_dir : subdir match
base_dom : domain match
base_end : suffix match
base_len : length match
base_reg : regex match
base_sub : substring match

path : string
#提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)
<scheme>://<user>:<password>@<host>:<port>#/<path>;<params>#?<query>#<frag>
path : exact string match
path_beg : prefix match #请求的URL开头,如/static、/images、/img、/css
path_end : suffix match #请求的URL中资源的结尾,如 .gif .png .css .js .jpg .jpeg
path_dom : domain match
path_dir : subdir match
path_len : length match
path_reg : regex match
path_sub : substring match

#示例:
path_beg -i /haproxy-status/
path_end .jpg .jpeg .png .gif
path_reg ^/images.*\.jpeg$
path_sub image
path_dir jpegs
path_dom timinglee

url : string
#提取请求中的整个URL。
url :exact string match
url_beg : prefix match
url_dir : subdir match
url_dom : domain match
url_end : suffix match
url_len : length match
url_reg : regex match
url_sub : substring match

dst #目标IP
dst_port #目标PORT

src #源IP
src_port #源PORT

#示例:
acl invalid_src src 10.0.0.7 192.168.1.0/24
acl invalid_src src 172.16.0.0/24

acl invalid_port src_port 0:1023

status : integer #返回在响应报文中的状态码

#七层协议
acl valid_method method GET HEAD
http-request deny if ! valid_method

5.4.1.3 ACL-flags 匹配模式

ACL匹配模式

-i 不区分大小写
-m 使用指定的正则表达式匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关系

5.4.1.4 ACL-operator 具体操作符

ACL 操作符

5.4.1.5 ACL-value 操作对象

value 的类型

5.4.2 多个ACL的组合调用方式

多个 ACL 的逻辑处理

与:隐式(默认)使用
或:使用“or" 或 “||"表示
否定:使用 "!" 表示

多个 ACL 调用方式:

#示例:
if valid_src valid_port #与关系,ACL中A和B都要满足为true,默认为与
if invalid_src || invalid_port #或,ACL中A或者B满足一个为true
if ! invalid_src #非,取反,不满足ACL才为true

5.4.3 ACL示例-域名匹配

测试结果:

5.4.4 ACL示例-基于源IP或子网调度访问

将指定的源地址调度至指定的 web 服务器组。

测试结果:

5.4.5 ACL示例-基于源地址的访问控制

拒绝指定 IP 或者 IP 范围访问

测试:

5.4.6 ACL示例-匹配浏览器类型

匹配客户端浏览器,将不同类型的浏览器调动至不同的服务器组、

范例: 拒绝curl和wget的访问

示例:

测试:

5.4.7 ACL示例-基于文件后缀名实现动静分离

测试:

5.4.8 ACL-匹配访问路径实现动静分离

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend testacl
bind :80
mode http

########### ACL settings #######################
acl url_static path_end -i .jpg .png .css .js .html
acl url_static path_end -m sub /static /images /javascript
acl acl_app path_beg -m sub /api

########### host ###########################
use_backend static_host if url_static
use_backend api_host if acl_app

########### default server ###################
default_backend default_webserver

backend static_host
mode http
server web2 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5

backend api_host
mode http
server web1 192.168.0.102:80 check weight 1 inter 3s fall 3 rise 5

backend default_webserver
mode http
server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5

#创建相关文件
[root@server1 ~]# mkdir /usr/share/nginx/html/static
[root@server1 ~]# echo static 192.168.0.101 > /usr/share/nginx/html/static/index.html
[root@server2 ~]# mkdir /var/www/html/api/
[root@server2 ~]# echo api 192.168.0.102 > /var/www/html/api/index.html
#测试访问
[root@client ~]# curl 172.25.254.100/api/
api 192.168.0.102
[root@client ~]# curl 172.25.254.100/static/
static 192.168.0.101

5.5 自定义HAProxy 错误界面

对指定的报错进行重定向,进行优雅的显示错误页面

使用errorfile和errorloc指令的两种方法,可以实现自定义各种错误页面

5.5.1 基于自定义的错误页面文件

示例:

测试:

关闭后端的RS主机
然后用浏览器去访问172.25.254.100

5.5.2 基于http重定向错误页面

示例:

5.6 HAProxy 四层负载

针对除 HTTP 以外的 TCP 协议应用服务访问的应用场景

MySQL
Redis
Memcache
RabbitMQ

四层负载示例

注意:如果使用frontend和backend,一定在 frontend 和 backend 段中都指定mode tcp

示例:对 MySQL 服务实现四层负载

[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
listen mysql_port
bind :3306
mode tcp
balance leastconn
server mysql1 192.168.0.101:3306 check
server mysql2 192.168.0.102:3306 check

#或者使用frontend和backend实现
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
...上面内容省略...
frontend mysql_port
bind :3306
mode tcp
use_backend mysql_rs

backend mysql_rs
mode tcp
balance leastconn
server mysql1 192.168.0.101:3306 check
server mysql2 192.168.0.102:3306 check

[root@haproxy ~]# systemctl restart haproxy.service

#在后端服务器安装和配置mariadb服务
[root@server1 ~]# yum install mariadb-server -y
[root@server2 ~]# yum install mariadb-server -y

[root@server1 ~]# vim /etc/my.cnf
[mysqld]
server-id=1 #在另一台主机为

[root@server2 ~]# vim /etc/my.cnf
[mysqld]
server-id=2 #在另一台主机为

[root@server1 ~]# systemctl start mariadb
[root@server2 ~]# systemctl start mariadb

[root@server1 ~]# mysql -e "grant all on *.* to yu@'%' identified by 'yu';"
[root@server2 ~]# mysql -e "grant all on *.* to yu@'%' identified by 'yu';"

#测试
[root@client ~]# mysql -uyu -pyu -h 172.25.254.100 -e "show variables like
'hostname'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| hostname      | rs2   |
+---------------+-------+
[root@client ~]# mysql -uyu -pyu -h 172.25.254.100 -e "show variables like
'hostname'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| hostname      | rs1   |
+---------------+-------+
[root@client0 ~]# mysql -uyu -pyu -h172.25.254.100 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 1           |
+-------------+
[root@client ~]# mysql -uyu -pyu -h172.25.254.100 -e "select @@server_id"
+-------------+
| @@server_id |
+-------------+
| 2           |
+-------------+

5.7 HAProxy https 实现

haproxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器用http通信

但基于性能考虑,生产中证书都是在后端服务器比如nginx上实现

5.7.1 证书制作

[root@haproxy ~]# mkdir /etc/haproxy/certs/
[root@haproxy ~]# openssl req -newkey rsa:2048 \ -nodes -sha256 –keyout /etc/haproxy/certs/timinglee.org.key \ -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.crt

5.7.2 https配置示例

http://www.lryc.cn/news/599864.html

相关文章:

  • 数据结构2-集合类ArrayList与洗牌算法
  • 在Word和WPS文字中添加的拼音放到文字右边
  • JS与Go:编程语言双星的碰撞与共生
  • 初识opencv04——图像预处理3
  • ModelWhale+数据分析 消费者行为数据分析实战
  • 判断子序列-leetcode
  • 广州 VR 安全用电技术:工作原理、特性及优势探析​
  • CTF-Web题解:“require_once(‘flag.php‘); assert(“$i == $u“);”
  • Linux系统基本配置以及认识文件作用
  • 双非上岸985!专业课140分经验!信号与系统考研专业课140+上岸中南大学,通信考研小马哥
  • 20分钟学会TypeScript
  • 本地内网IP映射到公网访问如何实现?内网端口映射外网工具有哪些?
  • VUE2 学习笔记6 vue数据监测原理
  • 局域网 IP地址
  • Linux tcpdump 抓取udp 报文
  • 开源语音TTS与ASR大模型选型指南(2025最新版)(疯聊AI提供)
  • 动态规划:从入门到精通
  • 中国开源Qwen3 Coder与Kimi K2哪个最适合编程
  • 电子电子架构 --- 软件项目的开端:裁剪
  • 【IDEA】IDEA中如何通过分支/master提交git?
  • Hadoop 之 Yarn
  • 【软件工程】构建软件合规防护网:双阶段检查机制的实践之道
  • 【AJAX】Promise详解
  • HashMap的线程安全性 vs ConcurrentHashMap
  • 机器学习中knn的详细知识点
  • 基于springboot的候鸟监测管理系统
  • 100条常用SQL语句大全
  • 用毫秒级视频回传打造稳定操控闭环之远程平衡控制系统技术实践
  • LE AUDIO CIS/BIS音频传输时延计算方法
  • 【神经网络概述】从感知机到深度神经网络(CNN RNN)