本章概要

  • HAProxy介绍
  • HAProxy配置
  • ACL

1、HAProxy介绍

HAProxy介绍

  • 前言
    lvs性能强,功能弱;nginx(haproxy)功能多,性能相对较弱,因此,一般情况下,在前端使用LVS四层调度器加haproxy七层调度的结构
  • HAProxy: 是法国人Willy Tarreau开发的一个开源软件,是一款应对客户
    端10000以上的同时连接的高性能的TCP和HTTP负载均衡器。其功能
    是用来提供基于cookie的持久性,基于内容的交换,过载保护的高级流
    量管制,自动故障切换,以正则表达式为基础的控制运行时间,基于
    Web的报表,高级日志记录以帮助排除故障的应用或网络及其他功能
  • LB Cluster:
      四层:lvs, nginx(stream),haproxy(mode tcp)
      七层:http: nginx(http), haproxy(mode http), httpd…
  • 官网:
      http://www.haproxy.org
      https://www.haproxy.com
  • 文档:https://cbonte.github.io/haproxy-dconv/

HAProxy功能

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

  • 版本:1.4、1.5、1.6、1.7、1.8、1.9

  • HAProxy结构

  • 支持http反向代理

  • 支持动态程序的反向代理

  • 支持基于数据库的反向代理

2、HAProxy配置

HAProxy组成

  • 程序环境:
      主程序:/usr/sbin/haproxy
      配置文件:/etc/haproxy/haproxy.cfg
      Unit file:/usr/lib/systemd/system/haproxy.service
  • 配置段:
      global:全局配置段
        进程及安全配置相关的参数
        性能调整相关参数
        Debug参数
      proxies:代理配置段
        defaults:为frontend, backend, listen提供默认配置
        frontend:前端,相当于nginx中的server {}
        backend:后端,相当于nginx中的upstream {}
        listen:同时拥有前端和后端,适用于一对一环境
    示例1:
frontend webbind *:80default_backend websrvs
backend websrvsbalance roundrobinserver srv1 192.168.0.101:80 checkserver srv2 192.168.0.102:80 check

示例2:

RS1:[root@rs1 conf.d]# vim vhosts.conf <VirtualHost *:80>ServerName www.a.comDocumentRoot "/var/www/html"<Directory "/var/www/html">Require all granted</Directory></VirtualHost>
RS2:[root@rs1 conf.d]# vim vhosts.conf <VirtualHost *:80>ServerName www.a.comDocumentRoot "/var/www/html"<Directory "/var/www/html">Require all granted</Directory></VirtualHost>haproxy服务器:
删除或注释defaults以下的所有配置,重新配置haproxy配置文件
vim /etc/haproxy/haproxy.cfg    frontend webbind *:80default_backend websrvsbackend websrvsbalance roundrobin      轮询调度算法server srv1 192.168.32.130:80 server srv2 192.168.32.131:80
重新加载服务systemctl reload haproxy
查看端口号,发现默认5000端口消失,而80端口被监听,这里的80端口就是frontend定义的80端口,即frontend定义哪个端口,系统将会自动监听该端口
测试:while true ;do curl www.a.com;sleep 0.5 ;done;注意:haproxy即使在server后不加check,也具有健康监测功能,当关闭后端服务器RS1和RS2中的某一台服务器时,会自动调度到另外一台服务器上,且返回代码为503

global配置

  • global配置参数:
  • 进程及安全管理:chroot, deamon,user, group, uid, gid
      nbproc <number> 要启动的haproxy的进程数量,系统默认单进程,要求使用daemon模式
      ulimit-n <number> 每个haproxy进程可打开的最大文件数,系统自动会指定,不建议设置
      daemon 后端方式运行,建议使用
      log 定义全局的syslog服务器;最多可以定义两个
      log <address> [len <length>] <facility> [max level [min level]]
        address: rsyslog服务器地址
        len: 记录日志的长度,默认1024

日志系统

  • log:
      log global
      log <address> [len <length>] <facility> [<level> [<minlevel>]]
        length 日志行的长度,默认1024
      no log
      注意:
        默认发往本机的日志服务器
        (1) local2.* /var/log/local2.log
        (2) ModLoadimudpModLoad imudp       ModLoadimudp      UDPServerRun 514
  • log-format <string>:
      课外实践:参考文档实现combined格式的记录
    示例:
    haproxy配置文件中,日志配置如下: globallog         127.0.0.1 local2   注意:local2是指保存本地日志local0-loca7文件中的一个,由于指定的日志路径为本地ip地址127.0.0.1,因此必须开启网络功能才能保存haproxy日志在rsyslog日志配置文件中配置haproxy日志:vim /etc/rsyslog.conf $ModLoad imudp    启用日志模块$InputTCPServerRun 514   监听udp/514端口,接收日志local2.*          /var/log/haproxy.log    设置保存日志的文件重启日志服务systemctl restart rsyslog查看日志:cat /var/log/haproxy.log注意:由于haproxy的日志是基于网络指向其他主机来保存日志,因此当改变日志保存位置时,需要把ip地址指向保存日志的主机ip,并开启网络日志功能以及监听514端口

日志管理

  • 将特定信息记录在日志中
  • capture cookie <name> len <length>
      捕获请求和响应报文中的 cookie并记录日志
  • capture request header <name> len <length>
      捕获请求报文中指定的首部并记录日志
    示例:
      capture request header X-Forwarded-For len 15
  • capture response header <name> len <length>
      捕获响应报文中指定的首部并记录日志
    示例:
      capture response header Content-length len 9
      capture response header Location len 15

