目录
haproxy配置文件组成
实验环境
haproxy安装
haproxy的配置文件说明
全局配置段global
多进程和多线程配置
代理配置段proxies
server配置说明
实验相关配置
测试效果:
haproxy的状态页
socat命令
socat命令的一些常用示例
HAProxy的调度算法
静态算法
static-rr(静态轮询)
first(优先调度)
动态算法
roundrobin(加权轮询)
leastconn(最少连接数)
其他算法
source(源地址哈希)
uri(URI哈希)
编辑
url_param(URL参数哈希)
编辑
hdr(HTTP头部哈希)
haproxy的高级功能配置
配置选项说明
IP透传
四层IP透
未开启四层IP透传时
开启四层IP透传后
七层IP透传
ACL
ACL配置选项说明
aclname名称
criterion匹配规范
flags匹配模式
多个acl的组合调用方式
ACL相关实验
ACL域名匹配
ACL基于源IP或子网调度访问
ACL基于源地址的访问控制
ACL匹配浏览器类型
ACL基于文件后缀名实现动静分离
ACL匹配访问路径实现动静分离
自定义HAProxy错误页面
基于自定义的错误页面配置
基于http重定向错误页面配置
HAProxy四层负载
对于MySQL服务实现四层负载
HAProxy的https实现
证书的制作
haproxy配置
HAProxy(高可用代理)是一款开源的、高性能的负载均衡和反向代理软件,它在网络服务架构中扮演着至关重要的角色,主要负责分发网络流量,以实现负载均衡和高可用性。HAProxy采用C语言编写,能够有效地处理大量并发连接,并支持多种负载均衡算法,如轮询、最少连接、源地址哈希等。它通常运行在透明模式下,将客户端请求转发到多个服务器上,从而分散负载,提升系统整体性能和吞吐量。
haproxy配置文件组成
实验环境
操作系统:RHEL9.3
haproxy
ens160 172.25.254.100 ens224 192.168.0.100
webserver1 ens160 192.168.0.10
webserver2 ens160 192.168.0.20
haproxy安装
[root@haproxy ~]# yum install haproxy -y
haproxy的配置文件说明
haproxy的配置文件为/etc/haproxy/haproxy.cfg,主要有全局配置段global、代理配置段proxies组成。
全局配置段global
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfgglobal #用于定义全局参数,属于进程级的配置,通常和操作系统配置有关log 127.0.0.1 local2 #定义全局的syslog服务器;日志服务器需开启UDP协议chroot /var/lib/haproxy #更改当前工作目录pidfile /var/run/haproxy.pid #指定pid文件路径maxconn 4000 #每个haproxy进程的最大连接并发数,优先级最低,如果default或frontend也有,会优先选择frontend,default次之user haproxy #运行haproxy的所属用户group haproxy #运行haproxy的所属组daemon #以守护进程方式运行haproxystats socket /var/lib/haproxy/stats mode 600 level admin #套接字文件
多进程和多线程配置
多进程和socket的配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
globallog 127.0.0.1 local2chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 4000user haproxygroup haproxydaemon# turn on stats unix socket#这里启用了多个socket套接字文件stats socket /var/lib/haproxy/stats1 mode 600 level admin process 1stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2nbproc 2 #启用多进程cpu-map 1 0 #进程和cpu核心绑定,防止cpu抖动从而减少系统资源消耗cpu-map 2 1 #2表示第二个进程,1表示第二个cpu核心#每次完配置文件后,一定要重启haproxy,后面也一样,不再进行说明
[root@haproxy ~]# systemctl restart haproxy.service#查看多进程信息
[root@haproxy ~]# pstree -p | grep haproxy|-haproxy(2360)-+-haproxy(2362)| `-haproxy(2363)
多线程的配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfggloballog 127.0.0.1 local2chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 4000user haproxygroup haproxydaemon# turn on stats unix socketstats socket /var/lib/haproxy/stats1 mode 600 level admin process 1stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2# utilize system-wide crypto-policiesnbthread 2 #启动多线程#未启动多线程时
[root@haproxy ~]# cat /proc/2363/status | grep -i thread #2363为haproxy子进程的id(通过查看多进程信息获取),-i表示不区分大小写进行匹配
Threads: 1
Speculation_Store_Bypass: thread vulnerable#开启多线程后,我们可以发现,线程数变为2
[root@haproxy ~]# cat /proc/2447/status | grep -i thread
Threads: 2
Speculation_Store_Bypass: thread vulnerable
代理配置段proxies
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg#defaults,用于配置默认参数,这些参数可以被用到frontend、backend、listen组件
defaultsmode http #默认的模式mode(tcp/http/health),tcp是4层,http是七层,health只会返回OKlog global #应用全局的日志配置option httplog #启用日志记录http请求,默认haproxy日志记录是不记录http请求日志的option dontlognull #启用该项,日志中将不会记录空连接。所谓空连接,就是在上游的负载均衡或者监控系统为了探测该服务是否存活可用时,需要定期的连接或者获取某一固定的组件或页面,或者探测扫描端口是否在**或开放等动作被称为空连接;官方文档中标注,如果该服务上游没有其他的负载均衡器的话,建议不要使用该参数,因为互联网上的恶意扫描或其它动作就不会被记录下来option http-server-close #每次请求完毕后主动关闭http通道option forwardforexcept 172.0.0.0/8 #如果服务器上的应用程序想记录发起请求的客户端的IP地址,需要再haproxy上配置该选项,这样haproxy会把客户端的IP信息发送给服务器,在http请求中添加"X-Forwarded-For"字段。启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IPoption redispatch #当使用了cookie时,haproxy将会将其请求的后端服务器的serverID插入到cookie中,以保证会话的session持久性;而此时,如果后端的服务器宕机了,但是客户端的cookie是不会刷新的,如果设置此参数,将会将客户的请求强制定向到另外一个后端server上,以保证服务的正常运行retries 3 #定义连接后端服务器的失败重连次数,连接失败次数超出此值后,将会将对应后端服务器标记为不可用timeout http-request 10s #http请求超时时间timeout queue 1m #一个请求在队列里的超时时间timeout connect 10s #连接超时时间timeout client 1m #客户端超时时间timeout server 1m #服务器超时时间timeout http-keep-alive 10s #http-keep-alive的超时时间timeout check 10s #检测超时时间maxconn 3000 #每个进程可用的最大连接数#listen,常常用于状态页面的监控,以及后端server检查,是frontend和backend的组合体
listen webclusterbind *:80mode httpbalance roundrobinredirect prefix http://www.baidu.comserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1server web_sorry 192.168.0.100:8080 backup#frontend,用于定义前端服务的配置。在frontend中配置acl规则,可将请求定向到相关的backend
frontend mainbind *:80 #设置所有IP的80端口为监听端口,即haproxy提供的web服务端口acl url_static path_beg -i /static /images /javascript /stylesheets #定义acl规则use_backend static if url_static #匹配了url_static规则的请求转发给名称为static的后端default_backend app #默认请求转发至名称为app的后端#backend,用来定义后端集群的配置,真实服务器,一个backend对应一个或者多个实体服务器
backend static #使用了静态动态分离(如果url_path匹配/static /images /javascript /stylesheets静态文件,则访问此后端)balance roundrobin #负载均衡算法server static 127.0.0.1:4331 check #静态文件部署在本机(也可以部署在其他机器或者squid缓存服务器)
server配置说明
#对于一条server配置来说
check #对指定real进行健康状态检查,如果不加此设置,默认不开启检查,只有check后面没有其它配置也可以开启检查功能#默认对应的后端服务器IP和端口,利用TCP连接进行周期性健康检查,注意必须指定端口才能进行检查
addr <IP> #可指定的健康状态监测IP,可以是专门的数据网段,减少业务网络的流量
port <num> #指定的健康状态监测端口
inter <num> #健康状态检查间隔时间 ,默认2000ms
fall <num> #后端服务器从线上转为线下的检查连续失效次数,默认为3次
rise <num> #后端服务器从下线回复上线2的检查连续有效次数,默认为2次
weight <num> #默认权重为1,最大为256,0表示不参与负载均衡,但仍接受持久连接
disabled #将后端服务器标记为不可用状态,即维护状态,除了持久模式,将不再接受连接
实验相关配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance roundrobinserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果:
haproxy的状态页
#在配置文件中添加以下部分
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen statsmode httpbind *:9999stats enablestats refresh 5 #浏览器自动刷新时间stats uri /status #使用浏览器访问http://192.168.0.100:9999/status,即可看到服务器状态stats auth niu:niu #用户认证,用户名:密码
编辑好配置文件后,重启服务,然后通过浏览器对http://192.168.0.100:9999/status进行访问,输入我们在配置文件中所指定的账号密码,即可看到haproxy的状态页面
socat命令
socat是Linux下的一个多功能网络工具,名字来由是socket cat,相当于netCAT的增强版。socat的主要特点就是在两个数据流之间建立双向通道,且支持众多协议、连接方式。比如IP、TCP、UDP、Socket文件等。我们可以使用socat命令对服务器动态权重以及其它状态进行调整。
socat命令的一些常用示例
#编辑配置文件
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
globalstats socket /var/lib/haproxy/stats mode 600 level admin#查看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: 2
Nbproc: 1
Process_num: 1
Pid: 2104
Uptime: 0d 0h00m26s
Uptime_sec: 26
……#查看集群状态
[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 192.168.0.10 2 0 1 1 80 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
2 webcluster 2 web2 192.168.0.20 2 0 1 1 80 6 3 7 6 0 0 0 - 80 - 0 0 - - 0
2 webcluster 3 web_sorry 192.168.0.100 2 0 1 1 80 1 0 2 0 0 0 0 - 8080 - 0 0 - - 0
5 static 1 static 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 4331 - 0 0 - - 0
6 app 1 app1 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 5001 - 0 0 - - 0
6 app 2 app2 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 5002 - 0 0 - - 0
6 app 3 app3 127.0.0.1 0 0 1 1 79 8 2 0 6 0 0 0 - 5003 - 0 0 - - 0
6 app 4 app4 127.0.0.1 0 0 1 1 78 8 2 0 6 0 0 0 - 5004 - 0 0 - - 0#查看集群的权重
[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
1 (initial 1)@临时修改权重
[root@haproxy ~]# echo "set weight webcluster/web1 2" | socat stdio /var/lib/haproxy/stats[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
2 (initial 1)#下线后端服务器
[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
如果开启多进程的话,我们在对进程的sock文件进行操作时其对进程的操作是随机的。
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
globalstats socket /var/lib/haproxy/stats1 mode 600 level admin process 1stats socket /var/lib/haproxy/stats2 mode 600 level admin process 2
这样每个进程都会有单独的socket文件夹进行单独的管理
[root@haproxy ~]# ll /var/lib/haproxy/
total 0
srw-------. 1 root root 0 Aug 11 09:58 stats
srw-------. 1 root root 0 Aug 11 10:10 stats1
srw-------. 1 root root 0 Aug 11 10:10 stats2
HAProxy的调度算法
HAProxy的调度算法主要分为静态算法、动态算法以及其他算法三大类。下面将分别详细介绍这三类算法及其优缺点。
静态算法
静态算法按照事先定义好的规则进行轮询调度,不关心后端服务器的当前负载、连接数和响应速度等,且无法实时修改权重(只能为0和1),只能重启HAProxy后生效。
static-rr(静态轮询)
基于权重的轮询调度,不支持运行时利用socat进行权重的动态调整(有效值为0和1),及后端服务器慢启动,其后端主机数量没有限制。
-
优点:
-
配置简单,易于理解和使用。
-
适用于后端服务器性能相近的场景。
-
-
缺点:
-
无法实时调整权重,灵活性较差。
-
在后端服务器性能差异较大的情况下,可能导致负载不均衡。
-
实验相关配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance static-rrserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
first(优先调度)
根据服务器在列表中的位置,自上而下进行调度,但是当第一台服务器的连接数达到上限时,新请求才会被分配到下一台服务器,因此会忽略服务器的权重设置。不支持用socat进行动态修改权重,有效值只有0和1
-
优点:
-
在某些特定场景下,如需要优先处理某些服务器的请求时,可以使用此算法。
-
-
缺点:
-
忽略服务器权重,可能导致负载不均衡。
-
灵活性较差,无法根据服务器实际负载情况进行调整。
-
实验相关配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance firstserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
动态算法
动态算法基于后端服务器的当前状态进行调度,能够实时调整权重,无需重启HAProxy服务。
roundrobin(加权轮询)
基于权重的轮询动态调度算法,支持权重的运行时调整,支持慢启动(新加的服务器会逐渐增加转发数),每个后端backend中最多支持4095个server。
-
优点:
-
灵活性高,可以根据服务器实际负载情况动态调整权重。
-
支持慢启动,有利于新加入服务器的平稳过渡。
-
-
缺点:
-
在高并发场景下,如果服务器性能差异较大,可能导致整体性能下降。
-
实验相关配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance roundrobinserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
使用socat命令进行动态权重的调整
[root@haproxy ~]# echo "set weight webcluster/web1 2" | socat stdio /var/lib/haproxy/stats[root@haproxy ~]# echo "get weight webcluster/web1" | socat stdio /var/lib/haproxy/stats
2 (initial 1)
再次测试
leastconn(最少连接数)
当前后端服务器连接最少的优先调度,支持加权的最少连接和动态调整权重。
-
优点:
-
能够有效减少服务器过载的可能性,优化资源利用。
-
适用于长连接会话场景,能够更好地平衡服务器负载。
-
-
缺点:
-
在某些情况下可能不够公平,如果某些请求处理时间非常长,可能导致这些服务器连接数持续增长。
-
其他算法
除了静态和动态算法外,HAProxy还支持一些基于特定规则的调度算法。
source(源地址哈希)
基于用户源地址hash并将请求转发到后端服务器,支持静态和动态hash方式(通过hash-type选项更改)。
-
优点:
-
能够实现会话保持,确保来自同一客户端的请求被转发到同一台服务器上。
-
-
缺点:
-
可能导致负载不均衡,特别是当客户端分布不均时。
-
不适用于移动IP场景。
-
实验相关配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance sourceserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
uri(URI哈希)
基于用户请求的URI做hash并将请求转发到后端指定服务器。
-
优点:
-
可以根据请求的资源进行负载均衡,有利于缓存和性能优化。
-
-
缺点:
-
配置复杂度较高,需要定义URI的哈希规则。
-
可能导致负载不均衡,特别是当某些资源的访问量非常大时。
-
实验相关配置
#取模法配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance uriserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
#一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance urihash-type consistentserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
访问不通的uri,可将用户同样的请求转发至相同的服务器
[root@webserver1 ~]# echo webserver1 192.168.0.10 > /var/www/html/index1.html
[root@webserver1 ~]# echo webserver1 192.168.0.10 > /var/www/html/index2.html
[root@webserver2 ~]# echo webserver2 192.168.0.20 > /var/www/html/index1.html
[root@webserver2 ~]# echo webserver2 192.168.0.20 > /var/www/html/index2.html
url_param(URL参数哈希)
对用户请求的URL中的params部分中的参数name(key)作hash计算,并由服务器总权重相除以后派发至某挑出的服务器。
-
优点:
-
可以根据URL中的特定参数进行负载均衡,有利于处理特定业务逻辑。
-
-
缺点:
-
配置复杂度较高,需要定义URL参数的哈希规则。
-
可能导致负载不均衡,特别是当某些参数的访问量非常大时。
-
实验相关配置
#取模法配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance url_param name,useridserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
#一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance url_param name,useridhash-type consistentserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
hdr(HTTP头部哈希)
针对用户每个HTTP头部(header)请求中的指定信息做hash,并由服务器总权重相除以后派发至某挑选出的服务器。
-
优点:
-
可以根据HTTP请求中的特定头部信息进行负载均衡,实现更细粒度的控制。
-
-
缺点:
-
配置复杂度较高,需要定义头部字段的哈希规则。
-
解析HTTP头部信息可能会增加一定的处理时间,影响系统性能。
-
实验相关配置
#一致性hash配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpbalance hdr(User-Agent)hash-type consistentserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1
测试效果
haproxy的高级功能配置
基于cookie的会话保持
cookie value:为当前server指定的cookie值,实现基于cookie的会话粘滞性,相对于基于source地址hash调度算法对客户端更精准,但同时也加大了haproxy的负载,目前此模式使用较少,已经被session共享服务器所代替。
配置选项说明
name #cookie的key名称,用于实现持久连接
insert #插入新的cookie,默认不插入cookie
indirect #如果客户端已经有cookie了,则不会再发送cookie信息
nocache #当client和haproxy之间有缓存服务器(如CDN)时,不允许中间缓存器缓存cookie,因为这会导致很多经过同一个CDN的请求都发送到同一台后端服务器上
实验配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpcookie WEBCOOKIE insert nocache indirectserver web1 192.168.0.10:80 cookie webserver1 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 cookie webserver2 check inter 2 fall 3 rise 5 weight 1
我们可以通过浏览器访问http://192.168.0.100来验证cookie信息
同样,我们通过命令行也是可以访问到cookie信息的
IP透传
web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。
四层IP透
未开启四层IP透传时
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode tcpbalance roundrobinserver web1 192.168.0.10:80 check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1#nginx配置
[root@webserver1 ~]# 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;……}
}
对后端服务器进行访问后,我们通过nginx日志可以看出,是无法看到真实的访问源地址的
开启四层IP透传后
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode tcpbalance roundrobinserver web1 192.168.0.10:80 send-proxy check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1#nginx配置
[root@webserver1 ~]# vim /etc/nginx/nginx.conf
http {log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$proxy_protocol_addr"''"$http_user_agent" "$http_x_forwarded_for"';……server {listen 80 proxy_protocol;listen [::]:80;server_name _;root /usr/share/nginx/html;……}
}
再次对后端服务器进行访问后,我们通过nginx日志可以看出,看到了真实的访问源地址
七层IP透传
当haproxy工作在七层的时候,也可以透传客户端真实IP至后端服务器
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen webclusterbind *:80mode httpoption forwardforbalance roundrobinserver web1 192.168.0.10:80 send-proxy check inter 2 fall 3 rise 5 weight 1server web2 192.168.0.20:80 check inter 2 fall 3 rise 5 weight 1#nginx配置
root@webserver1 ~]# vim /etc/nginx/nginx.conf
http {#proxy_add_x_forwarded_for,包括客户端IP和中间经过的所有代理的IPlog_format main '"$proxy_add_x_forwarded_for" - $remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';
}
测试效果
ACL
访问控制列表ACL(Access Control Lists),是一种基于包过滤的访问控制技术,它能够根据设定的条件对经过服务器传输的数据进行过滤(条件匹配),即对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃。
ACL配置选项说明
#用acl来定义或者声明一个acl
acl <aclname> <criterion> [flags] [operator] [<value>]#aclname acl的名称
#criterion acl的匹配规范
#flags acl的匹配模式
#operator acl的具体操作符
#value acl的操作对象类型
aclname名称
命名规范:可以使用大写字母A-Z,小写字母a-z,数字0-9,冒号:,点.,中横线-和下划线_,并且严格区分大小写,例如:my_acl和My_Acl就是两个完全不同的acl
criterion匹配规范
匹配规范 | 规范说明 |
---|---|
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也会被匹配到 |
flags匹配模式
-i 不区分大小写
-m 使用指定的正则表达式
-n 不做DNS解析
-u 禁止acl重名,否则多个同名acl匹配或关系
多个acl的组合调用方式
多个acl的逻辑处理
与:隐式(默认)使用
或:使用“or”或者“||”表示
非:使用“!”表示
ACL相关实验
由于我们以下实验是通过Windows来进行验证的,所以我们现在C:\Windows\System32\drivers\etc\hosts文件中编写访问地址的域名解析
ACL域名匹配
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webclusterbind *:80mode httpacl domain hdr_dom(host) -i www.super.orguse_backend webcluster-host if domaindefault_backend default-hostbackend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5
测试效果
ACL基于源IP或子网调度访问
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webclusterbind *:80mode httpacl ctrl_ip src 192.168.0.100use_backend webcluster-host if ctrl_ip default_backend default-hostbackend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5
测试效果
ACL基于源地址的访问控制
拒绝指定IP或者IP范围访问
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webclusterbind *:80mode httpacl ctrl_ip src 172.25.254.0/24http-request deny if ctrl_ipuse_backend webcluster-host if ctrl_ip default_backend default-hostbackend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5
测试效果
ACL匹配浏览器类型
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webclusterbind *:80mode http#拒绝curl和wget的访问acl badwebbrowers hdr_sub(User-Agent) -i curl wgethttp-request deny if badwebbrowersdefault_backend default-hostbackend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5
测试效果
ACL基于文件后缀名实现动静分离
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webclusterbind *:80mode httpacl static path_end -i .html .jpg .png .css .jsacl php path_end -i .phpuse_backend webcluster-host if phpdefault_backend default-hostbackend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5#我们还需要再webserver1上安装php,并配置其访问界面
[root@webserver1 ~]# yum install php -y
[root@webserver1 ~]# cat /var/www/html/index.php
<?phpphpinfo();
?>
测试效果
php动态
html静态
ACL匹配访问路径实现动静分离
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webclusterbind *:80mode httpacl static path_end -i .html .jpg .png .css .jsacl php path_end -i .phpuse_backend webcluster-host if phpdefault_backend default-hostbackend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5#webserver访问配置
[root@webserver1 ~]# mkdir /var/www/html/static
[root@webserver1 ~]# mkdir /var/www/html/php
[root@webserver1 ~]# echo static - 192.168.0.10 > /var/www/html/static/index.html
[root@webserver1 ~]# echo php - 192.168.0.10 > /var/www/html/php/index.html[root@webserver2 ~]# mkdir /var/www/html/static
[root@webserver2 ~]# mkdir /var/www/html/php
[root@webserver2 ~]# echo static - 192.168.0.20 > /var/www/html/static/index.html
[root@webserver2 ~]# echo php - 192.168.0.20 > /var/www/html/php/index.html
测试效果
自定义HAProxy错误页面
对指定的报错进行重定向,使用errorfile和errorloc指令的两种方式,可以实现自定义各种错误页面
基于自定义的错误页面配置
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaultsmode httplog globaloption httplogoption dontlognulloption http-server-closeoption forwardfor except 127.0.0.0/8option redispatchretries 3timeout http-request 10stimeout queue 1mtimeout connect 10stimeout client 1mtimeout server 1mtimeout http-keep-alive 10stimeout check 10smaxconn 3000errorfile 503 /etc/haproxy/errorpage/503.http#创建错误文件
[root@haproxy ~]# mkdir /etc/haproxy/errorpage/
[root@haproxy errorpage]# cat 503.http
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8<html><body><h1>哈哈</h1>
hhhhhhhhhhhhhhhhh
</body></html>#关闭webserver的web服务
[root@webserver1 ~]# systemctl stop httpd.service
测试效果
基于http重定向错误页面配置
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
defaultsmode httplog globaloption httplogoption dontlognulloption http-server-closeoption forwardfor except 127.0.0.0/8option redispatchretries 3timeout http-request 10stimeout queue 1mtimeout connect 10stimeout client 1mtimeout server 1mtimeout http-keep-alive 10stimeout check 10smaxconn 3000#我们通过503重定向到百度的URLerrorloc 503 https://www.baidu.com#关闭webserver的web服务
[root@webserver1 ~]# systemctl stop httpd.service
测试效果
我们访问192.168.0.100,即重定向到百度页面
HAProxy四层负载
主要针对于除http外的tcp协议协议应用服务访问的应用场景,例如MySQL、Redis、Memcache、RabbitMQ等
对于MySQL服务实现四层负载
#haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
listen dbserverbind *:3306mode tcp #注意:这里使用的是四层tcp模式balance roundrobinserver db1 192.168.0.10:3306 check inter 2 fall 2 rise 5server db2 192.168.0.20:3306 check inter 2 fall 2 rise 5#在webserver上配置mariadb服务
[root@webserver1 ~]# yum install mariadb-server -y
[root@webserver2 ~]# yum install mariadb-server -y
[root@webserver1 ~]# cat /etc/my.cnf.d/mariadb-server.cnf | grep server-id
server-id=1
[root@webserver2 ~]# cat /etc/my.cnf.d/mariadb-server.cnf | grep server-id
server-id=2
#启动mariadb服务
[root@webserver1 ~]# systemctl start mariadb.service
[root@webserver2 ~]# systemctl start mariadb.service
#我们通过命令行创建mysql用户,并对其进行授权
[root@webserver1 ~]# mysql -e "grant all on *.* to niu@'%' identified by 'niu'"
[root@webserver2 ~]# mysql -e "grant all on *.* to niu@'%' identified by 'niu'"#在测试机上也要安装mariadb服务,这里我们使用haproxy主机进行测试
[root@haproxy ~]# yum install mariadb -y
[root@haproxy ~]# systemctl start mariadb
测试效果
HAProxy的https实现
HAProxy可以实现https的证书安全,从用户到haproxy为https,从haproxy到后端服务器为http通信,但基于性能考虑,生产中证书都是在后端服务器上实现的
证书的制作
[root@haproxy ~]# mkdir /etc/haproxy/certs/
[root@haproxy ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /etc/haproxy/certs/super.org.key -x509 -days 365 -out /etc/haproxy/certs/super.org.crt
[root@haproxy certs]# cat super.org.key super.org.crt > super.org.pem
haproxy配置
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster-httpsbind *:443 ssl crt /etc/haproxy/certs/super.org.pemmode httpuse_backend webcluster-host
frontend webclusterbind *:80mode httpredirect scheme https if !{ ssl_fc } #进行全站加密backend webcluster-hostmode httpserver web1 192.168.0.10:80 check inter 2 fall 2 rise 5backend default-hostmode httpserver web2 192.168.0.20:80 check inter 2 fall 2 rise 5
测试效果
命令行测试
网页测试