HAProxy

HAProxy

HAProxy: 是法国开发者Willy Tarreau开发的一个开源软件,是一款具备高并发、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计。

LB Cluster:

  • 四层:lvs, nginx(stream模式且nginx1.9.0或更新版本),haproxy(mode tcp)
  • 七层:http: nginx(http), haproxy(mode http), httpd…

HAProxy功能

HAProxy是TCP / HTTP反向代理服务器,尤其适合于高可用性高并发环境

  • 可以针对HTTP请求添加cookie,进行路由后端服务器
  • 可平衡负载至后端服务器,并支持持久连接
  • 支持基于cookie进行调度
  • 支持所有主服务器故障切换至备用服务器
  • 支持专用端口实现监控服务
  • 支持不影响现有连接情况下停止接受新连接请求
  • 可以在双向添加,修改或删除HTTP报文首部
  • 支持基于pattern实现连接请求的访问控制
  • 通过特定的URI为授权用户提供详细的状态信息

使用HAProxy

安装启动haproxy

编译安装

1
2
3
[root@master haproxy-1.8.17]# yum install gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl  openssl-devel systemd-devel net-tools vim iotop bc  zip unzip zlib-devel lrzsz tree screen lsof tcpdump wget ntpdate #解决依赖关系
[root@master haproxy-1.8.17]# make ARCH=x86_64 TARGET=linux2628 USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 PREFIX=/usr/local/haproxy
[root@master haproxy-1.8.17]# make install PREFIX=/usr/local/haproxy

在编译的过程中会在当前目录生成一个haproxy可执行程序,将其拷贝到/usr/sbin/目录下。

创建启动文件

1
2
3
4
5
6
7
8
9
10
[root@master haproxy-1.8.17]# vi /usr/lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target
[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID
[Install]
WantedBy=multi-user.target

创建配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[root@master haproxy]# cat /etc/haproxy/haproxy.cfg 
global
maxconn 100000
chroot /usr/local/haproxy
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
uid 188
gid 188
daemon
nbproc 4
cpu-map 1 0
cpu-map 2 1
cpu-map 3 2
cpu-map 4 3
pidfile /usr/local/haproxy/run/haproxy.pid
log 127.0.0.1 local3 info

defaults
option http-keep-alive
option forwardfor
maxconn 100000
mode http
timeout connect 300000ms
timeout client 300000ms
timeout server 300000ms

listen stats
mode http
bind 0.0.0.0:9999
stats enable
log global
stats uri /haproxy-status
stats auth haadmin:q1w2e3r4ys

listen web_port
bind 0.0.0.0:80
mode http
log global
server web1 127.0.0.1:8080 check inter 3000 fall 2 rise 5

创建目录和用户

1
2
3
4
[root@master haproxy-1.8.17]# mkdir  /etc/haproxy
[root@master haproxy-1.8.17]# useradd haproxy -s /sbin/nologin
[root@master haproxy-1.8.17]# mkdir /var/lib/haproxy
[root@master haproxy-1.8.17]# chown haproxy.haproxy /var/lib/haproxy/ -R

haproxy.cfg文件中定义了chroot、pidfile、user、group等参数,如果系统没有相应的资源会导致haproxy无法启动,具体参考日志文件/var/log/messages

启动haproxy

1
2
~]# systemctl daemon-reload
~]# systemctl start haproxy

haproxy基本配置

HAProxy组成
程序环境

  • 主程序:/usr/sbin/haproxy
  • 配置文件:/etc/haproxy/haproxy.cfg
  • unit file:/usr/lib/systemd/system/haproxy.service

配置段:

  • global:全局配置段

    进程及安全配置相关的参数
    性能调整相关的参数
    debug参数