性能调整

  • 性能调整:
    maxconn <number>:设置每个haproxy进程所能接受的最大并发连接数
    maxconnrate <number>:设置每个进程每秒种所能建立的最大连接数量
    maxsessrate <number>:设置每个进程每秒种所能建立的最大会话数量
      注意:连接数和会话数的区别在于,连接属于OSI七层参考模型的传输层,会话属于ISO参考模型的应用层
    maxsslconn <number>: 每进程支持SSL的最大连接数量
    spread-checks <0…50, in percent> 健康检测延迟时长百分比,建议2-5之间
      健康检测延迟时长百分比,建议2-5之间
      注意:当进行健康监测时,会向后端服务器发送健康监测数据,如果后端服务器数量较多,并且同时发送检测数据,会对haproxy服务器造成较大的负载压力,因此可以把检测延时发送,分开来发即可减轻haproxy的压力
      另外,如果延时设置为50%,那么前一个延时50%,后一个提前50%,会造成检测数据发送时间正好相连接,也会造成瞬间数据的负载压力,因此推荐延时为2%-5%之间

配置段

  • 代理配置段:
  • defaults <name>
  • frontend <name>
  • backend <name>
  • listen <name>
  • Frontend段:指定接收客户端连接侦听套接字设置
  • Backend段:指定将连接请求转发至后端服务器的相关设置
  • Listen段:指定完整的前后端设置
  • proxy 名称:使用字母 数字 - _ . : 并区分字符大小写

配置参数

  • 配置参数:
  • bind:指定一个或多个前端侦听地址和端口
      bind [<address>]:<port_range> [, ...] [param*]
    示例:
listen http_proxybind :80,:443bind 10.0.0.1:10080,10.0.0.1:10443bind /run/ssl-frontend.sock user root mode 600 accept-proxy

Balance配置

  • balance:后端服务器组内的服务器调度算法
    balance <algorithm> [ <arguments> ]
    balance url_param <param> [check_post]
  • 调度算法:
    (1) roundrobin:基于权重轮询,动态算法,支持权重的运行时调整,支持慢启动;每个后端backend中最多支持4095个server
      server options: weight #
      动态算法,更改配置文件后,无需重启服务,只需重新加载服务即可
      慢启动,当新上线一台服务器后,把集群中其他服务器的访问量缓慢的调度到该服务器上,让该服务器动态平滑的负载访问数据,避免把大量的访问量瞬间调度到该服务器而导致服务器崩溃
    示例:roundrobin算法
frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvsbalance roundrobinserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check
重新加载服务(动态算法,无需重启,只需重新加载即可)
systemctl reload haproxy.service

(2) static-rr:基于权重轮询,静态算法,不支持权重的运行时调整及慢启动;后端主机数量无上限
(3) leastconn:加权最少连接,动态算法,最少连接的后端服务器优先分配接收新连接,相同连接时轮询,推荐在较长会话的场景使用,例如MySQL,LDAP等,不适合http
(4) first:根据服务器在列表中的位置,自上而下进行调度;前面服务器的连接数达到上限,新请求才会分配给下一台服务,不支持权重
(5) source:源地址hash,新连接先按权重分配,后续连接按source分配请求,实现会话绑定
  需要维护客户端ip地址hash值与服务器的对应关系表,消耗服务器内存,因此先把hash值对权重取模,按照取模所得到的值进行调度,无需记录对应关系表
  缺点:(1)源地址通过snat转换,可能存在大量私网ip客户端,无法精确进行调度。(2)一旦权重发生变化,会对服务器调度产生很大影响,需要使用一致性hash算法解决
(6) uri:
  对URI的左半部分或整个uri做hash计算,并除以服务器总权重取模,以后派发至某挑出的服务器,适用于后端缓存服务器
  <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
  左半部分:/<path>;<params>
  整个uri:/<path>;<params>?<query>#<frag>
示例:

在后端服务器生成不同的html页面,请求不同的html页面可能会调度到不同的服务器
注意:uri调度算法可以跟上hash算法
frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvsbalance urihash-type consistent   一致性hash算法server srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check
重新加载服务(动态算法,无需重启,只需重新加载即可)systemctl reload haproxy.service

(7) url_param:
  对用户请求的uri中的<params>部分中的参数的值作hash计算,并由服务器总权重相除以后派发至某挑出的服务器;通常用于追踪用户,以确保来自同一个用户的请求始终发往同一个Backend Server
  http://www.magedu.com/bbs/hello;type=title
(8) hdr(<name>):对于每个http请求,此处由<name>指定的http首部将会被取出做hash计算;并由服务器总权重相除以后派发至某挑出的服务器;无有效值的会被轮询调度
  hdr(Cookie)
示例:hdr算法

    根据请求报文头部信息做hash运算进行调度frontend webbind 172.20.120.255:80default_backend websrvsbackend websrvsbalance hdr(Host)   根据请求报文主机头信息进行调度server srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check
请求报文头部信息包括:Host  主机头   请求同一个域名,调度到固定的服务器User-Agent  浏览器类型   同一个浏览器类型,调度到固定的服务器curl命令可以模拟浏览访问服务器curl -A ie10  http://www.a.comcurl -A chrome  http://www.a.com好处:可以根据不同的浏览器类型,把请求调度到不同的服务器,如可以把手机浏览器和PC浏览的访问请求分开调度到不同的服务器cookie  根据cookie调度,绑定session会话,进行会话保持会话保持的三种方案:记录调度选择根据源ip地址判断根据cookie信息判断用户信息,把用户调度到固定的服务器上,cookie属于应用层,因此需要应用层反向代理服务器复制会话    把cookie复制到全部的服务器,会造成数据冗余会话服务器   设置专门的session服务器缺点:后端服务器出现故障,仍然会向该服务器调度访问因此,一般情况下,session信息不会存放到后端服务器上,会单独设置存储session信息的服务器,目前主流的解决方案:redis服务器集群

