--- title: "7. ACL 与样本提取" linkTitle: "7. ACL 与样本" weight: 180 description: "ACL 匹配、条件、转换器、样本提取和预定义 ACL" icon: fa-solid fa-filter module: [HAPROXY] categories: [参考] aliases: - /haproxy/configuration/acls-and-samples/ - /docs/haproxy/configuration/acls-and-samples/ - /haproxy/acls-and-samples/ upstream_link: "https://docs.haproxy.org/3.4/configuration.html" upstream_name: "HAProxy 3.4 Configuration Manual" upstream_ref: "v3.4.4, chapter 7" --- HAProxy 可从请求或响应流、客户端或服务器信息、表格、环境信息等来源提取数据。提取此类数据的动作称为获取样本。获取后,这些样本可用于多种用途,例如作为粘性表的键,但最常见的用法是将其与称为模式的预定义常量数据进行匹配。 ## 7.1. ACL 基础 {#section-7-1} 访问控制列表(ACL)用于声明一种命名的匹配方法,以将任意信息与预先定义的模式列表进行比较。ACL 可视为大多数编程语言中函数的实际等价物,其声明使得该方法可在后续需要时被调用。ACL 的评估结果仅返回匹配或不匹配,这与许多编程语言中的布尔值类似。与编程语言中的函数不同,ACL 可以针对同一名称多次重载,以定义额外的匹配方法。在此情况下,所有 ACL 将按声明顺序依次评估,直到其中一个匹配为止。 ACL 的使用提供了一种灵活的解决方案,用于执行内容切换,或基于从请求、响应或任何环境状态中提取的内容做出决策。其原理十分简单: - 从流、表或环境提取数据样本 - 可选地对提取的样本应用格式转换 - 对该样本应用一个或多个模式匹配方法 - 仅当模式与样本匹配时执行动作 动作通常包括阻止请求、选择后端或添加头。 要定义一个测试,需使用 "acl" 关键字。语法如下: ```text acl [flags] [operator] [] ... ``` 创建一个新的 ACL ``,或对已存在的 ACL 添加新的测试条件。这些测试条件适用于 `` 指定的请求/响应部分,可使用可选标志 [flags] 进行调整。部分条件支持指定操作符,操作符可置于值集合之前。可选地,可对样本应用转换操作符,转换操作符需以逗号分隔的关键词列表形式紧随首个关键词之后指定。值的类型由条件所支持,各值之间以空格分隔。 ACL 名称必须由大写字母、小写字母、数字、'-'(连字符)、'\_'(下划线)、'.'(点)和 ':'(冒号)组成。ACL 名称区分大小写,这意味着 "my_acl" 和 "My_Acl" 是两个不同的 ACL。 ACL 的数量没有强制限制。未使用的 ACL 不会影响性能,仅会占用少量内存。 判断标准通常为样本提取方法的名称,或其 ACL 特定形式之一。默认的测试方法由该样本提取方法的输出类型决定。ACL 特定形式可用于描述同一样本提取方法的其他匹配方法。样本提取方法是唯一支持转换的类型。 样本提取方法返回的数据类型如下: - 布尔值 - 整数(有符号或无符号) - IPv4 或 IPv6 地址 - 字符串 - 数据块 转换器可将任意数据转换为任意其他数据。例如,某些转换器可将字符串转换为小写字符串,而其他转换器则可将字符串转换为 IPv4 地址,或对 IP 地址应用子网掩码。最终生成的样本类型为应用于列表的最后一个转换器的类型,其默认值为样本提取方法的类型。 每个样本或转换器返回特定类型的数据,该类型在本文档中通过其关键字指定。当使用标准样本提取方法声明 ACL 时,某些类型会自动关联默认匹配方法,具体如下表所示: ```text +---------------------+-----------------+ | Sample or converter | Default | | output type | matching method | +---------------------+-----------------+ | boolean | bool | +---------------------+-----------------+ | integer | int | +---------------------+-----------------+ | ip | ip | +---------------------+-----------------+ | string | str | +---------------------+-----------------+ | binary | none, use "-m" | +---------------------+-----------------+ ``` 请注意,若要匹配二进制样本,必须指定匹配方法,详见下文。 ACL 引擎可将这些类型与以下类型的模式进行匹配: - 布尔值 - 整数或整数范围 - IP 地址 / 网络 - 字符串(精确匹配、子串、后缀、前缀、子目录、域名) - 正则表达式 - 十六进制块 以下 ACL 标志当前受支持: ```text -i: ignore case during matching of all subsequent patterns. -f: load patterns from a list. -m: use a specific pattern matching method -n: forbid the DNS resolutions -M: load the file pointed by -f like a map. -u: force the unique id of the ACL --: force end of flags. Useful when a string looks like one of the flags. ``` “-f” 标志后跟的名称必须符合第 2.7 节中关于映射和 ACL 名称格式的描述。如果需从多个列表加载模式,可以传递多个“-f”参数。若引用了现有文件,所有行将被读取为独立的值。空行以及以井号('#')开头的行将被忽略。所有前导空格和制表符将被去除。若必须插入以井号开头的有效模式,只需在其前添加一个空格,以避免被误认为是注释。根据数据类型和匹配方式,HAProxy 可能会将行加载到二叉树中,从而实现极快的查找。IPv4 和精确字符串匹配即属此类情况,此时重复项将自动被移除。 “-M” 标志允许 ACL 使用映射。若设置此标志,列表将被解析为两列条目。第一列包含 ACL 使用的模式,第二列包含样本。该样本后续可被映射使用。在某些罕见场景中,这可用于在应用映射前,仅通过 ACL 检查模式是否存在于映射中。 "-u" 标志强制 ACL 的唯一 ID。该唯一 ID 用于套接字接口,以标识 ACL 并动态修改其值。请注意,即使设置了 ID,文件仍始终通过其名称进行标识。 此外请注意,“-i” 标志仅适用于其后的条目,而不适用于其前从文件加载的条目。例如: ```text acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test ``` 在本例中,"exact-ua.lst" 中的每一行将与请求的 "user-agent" 头进行精确匹配。随后,"generic-ua" 中的每一行将不区分大小写进行匹配。然后,单词 "test" 也将不区分大小写进行匹配。 "-m" 标志用于在输入样本上选择特定的模式匹配方法。所有 ACL 特定的条件均隐含模式匹配方法,通常无需此标志。然而,该标志在使用通用样本提取方法时非常有用,用于说明样本将如何与模式进行匹配。对于返回无明显匹配方法数据类型(例如字符串或二进制数据)的样本提取操作,此标志为必需。当指定 "-m" 并后接模式匹配方法名称时,该方法将取代条件的默认匹配方法。这使得能够以最初未计划的方式进行内容匹配,或与返回字符串的样本提取方法配合使用。匹配方法还会影响模式的解析方式,因此不得与带有匹配后缀(\_beg、\_end、\_sub...)的样本提取操作一同使用。此外,禁止指定多个 "-m" 模式匹配方法。 "-n" 标志禁止 DNS 解析。该标志与 IP 文件加载配合使用。默认情况下,若解析器无法解析 IP 地址,会认为被解析的字符串可能为域名并尝试进行 DNS 解析。标志 "-n" 可禁用此解析行为。该选项有助于检测格式错误的 IP 列表。请注意,若 DNS 服务器不可达,HAProxy 配置解析过程可能持续数分钟,等待超时。在此期间不会显示任何错误消息。标志 "-n" 可禁用此行为。此外,在运行时,该功能对于动态 ACL 修改将被禁用。 然而,存在一些限制。并非所有匹配方法均可与所有样本提取方法配合使用。 此外,若将 "-m" 与 "-f" 一同使用,必须将 "-m" 置于首位。模式匹配方法必须为以下之一: - "found": 仅检查请求的样本是否存在于流中,而不与任何模式进行比较。建议不要传递任何模式,以避免混淆。此匹配方法特别适用于检测特定内容(如头、Cookie 等)是否存在,即使其为空,也无需与任何内容比较或计数。 - "bool" : 将值作为布尔类型进行检查。仅可应用于返回布尔值或整数值的 fetch 操作,且不接受任何模式。值为零或 false 时不匹配,其余所有值均匹配。 - int:将值匹配为整数。可用于整数和布尔值样本。布尔值 false 对应整数 0,true 对应整数 1。 - "ip" : 以 IPv4 或 IPv6 地址形式匹配值。仅与 IP 地址样本兼容,因此为隐含项,无需显式指定。 - "bin" : 将内容与表示二进制序列的十六进制字符串进行匹配。此选项可用于二进制或字符串样本。 - "len" : 以整数形式匹配样本的长度。可与二进制或字符串样本配合使用。 - "str" : 精确匹配:将内容与字符串进行匹配。此选项可用于二进制或字符串样本。 - "sub" : 子串匹配:检查内容中是否包含至少一个提供的字符串模式。此模式可用于二进制或字符串样本。 - "reg" : 正则表达式匹配:将内容与一组正则表达式进行匹配。此选项可用于二进制或字符串样本。 - "beg" : 前缀匹配:检查内容是否以提供的字符串模式开头。此模式可用于二进制或字符串样本。 - "end" : 后缀匹配:检查内容是否以提供的字符串模式结尾。此模式可用于二进制或字符串样本。 - "dir" : subdir 匹配:检查内容中以斜杠分隔的部分是否与提供的某个字符串模式完全匹配。此功能可用于二进制或字符串样本。 - "dom" : 域名匹配:检查内容中以点分隔的部分是否与提供的某个字符串模式完全匹配。此模式可用于二进制或字符串样本。 例如,要快速检测 HTTP 请求中是否存在 Cookie "JSESSIONID",可以执行: ```text acl jsess_present req.cook(JSESSIONID) -m found ``` 为在缓冲区的前 500 字节数据上应用正则表达式,可使用以下 ACL: ```text acl script_tag req.payload(0,500) -m reg -i