1
2
3
4
5
6
7
8
9
10
11
12
13
chroot #锁定运行目录,当haproxy被侵入,则只能在锁定目录活动,能保护系统上的其他目录不受侵害。
deamon #以守护进程运行
#stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin #socket文件
user, group, uid, gid #运行haproxy的用户身份
nbproc #开启的haproxy进程数,与CPU保持一致
nbthread #指定每个haproxy进程开启的线程数,默认为每个进程一个线程
cpu-map 1 0 #绑定haproxy 进程至指定CPU
maxconn #每个haproxy进程的最大并发连接数
maxsslconn #SSL每个haproxy进程ssl最大连接数
maxconnrate #每个进程每秒最大连接数
spread-checks #后端server状态check随机提前或延迟百分比时间,建议2-5(20%-50%)之间
pidfile #指定pid文件路径
log 127.0.0.1 local3 info #定义全局的syslog服务器;最多可以定义两个
  • proxies:代理配置段

    defaults:为frontend,backend,listen提供默认配置
    frontend <\name>:前端,相当于nginx中的server{}
    backend <\name>:后端,相当于nginx中的upstream{}
    listen <\name>:同时拥有前端和后端,适用于一对一环境。

注意:name字段只能用”-“,”.”,”、”,”:”,并严格区分大小写,例如:Web和web时完全不同的两组服务器。

defaults[<\name>] #默认配置项,针对以下的frontend、backend和listen生效,可以多个name

1
2
3
4
5
6
7
8
9
10
option redispatch    #当server Id对应的服务器挂掉后,强制定向到其他健康的服务器  
option abortonclose #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
option http-keep-alive #开启会话保持
option forwardfor #开启IP透传
mode http #默认工作类型
timeout connect 120s #连接到一台后端server的最长时间
timeout client 600s #与客户端的最长空闲时间
timeout server 600s #等待服务端的超时时长
timeout http-keep-alive 120s #session 会话保持时间
#timeout check 5s #对后端服务器的检测超时时间

bind:指定HAProxy的监听地址,可以是IPV4或IPV6,可以同时监听多个IP或端口,可同时用于listen字段中
bind [

]: [, …] [param*]
mode http/tcp #指定负载协议类型
use_backend backend_name #调用的后端服务器组名称
示例:

1
2
3
4
frontend  WEB_PORT
bind :80,:8080
bind 192.168.7.102:10080,192.168.7.102:10043
use_backend backend_name
  • check #对指定real进行健康状态检查,默认不开启

    addr IP #可指定的健康状态监测IP
    port num #指定的健康状态监测端口
    inter num #健康状态检查间隔时间,默认2000 ms
    fall num #后端服务器失效检查次数,默认为3
    rise num #后端服务器从下线恢复检查次数,默认为2
    weight #默认为1,最大值为256,0表示不参与负载均衡
    backup #将后端服务器标记为备份状态
    disabled #将后端服务器标记为不可用状态
    redir http://www.magedu.com/ #将请求临时重定向至其它URL,只适用于http模式
    maxconn :当前后端server的最大并发连接数
    backlog :当server的连接数达到上限后的后援队列长度

也可以直接使用listen定义一组负载均衡:

1
2
3
4
5
6
7
8
[root@master ~]# tail /etc/haproxy/haproxy.cfg 
listen web-port-80
bind 192.168.34.100:80
mode http
option forwardfor
server web1 192.168.34.101:80
server web2 192.168.34.102:80
server web3 192.168.34.103:80

HAProxy算法

无状态和有状态:

  • 无状态的请求实质两次请求之间没有关联,有状态反之。

balance: 指明对后端服务器的调度算法,配置在listen或backend

静态算法
静态算法:按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、链接数和相应速度等,且无法实时修改权重,只能重启后生效

  • static-rr:基于权重的轮询调度,不支持权重的运行时调整及后端服务器慢启动,其后端主机数量没有限制

  • first:根据服务器在列表中的位置,自上而下进行调度,但是其只会当第一台服务器的连接数达到上限,新请求才会分配给下一台服务,因此会忽略服务器的权重设置。

