美文网首页
HAProxy(一)之常用配置介绍,ACL详解

HAProxy(一)之常用配置介绍,ACL详解

作者: 贰零壹柒_fc10 | 来源:发表于2017-09-10 22:01 被阅读0次

    1、HAProxy简介

    HAProxy 是一款高性能TCP/HTTP 反向代理负载均衡服务器,具有如下功能:

    • 根据静态分配的cookies完成HTTP请求转发
    • 在多个服务器间实现负载均衡,并且根据HTTP cookies 实现会话粘性
    • 主备服务器切换
    • 接受访问特定端口实现服务监控
    • 实现平滑关闭服务,不中断已建立连接的请求响应,拒绝新的请求
    • 在请求或响应HTTP报文中添加,修改,或删除首部信息
    • 根据正则规则阻断请求
    • 提供带有用户认证机制的服务状态报告页面

    HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持或七层处理。HAProxy运行在时下的硬件上,完全可以支持数以万计的 并发连接。并且它的运行模式使得它可以很简单安全的整合进您当前的架构中, 同时可以保护你的web服务器不被暴露到网络上。

    HAProxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的并发连接数。多进程或多线程模型受内存限制 、系统调度器限制以及无处不在的锁限制,很少能处理数千并发连接。事件驱动模型因为在有更好的资源和时间管理的用户端(User-Space) 实现所有这些任务,所以没有这些问题。此模型的弊端是,在多核系统上,这些程序通常扩展性较差。这就是为什么他们必须进行优化以 使每个CPU时间片(Cycle)做更多的工作。

    HAProxy实际工作中,它占用用户空间时间要比内核运行时间少20倍,所以对系统参数调优是十分必要的一项工作。

    另外衡量一个负载均衡服务器主要考量三个指标:

    1、session rate

    此项指标非常重要,它决定了一个load balancer 能不能分发所有接受的请求。这项指标通常是由CPU性能决定。测量指标的大小跟传输的每个对象的大小有关,通常用空对象来测试,Session rates 在 100,000 sessions/s 左右,使用 Xeon E5 在 2014测试。
    

    2、session concurrency

    该指标与前一指标相关联。这一指标与服务器内存和系统可以处理的文件描述符数量有关。 通常每个session占用34KB,即大概3W个session占用1GB内存空间,实际上,socket buffer也会占用内存空间,2W个session socket占用1GB内存。
    

    3、data forwarding rate

    这一指标与 session rate 相对立,它的衡量单位通常是 Megabytes/s (MB/s), 或者 Gigabits/s (Gbps)。传输较大的对象有利于该指标的提升,因为较大的对象传输可以减少session建立和关闭浪费的时间。而测量session rate 则在传输小对象时有利于指标提升。haproxy 在2014年使用 Xeon E5 测试成绩为40 Gbps。
    

    2、HAProxy程序环境

    本文环境:CentOS7, haproxy 1.5 通过yum 安装

    程序环境:
        配置文件:/etc/haproxy/haproxy.cfg
            Unit File: haproxy.service
            主程序:/usr/sbin/haproxy
            
    配置文件:
        global:全局配置段
            进程及安全配置相关的参数
            性能调整相关的参数
            Debug相关的参数
        proxies:代理配置段
            defaults:为frontend, backend以及listen提供默认配置;
            frontend:前端,相当于Nginx中的server{ ... };
            backend:后端,相当于nginx中的upstream { ...  };
            listen:前后端的直接组合;
        **关于前端与后端的关系:一个前端可以指向多个后端;同时一个后端可以被多个调用。
    
    

    3、HAProxy配置详解

    3.1 global配置段

    3.1.1 进程相关配置

    • 定义日志系统相关属性

        log <address> [len <length>] <facility> [max level [min level]]
      

    harpoxy 将日志发送到指定的rsyslog服务器,在本地记录也要开启rsyslog服务;
    全局端最多可配置两个log 服务器;
    < address> :日志服务器地址
    [ len ] 指定记录的日志最大长度

    • 定义运行用户,所属组
      1、username
      2、group groupname

    • 运行方式
      1、意味着后台守护进程

    3.1.2 参数调优

    maxconn <number>:设定单haproxy进程的最大并发连接数;
    maxconnrate <number>:设定单haproxy进程每秒接受的连接数;
    maxsslconn <number>:设定单haproxy进程的ssl连接最大并发连接数;
    maxsslrate <number>:单haproxy进程的ssl连接的创建速率上限;
    spread-checks <0..50, in percent>:避免对于后端检测同时并发造成
    的问题,设置错开时间比,范围0到50,一般设置2-5较好。
    

    3.1.3 用户列表

    用于对haproxy 状态监控页面的用户认证。至少要定义一个用户列表并且添加一个用户
    密码可以加密或明文。

    Example:

    userlist L1
      group G1 users tiger,scott
      group G2 users xdb,scott
    
      user tiger password $6$k6y3o.eP$JlKqe4(...)xHSwRv6J.C0/D7cV91
      user scott insecure-password elgato
      user xdb insecure-password hello
    
    userlist L2
      group G1
      group G2
    
      user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1
      user scott insecure-password elgato groups G1,G2
      user xdb insecure-password hello groups G2
    
    

    3.2 proxy配置段

    这部分配置在下列定义区域下使用

        - defaults  < name >
        - frontend < name >
        - backend  < name >
        - listen   < name >
    

    “defaults” 区域定义了frontend,backend,listen 的默认参数
    “frontend" 区域描述了接收客户端请求的监听配置
    "backend" 区域描述接受请求处理的后端服务器配置
    "listen" 区域描述一组前端和后端直接一对一绑定的组配置

    HAProxy 配置的关键字与区域限制特性,即有些关键字在某个区域不可以使用

    下面开始讲解关键字的用法

    3.2.1 常用配置指令

    1. bind [<address>]:<port_range> [, ...] [param*]
    

    仅在frontend和listen区域使用。定义服务监听端口地址等参数
    [ param* ] 参数根据系统而定,一般不需要指定

    example:

    bind :80     #监听本机所有IP的80端口
    bind *:80    #监听本机所有IP的80端口
    bind 192.168.12.1:8080,10.1.0.12:8090
    
    2. mode {tcp|http|health}
    

    tcp:基于layer4实现代理,可代理大多数基于tcp的应用层协议,例如ssh/mysql/pgsql等;
    http:客户端的http请求会被深度解析;
    health:工作为健康状态检查响应模式,当请求到达时仅回应“OK”即断开连接;

    3. balance <algorithm> [ <arguments> ]
       balance url_param <param> [check_post]
    

    在backend区域定义调度算法:

    < algorithm > 如下:

    • roundrobin:
    带有权重的轮询调度算法;
    server后面使用weight来定义权重;
    动态算法:支持权重的运行时调整,支持慢启动(缓慢接收大量请求在刚启动时);仅支持最大4095个后端活动主机
    
    • static-rr:
    静态的roundrobin算法;
    不支持权重的运行时调整及慢启动;但后端主机数量无限制;
    
    • leastconn:
    带权重的最少连接分配动态算法;
    适用长连接应用协议,如ssh等
    
    • first:
    第一优先算法;
    如果第一个服务端可接受请求则总是把连接分配给它,直到第一个服务端处于繁忙,分配给下一个,顺序按服务端的数字ID从小到大排列
    
    • source
    源IP hash 算法;
    该算法保证在后端服务器组没有减少或增加的情况下,能将来自同一客户端IP的请求分配至同一个服务端;
    该算法适合在无法使用cookie插入的TCP模式下使用
    动态算法或静态算法取决于hash-type;
    
    • uri
    uri hash 算法;
    该算法hash uri 的查询标记的左侧部分,或者指定whole 参数时hash全部uri;
    该算法保证访问同一uri的请求分配至同一服务端,适用于后端为缓存服务器的情况,以提高缓存命中率;
    动态算法或静态算法取决于hash-type;
    另外:该算法支持追加参数[ < arguments > ]:
    (1) whole :hash完整uri 
    (2) len number:hash指定uri的长度
    (3) depth nubmer:hash指定目录深度,每个"/"代表一个深度
    
    • uri_param
    param hash 算法;
    对用户请求的url中的< param >部分中的指定的参数的值(uri中"="部分)作hash计算;
    该算法适用于有用户识别参数的uri ,它保证同一user id 的请求分配至同一服务端;
    如果check_post 标识启用,则在uri中没有找到"?"参数时,对HTTP Post 请求实体查找参数声明;
    动态算法或静态算法取决于hash-type;
    

    Example:

    balance url_param userid
    balance url_param session_id check_post 64
    
    • hdr(< name >)
      HTTP 首部字段hash算法;

    指定的http首部将会被取出做hash计算。如果没有值,则降至轮询调度;
    动态算法或静态算法取决于hash-type;

    4. hash_type < method >
    

    在balance 指令中选定与hash 有关的算法,都会受此影响。
    默认采取的方法为map-based
    < method > 如下:

    • map-based:取模法,hash数据结构是静态数组;
      该hash是静态的,不支持在线调整权重,不支持慢启动;

    该算法调度平滑,后端服务器能够均匀承受负载;
    缺点也是明显的:当服务器的总权重发生变化时,即有服务器上线或下线,都会导致调度结果整体改变。如果想避免此种情况应采用consistent 方法;

    • consistent:一致性哈希,哈希的数据结构是“树”;
      该hash是动态的,支持在线调整权重,支持慢启动

    每一个server 会在"树"中出现多次, 在树中查找hash key,并选择最近的server;
    该方法的优点在于,当服务器的总权重发生变化时,对调度结果影响是局部的,不会引起大的变动。所以十分适合缓存服务器;
    缺点:该算法不够平滑,很容易导致后端服务器负载不均衡。所以很有必要对服务器的权重以或者服务器ID进行调整;
    为保持均匀负载,应该保证所有服务器ID保持一致;

    5. server <name> <address>[:[port]] [param*]
    

    default-server [param*]
    server用于在backend和listen中定义一个主机;
    default-server 用于设定server的默认参数;

    [param*] 如下:

    • weight < weight >:当前server的权重;
    • id < number > :设定server ID
    • cookie < value >:为当前server指定其cookie值,此值会在收到请求报文时进行检测,其功能在于实现基于cookie会话保持;
    • check:对当前server进行健康状态检测;
      inter < delay >:时间间隔;
      rise < count >:判定为“健康”状态需要检测的次数,默认2;
      fall < count >:判定为“不健康”状态需要检测的次数,默认3;
      addr <ipv4|ipv6>:健康状态检测时使用的地址;
      port < port >:健康状态检测时使用的端口;
      注意:默认为传输层检测,即探测端口是否能响应;需要执行应用层检测,则需要httpchk, smtpchk, mysql-check, pgsql-check, ssl-hello-chk;
    • maxconn <maxconn>:当前server的最大并发连接数;
    • maxqueue <maxqueue>:当前server的等待队列的最大长度;
    • disabled:将主机标记为不可用;
    • redir <prefix>:将发往当前server的所有请求GET和HEAD类的请求均重定向至指定的URL;

    Examples :

    server first  10.1.1.1:1080 id 3 cookie first  check inter 1000 maxconn 10000 maxqueue 2000
    server second 10.1.1.2:1080 id 4 cookie second check inter 1000
    
    6. option httpchk
       option httpchk <uri>
       option httpchk <method> <uri>
       option httpchk <method> <uri> <version>    
    

    基于http协议作7层健康状态检测机制,默认是基于tcp层进行检测;
    TCP 模式也可以使用该检测机制
    < method > < uri > < version >:请求报文的超始行;
    method 默认方法为 OPTIONS;返回状态码2XX,3XX意味成功;

    Examples :

    # Relay HTTPS traffic to Apache instance and check service availability
    # using HTTP request "OPTIONS * HTTP/1.1" on port 80.
    backend https_relay
        mode tcp
        option httpchk OPTIONS /index.html HTTP/1.1\r\nHost:\ www
        server apache1 192.168.1.1:443 check port 80
    
    
    7. http-check expect [!] <match> <pattern>
    

    定义检测有效期望值;
    ! 表示认定的错误值;< match > 可取值为:

    • status < string >
    • rstatus < regex > 正则方式
    • string < string >
    • rstring < regex >

    Examples :

    # only accept status 200 as valid
    http-check expect status 200
    
    # consider SQL errors as errors
    http-check expect ! string SQL\ Error
    
    # consider status 5xx only as errors
    http-check expect ! rstatus ^5
    
    # check that we have a correct hexadecimal tag before /html
    http-check expect rstring <!--tag:[0-9a-f]*</html>
    
    
    8. cookie <name> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <domain> ]* [ maxidle <idle> ] [ maxlife <life> ]
    

    启用基于cookie的会话黏性,要结合server指定的cookie参数一起实现;
    常用形式:cookie WEBSRV insert nocache indirect

    Example:

    backend websrvs
    balance     roundrobin
    cookie WEBSRV insert nocache indirect
    server      web1 10.1.0.68:80 check weight 2 maxconn 5000 cookie web1
    server      web2 10.1.0.69:80 check weight 1 maxconn 3000 cookie web2
    
    9. default_backend <backend>
    

    当use_backend 的使用规则没有被匹配时,由default_backend 指定默认服务器组;
    关于use_backend 使用后续会在acl 章节中讲解;

    3.2.2 log 相关

    frontendbackend定义日志记录机制;

    log global  :使用全局定义的日志记录方式
    log <address> [len <length>] <facility> [<level> [<minlevel>]]:自定义
    no log :不记录
    capture request header <name> len <length>
    -->记录请求报文中的指定的首部的值于日志中;len用于指定要记录的信息的长度;
    capture response header <name> len <length>
    -->记录响应报文中的指定的首部的值于日志中;len用于指定要记录的信息的长度;
    示例:
        capture request header Referer len 30
    

    3.2.3 自定义错误页面

    errorfile <code> <file>
    

    < code > 指定HTTP返回的状态码。200, 400, 403, 408, 500, 502, 503, and 504 可使用;
    < file > 指定一个文件代替HTTP响应;

    Example:

    errorfile 503 /etc/haproxy/errorfiles/503sorry.http
    
    - errorloc <code> <url>
    - errorloc302 <code> <url>
    

    发生错误时由haproxy重定向至指定url,以上两个命令等同,响应状态码为302

    Example:

    errorloc 503 http://www.mydomain.com/index...
    
    - errorloc303 <code> <url>
    

    响应状态码为303,表示以GET方法重新请求页面

    3.2.4 修改请求或响应报文首部

    option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
    

    HAProxy把请求报文发往后端主机之前在请求报文添加“X-Forwared-For”首部
    目的为使后端服务器可记录发出请求客户端的IP地址
    [ except < network> ] :选择排除的网络地址
    [ header < name> ] :不使用X-Forwared-For,自定义名称
    [ if-none ]:有时请求原来带有该字段,此时不再更改

    Example:option forwardfor if-none

    reqadd  <string> [{if | unless} <cond>]
    rspadd <string> [{if | unless} <cond>]
    

    在HTTP请求或响应首部内容尾部添加值
    Example:rspadd X-Via: HAProxy/1.5

    reqdel  <search> [{if | unless} <cond>]
    reqidel <search> [{if | unless} <cond>]  (不区分大小写)        
    

    删除HTTP请求中正则匹配的所有首部

    rspdel  <search> [{if | unless} <cond>]
    rspidel <search> [{if | unless} <cond>]  (不区分大小写)
    

    删除HTTP响应中正则匹配的所有首部。属于安全加强策略,删除一些服务器版本信息,防止针对攻击
    Example:rspidel Server.*

    3.2.5 超时时长设定

    timeout client <timeout>
    

    设定客户端最大非活动时长, 默认单位是ms;最好与timeout server一致

    timeout server <timeout>
    

    设定服务端最大非活动时长, 默认单位是ms;

    timeout connect <timeout>
    

    设定最大与服务端建立连接的时长

    timeout http-keep-alive <timeout>
    

    设定最大等待新请求的空闲时长,默认单位为ms;

    timeout client-fin <timeout>
    

    在客户端侧设定半关闭连接非活动超时

    timeout server-fin <timeout>
    

    在服务端侧设定半关闭连接非活动超时

    Example:

    defaults http
    timeout connect 5s
    timeout client 30s
    timeout server 30s
    timeout client-fin 10s
    timeout http-keep-alive 500
    
    

    4、使用ACLs和获取样本

    Haproxy 能够从请求报文,响应报文,从客户端或者服务端信息,从表,环境信息等等中提取数据。提取这样的数据的动作我们称之为获取样本。进行检索时,这些样本可以用来实现各种目的,比如作为粘滞表的键,最常用的用途是,根据预定义的模式来进行匹配。
    访问控制列表(ACL)提供一个灵活方案进行内容切换,或者在从请求,响应,任何环境状态中提取的数据基础之上做出决策。控制列表的原则很简单:

    • 从数据流,表,环境中提取数据样本
    • 对提取的样本可选地应用格式转换
    • 对一个样本应用一个或多个模式匹配
    • 当模式匹配样本时才执行动作

    执行的动作通常是阻断请求,选择一个后端服务器或者添加一个HTTP首部
    需要提醒的是,获取的样本数据不光可以使用在acl中,也可以使用别处,例如记录log中

    定义ACL的语法为:

    acl <aclname> <criterion> [flags] [operator] [<value>] ...
    

    这样一条语句建立了一个acl 测试;
    这些测试应用在请求或响应中被"标准"< criterion > 部分所指定的内容,而且可以指定[ flags] 进行特性调整,有些< criterion > 支持操作符[operator] 进行运算,同时一些转换格式的关键字可以跟在< criterion >后面,使用" , "隔开。而值[< value >] 要求被
    < criterion > 所支持的数据形式,多个值使用空格分隔。
    < criterion > 通常是指获取样本方法的名称。使用一个获取样本方法,暗含着其输出样本的类型,类型是以下列出的一种:

    • boolean
    • integer (signed or unsigned)
    • IPv4 or IPv6 address
    • string
    • data block

    ACL引擎匹配数据使用的模式类型如下:

    • boolean
    • integer or integer range
    • IP address / network
    • string (exact, substring, suffix, prefix, subdir, domain)
    • regular expression
    • hex block

    ACL flags 可用列表如下:

    • -i : 忽略大小写
    • -f filename : 从文件中载入模式
    • -m method : 指定模式匹配方法
    • -n : 禁止DNS解析
    • -M : -f 载入的文件作为映射文件使用
    • -u : 强制ACL的名称唯一
    • -- : 强制结束flag结束,避免了字符串中含有的- 引起混淆
      其中flag中的 -m 选项可使用的模式匹配方法如下,需要说明的是有些方法已被默认指定无需声明,例如int,ip
    • "found" : 只是用来探测数据流中是否存在指定数据,不进行任何比较
    • "bool" : 检查结果返回布尔值。匹配没有模式,可以匹配布尔值或整数,不匹配0和false,其他值可以匹配
    • "int" : 匹配整数类型数据;可以处理整数和布尔值类型样本,0代表false,1代表true
    • "ip" : 匹配IPv4,IPv6地址类型数据。该模式仅被IP地址兼容,不需要特别指定
    • "bin" : 匹配二进制数据
    • "len" : 匹配样本的长度的整数值
    • "str" : 精确匹配,根据字符串匹配文本
    • "sub" : 子串匹配,匹配文本是否包含子串
    • "reg" : 正则匹配,根据正则表达式列表匹配文本
    • "beg" : 前缀匹配,检查文本是否以指定字符串开头
    • "end" : 后缀匹配,检查文本是否以指定字符串结尾
    • "dir" : 子目录匹配,检查部分文本中以" / "作为分隔符的内容是否含有指定字符串
    • "dom" : 域匹配。检查部分文本中以" . "作为分隔符的内容是否含有指定字符串

    如果获取样本值为整数,数值比较符可使用,:

    eq : true if the tested value equals at least one value
    ge : true if the tested value is greater than or equal to at least one value
    gt : true if the tested value is greater than at least one value
    le : true if the tested value is less than or equal to at least one value
    lt : true if the tested value is less than at least one value

    想必前面一堆理论性的论述已经把大家搞的晕头转向,下面结合获取样本方法和访问控制动作指令具体阐述ACL使用方法

    先介绍控制动作指令

    • layer 4 传输层控制指令

        tcp-request connection <action> [{if | unless} <condition>]
      

    对tcp请求控制指令:
    < condition > 即为ACL定义的访问控制列表
    < action > 常用值有 "accept", "reject"

    • layer 7 应用层控制指令
    #阻断符合ACL的访问请求
    block { if | unless } <condition> 
    #http请求的控制指令
    http-request { allow | deny}  [ { if | unless } <condition> ]
    
    
    • 后端主机调用

        #根据条件来调用指定后端
        use_backend <backend> [{if | unless} <condition>]
      
    • 由ACL定义的多个< condition > 组成联合条件,逻辑符为

    • and (默认操作符,可省略)

    • or (或者使用 "||")

    • ! (取反)

    4.1 获取内部状态样本

    # 与后端建立会话速率,每秒钟建立的新会话
    be_sess_rate([<backend>]) : integer
    

    Example :

    # 某后端被请求过于繁忙,则重定向至错误页
        mode http
        acl being_scanned be_sess_rate gt 100
        redirect location /denied.html if being_scanned
    

    4.2 获取layer 4 样本

    在传输层获取样本,通常是TCP/IP 协议的IP和端口,以及建立连接速率等等。而且此部分样本通常用于"tcp-request connection"指令中的规则之中。

        dst : ip             #目标地址
        dst_port : integer
        src : ip             #源地址
        src_port : integer
    

    Example:

    #阻断来自非指定IP的访问8080端口的请求
    acl myhost src 10.1.0.200
    acl myport dst_port 8080
    tcp-request connection reject if !myhost myport        
    
    

    4.3 获取layer 7 样本

    /1

    path : string
    

    提取请求url的地址信息,从第一个"/"开始,不包含host,不包含参数
    ACL 衍生,即包含了-m 选项中匹配模式方法 :
    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

    Example:

    #请求资源为图片,则调用图片服务器后端
     acl picture path_end -i .jpg .png .gif
     use_backend server_pic if picture
    
    

    /2

    url : string
    

    提取URL的全部内容,包含host和参数
    ACL 衍生类似,不再列举

    /3

    req.hdr([<name>[,<occ>]]) : string
    

    提取http请求的指定首部字段值,< occ >可指定出现的位置
    ACL 衍生 :

      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
    

    Example:

    #阻断火狐浏览器发送的请求
    acl firefox hdr_reg(User-Agent)     -i      .*firefox.*
    block if firefox
    
    

    /4

    method : integer + string
    

    提取请求报文中的请求方法

    Example:

    
    #拒绝GET HEAD 方式之外的HTTP请求
    acl valid_method method GET HEAD
    http-request deny if ! valid_method
    
    

    4.4 内建ACL

    HAProxy有众多内建的ACLs,这些ACLs可直接调用,例如

    • LOCALHOST 匹配来自本地IP的连接,127.0.0.1/8
    • HTTP_1.1 匹配http版本1.1
    • METH_GET 匹配http请求GET或HEAD方法
    • TRUE
    • FALSE

    Example:

    #拒绝GET HEAD 方式之外的HTTP请求
    http-request deny if ! METH_GET
    
    

    相关文章

      网友评论

          本文标题:HAProxy(一)之常用配置介绍,ACL详解

          本文链接:https://www.haomeiwen.com/subject/chntsxtx.html