跳转到主要内容

标准功能

样本提取、映射、ACL、内容切换、粘性表、重写和服务器保护

在本段中,列举了一些在 HAProxy 中非常常见但未必存在于其他负载均衡器上的功能。

3.4.1. 标准功能:采样与信息转换

HAProxy 支持使用多种“样本提取函数”进行信息采样。其原理是提取称为样本的信息片段,以供即时使用。该机制用于实现会话粘性、构建条件判断、生成日志信息或丰富 HTTP 头。

样本可从多种来源获取:

  • 常量:整数、字符串、IP 地址、二进制块;

  • 进程:日期、环境变量、服务器/前端/后端/进程状态、字节/连接数及速率、队列长度、随机数生成器等

  • 变量:会话级、请求级、响应级变量;

  • 客户端连接:源地址和目标地址及端口,以及所有相关统计信息计数器;

  • SSL 客户端会话:协议、版本、算法、加密套件、密钥长度、会话 ID、所有客户端和服务器证书字段、证书序列号、SNI、ALPN、NPN、客户端对特定扩展的支持情况;

  • 请求和响应缓冲区内容:偏移/长度处的任意负载、数据长度、RDP;Cookie;SSL Hello 类型解码;TLS SNI 解码

  • HTTP(请求和响应):方法、URI、路径、查询字符串参数、状态码、头字段值、位置头字段值、Cookie、捕获内容、认证信息、请求体元素;

一个样本随后可经过多个称为“转换器”的运算符,以实现某种转换。转换器会消耗一个样本并生成一个新的样本,新样本的类型可能完全不同。例如,转换器可用于仅返回输入字符串的整数长度,或可将字符串转换为大写。在最终使用前,可对样本依次应用任意数量的转换器。在所有可用的样本转换器中,以下几种最为常用:

  • 算术与逻辑运算符:可用于对输入数据执行高级计算,例如计算比率、百分比,或仅将一种单位转换为另一种单位;

  • IP 地址掩码在需要将某些地址按更大的网络进行分组时非常有用;

  • 数据表示:URL 解码、Base64、十六进制、JSON 字符串、哈希;

  • 字符串转换:在固定位置或固定长度处提取子字符串,按特定分隔符提取字段,提取特定单词,转换大小写,应用基于正则表达式的替换;

  • 日期转换:转换为 HTTP 日期格式,转换本地时间与 UTC 时间,以及添加或移除偏移量;

  • 在粘性表中查找条目,以获取统计信息或已分配的服务器;

  • 基于文件的映射(主要用于地理定位)的键值转换。

3.4.2. 标准功能:映射

映射是一种强大的转换器类型,其工作方式是在启动时将一个包含两列的文件加载到内存中,随后对每个输入样本在第一列中进行查找。若找到匹配项,则返回第二列对应的模式;若未找到,则返回默认值。由于输出信息本身也是一个样本,因此可进一步接受其他转换操作,包括其他映射查找。映射最常用于将客户端的 IP 地址转换为自治系统编号(AS number)或国家代码,因为其支持网络地址的最长前缀匹配。此外,映射也可用于多种其他用途。

其强大之处部分源于可随时通过 CLI 或使用其他样本执行特定动作进行更新,从而能够在后续访问之间存储和检索信息。另一大优势则来自基于二叉树的索引机制,即使包含数十万条条目,也能实现极高的处理速度,使地理位置定位变得极为廉价且易于部署。

3.4.3. 标准功能:ACL 和条件判断

HAProxy 中的大多数操作均可设置条件。条件通过使用逻辑运算符(AND、OR、NOT)组合多个 ACL 构建而成。每个 ACL 是一系列基于以下元素的测试:

  • 用于获取待测试元素的样本提取方法;

  • 可选的一系列转换器,用于转换元素;

  • 用于匹配的模式列表;

  • 用于指示如何将模式与样本进行比较的匹配方法

例如,样本可从 HTTP “Host” 头中获取,随后转换为小写,再使用正则匹配方法与多个正则模式进行匹配。

从技术上讲,ACL 与映射共享相同的底层核心,二者具有完全相同的内部结构、匹配方法和性能表现。唯一的实际区别在于,ACL 不返回样本,仅返回“找到”或“未找到”。在使用方面,ACL 模式可直接在配置文件中内联声明,无需单独的文件。ACL 可以命名,以方便使用或提升配置的可读性。命名的 ACL 可多次声明,系统将依次评估所有定义,直至匹配到第一个符合条件的规则。