动态算法
动态算法:基于后端服务器 状态进行调度适当调整,比如优先调度至当前负载较低的服务器,且权重可以在haproxy运行时动态调整无需重启。

  • roundrobin:基于权重的轮询动态调度算法,支持权重的运行时调整,不等于lvs 的rr,支持慢启动即新加的服务器会逐渐增加转发数,每个后端backend中最多支持4095个server,此为默认调度算法,server 权重设置 weight

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

  • source:源地址hash,基于用户源地址hash并将请求转发到后端服务器,默认为静态即取模方式,但是可以通过hash-type支持的选项更改,后续同一个源地址请求将被转发至同一个后端web服务器,比较适用于session保持等场景。

    map-based:取模法,基于服务器权重的hash数组取模,该hash是静态的即不支持在线调整权重,不支持慢启动,其对后端服务器调度均衡,缺点是当服务器的总权重发生变化时,即有服务器上线或下线,都会因权重发生变化而导致调度结果整体改变。

consistent:一致性哈希,该hash是动态的,支持在线调整权重,支持慢启动,优点在于当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动,该算法很容易导致后端服务器负载不均衡,但是比较适合session保持。

source算法示例:

1
2
3
4
5
6
7
8
9
listen  web_prot_http_nodes
bind 192.168.7.101:80
mode http
balance source
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
  • uri:基于对用户请求的uri做hash并将请求转发到后端指定服务器

    map-based:取模法
    consistent:一致性哈希

uri: uniform resource identifier,统一资源标识符,是一个用于标识某一互联网资源名称的字符串

uri调度算法示例:

1
2
3
4
5
6
7
8
9
listen  web_prot_http_nodes
bind 192.168.7.101:80
mode http #不支持tcp,会切换到tcp的roundrobin负载模式
balance uri
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise
  • url_param:对用户请求的url中的部分中的参数name作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server

url_param调度算法示例:

1
2
3
4
5
6
7
8
9
listen  web_prot_http_nodes
bind 192.168.7.101:80
mode http #不支持tcp,会切换到tcp的roundrobin负载模式
balance url_param name #基于参数name做hash
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
  • hdr():针对用户每个http头部(header)请求中的指定信息做hash,此处由指定的http首部将会被取出并做hash计算,然后由服务器总权重相除以后派发至某挑出的服务器,假如无有效的值,则会被轮询调度

    hdr( Cookie、 User-Agent、host )

1
2
3
4
5
6
7
8
9
listen  web_prot_http_nodes
bind 192.168.7.101:80
mode http
balance hdr(User-Agent)
hash-type consistent
log global
option forwardfor
server 192.168.7.101 192.168.7.101:8080 check inter 3000 fall 3 rise 5
server 192.168.7.102 192.168.7.102:8080 check inter 3000 fall 3 rise 5
  • rdp-cookie对远程桌面的负载,使用cookie保持会话
    rdp-cookie()

示例

1
2
3
4
5
6
listen RDP
bind 192.168.7.101:3389
balance rdp-cookie
mode tcp
server rdp0 172.18.139.20:3389 check fall 3 rise 5 inter 2000 weight 1
server rdp1 172.18.139.21:3389 check fall 3 rise 5 inter 2000 weight 1

基于iptables实现目标地址转换

1
2
3
~]# iptables -t nat -A PREROUTING -d 192.168.34.101 -p tcp --dport 3389 -j DNAT --to-destnation 192.167.34.101:80
~]# iptables -t nat -A POSTROUTING -s 192.168.34.0/24 -j SNAT --to-source 192.168.34.101
~]# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf

算法总结:
roundrobin——–>tcp/http 动态
leastconn———–>tcp/http 动态
static-rr————–>tcp/http 静态
first——————–>tcp/http 静态

source—————->tcp/http
Uri———————->http
url_param———->http 取决于hash_type是否consistent
hdr———————>http
rdp-cookie———>tcp

