3-4-8-HAProxy高级功能与配置之ACL

熊 0 阅读 Linux集群服务

访问控制列表 ( ACL , Access Control Lists ) 是一种基于包过滤的访问控制技术 , 它可以根据设定的条件对经过服 务器传输的数据包进行过滤(条件匹配) , 即对接收到的报文进行匹配和过滤 , 基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作 , 比如允许其通过或 丢弃。

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

  • 从数据流 , 表 , 环境中提取数据样本

  • 对提取的样本可选的应用格式转换

  • 对一个样本应用一个或多个模式匹配

  • 当模式匹配样本时才执行动作

HAProxy ACL允许您定义自定义规则 , 用于阻止恶意请求、选择后端、重定向到HTTPS和使用缓存对象。

对ACL的数量没有强制限制。 未使用的ACL并不影响性能 , 它们只是消耗少量的内存。

1. ACL 配置选项

  • 语法 : acl <aclname> <criterion> [flags] [operator] [<value>]

  • aclname : 可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线-和下划线_ , 并且严格区分大小写 , 比如Image_site和image_site就是两个完全不同的acl。

  • criterion : 测试标准 , 即对什么信息发起测试;测试方式可以由[flags]指定的标志进行调整 ; 而有些测试标准也可以需要为其在<value>之前指定一个操作符[operator];

  • flags : 可选项 , 表示标识位。一般会用到的标识位只有"-i" , 表示不区分大小写。

  • operator : ACL 操作符

  • value : 访问控制的具体内容或值。根据criterion的不同 , 值的类型不同。

示例:

frontend www
   bind :80
​
   # Boolean. Did the connection arrive over SSL?
   # Note that boolean expressions do not include an explicit value to match against.
   acl ssl_was_used ssl_fc
​
   # Integer. Is the destination port 8080?
   acl is_8080 dst_port 8080
​
   # IP address. Is the destination IP address localhost (i.e. 127.0.0.1)?
   acl localhost dst 127.0.0.1
​
   # Binary. Does the request body contain the substring 'PING'?
   # For binary fetches, you must set a match type.
   acl contains_ping req.body -m sub PING

1.1 ACL-criterion