(9) rdp-cookie 远程桌面相关
(10) rdp-cookie(<name>)

哈希算法

  • hash-type:哈希算法
    hash-type <method> <function> <modifier>
      method:
        map-based:除权取余法,哈希数据结构是静态数组
        consistent:一致性哈希,哈希数据结构是一棵树
      function : 哈希函数,取值:sdbm,djb2,wt6
      modifier: 取值avalanche时,将修改哈希值,而非直接使用
  • default_backend <backend>
      无use_backend 匹配时,使用默认的backend,用于frontend中
  • default-server [param*]
      为backend中的各server设定默认选项
      支持配置段:defaults,listen,backend
    示例1:default_backend
    frontend webbind 172.20.120.255:80default_backend websrvs   收到请求报文,默认发送给websrvs服务器组backend websrvsbalance hdr(Host)   server srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check注意:可以根据条件判断,把满足条件的请求数据发送到默认后端服务器,不满足条件的请求数据发送到其他非默认的后端服务器,这样就可以对数据进行分流,即一个调度规则可对应多个服务器组

示例2:default-server

frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvsdefault-server inter 1000 weight 10   为服务器组设置默认值balance roundrobinserver srv1 192.168.32.130:80 check weight 2server srv2 192.168.32.131:80 check   没有设置权重,默认为10

示例3:listen指令

使用listen指令,可以把调度规则和后端服务器形成一一对应关系,而无需使用前端frontend和后端backend,不推荐这种写法listen http#frontend webbind 172.20.120.255:80#default_backend websrvs#backend websrvsbalance roundrobinserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check

配置

  • server <name> <address>[:[port]] [param*]
    定义后端主机的各服务器及其选项
    server <name> <address>[:port] [settings …]
    default-server [settings …]
    <name>:后端服务器在haproxy上的内部名称;出现在日志及警告信息
    <address>:后端服务器地址,支持使用主机名
    [:[port]]:端口映射;省略时,表示同bind中绑定的端口
    [param*]:参数
      weight <weight>:权重,默认为1
      maxconn <maxconn>:当前后端server的最大并发连接数
      backlog <backlog>:当server的连接数达到上限后的后援队列长度
      backup:设定当前server为备用服务器Sorry Server
    示例:设置backup服务器,即sorryserver
frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvsdefault-server inter 1000 weight 10balance roundrobinserver srv1 192.168.32.130:80 check weight 2server srv2 192.168.32.131:80 checkserver backupsrv 127.0.0.1:8080 check backup
注意:设置backup服务器时不能添加backlog参数,即后援队列,否则本机将无法监听80端口,另外,backup服务器的ip地址可以设置为haproxy服务器的本地回环网口的ip,内网ip地址或外网ip地址,推荐设置为内网或本地lo网卡的ip地址

健康状态检测

  • check:对当前server做健康状态检测,只用于四层检测
    注意:httpchk,“smtpchk”, “mysql-check”, “pgsql-check” and “ssl-hello-chk” 用于定义应用层检测方法
      addr :检测时使用的IP地址
      port :针对此端口进行检测
      inter <delay>:检测之间的时间间隔,默认为2000ms
      rise <count>:连续多少次检测结果为“成功”才标记为可用;默认为2
      fall <count>:连续多少次检测结果为“失败”才标记为不可用;默认为3
  • disabled:标记为不可用
      应用程序版本升级,系统维护时使用
        蓝绿发布 两套相同的环境,相互替换使用
        金丝雀发布 应用程序升级时,先升级一部分服务器供vip使用,待应用程序稳定运行一段时间后,再全部切换
        灰度发布 部分切换,逐步完成全部切换
  • redir <prefix>:将发往此server的所有GET和HEAD类的请求重定向至指定的URL
    示例:redir 重定向
    frontend webbind 172.20.120.255:80default_backend websrvsbackend websrvsbalance roundrobinserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check redir http://172.20.120.255:8080注意:使用curl命令测试时,由于redir为把请求重定向到其他链接,因此需要使用-L选项才能显示重定向的内容另外,重定向指定的主机ip地址必须为客户端能够访问的ip地址(即外网地址),否则客户端将无法访问而造成重定向失败

cookie配置

  • cookie <value>:为当前server指定cookie值,实现基于cookie的会话黏性
    cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
      <name>:cookie名称,用于实现持久连接
        rewrite:重写
        insert:插入
        prefix:前缀
        nocache:当client和hapoxy之间有缓存时,不缓存cookie
          当client和hapoxy之间有缓存时,如果cookie被缓存,当客户端访问时,会根据缓存的cookie信息把所有的请求调度到同一台服务器上,nocache是指不缓存cookie信息
          注意:每个后端服务器的cookie是固定的,后端服务器有多少个,cookie值就有多少个
    示例1:基于cookie的session sticky的实现
    backend websrvscookie WEBSRV insert nocache   定义cookie的名称,相当于K/V中的key,通过调用此名称,调用cookie值server srv1 172.16.0.6:80 weight 2 check rise 1 fall 2 maxconn 3000 cookie srv1   给cookei赋值,相当于K/V中的valueserver srv2 172.16.0.7:80 weight 1 check rise 1 fall 2 maxconn 3000 cookie srv2   给cookei赋值,相当于K/V中的value