HAProxy-服务器动态上下线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
[root@master ~]# yum -y install socat
[root@master ~]# echo "show info"|socat stdio /var/lib/haproxy/haproxy.sock
proxy.sock
Name: HAProxy
Version: 1.8.17
Release_date: 2019/01/08
Nbthread: 1
Nbproc: 2
Process_num: 2
Pid: 17966
Uptime: 0d 1h10m29s
Uptime_sec: 4229
Memmax_MB: 0
PoolAlloc_MB: 0
PoolUsed_MB: 0
PoolFailed: 0
Ulimit-n: 200032
Maxsock: 200032
Maxconn: 100000
Hard_maxconn: 100000
CurrConns: 0
CumConns: 5
CumReq: 8
MaxSslConns: 0
CurrSslConns: 0
CumSslConns: 0
Maxpipes: 0
PipesUsed: 0
PipesFree: 0
ConnRate: 0
ConnRateLimit: 0
MaxConnRate: 1
SessRate: 0
SessRateLimit: 0
MaxSessRate: 1
SslRate: 0
SslRateLimit: 0
MaxSslRate: 0
SslFrontendKeyRate: 0
SslFrontendMaxKeyRate: 0
SslFrontendSessionReuse_pct: 0
SslBackendKeyRate: 0
SslBackendMaxKeyRate: 0
SslCacheLookups: 0
SslCacheMisses: 0
CompressBpsIn: 0
CompressBpsOut: 0
CompressBpsRateLim: 0
ZlibMemUsage: 0
MaxZlibMemUsage: 0
Tasks: 5
Run_queue: 1
Idle_pct: 100
node: master
Stopping: 0
Jobs: 4
Listeners: 3

IP地址透传与基于cookie实现会话保持

四层负载和七层的区别:
四层

在四层负载设备中,把client发送的报文目标地址(原来是负载均衡设备的IP地址),根据均衡设备设置的选择web服务器的规则选择对应的web服务器IP地址,这样client就可以直接跟此服务器建立TCP连接并发送数据。

七层

七层负载均衡服务器起了一个代理服务器的作用,服务器建立一次TCP连接要三次握手,而client要访问webserver要先于七层设备进行三次握手后建立TCP连接,把要访问的报文信息发送给七层负载均衡,然后七层负载均衡再根据设置的均衡规则选择特定的webserver,然后通过三次握手与此台webserver建立TCP连接,然后webserver把需要的数据发送给七层负载均衡设备,负载均衡设备再把数据发给client;所以,七层负载均衡设备起到了代理服务器的作用。

抓包命令:

  • tcpdump tcp -i eth0 -nn port !22 -w dump-tcp.pcap -v

内核参数优化:

  • /etc/sysctl.conf
  • /etc/security.conf
七层ip透传

haproxy设置

1
2
3
4
5
listen  web_prot_http_nodes
bind 192.168.7.102:80
mode http
option forwardfor
server 192.168.7.102 blogs.studylinux.net:80 check inter 3000 fall 3 rise 5

后端server配置
nginx

1
2
3
4
5
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;

httpd

1
2
LogFormat "\"%{X-Forwarded-For}i\" %l %u %t \"%r\" %>s %b" common1
CustomLog "logs/access_log" common1
四层ip透传

配置haproxy

1
2
3
4
listen  web_prot_http_nodes
bind 192.168.7.102:80
mode tcp
server 192.168.7.102 blogs.studylinux.net:80 send-proxy check inter 3000 fall 3 rise 5

配置后端服务器(nginx)

1
2
listen       80 proxy_protocol;
'"tcp_ip":"$proxy_protocol_addr",' #TCP获取客户端真实IP日志格式
基于cookie实现会话保持

cookie :为当前server指定cookie值,实现基于cookie的会话黏性
cookie [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain ]* [ maxidle ] [ maxlife ]
:cookie名称,用于实现持久连接
rewrite:重写
insert:插入
prefix:前缀
nocache:当client和hapoxy之间有缓存时,不缓存cookie

配置示例:

1
2
3
4
5
6
listen  web_prot_http_nodes
bind 192.168.34.100:80
mode http
cookie SERVER-COOKIE insert indirect nocache
server web1 192.168.34.101:80 cookie web1 check inter 3000 fall 3 rise 5
server web2 192.168.34.102:80 cookie web2 check inter 3000 fall 3 rise 5