定义ACL匹配规范,主要是选择一个合适的取样方式 , 然后将取出的样本信息与后面value相对比。使用一个获取样本方法 , 暗含着其输出样本的类型 , 类型是以下列出的一种: boolean 、integer (signed or unsigned)、IPv4 or IPv6 address、string、data block。

  • haproxy内部状态信息取样规则

    • always_false : boolean

      返回布尔值false 。它可以与ACL一起使用。作为调整配置时另外一个ACL临时替换。

    • always_true : boolean

      返回布尔值 true。它可以与ACL一起使用 , 作为调整配置时另一个ACL的临时替代。

    • avg_queue ([<backend>]) : integer

      返回指定backend排队连接的总数除以活动服务器的数量(等待队列长度的平均数)。如果没有指定的backend , 则使用当前的backend。这与 "queue "非常相似 , 只是考虑了农场的大小 , 以便对处理一个新连接可能需要的时间进行更准确的测量。主要用途是在ACL中 , 当确定新用户将得到降级的服务时 , 向他们返回一个抱歉的页面 , 或者在头中传递给后端服务器 , 以便他们决定在降级模式下工作或禁用某些功能以加快处理速度。请注意 , 在不再有任何活动服务器的情况下 , 排队的连接数的两倍将被视为测量值。这是一个合理的估计 , 因为我们期望一个服务器很快就会回来 , 但我们仍然倾向于将新的流量发送到另一个后端 , 如果情况更好。也请看 "queue"、"be_conn "和 "be_sess_rate "的取样。

    • be_conn ([<backend>]) : integer , 返回指定backend中当前已建立的连接数(possibly including the connection being evaluated) , 如果在指定范围内 , 返回ture。如果没有特别指定是那个 backend , 则表示使用当前的backend。可用于这样的场景 , 如果被测试的backend中连接数已经满负荷 将其流量转发给另一个backend。

    • be_sess_rate([<backend>]) : integer , 用于测试指定的backend上会话创建的速率 ( 即每秒创建的会话数 ) 是否满足指定的条件:常用于在指定backend上的会话速率过高时将用户请求转发至另外的backend , 或用于阻止攻击行为

      #某后端被请求过去繁忙 , 则重定向到错误页面
      mode http
      acl being_scanned be_sess_rate gt 100
      redirect location /denied.html if being_scanned
    • bin(<hex>) : bin ,返回一个二进制链。输入是十六进制表示的字符串。

    • bool(<bool>) : bool , 返回一个布尔值。<bool>可以是'true'、'false'、'1'或'0'。'false'和'0'是一样的。'true'和'1'是一样的。

    • connslots ([<backend>]) : integer , connslots = backend 服务器剩余的可容纳的连接数 + backend的等待队列中剩余的可容纳的连接数 , 在指定范围内时返回true。简单来说 , 就是衡量一个 backend当前还能接收多少新建连接。基于这个值 , 可以做更好的负载均衡。一般配合fe_conn( frontend当前已经接收的连接数) 一起做判断。

    • fe_conn ([<frontend>]) : integer , 返回某个frontend中已经建立的连接数(possibly including the connection being evaluated ) , 如果在指定范围内 , 返回true。如果未指定是哪个frontend ,使用当前的frontend。如果所关联的backend接收的连接数被认为已经到达满负荷 , 可用于在hard-blocking之前返回sorry页面 ;或者使用某个指定的backend接收新的请求。

    • fe_req_rate([<frontend>]) : integer , 返回一个整数值 , 对应于每秒发送到前端的HTTP请求的数量。在启用了客户端的keep-alive的情况下 , 这个数字可能与 "fe_sess_rate"不同。

    • fe_sess_rate ([<frontend>]) : integer , 用于测试指定的frontend上的会话创建速率是否满足指定的条件;常用于为frontend指定的一个合理会话创建速率的上限以防止服务被滥用 , 例如下面的列子限定入站邮件速率不能大于50封/秒 , 所有在此指定范围之外的请求都将被延迟50毫秒

    • hostname : string , 返回系统主机名

    • int(<integer>) : signed integer 。返回单个数字

    • ipv4(<ipv4>) : ipv4 , 返回IPv4

    • ipv6(<ipv6>) : ipv6, 返回IPv6

    • meth(<method>) : method , 返回method

    • nbsrv([<backend>]) : integer , 返回指定backend可用服务器数量。

    • srv_conn([<backend>/]<server>) : integer,返回一个整数值 , 对应于指定服务器上当前建立的连接数 , 可能包括正在评估的连接。如果<backend>被省略 , 那么该服务器将在当前的后端查找。它可以用来在一个服务器满员时使用一个特定的场景 , 或者根据服务器的活动连接数 , 调整后端服务器。

    • srv_conn_free([<backend>/]<server>) : integer , 返回一个对应于指定服务器上可用连接数的整数值 , 可能包括正在评估的连接。该值不包括队列槽。如果<backend>被省略 , 那么该服务器将在当前的<backend>查找。它可以用来在一个服务器满员时使用一个特定的场景 , 或者根据服务器的活动连接数 , 调整后端服务器。

      注 : 如果服务器的maxconn是0 , 那么这个fetch显然是没有意义的 , 在这种情况下 , 返回的值将是-1。

    • srv_is_up ([<backend>/]<server>) : boolean , 当指定backend或当前backend中的server正在运行 , 返回true , 否则返回false。不接受参数。当健康检查报告了一个外部状态时 ( eg: a geographical site's availability ) , 采取一定的动作。

    • srv_queue([<backend>/]<server>) : integer ,返回一个整数值 , 对应于当前在指定服务器队列中等待的连接数。如果<backend>被省略 , 那么该服务器将在当前的backend中查找。它有时可以和 "use-server"指令一起使用 , 当它没有太多的负载 , 以强制使用一个已知的速度较快的服务器。

    • srv_sess_rate([<backend>/]<server>) : integer ,返回一个整数 , 对应于指定服务器上的会话创建率 , 以每秒的新会话数量为单位。如果<backend>被省略, 那么服务器将在当前的后端查找。这主要用于ACL ,但对日志也有意义。当一个昂贵或脆弱的后端达到太高的会话率时 , 这个参数被用来切换到另一个后端 , 或限制服务的滥用(例如 , 防止潜伏的请求使服务器过载 ) 。

      # Redirect to a separate back
      acl srv1_full srv_sess_rate(be1/srv1) gt 50
      acl srv2_full srv_sess_rate(be1/srv2) gt 50
      use_backend be2 if srv1_full or srv2_full
    • srv_iweight ([<backend>/]<server>) :integer , 返回一个对应于服务器初始权重的整数。如果<backend>被省略 , 那么搜索当前backend所在的服务器。

    • srv_uweight ([<backend>/]<server>) :integer , 返回一个整数 ,对应于用户可见服务器的权重。如果<backend>被省略 , 那么搜索当前backend所在的服务器。

    • srv_weight ([<backend>/]<server>) :integer , 返回一个对应于当前(或有效)服务器权重的整数。如果<backend>被省略 , 那么该服务器将在当前的后台进行查询。

    • stopping : boolean , 如果调用该函数的进程目前正在停止 , 返回TRUE。这对于记录 , 或者放松某些检查 , 或者在优雅关闭时帮助关闭某些连接 , 都是很有用的。

    • queue([<backend>]) : integer , 返回当前 backend 或某个指定的 backend 的等待队列中的连接数。当队列长度超过警戒值 , 一般意味着遇到访问高峰 , 或者大量的服务器失效。一种可行的措施是拒绝新的用户 ,并且维持旧的连接。

  • layer 4取样规则

    第4层通常描述的只是传输层 , 在HAProxy中 , 传输层最接近连接 , 这里还没有提供内容。这里描述的获取方法可用于低至 "tcp-request connection"规则集 , 除非它们需要一些未来的信息。那些通常包括TCP/IP地址和端口 , 以及与传入连接相关的stick table中的元素。对于从粘性计数器中检索数值 , 可以使用预定义的 "sc0_"、"sc1_"或 "sc2_"前缀明确地将计数器编号设置为0、1、或2。这三个预定义的前缀只有在MAX_SESS_STKCTR值不超过3的情况下才能使用 , 否则在使用 "sc_"前缀时 , 可以将计数器编号指定为第一个整数参数。 从 "sc_0"开始到 "sc_N" , 其中N为(MAX_SESS_STKCTR-1)。可以用 "sc*"形式指定一个可选的表 , 在这种情况下 , 当前被追踪的键将被查到这个备用的表 , 而不是当前被追踪的表。

    • bc_dst : ip, 服务端连接的目的IP地址。这些IP也就是HAProxy需要去连接的服务器IP

    • bc_dst_port :integer ,对应于服务器端连接的目的TCP端口

    • bc_src : ip, 服务器端连接的源IP地址。这些IP也就是HAProxy本地去连接后端服务器的IP。

    • bc_src_port : integer , 与服务器端连接的TCP源端口。即HAProxy连接的端口

    • be_id : integer , 返回backend的id。可在frontend中使用 , 用于检测是被哪一个 backend所调用。

    • be_name : string , 返回backend的名字。可在frontend中使用 , 用于检测是被哪一个 backend所调用。

    • dst : ip, 这是客户端连接的目的IP地址 , 也就是客户端连接的地址。

    • dst_conn : integer , 对应于同一套接字上当前建立的连接数。它通常与ACL一起使用 , 但也可用于在HTTP头或日志中向服务器传递信息。提供了为不同的监听端口或地址分配不同限制的能力。

    • dst_is_local : boolean , 如果传入连接的目标地址是系统本地的 , 则返回true;如果该地址在系统中不存在 , 则返回false , 这意味着它是在透明模式下被拦截的。

    • dst_port : integer , 对应于客户端连接的目的TCP端口 , 也就是客户端连接的端口。

    • fc_dst : ip , 这是在客户端连接的原始目标IP地址。

    • fc_dst_is_local : boolean, 如果传入连接的原始目标地址是系统本地的 , 则返回true;如果该地址在系统中不存在 , 则返回false

    • fc_dst_port : integer , 返回对应于客户端连接的原始目标TCP端口。

    • fc_src/src : ip , 这是在客户端连接的源IP地址 。

    • fc_src_is_local/src_is_local : boolean , 如果传入连接的源地址是系统本地的 , 则返回true ;如果该地址在系统中不存在 , 则返回false

    • fc_src_port/src_port : integer , 返回对应于客户端连接的TCP源端口。

    • fe_id : integer , 返回当前frontend的ID。它可以用于backend , 以检查它是从哪个frontend调用的, 将所有通过同一个frontend的用户粘到同一个服务器

    • fe_name : string , 返回当前frontend的名称。它可以用于backend , 以检查它是从哪个frontend调用的, 将所有通过同一个frontend的用户粘到同一个服务器

    • sc_bytes_in_rate(<ctr>[,<table>]) : integer

    • sc0_bytes_in_rate([<table>]) : integer

    • sc1_bytes_in_rate([<table>]) : integer

    • sc2_bytes_in_rate([<table>]) : integer

      返回当前跟踪的计数器中客户端到服务器的平均字节数 , 以表格中配置的时间段内的字节数来衡量。

    • sc_bytes_out_rate(<ctr>[,<table>]) : integer

    • sc0_bytes_out_rate([<table>]) : integer

    • sc1_bytes_out_rate([<table>]) : integer

    • sc2_bytes_out_rate([<table>]) : integer

      返回当前跟踪的计数器中服务器到客户端的平均字节数 , 以表中配置的周期内的字节数来衡量。

    • sc_clr_gpc(<idx>,<ctr>[,<table>]) : integer

      清除与当前代理的stick table或指定的stick table <table>中ID为<ctr>的指定跟踪计数器相关的数组索引<idx>处的通用计数器 , 并返回其先前值。

      <idx>是0到99之间的整数 , <ctr>是0到2之间的整数。

      在第一次调用之前 , 存储的值是0 ,所以第一次调用将总是返回0。

      这个取值只适用于'gpc'数组数据类型 ( 而不适用于传统的'gpc0'或'gpc1'数据类型 ) 。

    • sc_clr_gpc0(<ctr>[,<table>]) : integer

    • sc0_clr_gpc0([<table>]) : integer

    • sc1_clr_gpc0([<table>]) : integer

    • sc2_clr_gpc0([<table>]) : integer

      清除与当前跟踪的计数器相关的第一个通用计数器 , 并返回其先前的值。在第一次调用之前 ,存储的值是0, 所以第一次调用将总是返回0。这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

      # 连续五次请求均高于10sess/s 则被阻塞。一旦流量减慢 , 立即重置计数器。
      acl abuse sc0_http_req_rate gt 10
      acl kill  sc0_inc_gpc0 gt 5
      acl save  sc0_clr_gpc0 ge 0
      tcp-request connection accept if !abuse save
      tcp-request connection reject if abuse kill
    • sc_clr_gpc1(<ctr>[,<table>]) : integer

    • sc0_clr_gpc1([<table>]) : integer

    • sc1_clr_gpc1([<table>]) : integer

    • sc2_clr_gpc1([<table>]) : integer

      清除与当前跟踪的计数器相关的第二个通用计数器 , 并返回其先前的值。在第一次调用之前 , 存储的值是0 , 所以第一次调用将总是返回0。这通常被用作表达式中的第二个ACL, 以便在第一个ACL被验证时标记一个连接。

    • sc_conn_cnt(<ctr[,<table>]>) : integer

    • sc0_conn_cnt([<table>]) : integer

    • sc1_conn_cnt([<table>]) : integer

    • sc2_conn_cnt([<table>]) : integer

      返回当前被跟踪的计数器的累积连接数。

    • sc_conn_cur(<ctr[,<table>]>) : integer

    • sc0_conn_cur([<table>]) : integer

    • sc1_conn_cur([<table>]) : integer

    • sc2_conn_cur([<table>]) : integer

      返回当前跟踪同一被跟踪计数器的并发连接量。这个数字在追踪开始时自动递增 , 追踪停止时自动递减。

    • sc_conn_rate(<ctr>[,<table>]) : integer

    • sc0_conn_rate([<table]) : integer

    • sc1_conn_rate([<table]) : integer

    • sc2_conn_rate([<table]) : integer

      返回当前跟踪的计数器的平均连接率。在表中配置的时间段内 , 以连接数来衡量。

    • sc_get_gpc(<idx>,<ctr>[,<table>]) : integer

      返回GPC数组中索引<idx>的通用计数器的值 , 该值与当前代理的stick1 table或指定的stick table <table>中ID为<ctr>的当前跟踪的计数器相关。

      <idx>是0到99之间的整数 , <ctr>是0到2之间的整数。

      如果在这个索引处没有存储gpc , 则返回0。这种获取方式只适用于 "gpc"数组数据类型(而不适用于传统的 "gpc0"或 "gpc1 "数据类型 ) 。

    • sc_get_gpc0(<ctr>[,<table>]) : integer

    • sc0_get_gpc0(<ctr>[,<table>]) : integer

    • sc1_get_gpc0(<ctr>[,<table>]) : integer

    • sc2_get_gpc0(<ctr>[,<table>]) : integer

      返回与当前跟踪的计数器相关的第一个通用计数器的值。

    • sc_get_gpc1(<ctr>[,<table>]) : integer

    • sc0_get_gpc1(<ctr>[,<table>]) : integer

    • sc1_get_gpc1(<ctr>[,<table>]) : integer

    • sc2_get_gpc1(<ctr>[,<table>]) : integer

      返回与当前跟踪的计数器相关的第二个通用计数器的值。

    • sc_get_gpt(<idx>,<ctr>[,<table>]) : integer

      返回与ID为<ctr>的跟踪计数器相关的数组中索引<idx>的第一个通用标签的值 , 并从当前代理的sitck-table或指定的stick-table <table>中获取。

    • sc_get_gpt0(<ctr[,<table]>) : integer

    • sc0_get_gpt0(<ctr>[,<table>]) : integer

    • sc1_get_gpt0(<ctr>[,<table>]) : integer

    • sc2_get_gpt0(<ctr>[,<table>]) : integer

      返回与当前跟踪的计数器相关的第一个通用标签的值。

    • sc_gpc_rate(<idx>,<ctr>[,<table>]) : integer

      返回通用计数器的平均增量 , 其索引<idx>与当前代理表或指定的stick table <table>中ID为<ctr>的被跟踪计数器相关联。它报告gpc计数器在配置的期间内被增加的频率。

      <idx>是0到99之间的整数 , <ctr>是0到2之间的整数。

      请注意 , 'gpc_rate'计数器阵列必须存储在stick-table中才能返回一个值 , 因为'gpc'只保存事件计数。这种获取方式只适用于'gpc_rate'数组数据类型(而不适用于传统的'gpc0_rate'或'gpc1_rate'数据类型 ) 。

    • sc_gpc0_rate(<ctr>[,<table>]) : integer

    • sc0_gpc0_rate([<table>]) : integer

    • sc1_gpc0_rate([<table>]) : integer

    • sc2_gpc0_rate([<table>]) : integer

      返回与当前跟踪的计数器相关的第一个通用计数器的平均增量。它报告了gpc0计数器在配置的时间段内被递增的频率。

      注意 , "gpc0_rate"计数器必须存储在stick table中才能返回一个值 , 因为 "gpc0"只保存事件计数。

    • sc_http_err_cnt(<ctr>[,<table>]) : integer

    • sc0_http_err_cnt([<table>]) : integer

    • sc1_http_err_cnt([<table>]) : integer

    • sc2_http_err_cnt([<table>]) : integer

      返回当前跟踪的计数器中HTTP错误的平均率 , 以表中配置的时期内的错误量来衡量。这包括请求错误和4xx错误响应。

    • sc_http_fail_cnt(<ctr>[,<table>]) : integer

    • sc0_http_fail_cnt([<table>]) : integer

    • sc1_http_fail_cnt([<table>]) : integer

    • sc2_http_fail_cnt([<table>]) : integer

      返回当前跟踪的计数器中HTTP响应失败的累积数量。这包括响应错误和除501和505之外的5xx状态代码。

    • sc_http_fail_rate(<ctr>[,<table>]) : integer

    • sc0_http_fail_rate([<table>]) : integer

    • sc1_http_fail_rate([<table>]) : integer

    • sc2_http_fail_rate([<table>]) : integer

      返回当前跟踪的计数器中HTTP响应失败的平均比率 , 以表中配置的时期内的失败数量来衡量。这包括响应错误和除501和505之外的5xx状态代码。

    • sc_http_req_cnt(<ctr>[,<table>]) : integer

    • sc0_http_req_cnt([<table>]) : integer

    • sc1_http_req_cnt([<table>]) : integer

    • sc2_http_req_cnt([<table>]) : integer

      返回当前跟踪的计数器中HTTP请求的累积数量。这包括每一个开始的请求 , 无论有效与否。

    • sc_http_req_rate(<ctr>[,<table>]) : integer

    • sc0_http_req_rate([<table>]) : integer

    • sc1_http_req_rate([<table>]) : integer

    • sc2_http_req_rate([<table>]) : integer

      返回当前跟踪的计数器的HTTP请求的平均率 , 以表中配置的期间的请求量来衡量。这包括每个开始的请求 , 无论是否有效。

    • sc_inc_gpc(<idx>,<ctr>[,<table>]) : integer

      增加与当前代理的stick table或指定的stick table <table>中的ID为<ctr>的指定跟踪计数器相关的数组索引<idx>的通用计数器 , 并返回其新值。

      <idx>是0到99之间的整数 , <ctr>是0到2之间的整数。

      在第一次调用之前 , 存储的值是0 , 所以第一次调用将把它增加到1 , 并将返回1。这个取值只适用于'gpc'数组的数据类型 ( 而不适用于传统的'gpc0'或'gpc1'数据类型 ) 。

    • sc_inc_gpc0(<ctr>[,<table>]) : integer

    • sc0_inc_gpc0([<table>]) : integer

    • sc1_inc_gpc0([<table>]) : integer

    • sc2_inc_gpc0([<table>]) : integer

      增加与当前跟踪的计数器相关的第一个通用计数器 , 并返回其新值。在第一次调用之前 , 存储的值是0 , 所以第一次调用将把它增加到1并返回1。这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

      acl abuse sc0_http_req_rate gt 10
      acl kill  sc0_inc_gpc0 gt 0
      tcp-request connection reject if abuse kill
    • sc_inc_gpc1(<ctr>[,<table>]) : integer

    • sc0_inc_gpc1([<table>]) : integer

    • sc1_inc_gpc1([<table>]) : integer

    • sc2_inc_gpc1([<table>]) : integer

      增加与当前跟踪的计数器相关的第二个通用计数器 , 并返回其新值。在第一次调用之前 , 存储的值是0 , 所以第一次调用将把它增加到1并返回1。这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

    • sc_kbytes_in(<ctr>[,<table>]) : integer

    • sc0_kbytes_in([<table>]) : integer

    • sc1_kbytes_in([<table>]) : integer

    • sc2_kbytes_in([<table>]) : integer

      返回当前跟踪的计数器的客户端到服务器的数据总量 , 以kb为单位。目前 , 该测试是在32位整数上进行的 , 这使得数值限制在4Tb以内。

    • sc_kbytes_out(<ctr>[,<table>]) : integer

    • sc0_kbytes_out([<table>]) : integer

    • sc1_kbytes_out([<table>]) : integer

    • sc2_kbytes_out([<table>]) : integer

      返回当前跟踪的计数器的服务器到客户端的数据总量 , 以kb为单位。目前 , 该测试是在32位整数上进行的 , 这就把数值限制在4Tb以内。

    • sc_sess_cnt(<ctr>[,<table>]) : integer

    • sc0_sess_cnt([<table>]) : integer

    • sc1_sess_cnt([<table>]) : integer

    • sc2_sess_cnt([<table>]) : integer

      返回被转化为session的传入connection的累积数量 , 这意味着它们来自当前跟踪的计数器, 并被 "tcp-request connection"规则接受。后台计算的session会话数可能多于connection连接数 , 因为如果在与客户端的连接上执行了一些HTTP keep-alive ,则每个连接可能导致许多后台session。

    • sc_sess_rate(<ctr>[,<table>]) : integer

    • sc0_sess_rate([<table>]) : integer

    • sc1_sess_rate([<table>]) : integer

    • sc2_sess_rate([<table>]) : integer

      返回当前跟踪的计数器的平均会话率 , 以表格中配置的时期内的会话量衡量。session是指通过早期 "tcp-request connection "规则的连接。一个backend可能会计算出比connection更多的session, 因为如果在与客户端的连接上执行一些HTTP keep-alive的话 , 每个conection可能会导致许多后端session 。

    • sc_tracked(<ctr>[,<table>]) : boolean

    • sc0_tracked([<table>]) : boolean

    • sc1_tracked([<table>]) : boolean

    • sc2_tracked([<table>]) : boolean

      如果指定的会话计数器目前正在被当前会话跟踪 , 则返回true。有利于我们决定是否要在传递给服务器的头部信息中设置一些值。

    • sc_trackers(<ctr>[,<table>]) : integer

    • sc0_trackers([<table>]) : integer

    • sc1_trackers([<table>]) : integer

    • sc2_trackers([<table>]) : integer

      返回当前跟踪同一被跟踪计数器的并发连接量。这个数字在跟踪开始时自动递增 , 在跟踪停止时自动递减。它与sc0_conn_cur不同的是 , 它不依赖于任何存储的信息 , 而是依赖于表的引用计数(CLI上 "show table "返回的 "use"值) 。这有时可能更适合于第七层的跟踪。例如 , 它可以用来告诉服务器有多少个来自某个地址的并发连接。

    • so_id : integer , 返回当前套接字的ID。在frontend中涉及多个bind行 , 或者将所有通过同一个套接字绑定到同一个后端服务器中。

    • so_name : string ,返回当前套接字的名称。在frontend中涉及多个bind行 , 或者将所有通过同一个套接字绑定到同一个后端服务器中。

    • src : ip , 这是该会话客户端的源IP地址。任何tcp/http规则都可以改变这个地址。它属于IP类型 , 在IPv4和IPv6表上都有效。

      # add an HTTP header in requests with the originating address' country
      http-request set-header X-Country %[src,map_ip(geoip.lst)]
    • src_bytes_in_rate([<table>]) : integer

      返回当前代理的stick table或指定的stick table中来自传入连接源地址的平均字节率 , 以表中配置的时间段内的字节量来衡量。如果没有找到该地址 , 则返回0。

    • src_bytes_out_rate([<table>]) : integer

      返回当前代理的stick table或指定stick table中发送至传入连接源地址的平均字节速率 , 以表中配置的时间段内的字节数衡量。如果找不到地址 , 则返回零。

    • src_clr_gpc(<idx>,[<table>]) : integer

      清除与当前代理的Stick-table或指定的Stick-table<table>中的传入连接源地址相关的数组索引<idx>的通用计数器 , 并返回其先前的值。

      <idx>是0-99之间的整数。如果没有找到该地址 , 将创建一个条目并返回0。

      这种获取方式只适用于gpc数组数据类型(而不适用于传统的'gpc0'或'gpc1'数据类型 ) 。

    • src_clr_gpc0([<table>]) : integer

      清除与当前代理的stick table或指定的stick table中传入连接的源地址相关的第一个通用计数器 , 并返回其先前的值。如果没有找到该地址 , 将创建一个条目并返回0。这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

      # block if 5 consecutive requests continue to come faster than 10 sess
      # per second, and reset the counter as soon as the traffic slows down.
      acl abuse src_http_req_rate gt 10
      acl kill  src_inc_gpc0 gt 5
      acl save  src_clr_gpc0 ge 0
      tcp-request connection accept if !abuse save
      tcp-request connection reject if abuse kill
    • src_clr_gpc1([<table>]) : integer

      清除与当前代理的stick table或指定的stick table中传入连接的源地址相关的第二个通用计数器 , 并返回其先前的值。如果没有找到该地址 , 将创建一个条目并返回0。这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

    • src_conn_cnt([<table>]) : integer

      返回从当前代理的stick table或指定的stick table中的当前传入连接的源地址发起的连接的累积数量。如果没有找到该地址 , 则返回0。

    • src_conn_cur([<table>]) : integer

      返回当前代理的stick-table或指定的stick-table中 ,从当前传入连接的源地址发起的并发连接的数量。如果没有找到该地址 , 则返回0。

    • src_conn_rate([<table>]) : integer

      返回从当前代理的stick-table或指定的stick-table中传入的连接源地址的平均连接率 , 以表格中配置的时间段内的连接数量来衡量。如果没有找到该地址 , 则返回0。

    • src_get_gpc(<idx>,[<table>]) : integer

      返回在当前代理的stick-table或指定的stick-table <table>中与传入连接的源地址相关的数组索引<idx> 中的通用计数器的值。

      <idx>是0-99之间的整数。如果没有找到地址或没有gpc存储在这个索引 , 则返回0。这种获取方法只适用于'gpc'数组数据类型(而不适用于传统的'gpc0'或'gpc1'数据类型) 。

    • src_get_gpc0([<table>]) : integer

      返回与当前代理的棍子表或指定的棍子表中传入连接的源地址相关的第一个通用计数器的值。如果没有找到该地址 , 则返回0。

    • src_get_gpc1([<table>]) : integer

      返回与当前代理的棍子表或指定的棍子表中传入连接的源地址相关的第二个通用计数器的值。如果没有找到该地址 , 则返回0。

    • src_get_gpt(<idx>[,<table>]) : integer

      返回在当前代理的stick-table或指定的stick-table <table>中与传入连接的源地址相关的数组中索引<idx>的第一个通用标签的值。

      <idx>是0到99之间的整数。如果没有找到地址或没有存储GPT , 则返回0。

    • src_get_gpt0([<table>]) : integer

      返回与当前代理的stick table或指定的stick-table中传入连接的源地址相关的第一个通用标签的值。如果没有找到该地址 , 则返回0。

    • src_gpc_rate(<idx>[,<table>]) : integer

      返回通用计数器的平均增量 , 其索引<idx>与当前代理的stick-table或指定的stick-table <table> 中传入连接的源地址相关。它报告gpc计数器在配置的期间内被增加的频率。

      <idx>是0到99之间的整数。请注意 , 'gpc_rate'计数器必须存储在stick-table中才能返回一个值 , 因为'gpc'只保存事件计数。这个取值只适用于'gpc_rate'数组数据类型(而不适用于传的 'gpc0_rate' 或'gpc1_rate'数据类型 ) 。

    • src_gpc0_rate([<table>]) : integer

      返回与当前代理的stick-table或指定的stick-table中传入连接的源地址相关的第一个通用计数器的平均增量。它报告gpc0计数器在配置的时间段内的增量。

      注意 , "gpc0_rate"计数器必须存储在棍子表中才能返回一个值 , 因为 "gpc0"只保存事件计数。

    • src_gpc1_rate([<table>]) : integer

      返回与当前代理的stick-table或指定的stick-table中传入连接的源地址相关的第二个通用计数器的平均增量。它报告gpc0计数器在配置的时间段内的增量。

      注意 , "gpc0_rate"计数器必须存储在棍子表中才能返回一个值 , 因为 "gpc0"只保存事件计数。

    • src_http_err_cnt([<table>]) : integer

      返回当前代理的stick-table或指定的stick-table中传入连接的源地址的HTTP错误的累积数量。这包括请求错误和4xx错误响应。

    • src_http_err_rate([<table>]) : integer

      返回在当前代理的stick-table或指定的stick-table中 ,来自传入连接的源地址的HTTP错误的平均率 ,以表中配置的时间段内的错误数量来衡量。这包括请求错误和4xx错误响应。如果没有找到该地址 , 则返回0。

    • src_http_fail_cnt([<table>]) : integer

      返回由当前代理的stick-table或指定的stick-table中的传入连接的源地址引发的HTTP响应失败的累积数量。这包括响应错误和501和505以外的5xx状态代码。如果没有找到该地址, 则返回0。

    • src_http_fail_rate([<table>]) : integer

      返回由当前代理的stick-table或指定的stick-table中传入连接的源地址引发的HTTP响应失败的平均比率 , 以表中配置的时间段内的失败数量衡量。这包括响应错误和501和505以外的5xx状态代码。如果没有找到该地址 ,则返回0。

    • src_http_req_cnt([<table>]) : integer

      返回当前代理的stick-table或指定的stick-table中 ,来自传入连接源地址的HTTP请求的累积数量。这包括每一个开始的请求 , 无论有效与否。如果没有找到该地址 , 则返回0。

    • src_http_req_rate([<table>]) : integer

      返回在当前代理的stick-table或指定的stick-table中 , 从传入连接的源地址发出的HTTP请求的平均速率 , 以表内配置的期间的请求量来衡量。这包括每一个开始的请求 ,无论请求是否有效。如果没有找到该地址 , 则返回0。

    • src_inc_gpc(<inx>,[<table>]) : integer

      增加通用计数器的索引<idx> , 该数组与当前代理的stick-table或指定的stick-table <table>中的传入连接源地址相关 , 并返回其新值。

      <idx>是0-99之间的整数。如果没有找到该地址 ,将创建一个条目并返回1。

      这种获取方式只适用于'gpc'数组数据类型(而不适用于传统的'gpc0'或'gpc1'数据类型 ) 。

    • src_inc_gpc0([<table>]) : integer

      递增当前代理的stick-table或指定的stick-table中与传入连接的源地址相关的第一个通用计数器 ,并返回其新值。如果没有找到该地址 , 将创建一个条目并返回1。

      这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

      acl abuse src_http_req_rate gt 10
      acl kill  src_inc_gpc0 gt 0
      tcp-request connection reject if abuse kill
    • src_inc_gpc1([<table>]) : integer

      递增当前代理的stick-table或指定的stick-table中与传入连接的源地址相关的第二个通用计数器 ,并返回其新值。如果没有找到该地址 , 将创建一个条目并返回1。

      这通常被用作表达式中的第二个ACL , 以便在第一个ACL被验证时标记一个连接。

    • src_is_local : boolean

      如果传入连接的源地址是系统的本地地址 , 则返回true ;如果该地址在系统中不存在 , 意味着它来自远程机器 , 则返回false。

      注意 , UNIX地址被认为是本地的。根据客户端的来源 , 应用某些访问限制可能是有用的(例如 , 对远程机器要求auth或https)。请注意 , 这个检查涉及到一些系统调用 , 所以最好是每个连接只做一次。

    • src_kbytes_in([<table>]) : integer

      返回在当前代理的stick-table或指定的stick-table中从传入连接的源地址j接收到的数据总量 , 以kb为单位计算。如果没有找到该地址 , 则返回0。目前 , 该测试是在32位整数上进行的 , 它将数值限制在4Tb。

    • src_kbytes_out([<table>]) : integer

      返回在当前代理的stick-table或指定的stick-table中发送到传入连接的源地址的数据总量 , 以kb为单位计算。如果没有找到该地址 , 则返回0。目前 , 该测试是在32位整数上进行的 , 它将数值限制在4tb。

    • src_port : integer

      返回一个对应于客户端连接的TCP源端口的整数值 , 也就是客户端连接的端口。任何tcp/http规则都可能改变这个地址。这个函数的用法非常有限 , 因为现在的协议已经不太关心源端口了。

    • src_sess_cnt([<table>]) : integer

      返回从当前代理的stick-table或指定的stick-table中的传入连接的源IPv4地址发起的连接的累积数量 , 这些连接被转化为会话 , 这意味着它们被 "tcp-request"规则接受。如果没有找到该地址 , 则返回0。

    • src_sess_rate([<table>]) : integer

      返回从当前代理的stick-table或指定的stick-table中传入的连接源地址的平均会话率 , 以表中配置的期间的会话量来衡量。会话是指经过早期 "tcp-request"规则的连接。如果没有找到地址 , 则返回0。

    • src_updt_conn_cnt([<table>]) : integer

      在当前代理的stick-table或指定的stick-table中创建或更新与传入连接的源地址相关的条目。该表必须被配置为存储 "conn_cnt"数据类型 , 否则匹配将被忽略。当前计数增加1 ,并刷新过期定时器。更新后的计数被返回 , 所以这个匹配不能返回0。这被用来拒绝基于其源地址的服务滥用者。

      注意:建议使用 "tcp-request "规则中更完整的 "track-sc*"动作来代替。

      # This frontend limits incoming SSH connections to 3 per 10 second for
      # each source address, and rejects excess connections until a 10 second
      # silence is observed. At most 20 addresses are tracked.
      listen ssh
          bind :22
          mode tcp
          maxconn 100
          stick-table type ip size 20 expire 10s store conn_cnt
          tcp-request content reject if { src_updt_conn_cnt gt 3 }
          server local 127.0.0.1:22
    • srv_id : integer , 处理响应时, 返回后端服务器的ID值。虽然它几乎只用于ACL , 但它可以用于记录或 调试。它也可以用于tcp-check或http-check规则集。

    • srv_name : string ,处理响应时, 返回后端服务器的名称。虽然它几乎只用于ACL , 但它可以用于记录或 调试。它也可以用于tcp-check或http-check规则集。

  • layer 5 取样规则

    • ssl_bc : boolean , 当后面的连接是通过SSL/TLS传输层进行的 , 并且是本地解密的 , 返回true。这意味着传出的连接是由带有 "ssl"选项的其他服务器进行的。它可以被用于tcp-check或http-check规则集。

    • ssl_bc_alg_keysize : integer , 当传出的连接是通过SSL/TLS传输层进行时 , 返回支持的对称密码密钥大小(比特)。它可以在tcp-check或http-check规则集中使用。

    • ssl_bc_alpn : string , 这是从一个通过TLS传输层建立的出站连接中提取应用层协议协商字段。其结果是一个包含与服务器协商的协议名称的字符串。构建SSL库时必须启用对TLS 扩展的支持(检查haproxy -vv)。请注意 , 除非 "server "行的 "alpn"关键字指定了一个协议列表 , 否则TLS ALPN扩展不会被公布。另外 ,没有任何东西强迫服务器从这个列表中选择一个协议 , 任何其他的协议都可以被请求。TLS ALPN扩展是为了取代TLS NPN扩展。也请参见 "ssl_bc_npn"。它可以用在tcp-check或http-check规则集中。

    • ssl_fc : boolean ,当前面的连接是通过SSL/TLS传输层进行的 , 并且是本地破译的 , 返回true。这意味着它与一个带有 "ssl"选项的 "bind"行声明的套接字匹配。

      # This passes "X-Proto: https" to servers when client connects over SSL
      listen http-https
          bind :80
          bind :443 ssl crt /etc/haproxy.pem
          http-request add-header X-Proto https if { ssl_fc }

  • layer 6 取样规则

    从缓冲区内容中获取样本与上面前面的样本获取有点不同 , 因为取样的数据是短暂的。这些数据只能在它们可用的时候使用 , 当它们被转发时将会丢失。因此 , 在请求期间从缓冲区内容中获取的示例不能用于响应等。即使在数据被取走的时候 , 它们也会发生变化。有时有必要设置一些延迟或结合多种样本获取方法 , 以确保预期的数据是完整和可用的 , 例如通过TCP请求内容检查。

    注 : 如果从HTTP代理处使用 ,以下的取样会被忽略。它们只处理缓冲区中的原始内容。在他们那边 , HTTP代理使用结构化的内容。因此 ,这些数据的原始含义是没有意义的。如果一个ACL依赖于以下的样本提取之一 , 就会发出警告。但不可能检测到所有无效的用法 ( 例如在日志格式字符串或样本表达式里面 ) 。

    • req.len : integer ,返回一个对应于请求缓冲区中存在的字节数的整数值。 这主要用于ACL中。 重要的是要理解 , 只要缓冲区在变化 , 这个测试就不会返回错误。 这意味着在会话开始时 , 与零相等的检查几乎总是立即匹配 , 而对更多数据的测试将等待这些数据的进入 , 只有在HAProxy确定不会有更多数据进入时才会返回错误。 这个测试被设计为与TCP请求内容检查一起使用。

    • req.payload(<offset>,<length>) : binary ,这将提取一个<length>字节的二进制块 , 从请求缓冲区的<offset>字节开始。作为一种特殊情况 , 如果<length>参数为零 , 则提取从<offset>到最后的整个缓冲区。这可以与ACL一起使用 ,以检查缓冲区内任何位置是否存在某些内容。

      衍生指令:req.payload(<offset>,<length>) , 16进制匹配

    • req.proto_http : boolean , 当请求缓冲区中的数据看起来像HTTP并且正确解析时 , 返回true。它与常用的HTTP请求解析器相同 , 所以应该不会有什么意外。在请求完成、失败或超时之前 , 该测试是不匹配的。这个测试可以用来报告TCP日志中的协议 , 但最大的用途是阻止TCP请求分析 , 直到缓冲区中出现一个完整的HTTP请求 , 例如跟踪一个报文头部信息。

      # track request counts per "base" (concatenation of Host+URL)
      tcp-request inspect-delay 10s
      tcp-request content reject if !HTTP
      tcp-request content track-sc0 base table req-rate
    • req.ssl_hello_type : integer ,返回一个整数值 , 其中包含请求缓冲区中发现的SSL hello消息的类型 , 如果缓冲区包含可解析为完整的SSL(v3或更高)客户端hello消息的数据。

      请注意 , 这只适用于在请求缓冲区中发现的原始内容 , 而不是通过SSL数据层破译的内容 , 所以这将不会对有 "ssl"选项的 "bind"行起作用。这主要用于ACL检测SSL hello消息的存在 , 该消息应该包含一个可用于粘性的SSL会话ID。

      • 0 : means there was no client hello

      • 1 : is a client hello

      • 2 : is a server hello

          # make sure we cover type 1 (fallback)
          acl clienthello req_ssl_hello_type 1
          acl serverhello rep_ssl_hello_type 2
      
          # use tcp content accepts to detects ssl client and server hello.
          tcp-request inspect-delay 5s
          tcp-request content accept if clienthello
      
          # no timeout on response inspect delay by default.
          tcp-response content accept if serverhello
    • req.ssl_sni : string , 返回一个字符串 , 包含客户端在通过请求缓冲区的TLS流中发送的服务器名称TLS扩展的值 , 如果缓冲区包含的数据可以解析为一个完整的SSL(v3或更高)客户端hello消息。请注意 , 这只适用于在请求缓冲区中发现的原始内容 , 而不是通过SSL数据层破译的内容 , 所以这将不会对具有 "ssl"选项的 "bind"行起作用。这只适用于实际的隐式TLS协议 如HTTPS(443 ) 、IMAPS(993)、SMTPS(465) , 但它不适用于显式TLS协议 ,如SMTP(25/587)或IMAP(143)。

      SNI通常包含客户端尝试连接到的主机的名称(对于最近的浏览器)。当客户端使用SSL/TLS时 , SNI对于允许或拒绝对某些主机的访问非常有用。此测试旨在与TCP请求内容检查一起使用。如果需要进行内容切换 , 建议先等待完整的客户端问候(类型 1) , 如下面的示例所示。

      # Wait for a client hello for at most 5 seconds
      tcp-request inspect-delay 5s
      tcp-request content accept if { req.ssl_hello_type 1 }
      use_backend bk_allow if { req.ssl_sni -f allowed_sites }
      default_backend bk_sorry_page

    • req.ssl_ver : integer,返回一个整数值 , 包含请求缓冲区中存在的流的SSL/TLS协议的版本。同时支持SSLv2 hello消息和SSLv3消息。TLSv1被宣布为SSL3.1版本。该值是由主要版本乘以65536 , 再加上次要版本组成。请注意 ,这只适用于在请求缓冲区发现的原始内容 , 而不是通过SSL数据层破译的内容 , 所以这对具有 "ssl "选项的 "bind"行不起作用。ACL版本的测试与MAJOR.MINOR形式的十进制符号相匹配。这种取法主要用于ACL中。

      acl sslv3 req.ssl_ver 3
      acl is_ssl req_ssl_ver 2:3.1
      acl tlsv1 req.ssl_ver 3.1
      acl ssl3_or_tls1 req.ssl_ver 3:3.1
    • res.len : integer, 返回对应于响应缓冲区中存在的字节数的整数值。这主要用于ACL中。重要的是要理解,只要缓冲区在变化 , 这个测试就不会返回错误。这意味着一个与零相等的检查几乎总是在会话开始时立即匹配 ,而对更多数据的测试将等待这些数据的进入 , 只有当haproxy确定不会有更多的数据进入时才返回错误。这个测试被设计为与TCP响应内容检查一起使用。

    • res.payload(<offset>,<length>) : binary , 这将提取一个<length>字节的二进制块 , 从响应缓冲区的<offset>字节开始。作为一种特殊情况 , 如果<length>参数为0 ,则提取从<offset>到最后的整个缓冲区。这可以与ACL一起使用 ,以检查缓冲区中任何位置是否存在某些内容。

    • res.ssl_hello_type : integer ,返回一个整数值 , 其中包含在响应缓冲区中发现的SSL hello消息的类型 , 如果缓冲区包含的数据被解析为完整的SSL(v3或更高)hello消息。请注意, 这只适用于在响应缓冲区中发现的原始内容 , 而不是通过SSL数据层破译的内容 ,所以这对有 "ssl"选项的 "server "行不起作用。这主要用于ACL ,以检测SSL hello消息的存在,该消息应包含可用于粘性的SSL会话ID。

    • wait_end : boolean ,这个取数在检查期结束时要么返回真 , 要么不取数。它只在ACL中使用 , 与内容分析一起使用 ,以避免提前返回一个错误的判决。它也可以用来延迟一些行动 ,比如对一些特殊地址进行延迟拒绝。因为它要么停止规则的评估 , 要么立即返回真 , 所以建议将这个ACL作为规则的最后一个。请注意 , 默认的ACL "WAIT_END "总是可用的 , 不需要事先声明。这个测试被设计为与TCP请求内容检查一起使用。

      # delay every incoming request by 2 seconds
      tcp-request inspect-delay 2s
      tcp-request content accept if WAIT_END
      ​
      # don't immediately tell bad guys they are rejected
      tcp-request inspect-delay 10s
      acl goodguys src 10.0.0.0/24
      acl badguys  src 10.0.1.0/24
      tcp-request content accept if goodguys
      tcp-request content reject if badguys WAIT_END
      tcp-request content reject
  • layer 7取样规则

    • base : string , 返回第一个主机头和请求的路径部分的连接 , 该请求从第一个斜杠开始 ,并在问号之前结束。对虚拟主机有用完整的url中 : <scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag> ,base指的是<host>:<port>/<path>;<params>

      ACL衍生指令:

      • 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

    • base32 : integer , 这将返回由上述 "base "获取方法返回的32位哈希值。这对于跟踪高流量网站的每个URL活动是非常有用的 , 不需要存储所有的URL。取而代之的是一个较短的哈希值被存储 , 节省了大量的内存。输出类型是一个无符号整数。使用的哈希函数是SDBM , 输出为全雪崩。从技术上讲 , base32正好等于 "base,SDBM(1)"。

    • base32+src : binary , 这将返回上面的base32提取和下面的src提取的串联。结果类型是二进制类型 , 大小为8或20字节 , 具体取决于源地址系列。这可用于跟踪每个 IP、每个 URL 的计数器。

    • capture.req.hdr(<idx>) : string , 这将提取由 capture request header捕获的头的内容 , idx是捕获关键字在配置中的位置。

    • capture.req.method : string , 它提取了一个HTTP request的METHOD。它可以在请求和响应中使用。与 "method "不同 , 它可以在请求和响应中使用 , 因为它是分配的。

    • capture.req.uri : string , 这将提取request中的URI , 它从第一个斜线开始 , 在request的第一个空格前结束(没有host部分)。与 path 和 url 不同 , 它可以在请求和响应中使用 , 因为它是分配的。

    • capture.req.ver : string , 这将提取request的HTTP版本并返回HTTP/1.0或 HTTP/1.1。与req.ver不同的是 , 它可以同时用于请求、响应和 日志中使用 ,因为它依赖于一个持久的标志。

    • capture.res.hdr(<idx>) : string , 这将提取capture response header 所捕获的头的内容 , idx是capture关键字在配置中的位置。第一个条目的索引为0。

    • capture.res.ver : string , 它提取reponse的HTTP版本并返回HTTP/1.0 或 HTTP/1.1。与res.ver 不同 , 它可以在日志中使用 ,因为它依赖于一个持久的标志。

    • req.cook ([<name>]) : string , 获取请求头中cookie字段内容上最后出现的cookie名称<name>。如果没有指定名称 , 则返回第一个cookie值。当与acl一起使用时 , 将评估所有匹配的cookie。

      ACL衍生指令:

      • req.cook([<name>]) : exact string match

      • req.cook_beg([<name>]) : prefix match

      • req.cook_dir([<name>]) : subdir match

      • req.cook_dom([<name>]) : domain match

      • req.cook_end([<name>]) : suffix match

      • req.cook_len([<name>]) : length match

      • req.cook_reg([<name>]) : regex match

      • req.cook_sub([<name>]) : substring match

    • req.cook_cnt([<name>]) : integer , 返回request中出现的cookie <name>的数量 , 如果没有指定<name> , 则返回所有的cookie数量。

    • hdr([<name>[,<occ>]]) : string , 当用于请求时 , 这相当于req.hdr() ; 而当用于响应时 , 相当于res.hdr()。

    • req.fhdr([<name>[,<occ>]]) : string , 返回HTTP请求中最后出现的头信息<name>的完整值。它与req.hdr()的不同之处在于 , 返回值中存在的任何逗号 , 而不是作为分隔符使用。这对诸如User-Agent这样的头信息有时很有用。

    • req.fhdr_cnt([<name>]) : integer , 返回一个整数 , 代表请求头域名称<name>的出现次数 , 如果没有指定<name> , 则代表头域的总数。

    • req.hdr([<name>[,<occ>]]) : string , 返回HTTP请求中header报文中的<name>的最后一个逗号分隔的值。取值时考虑将任何逗号作为独立值的分隔符。如果你需要处理被定义为数值列表的头信息 , 例如Accept或X-Forwarded-For , 这很有用。如果需要全行头信息 , 请使用req.fhdr()。

      ACL 衍生指令:

      • hdr([<name>[,<occ>]]) : exact string match。完全匹配字符串,header的指定信息

      • hdr_beg([<name>[,<occ>]]) : prefix match。前缀匹配。 用于测试请求报文的指定首部的开头部分是否符合<string>指定的模式。例如 , 下面的例子用记测试请求是否为提供静态内容的主机img、video、download或ftp。

        acl host_static hdr_beg(host)  -i  img.  video. download.  ftp.
      • hdr_dir([<name>[,<occ>]]) : subdir match。路径匹配 , header的uri路径。

      • hdr_dom([<name>[,<occ>]]) : domain match。域匹配 , header中的domain name。

      • hdr_end([<name>[,<occ>]]) : suffix match。后缀匹配, 用于测试请求报文的指定首部的结尾部分是否符合<string>指定的模式。

      • hdr_len([<name>[,<occ>]]) : length match。长度匹配 , header的长度匹配

      • hdr_reg([<name>[,<occ>]]) : regex match。正则表达式匹配 , 自定义表达式(regex)模糊匹配

      • hdr_sub([<name>[,<occ>]]) : substring match。子串匹配 , header中的uri模糊匹配

      示例

      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
      有些功能是类似的 , 比如以下几个都是匹配用户请求报文中host的开头是不是www:
      acl short_form hdr_beg(host) www.
      acl alternate1 hdr_beg(host) -m beg www.
      acl alternate2 hdr_dom(host) -m beg www.
      acl alternate3 hdr(host) -m beg www.

    • req.hdr_cnt([<name>]) : integer , 返回一个整数 , 代表请求头字段名称<name>的出现次数 , 如果没有指定<name> , 则代表头字段值的总数。和req.hdr()一样 , 它计算头信息的每个逗号分隔部分的值。如果需要对全行头进行计数 , 则应使用req.fhdr_cnt()来代替。

    • req.hdr_ip([<name>[,<occ>]]) : ip , 它提取HTTP请求中最后出现的头信息<name> , 将其转换为IPv4或IPv6地址并返回该地址。当与ACL一起使用时 , 所有的出现都会被检查 , 如果<name>被省略 , 每个头的每个值都会被检查。

    • req.hdrs : string , 以字符串的形式返回当前请求报头 ,包括将报头与请求正文分隔开的最后一行空行。最后的空行可以用来检测被截断的报头块。

    • method : integer + string , 返回一个与HTTP请求中的方法相对应的整数值。例如 , GET等于1(检查来源以建立匹配)。值9表示 "其他方法"。这不应该直接作为样本使用 , 这只是为了从ACL中使用 , 它可以透明地将方法从模式转换为这些整数+字符串值

      # only accept GET and HEAD requests
      acl valid_method method GET HEAD
      http-request deny if ! valid_method
    • path : string , 提取请求的URL路径 , 它从第一个斜线开始 , 在问号前结束(不包括主机部分)。请注意 对于外发的缓冲区 , 使用 url 代替会更明智。对于ACL , 它通常用于匹配精确的文件名 ( 例如"/login.php" ) , 或使用衍生形式的目录部分。

      ACL衍生指令

      • path : exact string match。

      • path_beg : prefix match。用于测试请求的URL是否以指定的模式开头。下面的例子用于测试URL是否以/static、/images、/javascript或/stylesheets头。

        acl  url_static  path_beg   -i  /static /images /javascript /stylesheets
      • path_dir : subdir match。用于测试请求的URL是否以<string>指定的模式结尾。例如 , 下面的例子用户测试URL是否以jpg、gif、png、css或js结尾。

        acl  url_static  path_beg   -i  .ipg .gif .png .css .js
      • path_dom : domain match。当path中包含以.分隔的string时 , 返回true ;可用于域名匹配;

      • path_end : suffix match。当path以某个string为结束时 , 返回true ; 可用于控制文件扩展名;

      • path_len : length match。当path的长度与指定值或范围匹配时 , 返回true ; 可用于检测abusive requests ;

      • path_reg : regex match。当path与正则表达式匹配时 ,返回 true。

        acl url_static  path_reg  -i .jpg$ .html$  ^/static ^/images ^/stylsheets 
      • path_sub : substring match。当path包含某个string时 , 返回true ; 可用于检测 path中的指定模式 , 比如 "../" ;

    • req.hdr_names([<delim>]) : string , 当规则被评估时 , 这将建立一个由所有头名称连接而成的字符串 , 这些头名称在请求中出现。默认的分隔符是逗号(,) , 但它可以作为一个可选的参数<delim>被覆盖。在这种情况下 , 只有<delim>的第一个字符被考虑。

    • req.ver : string , 返回HTTP请求中的版本字符串 , 例如1.1。这对日志来说是有用的 , 但主要是为了ACL。一些预定义的ACL已经检查了1.0和1.1版本。

    • res.cook([<name>]) : string , 这是从响应报文中提取 Set-Cookie 头行上最后出现的cookie名称<name> , 并将其值作为字符串返回。如果没有指定名称 , 将返回第一个cookie值。它可以用于基于tcp-check的期望规则中。

    • res.cook_cnt([<name>]) : integer , 返回一个整数 , 代表响应报文中出现的cookie <name>的数量 , 如果没有指定<name> , 则返回所有cookie。这在与ACL结合使用时非常有用 , 可以检测可疑的响应。 它可用于基于tcp-check的expect规则中。

    • res.fhdr([<name>[,<occ>]]) : string , 这个取数的工作原理与req.fhdr()取数类似 , 不同的是它作用于HTTP响应中的头文件。和req.fhdr()一样 , res.fhdr()获取的是完整的值。如果头信息被定义为一个列表 , 你应该使用res.hdr()。这种获取方式有时对诸如Date或Expires这样的头文件很有用。 它可以用于基于tcp-check的expect规则中。

    • res.fhdr_cnt([<name>]) : integer , 这个取数的工作原理与req.fhdr_cnt()取数类似 , 不同的是它作用于HTTP响应中的头文件。和req.fhdr_cnt()一样 ,res.fhdr_cnt()取值也是作用于全值。如果头信息被定义为一个列表 , 你应该使用res.hdr_cnt()。它可以用于基于tcp-check的expect规则中。

    • res.hdr([<name>[,<occ>]]) : string , 这个取数的工作原理与req.hdr()取数类似 , 不同的是它作用于HTTP响应中的头文件。与req.hdr()一样 , res.hdr()取值也认为逗号是一个分隔符。如果不希望这样 , 应该使用res.hdr()。它可以用于基于tcp检查的expect规则中。

      ACL衍生指令

      • res.hdr([<name>[,<occ>]]) : exact string match

      • res.hdr_beg([<name>[,<occ>]]) : prefix match

      • res.hdr_dir([<name>[,<occ>]]) : subdir match

      • res.hdr_dom([<name>[,<occ>]]) : domain match

      • res.hdr_end([<name>[,<occ>]]) : suffix match

      • res.hdr_len([<name>[,<occ>]]) : length match

      • res.hdr_reg([<name>[,<occ>]]) : regex match

      • res.hdr_sub([<name>[,<occ>]]): substring match

    • res.hdr_cnt([<name>]) : integer , 这种获取方式与req.hdr_cnt()获取方式类似 , 不同的是它对HTTP响应中的头信息采取行动。和req.hdr_cnt()一样 , res.hdr_cnt()取值也认为逗号是一个分隔符。如果不希望这样 , 应该使用res.fhdr_cnt()。它可以用于基于tcp检查的expect规则中。

    • res.hdr_ip([<name>[,<occ>]]) : ip , 这种获取方式与req.hdr_ip()的获取方式类似 , 不同的是它作用于HTTP响应中的头文件。可以通过这种方式将数据写入到stick 表中。它可以用在基于tcp检查的expect规则中。

    • res.hdr_names([<delim>]) : string , 当规则被评估时 , 这将建立一个由所有头名称连接而成的字符串 , 这些头名称出现在响应中。默认的分隔符是逗号(','),但它可以作为一个可选的参数<delim>被覆盖。在这种情况下 , 只考虑<delim>的第一个字符。它可以用于基于tcp-check的expect规则中。

    • res.hdrs : string , 返回当前响应头的字符串 , 包括分隔头和请求正文的最后一行空行。最后的空行可以用来检测截断的头信息块。这个取样对一些SPOE头信息分析器和高级日志很有用。它也可以用在基于tcp检查的expect规则中。

    • res.ver : string , 返回HTTP响应中的版本字符串 , 例如1.1。这对日志来说是有用的 , 但主要是为了ACL。它可以在基于tcp检查的expect规则中使用。

    • status : integer , 返回一个包含HTTP响应中的HTTP状态代码的整数 , 例如 ,302。它主要用于ACL和整数范围内 , 例如 ,如果响应不是3xx , 则删除任何Location header。它可以在基于tcp检查的expect规则中使用。

    • url : string , 这将提取在请求中显示的请求URL。对于ACL ,使用path比使用url更好 , 因为客户可能会发送一个完整的URL, 就像通常使用代理那样。唯一真正的用途是匹配在path中不匹配的"*", 而且已经有一个预定义的ACL。

      ACL衍生指令

      • url : exact string match

      • url_beg <string> : prefix match。当URL以某个string起始时 , 返回true ;可用于检查是否以 / 或者某个协议的 scheme 起始;

      • url_dir <string> : subdir match。如果URL中包含以 / 分隔的string , 返回true;用于文件名和目录名匹配;

      • url_dom <string> : domain match。如果URL中包含以. 分隔的string , 返回true ;用于域名匹配;

      • url_end <string> : suffix match。当URL以某个string结束时 , 返回true ;用处很少;

      • url_len <integer> : length match。当URL的长度与指定值或范围匹配时 ,返回true ; 可用于检测abusive requests ;

      • url_reg <regex> : regex match。当URL与正则表达式匹配时 , 返回true ;

      • url_sub <string> : substring match。当URL包含某个string时 , 返回true ;可用于检查query string中的某些pattern ;

    • url_ip : ip , 当主机部分以IP地址的形式出现时 , 这将从请求的URL中提取IP地址。例如 , 监控系统可以使用这个字段作为源IP的替代品 , 以测试一个给定的源地址将遵循什么路径 , 或者强制在一个给定的源地址的表中输入。它可以与 "http-request set-dst"结合使用 , 以模拟旧的 "option http_proxy"

    • url_port : integer ,这是从请求的URL中提取端口部分。注意 ,如果请求中没有指定端口 ,则假定端口为80。

    • urlp([<name>[,<delim>]])/url_param([<name>[,<delim>]]) : string , 这将提取查询字符串中第一次出现的参数<name> , 该参数在'? '或<delim>之后开始 , 在'&'、';'或<delim>之前结束。参数名称是区分大小写的。如果没有给定名称 , 任何参数都将被匹配 , 并且第一个参数将被返回。 结果是一个字符串 , 对应于请求中呈现的参数<name>的值(不执行URL解码)。这可以用于基于客户端ID的会话粘性 , 提取作为URL参数传递的应用程序cookie ,或在ACL中应用一些检查。

      ACL衍生指令

      • urlp(<name>[,<delim>]) : exact string match

      • urlp_beg(<name>[,<delim>]) : prefix match

      • urlp_dir(<name>[,<delim>]) : subdir match

      • urlp_dom(<name>[,<delim>]) : domain match

      • urlp_end(<name>[,<delim>]) : suffix match

      • urlp_len(<name>[,<delim>]) : length match

      • urlp_reg(<name>[,<delim>]) : regex match

      • urlp_sub(<name>[,<delim>]) : substring match

      # match http://example.com/foo?PHPSESSIONID=some_id
      stick on urlp(PHPSESSIONID)
      # match http://example.com/foo;JSESSIONID=some_id
      stick on urlp(JSESSIONID,;)

1.2 ACL-flags

ACL支持以下falgs

  • -i : 在匹配所有后续模式时忽略大小写。

  • -f </path/to/file> : 从指定文件中加载匹配模式。空行以及以井字符('#')开头的行将被忽略。所有前面的空格和制表符都将被删除。如果必须要使用#开头 , 只需在前面加一个空格, 这样它就不会被当作一个注释。在使用-f的同时使用-m , -m必须在前面。这适用于IPv4和精确字符串匹配。在这种情况下 , 重复的内容会被自动删除。

    文件示例patterns.txt

    /images/
    /photos/

    配置示例:

    frontend www
       bind :80
       acl images_url path -i -m beg -f /etc/hapee-2.5/patterns.txt

  • -m <method> : 设置了一个特定的匹配类型 , 在与输入样本进行比较时使用。如果你将-f和-m一起使用 , 那么-m必须先出现。不是所有的匹配类型都能与所有的取样方法一起工作。

    匹配类型

    描述

    found

    只检查流中是否存在请求的样本。例如 , 用它来检查一个URL参数是否存在 , 而不关心它的值。

    bool

    将样本作为布尔值进行匹配。这个方法只适用于返回布尔值或整数值的检索。零或false的值不匹配 , 所有其他值都匹配

    int

    将样本匹配为一个整数。它可以适用于整数和布尔型样本。布尔值false是整数0 , true是整数1。

    ip

    将样本匹配为IPv4或IPv6地址。它只与IP地址样本兼容。

    bin

    将样本与代表二进制序列的十六进制字符串相匹配。它可以适用于二进制或字符串样本

    len

    匹配样本的长度为一个整数。它可以适用于二进制或字符串样本。

    str

    精确的字符串匹配。它可以适用于二进制或字符串样本。

    sub

    子串匹配 ; 检查样本是否包含所提供的字符串模式中的至少一个。它可以适用于二进制或字符串样本。

    reg

    Regex匹配 : 根据正则表达式列表匹配样本。这可以对二进制或字符串样本起作用。

    beg

    前缀匹配 : 检查样本的开头是否像所提供的任何模式。它可以适用于二进制或字符串样本。

    end

    后缀匹配:检查样本的后缀是否像所提供的任何模式。它可以适用于二进制或字符串样本。

    dir

    子目录匹配:检查样本中以斜线分隔的部分是否与提供的模式之一完全匹配。它可以适用于二进制或字符串样本。

    dom

    域匹配:检查样本中以点为界限的部分是否与提供的模式之一完全匹配。它可以适用于二进制或字符串样本。

  • -n : 禁止DNS解析。

    示例文件: safelist.txt
    192.168.0.10
    ssdfasdfasddfasdfa.com
    ​
    #Haproxy配置
    frontend www
       bind :80
       acl safe_ip src -n -f /etc/hapee-2.5/safelist.txt
       tcp-request content reject unless safe_ip  
    ​
    #重启Haproxy报错提示
    error detected while parsing ACL 'safe_ip' : 'ssdfasdfasddfasdfa.com' is not a valid IPv4 or IPv6 address at line 2

  • -M : 加载-f指定的文件 , 类似于映射文件。第一列是一个键 , 第二列是一个关联值。一个ACL行只读取第一列; 但你可以在以后使用第二列 , 比如通过http-request行的映射转换器。

    #redirects.map  
    ​
    www.test.com   www.test.com
    docs.test.com  www.test.com/docs
    blog.test.com  www.test.com/blog

    ACL只考虑第一列 , 与单列文件的-f标志的方式相同。然而 , 后面的http-request重定向行从key列中找到匹配的Host头 , 并从value列中填入重定向的URL。

    frontend www
       bind :80
    ​
       # Does the Host header match a key in the map file?
       acl requires_redirect req.hdr(Host) -i -M -f /etc/hapee-2.5/redirects.map
    ​
       # Use the correct redirect URL based on the Host header
       http-request redirect prefix https://%[req.hdr(Host),lower,map(/etc/hapee-2.5/redirects.map)] code 301 if requires_redirect

  • -u : 强制使用ACL的唯一ID。这个唯一的ID用于套接字接口来识别ACL并动态地改变其值。注意 , 即使设置了ID ,文件也总是由其名称来识别。当你使用Runtime API命令show acl时 , 它会在你定义的ACL旁边显示一个唯一的ID。

    $ echo "show acl" | socat tcp-connect:127.0.0.1:9024
    ​
    # id (file) description
    0 () acl 'ssl_fc' file '/etc/hapee-2.5/hapee-lb.cfg' line 45
    1 () acl 'dst_port' file '/etc/hapee-2.5/hapee-lb.cfg' line 48
    2 () acl 'dst' file '/etc/hapee-2.5/hapee-lb.cfg' line 51
    3 () acl 'req.body' file '/etc/hapee-2.5/hapee-lb.cfg' line 55
    4 () acl 'path' file '/etc/hapee-2.5/hapee-lb.cfg' line 6

    可以使用其他Runtime API命令 , 例如get acl , 根据ACL测试一个特定的值 , 你可以通过其唯一的ID来参考

    $ echo "get acl #4 /images/" | socat tcp-connect:127.0.0.1:9024 -
    type=str, case=sensitive, match=yes, idx=tree, pattern="/images/"
    ​
    $ echo "get acl #4 /test/" | socat tcp-connect:127.0.0.1:9024 -
    type=str, case=sensitive, match=no

    默认情况下 , HAProxy Enterprise会控制每个ACL的唯一ID。然而 , 你可以使用-u标志来自己设置。

    frontend www
       bind :80
       acl image_url path_beg -i -u 50 /images/
  • -- : 强制结束标志。当一个字符串看起来像其中一个标志时很有用。

2. 特殊匹配

2.1 整数范围

用冒号分隔的下限和上限来表示一个整数范围。

frontend www
   bind :80
​
   # Is the response status from the server between 500 and 511?
   acl response_5xx status 500:511

当其中一个边界丢失时 , 表示该范围没有开始或没有结束。这意味着你要匹配高于或低于指定的下限或上限的任何东西。

frontend www
   bind *:80
​
   # Is port 1024 or higher?
   acl high_port dst_port 1024:
​
   # Is port 1023 or lower?
   acl low_port dst_port :1023

2.2 整数运算符号

使用运算符比较两个整数。

frontend www
   bind :80
​
   # Is the HTTP response body greater than 10000 bytes?
   acl 10kb_response res.body_len gt 10000

下列表格是可用于整数匹配的运算符

操作符

描述

eq

=

ge

>=

gt

>

le

<=

lt

<

2.3 十进制数字

作为一种特殊情况 , 一些ACL函数支持十进制数字 ,它是由句号分隔的两个整数。在下面的例子中 , 两个ACL , tlsv1和ssl3_or_tls1调用req.ssl_ver fetch方法 ,该方法返回一个十进制数字 , 表示使用的SSL/TLS的版本 。然后我们将该值与一个字面值3.1和3:3.1的范围进行比较。

frontend www
   bind :80
​
   # Match TLV v1.0
   acl tlsv1 req.ssl_ver 3.1
​
   # Match SSL 3.0 or TLS 1.0
   acl ssl3_or_tls1 req.ssl_ver 3:3.1

所有的整数属性都适用于十进制数字 , 包括范围和运算符。

2.4 字符串匹配

字符串匹配适用于字符串或二进制的获取方法或转换器。它分为六种匹配类型 , 使用-m标志来指示匹配类型。

参数

描述

-m str

准确匹配字符串

-m sub

匹配字符串的一部分

-m beg

匹配字符串的开头

-m end

匹配字符串的结尾

-m dir

匹配URL或文件路径的一部分 , 以斜线(/)为界。

-m dom

匹配域的一部分 , 以句号(.)为分隔符。

注 : \适用于特殊字符的字符转义, 可以转义类似于空格等特殊字符

2.5 正则表达式

使用-m reg匹配类型来比较一个获取方法的值和一个正则表达式。你可以通过在反斜线前加上另一个反斜线来转义反斜线\。

frontend www
   bind :80
​
   # Path contains cat, caat, caaat, etc.
   acl contains_cat path -m reg ca+t

2.6 任意的数据块

当你不能安全地将其表示为字符串时 , 有可能将样本与二进制块匹配。要做到这一点 . 必须将模式作为一系列偶数的十六进制数字来传递。将匹配类型设置为bin。每两个数字的序列代表一个字节。十六进制数字可以是大写或小写。

# Match the string Hello at the beginning of the input stream
# (Hexadecimal values: x48 x65 x6c x6c x6f x0a)
acl hello payload(0,6) -m bin 48656c6c6f0a

2.7 IPv4/IPv6地址

你可以与带掩码的IPv4地址进行匹配。当你使用网络掩码时 , 只要是在网络中的IPv4地址都可以匹配。可以以通常的形式输入IPv6地址 , 也可以不输入附加的网络掩码。对于IPv6网络掩码 , 只接受位数。

frontend www
   bind :80
​
   # Is the client's IP address localhost?
   acl is_localhost src 127.0.0.1
​
   # Is the client's IP address in the IPv4 range?
   acl allowed_ipv4 src 192.168.0.0/16
​
   # Is the client's IP address in the given IPv6 range?
   acl allowed_ipv6 src 2001:db8::/48

3 内联ACL

尽管你可以通过使用acl指令来定义一个ACL , 在这种情况下 , 它可以在另一行中以名字来引用。

frontend www
   bind :80
   acl api_url path_beg /api/
   use_backend api_servers if api_url
​
backend api_servers
   server s1 192.168.50.20:80

也可以通过用大括号({})包围表达式来声明ACL的内联

frontend www
   bind :80
   use_backend api_servers if { path_beg /api/ }
​
backend api_servers
   server s1 192.168.50.20:80

4 ACL 中的条件判断

  • 与 : 默认使用

  • 或 : 使用or 或||表示

  • 非 : 使用!表示

    if valid_src valid_port #与关系,A和B都要满足为true
    if invalid_src || invalid_port #或 , A或者B满足一个为true
    if ! invalid_src #非 , 取反 , A和B哪个也不满足为true

使用方式: [!]acl1 [!]acl2 ... [!]acln { or [!]acl1 [!]acl2 ... [!]acln } ... 。

这种条件判断一般用在 "if"或 "unless "语句之后。表明该条件判断何时会触发运行。

示例

#阻止使用OPTIONS 以外的方法对所有(*) 网址的HTTP请求,同时阻止没有content-length的POST请求,和content-length大于0的GET或HEAD 请求。 
#最后将全是除GET/HEAD/POST/OPTIONS的请求  
   acl missing_cl req.hdr_cnt(Content-length) eq 0
   http-request deny if HTTP_URL_STAR !METH_OPTIONS || METH_POST missing_cl
   http-request deny if METH_GET HTTP_CONTENT
   http-request deny unless METH_GET or METH_POST or METH_OPTIONS
   
   
#为www网站上的静态内容请求和img、video、download和ftp主机上的每个请求选择一个不同的后端   
   acl url_static  path_beg         /static /images /img /css
   acl url_static  path_end         .gif .png .jpg .css .js
   acl host_www    hdr_beg(host) -i www
   acl host_static hdr_beg(host) -i img. video. download. ftp.
​
   # now use backend "static" for all static-only hosts, and for static URLs
   # of host "www". Use backend "www" for the rest.
   use_backend static if host_static or host_www url_static
   use_backend www    if host_www

可以使用 "匿名ACL "来设置规则。这些是不具名的ACL表达式 , 它们是临时建立的 , 不需要被声明。它们必须用大括号括起来 , 每个大括号前后都有一个空格(因为大括号必须被看作是独立的词)。 例子 :

acl missing_cl req.hdr_cnt(Content-length) eq 0
http-request deny if METH_POST missing_cl
#等价于
http-request deny if METH_POST { req.hdr_cnt(Content-length) eq 0 }
​
​
acl site_dead nbsrv(dynamic) lt 2
acl site_dead nbsrv(static)  lt 2
monitor fail  if site_dead
等价于
monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 }