本文提供约 13 种不同的模式匹配方法,其中包括 IP 地址掩码、整数范围、子字符串和正则表达式。这些方法的工作方式类似于函数,与任何编程语言一样,仅评估所需部分。因此,当涉及 OR 的条件已为真时,后续条件不再评估;同理,当涉及 AND 的条件已为假时,其余条件也不再评估。

声明的 ACL 数量没有实际限制,且提供了若干常用 ACL。然而,经验表明,使用大量命名 ACL 的配置较难排查故障,有时在分析范围内直接使用匿名 ACL 反而更简便,因为这样所需的外部引用更少。

3.4.4. 标准功能:内容切换

HAProxy 实现了一种称为基于内容切换的机制。其原理是:连接或请求到达前端后,会处理与该请求或连接一同携带的信息,此时可编写基于 ACL 的条件,利用这些信息决定由哪个后端处理请求。因此,流量可根据请求内容被导向不同的后端。最常见的示例是利用 Host 头和/或路径中的元素(子目录或文件名扩展名)判断 HTTP 请求是针对静态资源还是应用程序,并将静态资源流量路由至由快速轻量级服务器组成的后端,其余流量则路由至更复杂的应用服务器,从而构成细粒度的虚拟主机解决方案。这种方式非常便于多种技术共存,作为更全面的解决方案。

另一种内容切换的用例是根据不同的条件使用不同的负载均衡算法。缓存可使用 URI 哈希,而应用程序则使用轮询。

最后但同样重要的是,它通过为每个后端(即每个客户)强制实施连接限制,允许多个客户共享一个公共资源的少量份额。

内容切换规则的扩展性非常好,尽管其性能可能受当前使用的 ACL 数量和复杂度的影响。但也可以编写动态内容切换规则,使样本值直接转换为后端名称,完全无需使用 ACL。据报告,此类配置在生产环境中至少支持 300000 个后端时仍能正常工作。

3.4.5. 标准功能:粘性表

会话粘性通常通过会话表(stick-table)来存储,即记录某个访问者被引导至的服务器的引用。键(key)是与该访问者关联的标识符(如源地址、连接的 SSL ID、HTTP 或 RDP Cookie、从 URL 或负载中提取的客户编号等),而存储的值则是对应服务器的标识符。

粘性表可使用三种不同类型的样本作为键:整数、字符串和地址。 每个代理只能引用一个粘性表,且在所有位置均以代理名称进行标识。 最多可并行跟踪 8 个键。 在请求或响应处理过程中,一旦键和服务器均被确定,服务器标识即被确认。

粘性表内容可在活动-活动模式下与其他已知为“对等节点”的 HAProxy 节点同步,也可在重载操作期间与新进程同步,从而确保所有负载均衡节点共享相同信息,并在客户端请求分布于多个节点时做出相同的路由决策。

由于会话粘性表基于用于识别客户端的字段进行索引,因此它们通常也用于存储额外信息,例如客户端级别的统计信息。额外的统计信息会占用额外空间,且必须显式声明。可存储的统计类型包括输入和输出带宽、并发连接数、特定时间段内的连接速率与连接次数、错误发生量与频率、特定标签与计数器等。为支持在不强制绑定至特定服务器的情况下保留此类信息,引入了一项特殊“跟踪”功能,可同时跟踪来自不同表的最多 3 个不同键,且不受会话粘性规则限制。每项存储的统计信息均可通过 CLI 进行搜索、导出和清除,从而增强实时故障排查能力。

尽管该机制可用于区分返回访客或根据良好或不良行为调整服务质量,但其主要用途是防范服务滥用,更广泛地应对分布式拒绝服务(DDoS)攻击,因为它能够以高处理速度构建复杂模型,以检测特定不良行为。

3.4.6. 标准功能:格式化字符串

HAProxy 需要在多个位置操作字符字符串,例如日志记录、重定向、头字段添加等。为提供最大程度的灵活性,引入了“格式化字符串”概念,最初用于日志记录,因此至今仍称为“log-format”。这些字符串包含转义字符,可用于在字符串中插入各种动态数据,包括变量和样本提取表达式,甚至可在将结果转换为字符串时调整编码(例如添加引号)。这为构建头内容、生成响应数据或响应模板,以及自定义日志行提供了强大手段。此外,为简化常见字符串的构建,提供了约 50 个特殊标签,作为日志中常用信息的快捷方式。

3.4.7. 标准功能:HTTP 重写和重定向