测试

1
2
3
4
[root@node03 ~]# curl --cookie "SERVER-COOKIE=web1" 192.168.34.100
101
[root@node03 ~]# curl --cookie "SERVER-COOKIE=web2" 192.168.34.100
102

状态页、日志配置和报文操作

haproxy状态页的使用

stats enable   #基于默认的参数启用stats page
stats hide-version  # 隐藏版本
stats refresh <delay> # 设定自动刷新时间间隔
stats uri <prefix>  #自定义stats page uri,默认值:/haproxy?stats 
stats realm <realm> #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication
stats admin { if | unless } <cond> #启用stats page中的管理功能

配置

1
2
3
4
5
6
7
8
9
10
listen stats
bind :9009
stats enable
#stats hide-version
stats uri /haproxy-status
stats realm HAPorxy\ Stats\ Page
stats auth haadmin:123456
stats auth admin:123456
stats refresh 30s
stats admin if TRUE

在浏览器访问,就可以管理haproxy

修改报文首部
在请求报文尾部添加指定首部
reqadd [{if | unless} ] #支持条件判断
在响应报文尾部添加指定首部
rspadd [{if | unless} ]
示例:rspadd X-Via:\ HAPorxy
从请求报文中删除匹配正则表达式的首部
reqdel [{if | unless} ]
reqidel [{if | unless} ] 不分大小写

从响应报文中删除匹配正则表达式的首部
rspdel [{if | unless} ]
rspidel [{if | unless} ]
示例: rspidel server.* #从相应报文删除server信息
rspidel X-Powered-By:.* #从响应报文删除X-Powered-By信息

HAProxy日志配置
在default配置项定义:

log 127.0.0.1  local{1-7} info #基于syslog记录日志到指定设备,级别有(err、warning、info、debug)

配置rsyslog:

$ModLoad imudp
$UDPServerRun 514
local3.*    /var/log/haproxy.log

配置HAProxy:

listen  web_port
 bind 127.0.0.1:80
 mode http
 log global
option tcplog
 server web1  127.0.0.1:8080  check inter 3000 fall 2 rise 5

重启syslog服务并访问haproxy状态页

自定义日志记录
将特定信息记录在日志中

capture cookie <name> len <length> #捕获请求和响应报文中的 cookie并记录日志    
capture request header <name> len <length> #捕获请求报文中指定的首部内容和长度并记录日志
capture response header <name> len <length> #捕获响应报文中指定的内容和长度首部并记录日志

示例

1
2
capture request  header Host len  256
capture request header User-Agent len 512

压缩功能

compression algo   #启用http协议中的压缩机制,常用算法有gzip deflate
compression type  #要压缩的类型

示例

compression algo gzip
compression type compression type text/plain text/html text/css text/xml text/javascript application/javascript

web服务器状态监测
option httpchk
option httpchk
option httpchk
option httpchk

示例

1
2
3
4
5
6
7
8
listen  web_prot_http_nodes
bind 192.168.7.102:80
mode http
log global
option httpchk GET /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.0 #基于指定URL
#option httpchk HEAD /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.0\r\nHost:\ 192.168.7.102 #通过request获取的头部信息进行匹配进行健康检测
server 192.168.7.102 blogs.studylinux.net:80 check inter 3000 fall 3 rise 5
server 192.168.7.101 192.168.7.101:8080 cookie web1 check inter 3000 fall 3 rise 5

ACL

ACL必须在haproxy工作在http模式下才可以使用。

  • acl:对接收到的报文进行匹配和过滤,基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作。
1
acl <aclname>  <criterion>   [flags]           [operator]        [<value>]
  • acl 名称 条件 条件标记位 具体操作符 操作对象类型
1
acl   image_service hdr_dom(host)   -i   img.magedu.com
  • ACL名称,可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线,并且严格区分大小写,必须Image_site和image_site完全是两个acl。