5. 预定义ACL的使用

预定义的ACL是硬编码的 , 这样它们就不必在每个需要它们的frontend都被声明。它们的名字都是大写的 , 以避免混淆。

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 localhost

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

示例:

listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl static_path path_beg -i /static /images /javascript
    use_backend static_path_host if HTTP_1.1 TRUE static_path
    default_backend default_web
​
backend php_server_host
    mode http
    server web1 192.168.7.103 check inter 2000 fall 3 rise 5
    
backend static_path_host
    mode http
    server web1 192.168.7.104 check inter 2000 fall 3 rise 5
    
backend default_web
    mode http
    server web1 192.168.7.102:80 check inter 2000 fall 3 rise 5

6. 配置block拒绝访问

  • 语法 : block { if | unless} <condition>, 阻止7层请求if/unless一个条件匹配

示例:

#示例1
frontend http
   acl deny_src src 172.18.0.108
   #自定义源地址为172.18.0.108的acl组deny_src
   acl deny_port dst_port 80:100
   #自定义目标端口为80到100的acl组deny_port
   block if deny_src || deny_port
   #如果属于deny_src组或deny_port组则拒绝访问
   block unless deny_src #如果不属于acl组deny_src则拒绝访问
 
#示例2
acl bad_curl hdr_sub(User-Agent) -i curl
block if bad_curl

