安装
haproxy简介
haproxy 是一个开源的、高性能的、基于TCP和HTTP应用的负载均衡软件
haproxy 优点
- 可靠性和稳定性非常好,可以与硬件的F5相媲美
- 最高可以同时维护40000–50000个并发连接,单位时间内处理的最大请求数为20000个,最大数据处理能力可达10Gbps
- 支持多于8种负载均衡算法 ,同时也支持session保持
- 支持虚拟主机功能
- 从haproxy 1.3版本后开始支持连接拒绝、全透明代理等功能
- haproxy 拥有一个功能强大的服务器状态监控页面
- haproxy 拥有功能强大的ACL支持
下载
网址:https://src.fedoraproject.org/repo/pkgs/haproxy/
安装依赖
yum install -y openssl openssl-devel systemd-devel.x86_64 \
pcre pcre-devel gcc gcc-c++ make zlib-devel zlib glibc glibc-devel
解包编译
groupadd -r haproxy
useradd -g haproxy -M -s /sbin/nologin haproxy
tar -zxf haproxy-2.0.13.tar.gz -C /usr/local/src/
cd /usr/local/src/haproxy-2.0.13
make ARCH=x86_64 TARGET=linux-glibc USE_OPENSSL=1 USE_ZLIB=1 \
USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy
#开启https
#USE_OPENSSL=1
#指定为systemd模式
#USE_SYSTEMD=1
#可指定安装目录
#PREFIX=/usr/local/haproxy
#默认为/usr/local/sbin/
cp haproxy /usr/sbin/
mkdir /usr/local/haproxy/{etc,logs}
开启haproxy日志
在配置前,rsyslog日志的level: local0~local7 16~23保留为本地使用
emerg 0 系统不可用
alert 1 必须马上采取行动的事件
crit 2 关键的事件
err 3 错误事件
warning 4 警告事件
notice 5 普通但重要的事件
info 6 有用的信息
debug 7 调试信息
vim /etc/rsyslog.d/haproxy.conf
# Provides UDP syslog reception 启动udp,启动端口后将作为服务器工作
$ModLoad imudp
#默认端口是514
$UDPServerRun 514
#Provides TCP syslog reception 启动tcp监听端口
$ModLoad imtcp
$InputTCPServerRun 515
local2.* /usr/local/haproxy/logs/haproxy.log
以上修改haproxy日志会同时写入到/usr/local/haproxy/logs/haproxy.log和/var/log/messages两个文件里,由于haproxy日志量很多所以只让其写入到/usr/local/haproxy/logs/haproxy.log文件需要修改/etc/rsyslog.conf文件这个配置:
*.info;mail.none;authpriv.none;cron.none /var/log/messages
修改为:
*.info;mail.none;authpriv.none;cron.none /var/log/messages
vim /etc/sysconfig/rsyslog
SYSLOGD_OPTIONS="-r -m 0 -c 2"
#-c 2 使用兼容模式,默认是 -c 5
#-r 开启远程日志
#-m 0 标记时间戳。单位是分钟,为0时,表示禁用该功能
重启rsyslog
systemctl restart rsyslog
加入service
vim /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/etc/haproxy.cfg -c -q
ExecStart=/usr/local/haproxy/sbin/haproxy -Ws -f /usr/local/haproxy/etc/haproxy.cfg -p /usr/local/haproxy/etc/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target
命令
检查配置文件语法
haproxy -c -f /usr/local/haproxy/etc/haproxy.cfg
后台模式启动,以systemd管理的daemon模式启动
haproxy -D -f /usr/local/haproxy/etc/haproxy.cfg [-p /usr/local/haproxy/etc/haproxy.pid]
haproxy -Ds -f /usr/local/haproxy/etc/haproxy.cfg [-p /usr/local/haproxy/etc/haproxy.pid]
启动调试功能,将显示所有连接和处理信息在屏幕
haproxy -d -f /usr/local/haproxy/etc/haproxy.cfg
重启:需要使用st选项指定pid
haproxy -f /usr/local/haproxy/etc/haproxy.cfg [-p /usr/local/haproxy/etc/haproxy.pid] -st `cat /usr/local/haproxy/etc/haproxy.pid`
reload:需要使用sf选项指定pid
haproxy -f /usr/local/haproxy/etc/haproxy.cfg [-p /usr/local/haproxy/etc/haproxy.pid] -sf `cat /usr/local/haproxy/etc/haproxy.pid`
显示haproxy编译和启动信息
haproxy -vv
配置详解
参考链接:https://blog.51cto.com/u_12244079/2125384
https://blog.51cto.com/u_13701082/2341826
https://blog.csdn.net/bbwangj/article/details/80337994 详细解释
https://www.cnblogs.com/qiuhom-1874/p/12789175.html
基本配置
vim /usr/local/haproxy/etc/haproxy.cfg
global
log 127.0.0.1 local2 info
#chroot /usr/local/haproxy #工作目录
pidfile /usr/local/haproxy/etc/haproxy.pid
maxconn 4000
nbproc 1
#cpu-map 1 0 一个进程不需要设置
user haproxy
group haproxy
daemon
defaults
log global
option dontlognull
timeout connect 10s
timeout client 10s
timeout server 10s
timeout check 10s
maxconn 60000
retries 3
listen admin_stats
bind 0.0.0.0:8089
stats enable
mode http
log global
stats uri /stats
stats realm Haproxy\ Statistics
stats auth admin:admin
stats hide-version
stats admin if TRUE
stats refresh 30s
frontend www
bind *:8088
mode http
option httplog
option forwardfor
option httpclose
log global
compression algo gzip
compression type text/html text/plain
default_backend webserver
backend webserver
mode http
option forwardfor
option httpclose
option redispatch
option abortonclose
balance roundrobin
cookie SERVERID insert nocache
option httpchk GET /index.html
server web1 192.168.8.30:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 192.168.8.30:81 cookie server2 weight 6 check inter 2000 rise 2 fall 3
errorfile 403 /usr/local/haproxy/html/error403.html
配置项说明
根据功能用途不同,其配置文件主要由五个部分组成,分别为global部分,defaults部分,frontend部分,backend部分,listen部分
- global部分
用于设置全局配置参数,属于进程级的配置,通常与操作系统配置相关
- defaults部分
默认参数的配置部分。在些部分设置的参数,默认会自动引用到下面的frontend, backend和listen部分
- frontend部分
用于设置接收用户请求的前端虚拟节点。frontend可以根据ACL规则直接指定要使用的后端backend
- backend部分
用于设置集群后端服务集群的配置,也就是用来添加一组真实服务器,以处理前端用户的请求
- listen部分
此部分是frontend和backend部分的结合体
global部分
1.log
log 127.0.0.1 local0 info
#或者log 127.0.0.1 local2
配置全局日志记录,local0为日志设备,info为输出的日志级别。其中日志级别有err, warning, info, debug 4种,表示使用本地(127.0.0.1)机器上的rsyslog服务中的local0设备记录日志,等级为info的日志配置syslog以接受网络日志事件。这是通过将’-r’选项添加到/etc/sysconfig/syslog中的SYSLOGD_OPTIONS选项来实现的
安装时开启haproxy日志步骤配置local2事件将日志输出到/var/log/haproxy.log文件。将以下行添加到/etc/sysconfig/syslog
local2.*/var/log/haproxy.log文件log [address] [facility] [level [minlevel]
为每个实例启用事件和流量日志,因此可用于所有区段。每个实例最多可以指定两个log参数,不过,如果使用了“log global”且”global”段已经定了两个log参数时,多余了log参数将被忽略。
- global:当前实例的日志系统参数同”global”段中的定义时,将使用此格式;每个实例仅能定义一次“log global”语句,且其没有任何额外参数;
- [address]:定义日志发往的位置,格式之一可以为<IPv4_address:PORT>,其中的port为UDP协议端口,默认为514;格式之二为Unix套接字文件路径,但需要留心chroot应用及用户的读写权限;
- [facility]:可以为syslog系统的标准facility之一
- [level]:定义日志级别,即输出信息过滤器,默认为所有信息;指定级别时,所有等于或高于此级别的日志信息将会被发送。
2.chroot
- chroot /usr/local/haproxy
设置工作目录
3.pidfile
- pidfile /usr/local/haproxy/etc/haproxy.pid
设置haproxy进程文件
4.user/group
- user haproxy #运行的程序用户
group haproxy #运行的程序用户组
5.maxconn
- maxconn 4096
设置每个HAProxy进程可接受的最大并发连接数;其不能用于backend区段
此最大值不能超出“global”段中的定义;haproxy会为每个连接维持两个缓冲,每个缓冲的大小为8KB,再加上其它的数据,每个连接将大约占用17KB的内存(RAM)空间。这意味着经过适当优化后,有着1GB的可用内存(RAM)空间时将能维护40000-50000并发连接
6.nbproc
- nbproc 4
设置HAProxy启动时可创建的进程数,此参数要求将HAProxy运行模式设置为daemon,默认只启动一个进程;建议该值设置时小于CPU核数
7.cpu-map
- cpu-map 1 0
cpu-map 2 1
cpu-map 3 2
cpu-map 4 3
该指令用于绑定haproxy对应cup核心;有点类似nginx里的worker_cpu_affinity参数的意义;
以上配置表示指定haproxy的进程数为4个,第一个进程绑定到0号核心上,第二个进程绑定到1号核心上,依次类推
8.daemon
- daemon
设置HAProxy进程进入后台运行,这是推荐的运行模式
defaults部分
1.mode
- mode http
设置HAProxy实例默认的运行模式,有tcp, http, health三个可选值,tcp是四层,http是七层,health只会返回OK,若是混合模式则mode不需要设置- tcp模式:
在此模式下,客户端和服务器端间将建立一个全双工的连接,不会对七层报文做任何检查,为默认的模式;经常用于SSL, SSH, SMTP等应用。- http模式
在此模式下,客户端请求在转发至后端服务器前将会被深度分析,所有不与RFC格式兼容的请求都会被拒绝- health模式
目前已经被废除
2.log
- log global
定义日志,采用全局定义
3.option dontlognull
- option dontlognull
不记录健康检查的日志信息
4.option httpclose
- option httpclose
此选项表示客户端和服务端完成一次连接请求后,HAProxy将主动关闭此TCP连接。
5.option httplog
- option httplog
默认情况下,HAProxy日志是不记录HTTP请求的,此选项的作用是启用日志记录HTTP请求;如果是混合模式,此处还需要加上tcpclog
6.option forwardfor
- option forwardfor #后端服务器可以从Http Header中获得客户端真实的IP
格式:option forwardfor expect [ network ] header [ name ] [ if-none ]
允许在发往服务器的请求首部中插入“X-Forwarded-For”首部。
[network]:若指定该参数,源地址匹配该参数的,此网络中的请求都禁用此功能。
[name]:自定义首部,若指定该参数,如“X-Client”来替代“X-Forwarded-For”。该参数就会代替X-Forwarded-For中的值。
[if-none]:若指定该参数,表示当首部不存在时,才将其添加至请求报文中。
HAProxy工作于反向代理模式时,传递到服务端的请求中客户端IP都为HAProxy主机的地址不是真正client的地址,这会使服务器端的日志记录不了真正的请求clientIP,此选项“X-Forwarded-For”首部就可以解决该问题。HAProxy可以向每个发往服务端的请求上添加此首部,并以client IP为其值。
HAProxy工作于隧道模式时,haproxy仅检查每一个连接的第一个请求,因此,仅第一个请求报文被附加此首部。若想为每一个请求都附加此首部,请确保同时使用“option httpclose”,“option forceclose”,“option http-server-close”这些选项。
例:option forwardfor except 127.0.0.1
7.option redispatch
- option redispatch
此参数用于cookie保持的环境中。在默认情况下,HAProxy会将其请求的后端服务器的serverID插入cookie中,以保证会话的session持久性。而如果后端服务器出现故障,客户端的cookie是不会刷新的,这就会造成无法访问。此时,如果设置了此参数,就会将客户的请求强制定向到另外一台健康的后端服务器上,以保证服务正常
8.balance roundrobin
- balance roundrobin
设置默认负载均衡算法,轮询方式- HAProxy支持的负载均衡算法:
– roundrobin
基于权重进行轮叫调度的算法
– static-rr
基于权重进行轮叫调度的算法,不过此算法为静态算法,在运行时调整其服务器权重不会生效
– source
基于请求源IP的算法。此算法先对请求的源IP进行HASH运算,然后将结果与后端服务器的权重总数相除后转发至某台匹配的后端服务器。这种方式可以使同一个客户端IP的请求始终转发到某特定的后端服务器
– leastconn
此算法会将新的连接请求转发到具有最少连接数目的后端服务器。在会话时间较长的场景中推荐使用此算法 ,例如数据库负载均衡
– uri
此算法会对部分或整个URI进行HASH运算,再经过与服务器的总权重相除,最后转发到某台匹配的后端服务器上
– uri_param
此算法会根据URL路径中的参数进行转发,这样可保证在后端真实服务器数据不变时,同一个用户的请求始终分发到同一台机器上
– hdr
此算法根据HTTP头进行转发,如果指定的HTTP头名称不存在,则使用roundrobin算法 进行策略转发
9.timeout connect
- timeout connect 10s
设置成功连接到一台服务器的最长等待时间,默认单位是毫秒,但也可以使用其他时间单位作后缀
10.timeout client
- timeout client 10s
设置连接客户端发送数据时最长等待时间,默认单位是毫秒,但也可以使用其他时间单位作后缀
11.timeout server
- timeout server 10s
设置服务器端回应客户端数据发送的最长等待时间,默认单位是毫秒,但也可以使用其他时间单位作后缀
12.timeout http-keep-alive
- timeout http-keep-alive 10s
定义保持连接的超时时长,默认单位是毫秒,但也可以使用其他时间单位作后缀
13.timeout queue
- timeout queue 1m
设置等待最大时长
14.timeout check
- timeout check 10s
设置对后端服务器的检测超时时间,默认单位是毫秒,但也可以使用其他时间单位作后缀
15.retries
- retries 3
设置连接后端服务器的失败重试次数,如果连接失败的次数超过该数值,HAProxy会将对应的后端服务器标记为不可用
frontend部分
1.frontend
- frontend www
定义了一个名为"www"的前端虚拟节点- bind
bind *:80
此选项用于定义一个或者几个监听的套接字,只能在frontend和listen中定义
bind [address]:[port_range] [, …]
bind [address]:[port_range] [, …] interface [interface]
1.mode http
解释见:defaults部分 1
2.option httplog
解释见:defaults部分 5
3.option forwardfor
解释见:defaults部分 6
4.option httpclose
解释见:defaults部分 4
5.log global
解释见:global部分 1
6.compression algo gzip
- compression algo gzip
compression type text/html text/plain
haproxy启用压缩功能同nginx的原理类似,在nginx里我们需要明确配置启动压缩功能,支持那些压缩算法,最小压缩大小以及压缩级别等等;在haproxy中要启用压缩功能我们只需要指定压缩算法,以及压缩资源类型即可;指定压缩算法是gzip,压缩资源类型为文本类型资源text/html text/plain
7.default_backend
- default_backend servers
在没有匹配的”use_backend”规则时指定后端默认的服务器池,不可应用于backend区段。
backend部分
1.backend
- backend servers
用于定义一个名称为servers的后端服务器组,根据需要可以定义多个
2.mode http
解释见:defaults部分 1
3.option redispatch
- option redispatch
该参数用于cookie保持的环境中。在默认情况下,HAProxy会将其请求的后端服务器的serverID插入cookie中,以保证会话的session持久性。而如果后端服务器出现故障,客户端的cookie是不会刷新的,这就会造成无法访问。此时,如果设置了此参数,就会将客户的请求强制定向到另外一台健康的后端服务器上,以保证服务正常
4.option abortonclose
- option abortonclose
该参数可以在服务器负载很高的情况下,自动结束当前队列中处理时间比较长的连接
5.balance
- balance roundrobin
指定负载均衡算法
解释见:defaults部分 8
6.cookie SERVERID
cookie SERVERID insert nocache
表示在后端服务器响应报文首部中添加一个cookie的名称为SERVERID,而对应cookie的值就来源于后面server段中的cookie的值;nocache表示该cookie不被共有缓存系统缓存;
7.option httpchk GET /index.php
- option httpchk GET /index.html
心跳检测,此选项表示启用HTTP的服务状态检测功能格式:
option httpchk [method] [uri] [version]method
表示HTTP请求的方式,常用的有OPTIONS,HEAD, GET几种方式。一般的健康检查可以采用HEAD方式进行,而不是采用GET方式,这是因为HEAD方式没有数据返回,仅检查响应报文的状态码是不是200.因此相对于GET, HEAD的方式更简单、更快
uri
表示要检测的URL地址
version
指定心跳检测时的HTTP的版本号
8.server
server web1 10.1.1.1:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 10.1.1.2:80 cookie server2 weight 6 check inter 2000 rise 2 fall 3
server用于定义多台后端真实服务器,不能用于frontend和listen段
格式如下:
server [name] [address]:[port] [param*]
–
name
为后端真实服务器指定一个内部名称,随便定义一个即可
–
address:port
指定后端服务器的IP地址及端口
–
[param]参数
常用的参数:
check 表示启用对此后端服务器执行健康状态检查
inter 设置健康状态检查的时间间隔,单位是毫秒
rise 检查多少次认为服务器可用
fall 检查多少次认为服务器不可用
weight 设置服务器的权重,默认为1, 最大为256。 设置为0表示不参与负载均衡
backup 设置备份服务器,用于所有后端服务器全部不可用时
cookie 为指定的后端服务器设置cookie值,此处指定的值将在请求入站时被检查,第一次为此值挑选的后端服务器将在后续的请求中一直被选中,其目的在于实现持久连接的功能
listen部分
监控页面配置
1.listen
- listen admin_stats
为haproxy访问状态监控页面配置,取名为admin_stats
2.bind
- bind 0.0.0.0:8089
监听端口
bind [address]:[port_range] [, …]
bind [address]:[port_range] [, …] interface [interface]
该指令仅能用于frontend和listen区段,用于定义一个或几个监听的套接字
3.stats enable
- stats enable
启用监听端口
4.mode
- mode http
http的7层模式
5.stats refresh
- stats refresh 30s
页面自动刷新时间30s
6.stats realm
- stats realm Welcome login
设置登录监控页面时,密码框上的提示信息
7.stats auth
- stats auth admin:admin
监控页面的用户和密码admin,用户密码之间用冒号隔开,可以设置多个,每行一个
8.stats uri
- stats uri /stats
stats uri :自定义stats page uri,默认值:/haproxy?stats
设置HAProxy监控页面访问的URI路径,即http://ip/stats访问监控页面
9.stats hide-version
- stats hide-version
隐藏统计页面上HAProxy的版本信息
10.stats admin
- stats admin if TRUE
设置此选项,可在监控页面上控制启用、禁用后端服务器,仅在1.4.9版本以后生效
基于cookie会话保持
什么叫cookie及原理
原文链接:https://www.cnblogs.com/qiuhom-1874/p/12776261.html
首先我们要清楚什么叫cookie?它的主要作用是干什么的?众所周知http是无状态的,所谓无状态就是前一秒客户端访问服务端,后一秒同一客户端访问服务端,服务端是无法判断是不是同一客户端;就相当于服务端没有任何能力记住客户端;这样一来就存在一个问题;如果是一需要验证的网站,如果服务端不能辨别客户端身份,这意味着它不能够辨认到底是哪个客户端登录了,这样一来用户每刷新一次网页,服务端就会要求客户端重新登录;这很显然不是正常的逻辑;为了解决这样的问题,服务端每当客户端登录的时候,就会检查请求报文中是否携带cookie信息;如果没有携带cookie服务端在响应客户端的时候就会在响应报文中添加一个set-cookie的首部,意思是告诉客户端,这是你的cookie;客户端拿到服务端的响应的同时,它会自动的把服务端发来的cookie保存到一个特定的地方,下次客户端再次访问服务端的时候,就会把上次服务器发送过来的cookie信息带上去访问服务器;这样一来服务端收到客户端的请求,一看请求报文中的cookie信息,服务端就知道这个请求是那个用户发送过来的;这样一来服务端就通过cookie来辨认客户端了;这也是cookie的主要作用;通常情况下保存在客户端的叫cookie;在服务端一侧类似cookie的功能的东西我们叫session;通常两者通过某些信息来对应的;比如在客户端cookie信息里记录了服务端上的session的号码;当客户端再次访问服务端时,就会把cookie中的信息发送给服务端;服务端收到客户端发送过来的cookie就会去找对应的session;从而实现了,服务端知道对应客户端上次的操作;cookie是有时限性的;通常在有效的时间内去访问服务端,服务端都能够准确的辨认客户端;过期以后,服务端会重新给客户端发送cookie信息;
从上面的描述,我们不难理解,cookie就是用来让服务端辨识客户端的一种机制;而对于haproxy来讲,基于cookie来做会话保持的原理就是通过对后端服务器响应报文中的cookie信息中添加(或覆盖的方式)一个键值对,在客户端下次访问时,检查对应cookie首部的信息,从而让haproxy能够判断把该请求调度在那个后端服务器上;通常我们会在server上设置一个cookie的值,在listen或backend中设置一个cookie的键,明确说明以怎样的方式设置cookie的键;通过listen或backend中设置的cookie的键结合server后面的cookie的值组成的cookie信息,从而实现不同的cookie信息调度到不同的server上去;
解释见backend部分 6
cookie SERVERID insert nocache
server web1 192.168.8.30:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 192.168.8.30:81 cookie server2 weight 6 check inter 2000 rise 2 fall 3
访问结果,分别利用cookie信息来访问。
当cookie值是SERVERID=server1时
[root@localhost etc]# curl --cookie "SERVERID=server1" 192.168.8.30:8088
80
[root@localhost etc]# curl --cookie "SERVERID=server1" 192.168.8.30:8088
80
当cookie值是SERVERID=server2时
[root@localhost etc]# curl --cookie "SERVERID=server2" 192.168.8.30:8088
81
[root@localhost etc]# curl --cookie "SERVERID=server2" 192.168.8.30:8088
81
修改报文首部
参考链接:https://www.cnblogs.com/qiuhom-1874/p/12789175.html
haproxy可以修改报文首部,haproxy可以让客户端看到某些首部,也可以让客户端看不到某些首部。
backend webserver
mode http
option forwardfor
option httpclose
option redispatch
option abortonclose
balance roundrobin
cookie SERVERID insert nocache
option httpchk GET /index.html
#添加请求首部via: haproxy haproxy是值
reqadd via:\ haproxy
#删除请求报文中的User-Agent首部
#reqdel User-Agent.* rspidel表示删除不区分字符大小写匹配到的响应首部,rspdel是区分字符大小写的
reqidel user-agent.*
#添加响应报文x-via: haproxy
rspadd x-via:\ haproxy-2.0.13
#删除响应报文中server首部
#rspdel Server.*
rspidel server.*
server web1 192.168.8.30:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 192.168.8.30:81 cookie server2 weight 6 check inter 2000 rise 2 fall 3
定义错误页面
参考链接:https://www.cnblogs.com/qiuhom-1874/p/12797913.html
haproxy通常作为代理服务器,对于404错误页面通常不会由haproxy自己指定,因为haproxy作为代理服务器对于后端server的资源是否能够找到,它不知道;即便我们在配置中指定了404错误对应的响应页面,在haproxy重启后是不会生效的。
haproxy指定错误页面的方式两种:第一种是指定本地文件系统文件作为对应错误状态码的错误页;第二种是指定对应错误状态码跳转的URL。
errorfile
:指定对应错误状态码对应文件系统上的文件作为该状态码响应的页面
自定义403错误页面
backend webserver
mode http
option forwardfor
option httpclose
option redispatch
option abortonclose
balance roundrobin
cookie SERVERID insert nocache
option httpchk GET /index.html
server web1 192.168.8.30:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 192.168.8.30:81 cookie server2 weight 6 check inter 2000 rise 2 fall 3
errorfile 403 /usr/local/haproxy/html/error403.html
errorloc 403 http://nginx.org/aaa.html
403错误页面跳转
backend webserver
mode http
option forwardfor
option httpclose
option redispatch
option abortonclose
balance roundrobin
cookie SERVERID insert nocache
option httpchk GET /index.html
server web1 192.168.8.30:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 192.168.8.30:81 cookie server2 weight 6 check inter 2000 rise 2 fall 3
errorloc 403 http://nginx.org/aaa.html
#表示对于403错误就跳转到指定http://nginx.org/aaa.html
errorloc303 403 http://nginx.org
errorloc和errorloc302都是同样的效果,都是以临时重定向到指定的url上;这里还需要注意一点,这两种方式都是跳转前请求的方法是什么,跳转对应url也是同样的方法;这样一来对于其他非GET方法请求出现403错误码的时候,对应的错误页就无法正常处理(通常只允许GET方法去请求别的URL);比如跳转前用PUT方法,出现错误403后,按照上面的配置,对应指定的错误页的url也会用PUT方法去请求;为了解决这样的问题,我们这里需要用到errorloc303来指定;该指令的意思是返回303响应码;如果请求前非GET方法,而出现对应错误后,用GET方法去请求对应错误状态码指定的URL.
非GET方法错误页面重定向到其他URL上
backend webserver
mode http
option forwardfor
option httpclose
option redispatch
option abortonclose
balance roundrobin
cookie SERVERID insert nocache
option httpchk GET /index.html
server web1 192.168.8.30:80 cookie server1 weight 6 check inter 2000 rise 2 fall 3
server web2 192.168.8.30:81 cookie server2 weight 6 check inter 2000 rise 2 fall 3
errorloc303 403 http://nginx.org
#以上配置就表示如果我们用非GET方法请求某资源,出现403错误后,返回303状态码;303表示请求重定向页面的方法要总是使用GET方法
haproxy的日志
参考链接:https://www.cnblogs.com/qiuhom-1874/p/12797913.html
log:启用事件和流量的每个实例日志记录。
no log:关闭日志记录;
log global:调用全局配置段中日志的定义;
log<address> [len <length>] <facility> [<level> [<minlevel>]]:
定义一个用于接收haproxy日志的rsyslog服务器地址,facility;默认是发往本机的rsyslog服务器上的local2上.
log-format <string>:设定日志格式
capture cookie <name> len <length> #捕获请求和响应报文中的 cookie并记录日志
capture request header <name> len <length> #捕获请求报文中指定的首部内容和长度并记录日志
capture response header <name> len <length> #捕获响应报文中指定的内容和长度首部并记录日志
自定义日志格式
frontend www
bind *:8088
mode http
option httplog #开启记录httplog日志格式选项
option forwardfor
option httpclose
log global
compression algo gzip
compression type text/html text/plain
default_backend webserver
capture request header Host len 64
capture request header User-Agent len 128
capture request header X-Forwarded-For len 100
capture request header Referer len 200
capture response header Server len 40
capture response header Server-ID len 40
#capture捕获信息
log-format %ci:%cp\ %si:%sp\ %B\ %U\ %ST\ %r\ %b\ %f\ %bi\ %hrl\ %hsl\
#log-format定义日志需显示内容(变量)
#利用capture捕获信息,log-format定义变量
日志格式参照表
+---+------+-----------------------------------------------+-------------+
| R | var | field name (8.2.2 and 8.2.3 for description) | type |
+---+------+-----------------------------------------------+-------------+
| | %o | special variable, apply flags on all next var | |
+---+------+-----------------------------------------------+-------------+
| | %B | bytes_read (from server to client) | numeric |
| H | %CC | captured_request_cookie | string |
| H | %CS | captured_response_cookie | string |
| | %H | hostname | string |
| H | %HM | HTTP method (ex: POST) | string |
| H | %HP | HTTP request URI without query string (path) | string |
| H | %HQ | HTTP request URI query string (ex: ?bar=baz) | string |
| H | %HU | HTTP request URI (ex: /foo?bar=baz) | string |
| H | %HV | HTTP version (ex: HTTP/1.0) | string |
| | %ID | unique-id | string |
| | %ST | status_code | numeric |
| | %T | gmt_date_time | date |
| | %Tc | Tc | numeric |
| | %Td | Td = Tt - (Tq + Tw + Tc + Tr) | numeric |
| | %Tl | local_date_time | date |
| H | %Tq | Tq | numeric |
| H | %Tr | Tr | numeric |
| | %Ts | timestamp | numeric |
| | %Tt | Tt | numeric |
| | %Tw | Tw | numeric |
| | %U | bytes_uploaded (from client to server) | numeric |
| | %ac | actconn | numeric |
| | %b | backend_name | string |
| | %bc | beconn (backend concurrent connections) | numeric |
| | %bi | backend_source_ip (connecting address) | IP |
| | %bp | backend_source_port (connecting address) | numeric |
| | %bq | backend_queue | numeric |
| | %ci | client_ip (accepted address) | IP |
| | %cp | client_port (accepted address) | numeric |
| | %f | frontend_name | string |
| | %fc | feconn (frontend concurrent connections) | numeric |
| | %fi | frontend_ip (accepting address) | IP |
| | %fp | frontend_port (accepting address) | numeric |
| | %ft | frontend_name_transport ('~' suffix for SSL) | string |
| | %lc | frontend_log_counter | numeric |
| | %hr | captured_request_headers default style | string |
| | %hrl | captured_request_headers CLF style | string list |
| | %hs | captured_response_headers default style | string |
| | %hsl | captured_response_headers CLF style | string list |
| | %ms | accept date milliseconds (left-padded with 0) | numeric |
| | %pid | PID | numeric |
| H | %r | http_request | string |
| | %rc | retries | numeric |
| | %rt | request_counter (HTTP req or TCP session) | numeric |
| | %s | server_name | string |
| | %sc | srv_conn (server concurrent connections) | numeric |
| | %si | server_IP (target address) | IP |
| | %sp | server_port (target address) | numeric |
| | %sq | srv_queue | numeric |
| S | %sslc| ssl_ciphers (ex: AES-SHA) | string |
| S | %sslv| ssl_version (ex: TLSv1) | string |
| | %t | date_time (with millisecond resolution) | date |
| | %ts | termination_state | string |
| H | %tsc | termination_state with cookie status | string |
+---+------+-----------------------------------------------+-------------+
ACL匹配规则
参考链接:https://blog.51cto.com/u_11886307/2406612#h0
HAProxy的ACL可以对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作
ACL语法格式
acl <aclname> <criterion> [flags] [operator] [<value>]
acl acl名称(必须定义) 条件 条件标记位(选项) 具体操作符(匹配字符) 操作对象类型
各个参数解释
aclname
区分字符大小写,且其只能包含大小写字母、数字、-(连接线)、_(下划线)、.(点号)和:(冒号);haproxy中,acl可以重名,这可以把多个测试条件定义为一个共同的acl
criterion
hdr([<name> [,<occ>]]):完全匹配字符串
hdr_beg([<name> [,<occ>]]):前缀匹配
hdr_dir([<name> [,<occ>]]):路径匹配
hdr_dom([<name> [,<occ>]]):域匹配
hdr_end([<name> [,<occ>]]):后缀匹配
hdr_len([<name> [,<occ>]]):长度匹配
hdr_reg([<name> [,<occ>]]):正则表达式匹配
hdr_sub([<name> [,<occ>]]):子串匹配
dst 目标IP
dst_port 目标PORT
src 源IP
src_port 源PORT
flags
-i 不区分大小写
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关
operator
整数比较:eq、ge、gt、le、lt
字符比较:
- exact match (-m str) :字符串必须完全匹配模式
- substring match (-m sub) :在提取的字符串中查找模式,如果其中任何一个被发现,ACL将匹配
- prefix match (-m beg) :在提取的字符串首部中查找模式,如果其中任何一个被发现,ACL将匹配
- suffix match (-m end) :将模式与提取字符串的尾部进行比较,如果其中任何一个匹配,则ACL进行 匹配
- subdir match (-m dir) :查看提取出来的用斜线分隔(“/”)的字符串,如果其中任何一个匹配,则 ACL进行匹配
- domain match (-m dom) :查找提取的用点(“.”)分隔字符串,如果其中任何一个匹配,则ACL进 行匹配
value
- Boolean #布尔值false,true
- integer or integer range #整数或整数范围,比如用于匹配端口范围,1024~32768 - IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24
-string exact –精确比较
substring—子串 www.magedu.com
suffix-后缀比较
prefix-前缀比较
subdir-路径,/wp-includes/js/jquery/jquery.js
domain-域名,www.magedu.com
- regular expression #正则表达式
- hex block #16进制
调用ACL规则
逻辑符号
多个acl作为条件时的逻辑关系
与:隐式(默认)使用
或:使用"or" 或 “||“表示
否定:使用”!” 表示
与:当用户请求的域名即满足第一个匹配条件也满足第二个条件时就调用后端的服务器组
或:当用户请求的域名满足第一个匹配条件或者第二个条件就调用某个后端服务器组
非:当用户的请求不满足条件是调用某个后端的服务器组
use_backend
当符合指定的条件时使用特定的backend,<backend>表示设置的backend名,if和unless为判断条件,
<condition>为比较的对象,可以是ACL规则,要注意的是在if和unless后面可以接两个ACL,默认表示两个ACL同时满足时才use_backend执行
use_backend <backend> [{if | unless} aclname]
block
拒绝一个七层请求满足/不满足某一ACL匹配条件
block { if | unless } aclname
例:
acl invalid_src src 192.18.29.101 #acl匹配条件为源地址为192.18.29.101,acl名为invalid_src
block if invalid_src #阻断满足名为invalid_src的acl匹配条件
errorfile 403 /etc/fstab #并定义错误页
http-request
七层的请求访问控制,与block阻塞不同,http-request更灵活,可做黑白名单控制。只能用在mode http中。
http-request { allow | deny } [ { if | unless } <aclname> ]
tcp-request
四层的请求访问控制
tcp-request connection {accept|reject} [{if | unless} <aclname>]
例:
acl aclname src ip/24 定义名为aclname的规则
tcp-request content accept if aclname 如果是aclname规则允许,就发起连接请求
tcp-request content reject 没有if语句 则拒绝所有(reject)
基于acl定义不同的域名调度到不同的后端服务器
1.根据用户的请求的域名的不同做匹配
frontend web
bind 192.168.8.20:80
mode http
acl pc_web_page hdr(host) -i www.mypc.com #忽略大小写匹配报文头部的主机名
acl m_web_page hdr(host) -i m.mym.com
use_backend pc_server if pc_web_page #ACL的调用
use_backend m_server if m_web_page
default_backend default_server #当请求都不符合时调转到默认页面
#acl pc_web_page hdr_dom(host) -i www.mypc.com
#配置acl规则,规则名字pc_web_page,匹配用户请求的域名,忽略大小写,匹配的内容为www.mypc.com
#acl mobile_web_page hdr_dom(host) -i m.mym.com
#配置acl规则,规则名字mobile_web_page,匹配用户请求的域名,忽略大小写,匹配的内容为m.mym.com
use_backend pc_server if pc_web_page #配置调用规则,当匹配规则所定义的条件时,调用pc_host所定义的后端服务器
use_backend mobile_server if mobile_web_page #配置调用规则,当匹配规则所定义的条件时,调用mobile_host所定义的后端服务器
backend pc_server
server web1 192.168.8.21:80 weight 1 check inter 3s fall 3 rise 5
backend m_server
server web2 192.168.8.22:80 weight 1 check inter 3s fall 3 rise 5
backend default_server
server web3 192.168.8.23:80 weight 1 check inter 3s fall 3 rise 5
2.结果
[root@localhost ~]# curl m.mym.com #匹配到规则后调用后端对应的服务器
m.mym.com
[root@localhost ~]# curl www.mypc.com
www.mypc.com
[root@localhost ~]# curl www.default.com #没有匹配到规则调用默认的服务器
welcome to default.com
acl基于源地址做调度
1.使用acl,对IP地址做匹配,做到从某个地址或者地址段来的就调度到哪个后端的服务器上
frontend web
bind 192.168.8.20:80
mode http
acl ip_range_test src 192.168.8.0/24 192.168.1.100
use_backend m_server if ip_range_test
default_backend default_server
backend pc_server
server web1 192.168.8.21:80 weight 1 check inter 3s fall 3 rise 5
backend m_server
server web2 192.168.8.22:80 weight 1 check inter 3s fall 3 rise 5
backend default_server
server web3 192.168.8.23:80 weight 1 check inter 3s fall 3 rise 5
2.结果
在192.168.1.100访问
[root@localhost ~]# curl m.mymcom
m.mym.com #访问到了m.mym.com的主页面
acl基于地址段做拒绝
1.使用acl对地址段做判断,对匹配的做拒绝操作
frontend web
bind 192.168.8.20:80
mode http
acl ip_range_test src 192.168.20.0/24 192.168.1.100
block if ip_range_test #对ip地址段做拒绝时使用block
default_backend backup_server
#option httpchk HEAD /monitor-page/index.html HTTP/1.0
backend pc_server
server web1 192.168.8.21:80 weight 1 check inter 3s fall 3 rise 5
backend m_server
server web2 192.168.8.22:80 weight 1 check inter 3s fall 3 rise 5
backend default_server
server web3 192.168.8.23:80 weight 1 check inter 3s fall 3 rise 5
2.结果
[root@localhost ~]# curl www.mypc.com
<html><body><h1>403 Forbidden</h1> #被拒绝
Request forbidden by administrative rules.
</body></html>
acl基于用户浏览器的类型
1.user-agent信息
日志
#google
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36
#FireFox
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0
user-agent信息:google(Chrome),FireFox(Firefox)
2.配置
frontend web
bind 192.168.8.20:80
mode http
acl google hdr(user-agent) -m sub -i "Chrome" #匹配请求首部user-agent中的字串是否包含chrome
acl firefox hdr(user-agent) -m sub -i "Firefox" #匹配字串中是否有Firefox
use_backend pc_server if google
use_backend m_server if firefox
default_backend default_server
backend pc_server
server web1 192.168.8.21:80 weight 1 check inter 3s fall 3 rise 5
backend m_server
server web2 192.168.8.22:80 weight 1 check inter 3s fall 3 rise 5
backend default_server
server web3 192.168.8.23:80 weight 1 check inter 3s fall 3 rise 5
acl规则匹配后重定向
当被acl规则匹配到后也可以将访问的url进行重定向,使用redirect进行调用规则
1.当浏览器为firefox时调度到baidu.com
frontend web
bind 192.168.8.20:80
mode http
acl google hdr(user-agent) -m sub -i "Chrome"
use_backend pc_server if google
acl firefox hdr(user-agent) -m sub -i "Firefox"
redirect prefix http://www.baidu.com if firefox #当浏览器为firefox时重定向到百度
default_backend default_server
backend pc_server
server web1 192.168.8.21:80 weight 1 check inter 3s fall 3 rise 5
backend m_server
server web2 192.168.8.22:80 weight 1 check inter 3s fall 3 rise 5
backend default_server
server web3 192.168.8.23:80 weight 1 check inter 3s fall 3 rise 5
基于HAProxy实现匹配后缀做动静分离
1.haproxy可以使用acl中的path_end,基于所要访问的文件的后缀做动静分离的匹配
frontend web
bind 192.168.8.20:80
mode http
acl php path_end -i .php #配置acl acl名为php 匹配后缀为 .php 忽略大小写
acl image path_end -i .jpg .jpeg .gif .png .css .js .html .txt .htm #配置acl acl名为image 匹配后缀为 .jpg .jpeg .gif .png 忽略大小写
use_backend php_server if php #配置调用规则当匹配php的条件时,调用php_server
use_backend image_server if image #匹配调用规则当匹配image的条件时,调用image_server
backend php_server
server web1 192.168.8.21 check port 80 inter 3s fall 3 rise 5
backend image_server
server web2 192.168.8.22 check port 80 inter 3s fall 3 rise 5
基于路径的头部做动静分离
1.haproxy中也可以基于文件访问的头部做匹配将其进行动静分离,比如某几个目录内都为静态文件,则将这几个目录进行匹配
frontend web
bind 192.168.8.20:80
mode http
acl php_path path_end -i php #定义匹配PHP后缀文件
acl static_path path_beg -i /static /images /javascript /tfs #定义匹配静态文件的目录
use_backend php_server if php_path #php后缀文件调用后端php_server
use_backend static_server if static_path #静态资源路径时调用后端static_server
backend php_server
backend php_server
server web1 192.168.8.21 check port 80 inter 3s fall 3 rise 5
backend image_server
server web2 192.168.8.22 check port 80 inter 3s fall 3 rise 5
http基于策略的访问控制
frontend web
bind 192.168.8.20:80
mode http #http的访问控制需要基于http的模式来进行
acl php_path path_end -i php
acl static_path path_beg -i /static /images /javascript /tfs
acl client_deny src 192.168.8.0/24 #定义拒绝访问的源地址
http-request deny if client_deny #对匹配到的源地址发来的请求进行拒绝
use_backend php_server if php_path
use_backend static_server if static_path
backend php_server
server web1 192.168.8.21:80 weight 1 check inter 3s fall 3 rise 5
backend static_server
server web2 192.168.8.22:80 weight 1 check inter 3s fall 3 rise 5
backend default_server
server web3 192.168.8.23:80 weight 1 check inter 3s fall 3 rise 5
2.结果
[root@localhost ~]# curl www.mypc.com
<html><body><h1>403 Forbidden</h1> #请求被拒绝
Request forbidden by administrative rules.
</body></html>
配置DDOS攻击
https://blog.csdn.net/wsfdl/article/details/42114855
https://blog.51cto.com/hnetworks/1595606