Criterion-acl
<\criterion> :匹配条件
dst 目标IP
dst_port 目标PORT
src 源IP
src_port 源PORT

hdr <\string>用于测试请求头部首部指定内容

hdr_dom(host)  请求的host名称,如 www.magedu.com
hdr_beg(host)  请求的host开头,如 www. img. video. download. ftp.
hdr_end(host)  请求的host结尾,如 .com .net .cn
path_beg   请求的URL开头,如/static、/images、/img、/css
path_end   请求的URL中资源的结尾,如 .gif  .png  .css  .js .jpg .jpeg

flags
<\flags>-条件标记
-i 不区分大小写
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关系
– 强制flag结束. 当字符串和某个flag相似时使用

operator
[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 #布尔值
- integer or integer range #整数或整数范围,比如用于匹配端口范围
- IP address / network #IP地址或IP范围
- 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” 或 “||”表示
- 否定:使用“!“ 表示

示例:
         if   invalid_src invalid_port      与关系
    if invalid_src || invalid_port      或
    if ! invalid_src             非

acl 示例-域名匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
listen  web_port
bind 192.168.7.102:8800
mode http
log global
acl test_host hdr_dom(host) www.magedu.com
use_backend test_host if test_host
default_backend default_web #以上都没有匹配到的时候使用默认backend

backend test_host
mode http
server web1 www.magedu.com check inter 2000 fall 3 rise 5

backend default_web
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5

acl 示例-源地址子网匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
listen  web_port
bind 192.168.7.102:8800
mode http
log global
acl ip_range_test src 192.168.4.0/24
use_backend web2 if ip_range_test
default_backend web1

backend web1
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5

backend web2
mode http
server web1 192.168.7.102:8080 check inter 2000 fall 3 rise 5

acl 示例-源地址访问控制

1
2
3
4
5
6
7
8
9
10
11
12
listen  web_port
bind 192.168.7.102:8800
mode http
log global
acl block_test src 192.168.7.103 192.168.7.104
block if block_test
default_backend web1

backend web1
mode http
log global
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5

acl示例-匹配浏览器

1
2
3
4
5
6
7
8
9
10
11
12
13
listen  web_port
bind 192.168.7.102:8800
mode http
log global
acl block_test src 192.168.7.103 192.168.7.104
acl redirect_test hdr(User-Agent) -m sub -i "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko"
block if block_test
redirect prefix http://192.168.7.101:8080 if redirect_test
default_backend web2
backend web1
mode http
log global
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5

自定义错误页面

1
2
3
4
errorfile 500  /usr/local/haproxy/html/500.html #自定义错误页面跳转
errorfile 502 /usr/local/haproxy/html/502.html
errorfile 503 /usr/local/haproxy/html/503.html
errorloc 503 http://192.168.7.103/error_page/503.html

基于acl+文件后缀实现动静分离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
listen  web_port
bind 192.168.7.102:80
mode http
acl php_server path_end -i .php
use_backend php_server_host if php_server
acl image_server path_end -i .jpg .png .jpeg -gif
use_backend image_server_host if image_server
default_backend default_host
backend default_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5
backend php_server_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5
backend image_server_host
mode http
server web1 192.168.7.102:8080 check inter 2000 fall 3 rise 5

acl-匹配访问路径

1
2
3
4
5
6
7
8
9
10
11
12
13
listen  web_port
bind 192.168.7.102:80
mode http
acl static_path path_beg -i /static /images /javascript
use_backend static_path_host if static_path

default_backend default_host
backend default_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5
backend static_path_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5

http模式下基于策略的访问控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
listen  web_port
bind 192.168.7.102:80
mode http
acl badguy_deny src 192.168.4.1
http-request deny if badguy_deny
http-request allow
default_backend default_host
backend default_host
mode http
server web1 192.168.7.102:8080 check inter 2000 fall 3 rise 5
backend static_path_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5
backend image_server_host
mode http
server web1 192.168.7.102:8080 check inter 2000 fall 3 rise 5

预定义acl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ACL name	Equivalent to	Usage
FALSE always_false never match
HTTP req_proto_http match if protocol is valid HTTP
HTTP_1.0 req_ver 1.0 match HTTP version 1.0
HTTP_1.1 req_ver 1.1 match HTTP version 1.1
HTTP_CONTENT hdr_val(content-length) gt 0 match an existing content-length
HTTP_URL_ABS url_reg ^[^/:]*:// match absolute URL with scheme
HTTP_URL_SLASH url_beg / match URL beginning with "/"
HTTP_URL_STAR url * match URL equal to "*"
LOCALHOST src 127.0.0.1/8 match connection from local host
METH_CONNECT method CONNECT match HTTP CONNECT method
METH_DELETE method DELETE match HTTP DELETE method
METH_GET method GET HEAD match HTTP GET or HEAD method
METH_HEAD method HEAD match HTTP HEAD method
METH_OPTIONS method OPTIONS match HTTP OPTIONS method
METH_POST method POST match HTTP POST method
METH_PUT method PUT match HTTP PUT method
METH_TRACE method TRACE match HTTP TRACE method
RDP_COOKIE req_rdp_cookie_cnt gt 0 match presence of an RDP cookie
REQ_CONTENT req_len gt 0 match data in the request buffer
TRUE always_true always match
WAIT_END wait_end wait for end of content analysis

预定义acl的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
listen  web_port
bind 192.168.7.102:80
mode http
acl static_path path_beg -i /static /images /javascript
use_backend static_path_host if HTTP_1.1 TRUE static_path
default_backend default_host

backend default_host
mode http
server web1 192.168.7.102:8080 check inter 2000 fall 3 rise 5
backend static_path_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5

四层访问控制

tcp-request connection {accept|reject} [{if | unless} ] 根据第4层条件对传入连接执行操作

示例

1
2
3
4
5
6
7
8
listen redis-port
bind 192.168.7.102:6379
mode tcp
balance leastconn
acl invalid_src src 192.168.1.0/24 192.168.7.101
tcp-request connection reject if invalid_src
server server1 192.168.7.104:6379 check
server server1 192.168.7.103:6379 check backup

HAProxy-https协议

配置HAProxy支持https协议: 
支持ssl会话;
    bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE    
    crt 后证书文件为PEM格式,且同时包含证书和所有私钥    
        cat  demo.crt demo.key > demo.pem 
把80端口的请求重向定443
    bind *:80
    redirect scheme https if !{ ssl_fc }    
向后端传递用户请求的协议和端口(frontend或backend)
    http_request set-header X-Forwarded-Port %[dst_port]
    http_request add-header X-Forwared-Proto https if { ssl_fc }

https证书制作

1
2
3
4
5
6
~]# mkdir /usr/local/haproxy/certs
~]# cd /usr/local/haproxy/cert
~]# openssl genrsa -out haproxy.key 2048
~]# openssl req -new -x509 -key haproxy.key -out haproxy.crt -subj "/CN=www.magedu.net"
~]# cat haproxy.key haproxy.crt > haproxy.pem
~]# openssl x509 -in haproxy.pem -noout -text #查看证书

配置haproxy支持https

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
frontend https
bind 192.168.7.102:443 ssl crt /usr/local/haproxy/certs/haproxy.pem
use_backend web_host

backend default_host
mode http
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5
server web2 192.168.7.102:8080 check inter 2000 fall 3 rise 5

backend web_host
mode http
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
server web1 192.168.7.101:8080 check inter 2000 fall 3 rise 5
server web2 192.168.7.102:8080 check inter 2000 fall 3 rise 5

HAProxy服务器动态上下线

1
2
3
4
~]# echo "show info" | socat stdio /var/lib/haproxy/haproxy.sock
~]# echo "get weight web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock
~]# echo "disable server web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock
~]# echo "enable server web_host/192.168.7.101" | socat stdio /var/lib/haproxy/haproxy.sock