示例2:

frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvscookie WEBSRV insert nocacheserver srv1 192.168.32.130:80 check cookie rs1server srv2 192.168.32.131:80 check cookie rs2server srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check redir http://172.20.120.255:8080
使用curl命令测试,使用-b选项在测试时添加cookie
curl -I 172.20.120.255  查看cookie值
curl -b WEBSRV=rs1 172.20.120.255   根据cookie值进行调度到固定服务器

统计接口启用相关的参数

  • stats enable
      启用统计页;基于默认的参数启用stats page
  • stats hide-version 隐藏版本
  • stats refresh <delay>
      设定自动刷新时间间隔
  • stats uri <prefix>
      自定义stats page uri,默认值:/haproxy?stats
  • stats realm <realm>
      认证时的realm,示例:stats realm : HAProxy\ Statistics
  • stats auth <user>:<passwd>
      认证时的账号和密码,可使用多次,默认:no authentication
  • stats admin { if | unless } <cond>
      启用stats page中的管理功能
    示例:
listen statsbind :9527stats enablestats hide-versionstats uri /hastatsstats realm HAPorxy\ Stats\ Pagestats auth admin1:password1stats auth admin1:password2stats refresh 3sstats admin if TRUE

知识扩展:

启用状态页frontend webbind 172.20.120.255:80default_backend websrvsstats enable       启用状态页stats hide-version    隐藏状态页haproxy的版本号stats refresh 3     设置自动刷新间隔为3sstats uri /hastatus   自定义访问状态页的uristats realm HAproxy\ statistics   设置验证提示信息,注意在配置文件中空格要进行转义才能被识别,因此HAproxy\ statistics中的\是指转义字符,是对空格进行转义,而且每一个空格都要用转义字符进行转义stats auth root:centos       设置验证用户名密码stats admin if TRUE    开启状态页管理功能,并可以设置acl权限,即什么条件下才会开启管理功能,if TRUE是指永远成立,注意TRUE为大写backend websrvscookie WEBSRV insert nocacheserver srv1 192.168.32.130:80 check cookie rs1server srv2 192.168.32.131:80 check cookie rs2
默认访问路径:http://haproxy服务器ip/haproxy?stats
注意:haproxy服务器的ip是指配置文件中监听的ip地址,即bind指令绑定的ip地址
另外,如果状态页的ip地址为公网地址,为了确保安全,除了可以改变状态的uri,还可以对状态页进行验证DRAIN  排干状态,把访问逐渐清除,清除完毕后再把机器安全下线,如果直接把服务器标记为下线会对正在访问的用户造成影响
MAINT  维护状态haproxy状态页并不需要调度到后台服务器,因此状态页可以单独定义
可将ip地址绑定在内网地址并监听一个不常用的端口如9527,只用于内部人员管理服务器,以增加安全性
listen haproxybind 192.168.32.129:9527stats enablestats hide-versionstats refresh 30stats uri /hastatusstats realm HAproxy\ statisticsstats auth root:centosstats admin if TRUE
frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvscookie WEBSRV insert nocacheserver srv1 192.168.32.130:80 check cookie rs1 maxconn 5000server srv2 192.168.32.131:80 check cookie rs2

工作模式

  • maxconn <conns>:为指定的frontend定义其最大并发连接数;默认为3000
  • mode { tcp|http|health }
      定义haproxy的工作模式
      tcp:基于layer4实现代理;可代理mysql, pgsql, ssh, ssl等协议,https时使用此模式,默认模式
      http:仅当代理协议为http时使用,CentOS中haproxy实际的默认模式
      health:工作为健康状态检查的响应模式,当连接请求到达时回应“OK”后即断开连接,较少使用
    示例:TCP模式
    listen ssh        bind :22222    定义监听端口,由于没有绑定具体ip地址,该端口会发布外网,为了防止外网访问,因此使用不常用的端口balance leastconn   最少连接算法适用于长连接,ssh远程连接属于长连接mode tcp     defaults配置段默认为http协议,使用四层调度,必须指定为tcp协议server sshsrv1 192.168.32.130:22 check  调度到后端服务器的22端口server sshsrv2 192.168.32.131:22 check  调度到后端服务器的22端口
在客户端进行访问测试ssh 172.20.120.255 -p 22222   -p选项指定端口
注意:haproxy的tcp四层调度属于伪四层调度,因为一般真正的tcp四层调度会直接转发报文,而不会更改报文中的ip地址信息代替客户端访问服务器,
但haproxy把客户端的请求报文解封装,然后把自己的ip地址封装进报文,代替客户端访问后端服务器,实现四层调度,
这就改变了请求报文中源ip地址,而后端服务器看到的源ip地址就是haproxy服务器的内网地址。

健康状态检测

  • 对后端服务器做http协议健康状态检测:通常用于backend
      option httpchk 默认向后端服务器发请求:OPTIONS / HTTP/1.0
      option httpchk <uri>
      option httpchk <method> <uri>
      option httpchk <method> <uri> <version>
        定义基于http协议的7层健康状态检测机制
      http-check expect [!] <match> <pattern>
        http协议健康状态检测响应内容或指定响应码
      注意:haproxy默认自带健康检测功能,但却是基于四层的健康检测,只针对ip地址,端口号等信息进行检测,无法识别应用层的数据。如果数据不存在,但ip地址和端口没有问题,仍然会向该服务器调度数据,因此并不完善。
      因此需要对应用层进行健康检测,即基于七层的健康检测
      关闭后端服务器网页,使用tcpdump命令抓包查看:
      tcpdump -nn -i ens33 port 80
    示例:
frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvsoption httpchk OPTIONS * HTTP/1.1\r\nHost:\ www    定义健康检测的内容和方法,注意每一个空格都要用转义字符http-check expect status 200   定义获取200状态码表示服务器处于健康状态,继续后续的调度server srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check
注意:option httpchk是基于http模式进行健康检测,因此defaults配置段中的mode必须是http模式,才能够进行健康检测

forwardfor配置

  • option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
    在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For”首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP
      [ except <network> ]:请求报请来自此处指定的网络时不予添加此首部,如haproxy自身所在网络
      [ header <name> ]:使用自定义的首部名称,而非“X-Forwarded-For”
      [ if-none ] 如果没有首部才添加首部,如果有使用默认值
  • 为指定的MIME类型启用压缩传输功能
      compression algo <algorithm> …:启用http协议的压缩机制,指明压缩算法gzip, deflate
      compression type <mime type> …:指明压缩的MIMI类型
    示例:
客户端的请求报文到达haproxy服务器后,haproxy会代替客户端访问后端服务器,
因此后端服务器看到的源ip地址是haproxy服务器的ip地址,无法看到真正的客户端ip地址。
在由haproxy发往后端主机的请求报文中添加“X-Forwarded-For”首部,其值为前端客户端的地址;用于向后端主发送真实的客户端IP。
haproxy配置文件中defaults配置段中,已经默认添加“X-Forwarded-For”首部信息:
option forwardfor     except 127.0.0.0/8    本机访问后端服务器时不添加首部信息
在后端服务器http配置文件日志格式中添加“X-Forwarded-For”字段,记录日志时能够显示该字段LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Ag
ent}i\" \"%{clientip}i\" \"{X-Forwarded-For}\"" combined也可以自定义“X-Forwarded-For”字段的名称option forwardfor       except 127.0.0.0/8 header testheader   把“X-Forwarded-For”更改为testheader
在后端服务器http配置文件日志格式中调用该名称即可
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Ag
ent}i\" \"%{clientip}i\" \"{testheader}\"" combined重启httpd服务
systemctl reload httpd
查看日志:
tail -f /var/log/httpd/access_log
192.168.32.129 - - [13/Nov/2018:21:19:07 +0800] "GET / HTTP/1.1" 200 11 "-"
"curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-" 172.20.120.193

错误页配置

  • errorfile <code> <file> 自定义错误页
      <code>:HTTP status code.
        支持200, 400, 403, 408, 500, 502, 503, 504.
      <file>:错误页文件路径
  • errorloc <code> <url>
    相当于errorloc302 <code> <url>,利用302重定向至指URL

示例1:

errorfile 400 /etc/haproxy/errorfiles/400badreq.http
errorfile 408 /dev/null # workaround Chrome pre-connect bug
errorfile 403 /etc/haproxy/errorfiles/403forbid.http
errorfile 503 /etc/haproxy/errorfiles/503sorry.http

示例2:errorloc 503 http://www.magedu.com/error_pages/503.html
示例3:

自定义错误页
[root@centos7 ~]# mkdir errorfile
[root@centos7 ~]# cd errorfile/
[root@centos7 errorfile]# vim 503.html
<h1>503,forbidden</h1>errorloc  重定向调度当返回错误码时,调度到指定的服务器上,把错误页面集中存放在某个服务器上
构建503错误进行测试
示例:backend websrvsserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 checkerrorloc 503 http://192.168.32.129:9527 errorfile 503 /etc/haproxy/errorfiles/403.http注意:503.html  需要关闭全部的后端服务器,才能够现实503错误页面

修改报文首部

  • 在请求报文尾部添加指定首部
      reqadd <string> [{if | unless} <cond>]
  • 在响应报文尾部添加指定首部
      rspadd <string> [{if | unless} <cond>]
      示例:rspadd X-Via:\ HAPorxy
  • 从请求报文中删除匹配正则表达式的首部
      reqdel <search> [{if | unless} <cond>]
      reqidel <search> [{if | unless} <cond>] 不分大小写
  • 从响应报文中删除匹配正则表达式的首部
      rspdel <search> [{if | unless} <cond>]
      rspidel <search> [{if | unless} <cond>] 不分大小写
      示例: rspidel server.*
    示例1:添加请求报文头部信息
frontend webbind 172.20.120.255:80default_backend websrvs
backend websrvsserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 checkreqadd X-Via:\ HAPorxy    注意:空格要用转义字符,每一个空格都要用一个转义字符
重启服务systemctl restart haproxy
在后端服务器配置文件日志格式中调用该头部字段“X-Via”LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" \"%{clientip}i\" %{testheader}i %{X-Via}i" combined
查看日志:192.168.32.129 - - [13/Nov/2018:22:17:25 +0800] "GET / HTTP/1.1" 200 11 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" "-" 172.20.120.193 HAPorxy

示例2:删除响应报文头部信息

配置端:前端后端都支持
frontend webbind 172.20.120.255:80default_backend websrvsrspidel server  删除响应报文中的server信息,rspidel指不区分大小写rspadd  server:\ testapache   自定义服务器名
backend websrvsserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 checkreqadd X-Via:\ HAPorxy
重启服务systemctl restart haproxy
查看响应报文头部信息,不存在server头部信息,并显示自定义的服务器名称[root@centos6 ~]# curl -I 172.20.120.255HTTP/1.1 200 OKDate: Tue, 13 Nov 2018 14:35:19 GMTLast-Modified: Mon, 12 Nov 2018 00:38:15 GMTETag: "b-57a6ceaa55e56"Accept-Ranges: bytesContent-Length: 11Content-Type: text/html; charset=UTF-8server: testapache    自定义服务器名称