7. ACL 示例

#域名匹配
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl web_host hdr_dom(host) www.magedu.net
    use_backend magedu_host if web_host
    default_backend default_web
    
backend magedu_host
    mode http
    server web1 192.168.7.103 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.104:80 check inter 2000 fall 3 rise 5
    
#基于源IP或子网调度访问, 将指定的源地址调度至指定的web服务器组。
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl ip_range_test src 172.18.0.0/16 192.168.7.103
    use_backend magedu_host if ip_range_test
    default_backend default_web
backend magedu_host
    mode http
    server web1 192.168.7.103 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.104:80 check inter 2000 fall 3 rise 5
    
#基于源地址的访问控制,拒绝指定IP或者IP范围访问
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl block_test src 192.168.7.103 192.168.0.0/24
    block if block_test
    default_backend default_web
backend magedu_host
    mode http
    server web1 192.168.7.103 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.104:80 check inter 2000 fall 3 rise 5
​
#匹配浏览器类型, 匹配客户端浏览器,将不通类型的浏览器调动至不同的服务器组
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl web_host hdr_dom(host) www.magedu.net
    use_backend magedu_host if web_host
    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"
    redirect prefix http://192.168.7.103 if redirect_test
    default_backend default_web
backend magedu_host
    mode http
    server web1 192.168.7.103 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.104:80 check inter 2000 fall 3 rise 5
    