在未针对此场景设计的应用程序前部署负载均衡器,若缺乏合适的工具,将是一项具有挑战性的任务。此类情况下最常被请求的操作之一,是调整请求和响应头,使负载均衡器看起来如同源服务器,并修复硬编码的信息。这包括修改请求中的路径(强烈建议避免)、修改 Host 头字段、修改重定向时的 Location 响应头字段、修改 Cookie 的路径和域名属性等。此外,部分服务器的响应信息较为冗余,容易泄露过多信息,从而增加遭受针对性攻击的风险。尽管从理论上讲,负载均衡器并不负责清理此类信息,但在实际部署中,它位于基础设施中最佳的位置,能够确保所有信息均被清理。

同样,有时负载均衡器必须拦截某些请求,并返回重定向至新的目标 URL。尽管有些人容易将重定向与重写混淆,但二者是完全不同的概念:重写会使客户端与服务器看到不同的内容(并就所访问页面的位置产生分歧),而重定向则要求客户端访问新的 URL,从而使客户端看到的位置与服务器一致。

为实现此目的,HAProxy 支持多种重写和重定向机制,其中包括:

  • 在请求和响应中基于正则表达式的 URL 和头重写。正则表达式是修改头值最常用的工具,因其易于操作且广为人知;

  • HTTP 头也可基于格式化字符串追加、删除或替换,以便在其中传递信息(例如客户端 TLS 算法和密码套件);

  • HTTP 重定向可使用任意 3xx 状态码,将请求重定向至相对 URI、绝对 URI 或完全动态(格式化字符串)的 URI;

  • HTTP 重定向还支持一些额外选项,例如设置或清除特定 Cookie、丢弃查询字符串、在缺少斜杠时追加斜杠等;

  • 强大的 return 指令允许使用动态内容甚至模板文件,自定义响应的各个部分,如状态码、头和正文。

  • 所有操作均支持基于 ACL 的条件;

3.4.8. 标准功能:服务器保护

HAProxy 通过多种手段最大限度地提升服务可用性,为此需投入大量努力以保护服务器免受过载和攻击。首要且最重要的原则是,仅将完整且有效的请求转发至服务器。首要原因在于,HAProxy 需要识别协议中所需的元素,以保持与字节流的同步;第二个原因是,在请求未完成前,无法判断某些元素是否会改变其语义。由此带来的直接好处是,服务器不会暴露于无效或不完整的请求之下。这一机制对 slowloris 攻击具有极强的防护效果,此类攻击对 HAProxy 几乎无影响。

另一个重要点是,HAProxy 包含用于存储请求和响应的缓冲区,通过仅在请求完整时才将其发送至服务器,并迅速从本地网络读取整个响应,可使服务器端连接的占用时间尽可能短,从而最大程度地节省服务器资源。

对这一机制的直接延伸是,HAProxy 可以人为限制发送至服务器的并发连接数或待处理请求数,从而确保即使在流量高峰期间服务器持续以 100% 的容量运行,也不会发生过载。所有超出限制的请求将被放入队列,待有空闲槽位时再进行处理。最终,这种巨大的资源节省通常能显著提升服务器响应速度,反而比让服务器过载更高效。队列中的请求可被重分派至其他服务器,或在客户端中断时于队列中中止,这同样可防止“刷新效应”——即访问者在页面加载缓慢时反复点击“刷新”按钮,通常会触发新的请求并使服务器长期处于过载状态。

慢启动机制还可防止重启中的服务器在启动完成或编译某些类期间遭受过高流量冲击。

关于协议层保护,可放宽 HTTP 解析器以接受非标准但无害的请求或响应,甚至可对其进行修复。这使得存在缺陷的应用程序在修复开发期间仍可访问。同时,违规消息会被完整捕获,并生成详细报告,有助于开发人员定位应用程序中的问题。最危险的协议违规行为将被正确检测并处理或修复。例如,包含两个 Content-Length 头的畸形请求或响应,若其值完全相同则予以修复,若不同则予以拒绝,因为这会引发安全问题。协议检查不仅限于 HTTP,还适用于 TLS、RDP 等其他协议。

当检测到协议违规或攻击时,可采取多种方式响应用户,例如返回常见的“HTTP 400 错误请求”、通过 TCP 重置关闭连接,或在长时间延迟后伪造错误(“tarpit”)以混淆攻击者。所有这些措施均有助于通过阻止违规客户端继续实施成本高昂的攻击来保护服务器。

HAProxy 还提供了一些更高级的选项,用于防范意外的数据泄露和会话交叉。它不仅能记录可疑的服务器响应,还会记录并可选地阻止可能影响特定访客隐私的响应。例如,当可缓存的响应中出现可缓存的 Cookie 时,可能导致中间缓存将该 Cookie 传递给其他访客,从而引发意外的会话共享。