连接超时

  • timeout client <timeout>
      客户端最长空闲连接超时时长 默认单位是毫秒
  • timeout server <timeout>
      后端服务器最长空闲连接超时时长
  • timeout http-keep-alive <timeout>
      持久连接的持久时长
  • timeout http-request <timeout>
      一次完整的HTTP请求的最大等待时长
  • timeout connect <timeout>
      成功连接后端服务器的最大等待时长
  • timeout client-fin <timeout>
      客户端半连接的空闲时长
  • timeout server-fin <timeout>
      后端服务器半连接的空闲时长

3、ACL

ACL

  • acl:访问控制列表(ACL)的使用提供了一个灵活的解决方案来执行内容交换,并且通常基于从请求中提取的内容、响应或任何环境状态进行决策
    acl <aclname> <criterion> [flags] [operator] [<value>] …
      <aclname>:ACL名称,可使用字母 数字 : . - _ ,区分字符大小写
      <criterion>: 比较的标准和条件
  • <value>的类型:
      - boolean
      - integer or integer range
      - IP address / network
      - string (exact, substring, suffix, prefix, subdir, domain)
      - regular expression
      - hex block
  • <flags>
      -i 不区分大小写
      -m 使用指定的pattern匹配方法
      -n 不做DNS解析
      -u 强制每个ACL必须唯一ID,否则多个同名ACL或关系
      – 强制flag结束. 当字符串和某个flag相似时使用
  • [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进行匹配
  • acl作为条件时的逻辑关系:
      - 与:隐式(默认)使用
      - 或:使用“or” 或 “||”表示
      - 否定:使用“!“ 表示
    示例:
    if invalid_src invalid_port 与关系if invalid_src || invalid_port 或if ! invalid_src 非
  • <criterion> :各种条件
      dst 目标IP
      dst_port 目标PORT
      src 源IP
      src_port 源PORT
      示例:acl invalid_src src 172.16.100.200
    示例:
listen haproxybind 192.168.32.129:9527acl valid_src src 192.168.32.1   定义acl规则valid_srcstats enablestats hide-versionstats refresh 30stats uri /hastatusstats realm HAproxy\ statisticsstats auth root:centosstats admin if valid_src   调用acl规则valid_src,只有满足该规则才能查看状态页
取反:stats admin if ! valid_src   对该命令取反是指不满足条件的主机无法使用管理功能,即图形界面下的可选框功能
  • 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
      path_dir : subdir match
      path_dom : domain match
      path_end : suffix match
      path_len : length match
      path_reg : regex match
      path_sub : substring match
    示例:ACL path
path_beg /images/
path_end .jpg .jpeg .png .gif
path_reg ^/images.\*\.jpeg$
path_sub image
path_dir jpegs
path_dom magedu/images/jpegs/20180123/logo.jpg
  • url : string
      提取请求中的URL。一个典型的应用是具有预取能力的缓存,以及需要从数据库聚合多个信息并将它们保存在缓存中的网页门户入口,推荐使用path
      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
  • req.hdr([<name>[,<occ>]]) : string
      提取在一个HTTP请求报文的首部
      hdr([<name>[,<occ>]]) : exact string match
      hdr_beg([<name>[,<occ>]]) : prefix match
      hdr_dir([<name>[,<occ>]]) : subdir match
      hdr_dom([<name>[,<occ>]]) : domain match
      hdr_end([<name>[,<occ>]]) : suffix match
      hdr_len([<name>[,<occ>]]) : length match
      hdr_reg([<name>[,<occ>]]) : regex match
      hdr_sub([<name>[,<occ>]]) : substring match
    示例:
acl bad_agent hdr_sub(User-Agent) -i curl wegt
block if bad_agent
  • status : integer
      返回在响应报文中的状态码

示例:

自定义错误页
[root@centos7 ~]# mkdir errorfile
[root@centos7 ~]# cd errorfile/
[root@centos7 errorfile]# vim 503.html
<h1>503,forbidden</h1>
客户端ip:172.20.120.193
(1)定义acl规则为无效的源ip地址frontend webbind 172.20.120.255:80default_backend websrvsrspidel serverrspadd  server:\ testapacheacl invalid_src src 172.20.120.193   定义acl规则无效的源ip地址block if invalid_src      调用acl规则,block意为阻止该acl规则errorfile 403 /etc/haproxy/errorfiles/403.http(2)定义acl规则为阻止以test为前缀的访问页面frontend webbind 172.20.120.255:80default_backend websrvsrspidel serverrspadd  server:\ testapacheacl invalid_page path_beg /test  定义acl规则为以test为前缀的访问请求block if invalid_page  调用acl规则,block意为阻止该acl规则errorfile 403 /etc/haproxy/errorfiles/403.http
(3)定义浏览器类型frontend webbind 172.20.120.255:80default_backend websrvsrspidel server rspadd  server:\ testapacheacl bad_agent hdr_sub(User-Agent) -i curl wegt   定义acl规则为curl和wget浏览器类型,并且不区分大小写block if bad_agent    调用acl规则,block意为阻止该acl规则backend websrvsserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check
测试:
wget -O - -q  http://www.a.com/index.html
curl   http://www.a.com

预定义ACL

ACL名称 等价于 说明
TRUE always_true 总是匹配
FALSE always_false 从不匹配
HTTP req_proto_http 匹配HTTP协议
HTTP_1.0 req_ver 1.0 匹配HTTP协议1.0
HTTP_1.1 req_ver 1.1 匹配HTTP协议1.1
HTTP_CONTENT hdr_val(content-length) gt 0 匹配已存在内容长度
HTTP_URL_ABS url_reg [/:]*?/ 匹配URL绝对路径
HTTP_URL_SLASH url_beg / 匹配URL相对路径
HTTP_URL_STAR url * 匹配 URL 等于 “*”
LOCALHOST src 127.0.0.1/8 匹配从localhost来的连接
METH_CONNECT method CONNECT 匹配HTTP CONNECT方法
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_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
WAIT_END wait_end wait for end of content analysis

示例:

frontend webbind 172.20.120.255:80default_backend websrvsblock if METH_HEAD    调用并阻止预定义aclMETH_HEAD
backend websrvsserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check使用curl命令测试:
可以查看页面内容,但不能查看报文头部信息
[root@centos6 ~]# curl 172.20.120.255
RS1 Server
[root@centos6 ~]# curl -I 172.20.120.255
HTTP/1.0 403 Forbidden
Cache-Control: no-cache
Connection: close
Content-Type: text/html

配置

  • use_backend <backend> [{if | unless} <condition>]
      当if/unless一个基于ACL的条件匹配时切换指定backend
  • block { if | unless } <condition>
      阻止7层请求if/unless一个条件匹配
    示例:
    acl invalid_src src 172.16.200.2block if invalid_srcerrorfile 403 /usr/share/haproxy/403.http
  • http-request { allow | deny |add-header <name> <fmt> |set-header <name> <fmt> } [ { if | unless } <condition> ]
      对7层请求的访问控制
    示例:基于ACL的动静分离
frontend web \*:80acl url_static path_beg -i /static /images /javascript /stylesheetsacl url_static path_end -i .jpg .gif .png .css .js .html .txt .htmuse_backend staticsrvs if url_staticdefault_backend appsrvs
backend staticsrvsbalance roundrobinserver staticsrv1 192.168.32.129:80 check
backend appsrvsbalance roundrobinserver app1 192.168.32.130:80 checkserver app1 192.168.32.131:8080 check

配置

  • tcp-request connection {accept|reject} [{if | unless} <condition>]
      根据第4层条件对传入连接执行操作
    示例:
listen ssh        bind :22222    定义监听端口,由于没有绑定具体ip地址,该端口会发布外网,为了防止外网访问,因此使用不常用的端口balance leastconn   最少连接算法适用于长连接,ssh远程连接属于长连接mode tcp     defaults配置段默认为http协议,使用四层调度,必须指定为tcp协议server sshsrv1 192.168.32.130:22 check  调度到后端服务器的22端口server sshsrv2 192.168.32.131:22 check  调度到后端服务器的22端口
在客户端进行访问测试
ssh 172.20.120.255 -p 22222   -p选项指定端口
注意:haproxy的tcp四层调度属于伪四层调度,因为一般真正的tcp四层调度会直接转发报文,而不会更改报文中的ip地址信息代替客户端访问服务器,
但haproxy把客户端的请求报文解封装,然后把自己的ip地址封装进报文,代替客户端访问后端服务器,实现四层调度,
这就改变了请求报文中源ip地址,而后端服务器看到的源ip地址就是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 }
      注意:haproxy服务器对外使用https进行加密传输确保安全,对内则使用http协议传输即可(由于内网能够确保安全性),因此haproxy服务器也可以称为https的卸载器
    示例:HAProxy支持https协议