#基于文件后缀名实现动静分离
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    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_web
backend php_server_host
    mode http
    server web1 192.168.7.103 check inter 2000 fall 3 rise 5
backend image_server_host
    mode http
    server web1 192.168.7.104 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.102:80 check inter 2000 fall 3 rise 5
    
# curl http://192.168.7.101/app/test.php
php
​
#匹配访问路径实现动静分离
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl static_path path_beg -i /static /images /javascript
    use_backend static_path_host if static_path
    default_backend default_web
backend static_path_host
    mode http
    server web1 192.168.7.104 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.102:80 check inter 2000 fall 3 rise 5
​
#基于ACL的http访问控制
listen web_host
    bind 192.168.7.101:80
    mode http
    balance roundrobin
    log global
    option httplog
    acl static_path path_beg -i /static /images /javascript
    use_backend static_path_host if static_path
    acl badguy_deny src 192.168.7.102
    http-request deny if badguy_deny
    http-request allow
    default_backend default_web
backend static_path_host
    mode http
    server web1 192.168.7.104 check inter 2000 fall 3 rise 5
backend default_web
    mode http
    server web1 192.168.7.102:80 check inter 2000 fall 3 rise 5
 #测试
[root@server2 ~]# curl --head http://192.168.7.101/static/1.jpg
HTTP/1.1 403 Forbidden
Content-length: 93
Cache-Control: no-cache
Connection: close
Content-Type: text/html