生成自签名证书:
cd  /etc/pki/tls/certs
[root@centos7 certs]# make a.pem
umask 77 ; \
PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
/usr/bin/openssl req -utf8 -newkey rsa:2048 -keyout $PEM1 -nodes -x509 -days 365 -out $PEM2  ; \
cat $PEM1 >  a.pem ; \
echo ""    >> a.pem ; \
cat $PEM2 >> a.pem ; \
rm -f $PEM1 $PEM2
Generating a 2048 bit RSA private key
...............................................................................................................................................................................................................................+++
.................+++
writing new private key to '/tmp/openssl.vZ5uCN'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:beijing
Locality Name (eg, city) [Default City]:beijing
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:opt
Common Name (eg, your name or your server's hostname) []:www.a.com
Email Address []:cp a.pem /etc/haproxy/
vim /etc/haproxy/haproxy.cfglisten haproxybind 192.168.32.129:9527acl valid_src src 192.168.32.1stats enablestats hide-versionstats refresh 30stats uri /hastatusstats realm HAproxy\ statisticsstats auth root:centosstats admin if valid_srcfrontend webbind 172.20.120.255:80bind 172.20.120.255:443 ssl crt /etc/haproxy/a.pem   使用ssl加密传输,监听443端口,调用证书crt并指定证书路径redirect scheme https if ! { ssl_fc }   使用redirect指令把http重定向到httpsdefault_backend websrvsbackend websrvsserver srv1 192.168.32.130:80 checkserver srv2 192.168.32.131:80 check
测试:
curl -k https://www.a.com   测试访问https协议
在后端服务器查看日志,发现传输协议仍然是http协议

知识扩展:http重定向https

实现http重定向https
vim /etc/haproxy/haproxy.cfgfrontend webbind 172.20.120.255:80bind 172.20.120.255:443 ssl crt /etc/haproxy/a.pem   使用ssl加密传输,调用证书crt并指定证书路径redirect scheme https if ! { ssl_fc }   使用redirect指令把http重定向到httpsdefault_backend websrvs
测试:
[root@centos6 ~]# curl -I http://www.a.com    查看报文头部是否有返回重定向响应码
HTTP/1.1 302 Found        302状态码表示重定向
Cache-Control: no-cache
Content-length: 0
Location: https://www.a.com/
Connection: close

知识扩展:自定义添加报文头部信息X-Forwarded-Port

自定义添加报文头部信息X-Forwarded-Port
vim /etc/haproxy/haproxy.cfgfrontend webbind 172.20.120.255:80bind 172.20.120.255:443 ssl crt /etc/haproxy/a.pemredirect scheme https if !{ ssl_fc }http_request set-header X-Forwarded-Port %[dst_port]default_backend websrvs
在后端服务器配置文件日志格式中添加自定义字段X-Forwarded-Port
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Ag
ent}i\" \"%{clientip}i\" %{testheader}i %{X-Via}i %{X-Forwarded-Port
}i" combined测试:
在客户端测试
curl -kL http://www.a.com
curl -kL https://www.a.com
在后端服务器查看日志,是否记录80和443端口号

Linux服务篇--反向代理及负载均衡器Haproxy相关推荐

  1. Nginx中配置服务的反向代理(服务器集群技术)

    需求:安装两个tomcat服务,通过nginx反向代理. 1:安装两个及以上tomcat 2:配置tomcat 修改端口:打开bin目录下的server.xml文件 修改下面三个端口, 不能重复防止冲 ...

  2. 【转】使用IIS做HTTP和WebSocket服务的反向代理

    反向代理对于服务器来说是非常实用的功能,可以将毫不相关的网站部署到同一个域名下,对于使用docker的人来说可以免去大量配置上的麻烦.它还能将HTTP流量转换成HTTPS,多个服务只需要一个证书就能解 ...

  3. linux 查看目录拓扑图,Linux服务篇之九:构建Cacti监控平台

    Linux服务篇之九:构建Cacti监控平台 作为一名Linux SA,日常最重要的就是保证网站正常稳定的运行,我们需要实时监控网站.服务器的运行状态,这时需要借助开源软件(cacti.nagios. ...

  4. Linux服务篇--openssh服务

    Linux高级篇–SSH服务 一. SSH ssh: secure shell, protocol, 22/tcp, 安全的远程登录 具体的软件实现:   OpenSSH: ssh协议的开源实现,Ce ...

  5. 精灵商场项目(五)--虚拟机Linux使用+Nginx反向代理

    文章目录 一.虚拟机Linux使用 1.1 Linux 介绍和使用 1.2 虚拟机配置 1.3 检查是否正常连接 1.4 虚拟机克隆 1.5 LinuxIP划分和链接 1.6 Xshell 1.6.1 ...

  6. Linux系统——Nginx反向代理与负载均衡

    集群 集群是指一组(若干个)相互独立的计算机,利用高速通信网路组成的一个较大的计算机服务系统,每个集群节点(即集群中的每台计算机)都是运用各自服务的独立服务器.这些服务器之间可以彼此通信,协同向用户提 ...

  7. Linux服务篇--LAMP架构

    本章概要 LAMP介绍 PHP配置 LAMP部署和相关应用配置 使用Xcache实现加速访问 PHP-FPM模式 源码编译LAMP 编译安装FPM模式的LAMP 1.LAMP介绍 LAM(M)P:   ...

  8. Linux服务篇--http协议和Apache

    本章概要 SOCKET概念 http协议 Httpd介绍 Httpd2.2配置 Httpd2.4配置 编译安装httpd 跨网络的主机间通讯 在建立通信连接的每一端,进程间的传输要有两个标志:   I ...

  9. Linux 下 nginx反向代理与负载均衡

    前面几篇记录下nginx的基本运功,代理服务器的访问,这里来试验下nginx的反向代理. 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给 ...

最新文章

  1. Project Server的页面如何修改Text
  2. vue.js+vscode+visual studio在windows下搭建开发环境
  3. 新一代海量数据搜索引擎 TurboSearch 来了!
  4. mdadm中文man帮助
  5. Apache 简单设置虚拟主机
  6. 转: iptables数据包处理流程
  7. 统计叶子结点c语言,统计二叉树中叶子结点个数
  8. 找回HDFS corrupted文件残留数据
  9. 一阶导数和二阶导数的一些性质
  10. 响应式原理(Vue2.x)下篇
  11. 分布式的坑(队列、缓存、分库分表、事务)
  12. 2019 计蒜之道 初赛 第一场(A. 商汤的AI伴游小精灵)
  13. Nexus5刷Firefox OS 2.0
  14. Angular + PrimeNG 安装配置
  15. 图像处理之基础---去污算法
  16. 当谈判处于下风怎么办?五大策略助你逆势翻盘
  17. 服装制造企业的云ERP管理
  18. Image Pyramid
  19. 与finally单独使用的是try
  20. 文化的影响:整体感知与分析感知

热门文章

  1. Linux Command dnf 软件包管理
  2. 国内课题基金英文翻译
  3. 新浪微博客户端源代码-新浪微博OAuth2.0接口
  4. ONLYOFFICE Docs 如何与 Alfresco 连接集成
  5. Unity3D一些Tips
  6. 寻找蒙赫阵列(monge array)的每行的最小值
  7. Apache Shiro Padding Oracle Attack (Shiro-721)漏洞复现
  8. 集成电路产业人才专项能力提升培训班正式开课
  9. THE HERMIT
  10. 用C语言求排列组合数