配置手册

版本 2.2.34

2025/04/23

本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。以下摘要旨在帮助您按名称查找章节并在文档中导航。文档贡献者须知:本文档每行格式化为80列,使用偶数个空格进行缩进,不使用制表符。请严格遵守这些规则,以便在任何地方都能轻松打印。如果某行需要逐字打印且不适合,请在每行末尾加上反斜杠('\'),并在下一行继续,缩进两个字符。有时,为了强调输入和输出之间的差异,当它们可能模糊不清时,用三个闭合尖括号('>>>')作为所有输出行(日志、控制台输出)的前缀也很有用。如果添加新章节,请更新下面的摘要以便于搜索。
1. 关于 HTTP 的快速提醒
1.1.
1.2.
1.2.1.
1.2.2.
1.3.
1.3.1.
1.3.2.

2.

配置 HAProxy
2.1.
2.2.
2.3.
2.4.
2.5.

3.

全局参数
3.1.
3.2.
3.3.
3.4.
3.5.
3.6.
3.7.
3.8.
3.9.

4.

代理
4.1.
4.2.

5.

绑定和服务​​器选项
5.1.
5.2.
5.3.
5.3.1.
5.3.2.

6.

缓存
6.1.
6.2.
6.2.1.
6.2.2.

7.

使用 ACL 和获取样本
7.1.
7.1.1.
7.1.2.
7.1.3.
7.1.4.
7.1.5.
7.1.6.
7.2.
7.3.
7.3.1.
7.3.2.
7.3.3.
7.3.4.
7.3.5.
7.3.6.
7.3.7.
7.4.

8.

日志
8.1.
8.2.
8.2.1.
8.2.2.
8.2.3.
8.2.4.
8.2.5.
8.3.
8.3.1.
8.3.2.
8.3.3.
8.3.4.
8.4.
8.5.
8.6.
8.7.
8.8.
8.9.

9.

支持的过滤器
9.1.
9.2.
9.3.
9.4.
9.5.

10.

FastCGI 应用程序
10.1.
10.1.1.
10.1.2.
10.1.3.
10.2.
10.3.
当 HAProxy 在 HTTP 模式下运行时,请求和响应都会被完全分析和索引,因此可以根据内容中找到的几乎任何信息来构建匹配标准。然而,重要的是要了解 HTTP 请求和响应是如何构成的,以及 HAProxy 是如何分解它们的。这样将更容易编写正确的规则并调试现有配置。

1.1. HTTP 事务模型

HTTP协议是面向事务的。这意味着每个请求只会产生一个且仅一个响应。传统上,客户端会建立一个到服务器的TCP连接,通过该连接发送请求,服务器响应,然后关闭连接。新的请求将涉及新的连接:[CON1] [REQ1] ... [RESP1] [CLO1] [CON2] [REQ2] ... [RESP2] [CLO2] ... 在这种模式下,称为“HTTP关闭”模式,每次HTTP事务都需要建立新的连接。由于服务器在响应后关闭连接,客户端不需要知道内容长度。鉴于协议的事务性,可以对其进行改进,以避免在两次连续事务之间关闭连接。但是,在这种模式下,服务器必须为每个响应指示内容长度,以免客户端无限期等待。为此,使用了一个特殊的头:“Content-length”。这种模式称为“keep-alive”模式:[CON] [REQ1] ... [RESP1] [REQ2] ... [RESP2] [CLO] ... 它的优点是事务之间的延迟降低,服务器端的处理能力要求也更少。它通常比关闭模式更好,但并非总是如此,因为客户端通常会将并发连接限制在较小的值。通信中的另一个改进是流水线模式。它仍然使用keep-alive,但客户端在收到第一个响应之前就可以发送第二个请求。这对于获取组成页面的大量图像非常有用:[CON] [REQ1] [REQ2] ... [RESP1] [RESP2] [CLO] ... 由于消除了连续请求之间的网络延迟,这显然可以带来巨大的性能提升。许多HTTP代理不支持流水线,因为在HTTP中没有办法将响应与相应的请求关联起来。因此,服务器必须按照接收请求的精确顺序进行响应。下一个改进是多路复用模式,例如HTTP/2中的实现。这一次,每个事务都被分配一个单一的流标识符,并且所有流都通过现有连接进行多路复用。客户端可以并行发送许多请求,响应也可以以任何顺序到达,因为它们也带有流标识符。默认情况下,HAProxy在持久连接方面以keep-alive模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间让双方连接处于空闲状态。当它从客户端接收到HTTP/2连接时,它会并行处理所有请求,并将连接保持空闲,等待新请求,就像它是keep-alive HTTP连接一样。HAProxy支持4种连接模式:- keep alive:处理所有请求和响应(默认)- tunnel:只处理第一个请求和响应,其余的都转发,不进行分析(已弃用)。- server close:服务器端连接在响应后关闭。- close:连接在响应结束后主动关闭。

1.2. HTTP 请求

首先,让我们考虑这个 HTTP 请求: 行号 内容 1 GET /serv/login.php?lang=en&profile=2 HTTP/1.1 2 Host: www.mydomain.com 3 User-agent: my small browser 4 Accept: image/jpeg, image/gif 5 Accept: image/png

1.2.1. 请求行

第1行是“请求行”。它总是由3个字段组成:- 方法:GET - URI:/serv/login.php?lang=en&profile=2 - 版本标签:HTTP/1.1 所有这些字段都由标准称为LWS(线性空格)的内容分隔,这些通常是空格,但也可能是制表符或行进/回车符后跟空格/制表符。方法本身不能包含任何冒号(':'),并且限制为字母。所有这些不同的组合使得HAProxy执行拆分操作而不是让用户编写复杂或不准确的正则表达式是可取的。URI本身可以有几种形式:- “相对URI”:/serv/login.php?lang=en&profile=2 这是一个完整的URL,但不包含主机部分。这通常是服务器、反向代理和透明代理接收到的。- “绝对URI”,也称为“URL”:http://192.168.0.12:8080/serv/login.php?lang=en&profile=2 它由“方案”(协议名称后跟“://”)、主机名或地址、可选的冒号(':')后跟端口号,然后是紧跟地址部分第一个斜杠('/')之后的相对URI组成。这通常是代理接收到的,但支持HTTP/1.1的服务器也必须接受这种形式。- 星号('*'):这种形式仅在与OPTIONS方法关联时接受,并且不可中继。它用于查询下一跳的能力。- 地址:端口组合:192.168.0.12:80 这与CONNECT方法一起使用,该方法用于通过HTTP代理建立TCP隧道,通常用于HTTPS,但有时也用于其他协议。在相对URI中,确定了两个子部分。问号之前的部分称为“路径”。它通常是服务器上静态对象的相对路径。问号之后的部分称为“查询字符串”。它主要用于发送到动态脚本的GET请求,并且非常特定于所使用的语言、框架或应用程序。HTTP/2不通过请求传递版本信息,因此版本假定与底层协议相同(即“HTTP/2”)。

1.2.2. 请求头

头信息从第二行开始。它们由行开头的一个名称组成,后面立即跟着一个冒号(':')。传统上,冒号后会添加一个LWS,但这并非必需。然后是值。多个相同的头信息可以通过逗号分隔值合并为一行,前提是它们的顺序得到尊重。这在“Cookie:”字段中经常遇到。如果后续行以LWS开头,则一个头信息可以跨越多行。在1.2中的示例中,第4行和第5行定义了“Accept:”头的总共3个值。与常见的误解相反,头信息名称不区分大小写,如果它们引用其他头信息名称(如“Connection:”头信息),则它们的值也不区分大小写。在HTTP/2中,头信息名称始终以小写发送,就像在调试模式下运行时一样。在内部,所有头信息名称都标准化为小写,以便HTTP/1.x和HTTP/2使用完全相同的表示,并且它们按原样发送到另一端。这解释了为什么用驼峰式大小写输入的HTTP/1.x请求会以小写形式传递。头信息的结束由第一个空行指示。人们常说这是双换行符,这并不准确,即使双换行符也是一种有效的空行形式。幸运的是,HAProxy在索引头信息、检查值和计数时会处理所有这些复杂的组合,因此没有理由担心它们可能被书写的方式,但如果不指责应用程序出现bug,它会执行一些不寻常但有效的事情,这一点很重要。重要提示:如RFC7231所建议,HAProxy通过用LWS替换头信息中间的换行符来规范化头信息,以合并多行头信息。这对于正确的分析是必需的,并且有助于能力较弱的HTTP解析器正确工作,而不被如此复杂的结构所欺骗。

1.3. HTTP 响应

HTTP响应看起来非常像HTTP请求。两者都称为HTTP消息。我们来看这个HTTP响应:行号 内容 1 HTTP/1.1 200 OK 2 Content-length: 350 3 Content-Type: text/html 特殊情况下,HTTP支持所谓的“信息性响应”,状态码为1xx。这些消息的特殊之处在于它们不携带响应的任何部分,它们仅用作一种信号消息,例如请求客户端继续发布其请求。在状态码100的情况下,请求的信息将由信息性消息后面的下一个非100响应消息携带。这意味着单个请求可能发送多个响应,并且这仅在启用keep-alive时有效(1xx消息仅适用于HTTP/1.1)。HAProxy处理这些消息,并且能够正确转发和跳过它们,只处理下一个非100响应。因此,除非明确说明,否则这些消息既不记录也不转换。状态码101消息表示同一连接上的协议正在更改,HAProxy必须切换到隧道模式,就像发生了CONNECT一样。然后,Upgrade头信息将包含有关连接正在切换到的协议类型的其他信息。

1.3.1. 响应行

第1行是“响应行”。它总是由3个字段组成:- 版本标签:HTTP/1.1 - 状态码:200 - 原因:OK 状态码始终是3位数字。第一位数字表示一般状态:- 1xx = 信息性消息,应跳过(例如,100,101)- 2xx = OK,内容正在加载(例如,200,206)- 3xx = OK,无内容(例如,302,304)- 4xx = 客户端错误(例如,401,403,404)- 5xx = 服务器错误(例如,500,502,503)请参考RFC7231以获取所有此类代码的详细含义。“原因”字段只是一个提示,但客户端不会解析它。其中可能包含任何内容,但遵循公认的消息是一种常见做法。它可以由一个或多个单词组成,例如“OK”、“Found”或“Authentication Required”。HAProxy自身可能会发出以下状态码:代码 何时/原因 200 访问stats页面,以及在响应监控请求时 301 在执行重定向时,取决于配置的代码 302 在执行重定向时,取决于配置的代码 303 在执行重定向时,取决于配置的代码 307 在执行重定向时,取决于配置的代码 308 在执行重定向时,取决于配置的代码 400 对于无效或过大的请求 401 在执行操作时需要身份验证(访问stats页面时) 403 当请求被“http-request deny”规则禁止时 404 当找不到请求的资源时 408 请求超时在请求完成之前触发 410 请求的资源不再可用且以后也不会可用 500 当haproxy遇到无法恢复的内部错误时,例如内存分配失败,这应该永远不会发生 502 当服务器返回空、无效或不完整的响应时,或者当“http-response deny”规则阻止响应时。 503 当没有可用的服务器来处理请求时,或者响应监控请求匹配“monitor fail”条件时 504 当响应超时在服务器响应之前触发 上面提到的4xx和5xx错误代码可以自定义(请参阅第4.2节中的“errorloc”)。

1.3.2. 响应头

响应头的处理方式与请求头完全相同,因此 HAProxy 对两者使用相同的解析函数。更多详情请参考 1.2.2 段。

2.1. 配置文件格式

HAProxy的配置过程涉及3个主要参数来源:- 命令行参数,它们始终具有最高优先级- 配置文件,其格式在此处描述- 正在运行的进程的环境,以防某些环境变量被显式引用配置文件遵循相当简单的分层格式,该格式遵守一些基本规则:1. 配置文件是语句的有序序列2. 语句是任何未受保护的“#”(hash)之前的单个非空行3. 行是由未受保护的空格或制表符分隔的一系列标记或“单词”4. 行的第一个单词或单词序列是本文档中列出的关键字之一或关键字序列5. 所有其他单词都是第一个单词的参数,其中一些是本文档中列出的已知关键字,其他则是值、对配置其他部分的引用或表达式6. 某些关键字界定一个部分,在该部分内仅支持关键字的子集7. 一个部分在文件末尾结束,或在启动一个新部分的特殊关键字处结束。了解这些就足以编写一个简单可靠的配置生成器,但这不足以可靠地解析任何配置或弄清楚如何处理某些边缘情况。首先,上述规则有一些后果。规则6和7意味着用于定义新部分的关键字在任何地方都有效,并且在特定部分不能具有不同的含义。这些关键字始终是单个单词(与单词序列相反),传统上,它们后面的部分使用相同的名称来指定。例如,在谈论“global section”时,它表示“global”关键字之后的配置部分。这种用法在错误消息中经常出现,以帮助定位需要解决的部分。许多部分创建了一个内部对象或配置空间,需要与其他部分区分开来。在这种情况下,它们将占用一个额外的单词,该单词将设置该特定部分的名称。对于其中一些,部分名称是强制的。例如,“frontend foo”将创建一个类型为“frontend”,名称为“foo”的新部分。通常,名称特定于其部分,并且不同类型的两个部分可以使用相同的名称,但不推荐这样做,因为它会使配置管理复杂化。规则7的一个直接后果是,当一次读取多个文件时,每个文件都必须以新部分开始,并且每个文件的结束将结束一个部分。一个文件不能包含子部分,也不能结束现有部分并开始新的部分。规则1提到顺序很重要。实际上,某些关键字创建的指令可以重复多次以创建有序的规则序列,并按特定顺序应用。例如,“tcp-request”可用于根据不同条件来交替“accept”和“reject”规则。因此,配置文件处理器在编辑文件时必须始终保留部分的顺序。部分的顺序通常无关紧要,除了全局部分必须放在其他部分之前,但如果需要,它可以重复。此外,一些自动标识符可能会自动分配给某些创建的对象(例如代理),并且通过重新排序部分,它们的标识符将发生变化。这些标识符出现在统计信息中,例如。因此,下面的配置将为“foo”分配ID号1,为“bar”分配ID号2,如果两个部分反转,它们的ID将互换:listen foo bind :80 listen bar bind :81 另一个重要点是,根据上述规则2和3,空行、空格、制表符以及未受保护的“#”字符后的注释不属于配置,因为它们仅用作分隔符。这意味着以下配置是严格等效的:global#this is the global section daemon#daemonize frontend foo mode http # or tcp and: global daemon # this is the public web frontend frontend foo mode http 常见的做法是将启动新部分的关键字左对齐,并将所有其他关键字缩进(即,在前面加上制表符或几个空格),以便立即显示它们属于同一部分(如上面的第二个示例所示)。在新部分之前放置注释有助于读者决定是否是所需的部分。在部分末尾留一个空行在编辑时也有助于直观地识别结束。制表符非常方便用于缩进,但它们不容易复制粘贴。如果改为使用空格,建议不要放置过多(2到4个),以免在字段编辑时,对于不支持自动缩进的有限编辑器来说,会带来负担。早期,由于大多数关键字最多只能接受两个参数,因此参数被拆分到固定的制表符位置是很常见的。随着现代版本引入复杂表达式,这种做法不再适用,也不被推荐。

2.2. 引号和转义

在现代配置中,某些参数需要使用以前被视为纯分隔符的字符。为了实现这一点,HAProxy支持通过在要转义的字符前面加上反斜杠('\')来实现字符转义,以及在双引号('"')内进行弱引用,在单引号("'")内进行强引用。这非常类似于在许多编程语言中以及在Bourne shell中常见的情况。原理如下:配置解析器将行分解为单词时,它还会处理引号和反斜杠,以确定一个字符是分隔符,还是当前单词中该字符的原始表示。然后,转义字符被移除,引号被移除,剩余的单词按原样用作关键字或参数。如果一个单词需要反斜杠,它必须要么用自身(即双反斜杠)进行转义,要么进行强引用。引号外的转义是通过在特殊字符前加上反斜杠('\')来实现的:\ 来标记一个空格并区别于分隔符 \# 来标记一个哈希并区别于注释 \\ 来使用一个反斜杠 \' 来使用一个单引号并区别于强引用 \" 来使用一个双引号并区别于弱引用此外,可以使用C语言的常规表示法来发出一些不可打印字符:\n 来插入换行符(LF,字符 \x0a 或十进制ASCII 10) \r 来插入回车符(CR,字符 \x0d 或十进制ASCII 13) \t 来插入制表符(字符 \x09 或ASCII 9) \xNN 来插入ASCII码为十六进制NN的字符(例如 \x0a 用于LF)。弱引用是通过在要保护的字符或字符序列周围加上双引号(“"”)来实现的。弱引用可防止解释:空格或制表符作为单词分隔符 ' 单引号作为强引用分隔符 # 哈希作为注释起始符弱引用允许通过在美元符号('$')前加上它来解释环境变量(环境变量在引号外不被求值)。如果双引号内需要美元字符,则必须用反斜杠转义。强引用是通过在要保护的字符或字符序列周围加上单引号(“'”)来实现的。在单引号内,没有任何东西被解释,这是引用正则表达式的有效方法。结果是,这是一个矩阵,显示了如何在不同上下文中输入特殊字符(不可打印字符用其在尖括号内的名称替换)。请注意,一些只能通过转义表示的字符在单引号内没有可能的表示,因此在单引号内不存在。
字符无引号弱引用强引用
<TAB>\<TAB>, \x09"<TAB>", "\<TAB>", "\x09"'<TAB>'
<LF>\n, \x0a"\n", "\x0a"
<CR>\r, \x0d"\r", "\x0d"
<SPC>\<SPC>, \x20"<SPC>", "\<SPC>", "\x20"'<SPC>'
"\", \x22"\"", "\x22"'"'
#\#, \x23"#", "\#", "\x23"'#'
$$, \$, \x24"\$", "\x24"'$'
'\', \x27"'", "\'", "\x27"
\\\, \x5c"\\", "\x5c"'\'
示例
# 以下这些都是完全等效的: log-format %{+Q}o\ %t\ %s\ %{-Q}r log-format "%{+Q}o %t %s %{-Q}r" log-format '%{+Q}o %t %s %{-Q}r' log-format "%{+Q}o %t"' %s %{-Q}r' log-format "%{+Q}o %t"' %s'\ %{-Q}r
在一种特殊情况下,可能需要第二级引用或转义。一些关键字在括号内接受参数,有时用逗号分隔。这些参数通常是整数或预定义的单词,但当它们是任意字符串时,可能需要执行单独的转义级别,以区分属于参数的字符与用于分隔参数本身的字符。一个非常常见的例子是“regsub”转换器。它接受一个正则表达式作为参数,如果需要一个闭合括号,则该括号需要有自己的引号。关键字参数解析器在引号方面与顶层解析器完全相同,只是它不会特殊处理反斜杠。但并非总是显而易见的是,内部使用的分隔符必须首先被转义或引用,以便它们不在顶层解析。以这个使用“regsub”转换器的示例为例,该转换器接受3个参数:一个正则表达式,一个替换字符串和一个标志集:# 在路径中替换所有出现的“foo”为“blah”:http-request set-path %[path,regsub(foo,blah,g)] 在这里不需要特殊的引用。但是,如果我们现在想将“foo”或“bar”替换为“blah”,我们将需要正则表达式“(foo|bar)”。我们不能写:http-request set-path %[path,regsub((foo|bar),blah,g)] 因为我们希望字符串像这样分割:http-request set-path %[path,regsub((foo|bar),blah,g)] |---------|----|-| arg1 _/ / / arg2 __________/ / arg3 ______________/ 但实际上传递的是开闭括号之间的字符串,然后是垃圾:http-request set-path %[path,regsub((foo|bar),blah,g)] |--------|--------| arg1=(foo|bar _/ / trailing garbage _________/ 显然的解决方案似乎是闭合括号需要被引用,但单独这样做是行不通的,因为如上所述,引号由顶层解析器处理,该解析器将在处理此单词之前解析它们:http-request set-path %[path,regsub("(foo|bar)",blah,g)] ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub((foo|bar),blah,g)] 所以我们并没有改变第二级参数解析器,它仍然将截断的正则表达式视为唯一参数,并在字符串末尾看到垃圾。通过转义引号,它们将未经修改地传递到第二级:http-request set-path %[path,regsub(\"(foo|bar)\",blah,g)] ------------ -------- ------------------------------------ word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2=blah ___________/ / arg3=g _______________/ 另一种方法是使用单引号括起整个字符串,并在内部使用双引号(这样双引号就不会再次被剥离):http-request set-path '%[path,regsub("(foo|bar)",blah,g)]' ------------ -------- ---------------------------------- word1 word2 word3=%[path,regsub("(foo|bar)",blah,g)] |---------||----|-| arg1=(foo|bar) _/ / / arg2 ___________/ / arg3 _______________/ 使用正则表达式时,可能会出现美元('$')字符出现在表达式中,或者反斜杠('\')用于替换字符串。在这种情况下,这些字符将在双引号内被处理,因此首选单引号(或双重转义)。示例:http-request set-path '%[path,regsub("^/(here)(/|$)","my/\1",g)]' ------------ -------- ----------------------------------------- word1 word2 word3=%[path,regsub("^/(here)(/|$)","my/\1",g)] |-------------| |-----||-| arg1=(here)(/|$) _/ / / arg2=my/\1 ________________/ / arg3 ______________________/ 请记住,反斜杠在单引号内不是转义字符,并且上面的整个word3已经使用了单引号进行保护。相反,如果整个表达式都使用了双引号,美元字符和反斜杠将在顶层解析,破坏第二级参数的内容。如有疑问,请不要使用任何引号,并开始在需要逗号或闭合括号的参数周围放置单引号或双引号,并考虑使用反斜杠转义这些引号,如果字符串包含美元或反斜杠。再次,这非常类似于Bourne shell中用于“eval”命令的双重转义。对于API编写者来说,最好的方法可能是为每个参数加上转义的引号,无论其内容如何。用户可能会发现,在整个表达式周围使用单引号,并在每个参数周围使用双引号,可以使配置更易读。

2.3. 环境变量

HAProxy 的配置支持环境变量。这些变量仅在双引号内被解释。变量在配置解析期间展开。变量名前必须加上美元符号("$"),并可选地用大括号("{}")括起来,类似于 Bourne shell 中的做法。变量名可以包含字母数字字符或下划线("_"),但不应以数字开头。
示例
bind "fd@${FD_APP1}" log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器 user "$HAPROXY_USER"
一些变量由 HAProxy 定义,它们可以在配置文件中使用,或者可以被程序继承(参见 3.7. 程序): * HAPROXY_LOCALPEER:在进程启动时定义,包含本地对等体的名称。(参见管理指南中的 "-L"。) * HAPROXY_CFGFILES:由 HAProxy 加载的配置文件列表,以分号分隔。如果您指定了一个目录,这可能很有用。 * HAPROXY_MWORKER:在主-工作者模式下,此变量设置为 1。 * HAPROXY_CLI:为每个进程配置的统计套接字的监听地址,以分号分隔。 * HAPROXY_MASTER_CLI:在主-工作者模式下,主 CLI 的监听地址,以分号分隔。另请参见“external-check command”了解其他变量。

2.4. 时间格式

一些参数涉及表示时间的值,例如超时。这些值通常以毫秒表示(除非另有明确说明),但也可以通过在数值后附加单位来以任何其他单位表示。考虑这一点很重要,因为每个关键字都不会重复说明。支持的单位有:- us:微秒。1 微秒 = 1/1000000 秒 - ms:毫秒。1 毫秒 = 1/1000 秒。这是默认单位。 - s:秒。1s = 1000ms - m:分钟。1m = 60s = 60000ms - h:小时。1h = 60m = 3600s = 3600000ms - d:天。1d = 24h = 1440m = 86400s = 86400000ms

2.5. 示例

# 一个简单的 HTTP 代理配置,在所有接口的 80 端口上监听,# 并将请求转发到名为 "servers" 的单个后端,该后端有一个名为 "server1" 的服务器,# 监听于 127.0.0.1:8000 global daemon maxconn 256 defaults mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms frontend http-in bind *:80 default_backend servers backend servers server server1 127.0.0.1:8000 maxconn 32 # 使用单个 listen 块定义的相同配置。更短但表达力较差,尤其是在 HTTP 模式下。 global daemon maxconn 256 defaults mode http timeout connect 5000ms timeout client 50000ms timeout server 50000ms listen http-in bind *:80 server server1 127.0.0.1:8000 maxconn 32 假设 haproxy 在 $PATH 中,请在 shell 中使用以下命令测试这些配置:$ sudo haproxy -f configuration.conf -c
“global”部分中的参数是进程范围的,并且通常是操作系统特定的。它们通常一次设置好,并且一旦正确设置后就不需要更改。其中一些具有命令行等效项。在“global”部分支持以下关键字:* 进程管理和安全- 51degrees-cache-size- 51degrees-data-file- 51degrees-property-name-list- 51degrees-property-separator- ca-base- chroot- cpu-map- crt-base- daemon- description- deviceatlas-json-file- deviceatlas-log-level- deviceatlas-properties-cookie- external-check- gid- group- h1-case-adjust- h1-case-adjust-file- hard-stop-after- insecure-fork-wanted- insecure-setuid-wanted- issuers-chain-path- localpeer- log- log-send-hostname- log-tag- lua-load- lua-prepend-path- mworker-max-reloads- nbproc- nbthread- node- pidfile- pp2-never-send-local- presetenv- resetenv- set-dumpable- setenv- ssl-default-bind-ciphers- ssl-default-bind-ciphersuites- ssl-default-bind-curves- ssl-default-bind-options- ssl-default-server-ciphers- ssl-default-server-ciphersuites- ssl-default-server-options- ssl-dh-param-file- ssl-server-verify- ssl-skip-self-issued-ca- stats- strict-limits- uid- ulimit-n- unix-bind- unsetenv- user- wurfl-cache-size- wurfl-data-file- wurfl-information-list- wurfl-information-list-separator* 性能调优- busy-polling- max-spread-checks- maxcompcpuusage- maxcomprate- maxconn- maxconnrate- maxpipes- maxsessrate- maxsslconn- maxsslrate- maxzlibmem- noepoll- noevports- nogetaddrinfo- nokqueue- nopoll- noreuseport- nosplice- profiling.tasks- server-state-base- server-state-file- spread-checks- ssl-engine- ssl-mode-async- tune.buffers.limit- tune.buffers.reserve- tune.bufsize- tune.chksize- tune.comp.maxlevel- tune.fail-alloc- tune.fd.edge-triggered- tune.h2.header-table-size- tune.h2.initial-window-size- tune.h2.max-concurrent-streams- tune.h2.max-frame-size- tune.http.cookielen- tune.http.logurilen- tune.http.maxhdr- tune.idle-pool.shared- tune.idletimer- tune.lua.forced-yield- tune.lua.maxmem- tune.lua.service-timeout- tune.lua.session-timeout- tune.lua.task-timeout- tune.maxaccept- tune.maxpollevents- tune.maxrewrite- tune.pattern.cache-size- tune.pipesize- tune.pool-high-fd-ratio- tune.pool-low-fd-ratio- tune.rcvbuf.client- tune.rcvbuf.server- tune.recv_enough- tune.runqueue-depth- tune.sched.low-latency- tune.sndbuf.client- tune.sndbuf.server- tune.ssl.cachesize- tune.ssl.capture-cipherlist-size- tune.ssl.default-dh-param- tune.ssl.force-private-cache- tune.ssl.keylog- tune.ssl.lifetime- tune.ssl.maxrecord- tune.ssl.ssl-ctx-cache-size- tune.vars.global-max-size- tune.vars.proc-max-size- tune.vars.reqres-max-size- tune.vars.sess-max-size- tune.vars.txn-max-size- tune.zlib.memlevel- tune.zlib.windowsize* 调试- debug- quiet- zero-warning

3.1. 进程管理与安全

用于提供设备检测服务的 51Degrees 数据文件的路径。该文件应该是解压缩的,并且 HAProxy 具有相关权限可以访问。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
要从数据集中加载的 51Degrees 属性名称列表。完整的名称列表可在 51Degrees 网站上找到:https://51degrees.com/resources/property-dictionary 请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
一个字符,将附加到包含 51Degrees 结果的响应头中每个属性值的末尾。如果未设置,则默认为 ','。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
将 51Degrees 转换器缓存的大小设置为 <数字> 个条目。这是一个 LRU 缓存,用于记录以前的设备检测及其结果。默认情况下,此缓存是禁用的。请注意,此选项仅在 HAProxy 编译时启用了 USE_51DEGREES 的情况下可用。
ca-base <dir>
当使用“ca-file”、“ca-verify-file”或“crl-file”指令使用相对路径时,指定一个默认目录来获取SSL CA证书和CRL。在“ca-file”、“ca-verify-file”和“crl-file”中指定的绝对位置优先,并忽略“ca-base”。
chroot <jail dir>
在降低权限之前,将当前目录更改为 <jail dir> 并在那里执行 chroot()。这提高了安全级别,以防未知漏洞被利用,因为它会使攻击者很难利用系统。这仅在进程以超级用户权限启动时有效。确保 <jail_dir> 既为空又对任何人不可写非常重要。
cpu-map [auto:]<process-set>[/<thread-set>] <cpu-set>...
在Linux 2.6及以上版本中,可以将进程或线程绑定到特定的CPU集。这意味着该进程或线程永远不会在其他CPU上运行。“cpu-map”指令为进程或线程集指定CPU集。第一个参数是进程集,后面可以跟线程集。这些集合的格式为all | odd | even | number[-[number]] <number>>必须是1到32或64之间的数字,具体取决于机器的字长。任何大于nbproc的进程ID和大于nbthread的线程ID都会被忽略。可以使用两个由连字符('-')分隔的数字指定一个范围。还可以使用“all”指定所有进程,“odd”指定奇数,“even”指定偶数,就像使用“bind-process”指令一样。第二个及后续参数是CPU集。每个CPU集要么是0到31或63之间的唯一数字,要么是由连字符('-')分隔的两个此类数字的范围。可以指定多个CPU编号或范围,并且进程或线程将可以绑定到所有这些CPU。显然,可以指定多个“cpu-map”指令。每个“cpu-map”指令在重叠时将替换之前的指令。线程将被绑定到其映射和它所附着的进程映射的交集上。如果交集为空,则不会为该线程设置特定绑定。范围可以部分定义。上限可以省略。在这种情况下,它将被相应的最大值替换,即32或64,取决于机器的字长。可以在进程集之前添加前缀“auto:”,让HAProxy通过递增进程/线程和CPU集来自动将进程或线程绑定到CPU。为了有效,两个集合的大小必须相同。无论CPU集的声明顺序如何,它都将从最低绑定到最高绑定。具有带“auto:”前缀的进程和线程范围是不支持的。只支持一个范围,另一个必须是固定数字。
示例
cpu-map 1-4 0-3 # 将进程 1 到 4 绑定到前 4 个 CPU cpu-map 1/all 0-3 # 将第一个进程的所有线程绑定到 # 前 4 个 CPU cpu-map 1- 0- # 将被替换为 "cpu-map 1-64 0-63" # 或 "cpu-map 1-32 0-31",具体取决于机器的 # 字大小。 # 所有这些行都将进程 1 绑定到 CPU 0,进程 2 绑定到 CPU 1 # 以此类推。 cpu-map auto:1-4 0-3 cpu-map auto:1-4 0-1 2-3 cpu-map auto:1-4 3 2 1 0 # 所有这些行都将线程 1 绑定到 CPU 0,线程 2 绑定到 CPU 1 # 以此类推。 cpu-map auto:1/1-4 0-3 cpu-map auto:1/1-4 0-1 2-3 cpu-map auto:1/1-4 3 2 1 0 # 使用 all/odd/even 关键字将每个进程绑定到恰好一个 CPU cpu-map auto:all 0-63 cpu-map auto:even 0-31 cpu-map auto:odd 32-63 # 无效的 cpu-map,因为进程和 CPU 集合大小不同。 cpu-map auto:1-4 0 # 无效 cpu-map auto:1 0-3 # 无效 # 无效的 cpu-map,因为自动绑定与进程范围一起使用 # 和线程范围。 cpu-map auto:all/all 0 # 无效 cpu-map auto:all/1-4 0 # 无效 cpu-map auto:1-4/all 0 # 无效
crt-base <dir>
当使用 "crtfile" 或 "crt" 指令并提供相对路径时,指定一个用于获取 SSL 证书的默认目录。指定的绝对位置优先,并忽略 "crt-base"。
使进程 fork 到后台运行。这是推荐的操作模式。它等同于命令行参数 "-D"。它可以通过命令行参数 "-db" 禁用。此选项在 systemd 模式下被忽略。
添加描述实例的文本。请注意,需要转义某些字符(例如 #),并且此文本将插入 HTML 页面中,因此您应避免使用“<”和“>”字符。
设置要由 API 加载的 DeviceAtlas JSON 数据文件的路径。该路径必须是一个有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
允许使用外部代理执行健康检查。出于安全考虑,此功能默认禁用,即使启用,检查仍可能失败,除非也启用了“insecure-fork-wanted”。如果启动的程序使用了 setuid 可执行文件(它真的不应该这样做),您可能还需要在全局部分设置“insecure-setuid-wanted”。请参阅“option external-check”、“insecure-fork-wanted”和“insecure-setuid-wanted”。
gid <number>
将进程的组 ID 更改为 <number>。建议将组 ID 专用给 HAProxy 或一小组类似的守护进程。HAProxy 必须以属于此组的用户或以超级用户权限启动。请注意,如果 haproxy 是从拥有附加组的用户启动的,则只有在以超级用户权限启动时才能放弃这些组。另请参阅“group”和“uid”。
group <group name>
与“gid”类似,但使用来自 /etc/group 的组名 <group name> 的 GID。另请参阅“gid”和“user”。
h1-case-adjust <from> <to>
定义在启用时应用于报头名称 <from> 的大小写调整,将其更改为 <to>,然后再将其发送到 HTTP/1 客户端或服务器。<from> 必须是小写,并且 <from> 和 <to> 除了大小写之外不得有任何区别。如果需要调整多个报头名称,则可以重复使用。不允许重复条目。如果需要调整大量报头名称,使用“h1-case-adjust-file”可能更方便。请注意,除非在代理中指定了“option h1-case-adjust-bogus-client”或“option h1-case-adjust-bogus-server”,否则不会应用任何转换。报头名称没有标准的大小写,因为如 RFC7230 所述,它们是大小写不敏感的。因此,应用程序必须以大小写不敏感的方式处理它们。但某些不符合标准的应用程序会错误地依赖于浏览器最常用的大小写。此问题在 HTTP/2 中变得至关重要,因为所有报头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。无论 HTTP 版本如何,所有报头名称都以小写形式发送给客户端和服务器。未能正确处理请求或响应的应用程序可能需要暂时使用此类解决方法来调整发送给它们的报头名称,以便应用程序能够及时修复。请注意,需要此类解决方法的应用程序可能容易受到内容伪装攻击,并且绝对必须进行修复。
示例
global h1-case-adjust content-length Content-Length
请参阅 "h1-case-adjust-file"、"option h1-case-adjust-bogus-client" 和 "option h1-case-adjust-bogus-server"。
定义一个文件,其中包含用于在将某些报头名称发送到 HTTP/1 客户端或服务器之前调整其大小写的键/值对列表。文件 <hdrs-file> 必须每行包含 2 个报头名称。第一个必须是小写,并且两者除了大小写之外不得有任何区别。以“#”开头的行和空行一样被忽略。将剥离前导和尾随的制表符和空格。不允许重复条目。请注意,除非在代理中指定了“option h1-case-adjust-bogus-client”或“option h1-case-adjust-bogus-client”,否则不会应用任何转换。如果重复使用此指令,将只处理最后一个。如果需要调整大量报头名称,它是指令“h1-case-adjust”的替代项。请阅读使用此项的风险。请参阅“h1-case-adjust”、“option h1-case-adjust-bogus-client”和“option h1-case-adjust-bogus-server”。
定义执行干净的软停止所允许的最长时间。
参数
<time> 是实例在通过 SIGUSR1 信号接收到软停止时将保持活动的最长时间(默认为毫秒)。
这可用于确保即使在软停止期间连接保持打开(例如,在 tcp 模式下为代理设置了长超时),实例也会退出。它适用于 TCP 和 HTTP 模式。
示例
global hard-stop-after 30s
默认情况下,haproxy 会尽力阻止在启动后创建任何线程和进程。这样做在处理来源不明的 Lua 文件以及尝试使用可能仍包含可利用性不确定错误的开发版本时尤为重要。总的来说,确保流量不会触发任何意外的后台活动是良好的做法。但这会阻止外部检查工作,并且可能会破坏一些积极依赖于 fork 能力的非常特定的 Lua 脚本。此选项用于禁用此保护。请注意,禁用它是不可取的,因为一旦禁用,库或 haproxy 本身中的漏洞将更容易被利用。此外,从 Lua 或其他地方进行 fork 并不可靠,因为 fork 的进程可能会随机嵌入另一个线程设置的锁,并且永远无法完成操作。因此,强烈建议不要使用此选项,并且应该重新考虑任何需要此类 fork 的工作负载,并将其移至更安全的解决方案(例如,使用代理而不是外部检查)。此选项支持“no”前缀来禁用它。
HAProxy 在运行时不需要调用可执行文件(除非使用强烈不推荐的外部检查),并且应该将自身隔离到一个空的 chroot 环境中。因此,在用户没有完全意识到风险的情况下,几乎没有有效理由允许调用 setuid 可执行文件。在 haproxy 需要调用外部检查和/或禁用 chroot 的情况下,利用库或 haproxy 本身的漏洞可能会导致执行外部程序。在 Linux 上,可以锁定进程,从而忽略此可执行文件上的任何 setuid 位。这在这种情况大大降低了权限提升的风险。HAProxy 默认这样做。如果这给外部检查带来了问题(例如,需要“ping”命令的外部检查),则可以通过在全局节中显式添加此指令来禁用此保护。如果启用,可以通过在其前面加上“no”关键字来将其关闭。
分配一个目录以加载证书链以进行发行者补全。所有文件必须是 PEM 格式。对于使用“crt”或“crt-list”加载的证书,如果证书链未包含在 PEM 中(也通常称为中间证书),则如果证书的发行者对应于使用“issuers-chain-path”加载的链中的第一个证书,haproxy 将会补全链。使用“crt”文件(包含 PrivateKey+Certificate+IntermediateCA2+IntermediateCA1)可能被 PrivateKey+Certificate 替换。如果文件(包含 IntermediateCA2+IntermediateCA1)存在于“issuers-chain-path”目录中,HAProxy 将补全链。所有具有相同发行者的其他证书将在内存中共享此链。此选项仅适用于从 bind 行使用的证书。
localpeer <name>
设置本地实例的对等名称。如果指定了 "-L" 命令行参数或在 "peers" 部分定义之后使用,它将被忽略。在这种情况下,在配置解析期间将发出警告消息。此选项还将设置 HAPROXY_LOCALPEER 环境变量。另请参阅管理指南中的 "-L" 和下面的 "peers" 部分。
log <address> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [max level [min level]]
添加一个全局 syslog 服务器。可以定义多个全局服务器。它们将接收启动和退出的日志,以及使用“log global”配置的所有代理的日志。<address> 可以是以下之一: - IPv4 地址,后面可选地跟着冒号和 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。 - IPv6 地址,后面跟着冒号和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。 - 到 datagram UNIX 域套接字的本地文件系统路径,并考虑 chroot(确保路径在 chroot 内可访问)和 uid/gid(确保路径具有适当的写入权限)。 - 文件描述符编号,形式为“fd@<number>”,它可能指向管道、终端或套接字。在这种情况下,将使用无缓冲日志,并且每个日志执行一次 writev() 调用。这有点昂贵,但对于大多数工作负载来说是可以接受的。通过这种方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,DroppedLogs 计数器将递增。writev() 调用即使在管道上对于最大为 PIPE_BUF 大小的消息也是原子的,POSIX 建议至少为 512,在大多数现代操作系统上为 4096 字节。任何更大的消息可能会与其他进程的消息交错。作为调试目的的例外,文件描述符也可以指向一个文件,但这将大大减慢 haproxy 的速度,因为会忽略非阻塞调用。此外,如果没有重新启动进程,将无法清除或轮换此文件。请注意,配置的 syslog 格式会保留,因此输出适用于 TCP syslog 服务器。另请参阅下面的“short”和“raw”格式。 - “stdout”/“stderr”,它们分别是“fd@1”和“fd@2”的别名,请参阅上文。 - 形式为“ring@<name>”的环形缓冲区,它将对应于可通过 CLI 使用“show events”命令访问的内存环形缓冲区,该命令还将列出现有环形缓冲区及其大小。此类缓冲区在重新加载或重新启动时会丢失,但当作为补充使用时,可以通过即时可用的日志来帮助故障排除。您可能希望在地址参数中引用某些环境变量,有关环境变量的更多信息,请参阅 第 2.3 节。<length> 是可选的最大行长度。大于此值的日志行将在发送前被截断。原因是 syslog 服务器对日志行长度的处理方式不同。所有服务器都支持 1024 的默认值,但某些服务器会丢弃较长的行,而另一些则会记录它们。如果服务器支持长行,在此处设置此值以避免截断长行可能很有意义。同样,如果服务器丢弃长行,最好在发送它们之前截断它们。可接受的值为 80 到 65535(含)。1024 的默认值对于所有标准用法通常都很好。某些特殊情况下的长捕获或 JSON 格式的日志可能需要更大的值。如果您的请求 URI 被截断,您可能还需要增加“tune.http.logurilen”。<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一: rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164) rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424) short 包含角度括号之间的级别(例如“<3>”)的消息,后跟文本。将省略 PID、日期、时间、进程名称和系统名称。此格式旨在与本地日志服务器一起使用。此格式与 systemd 日志记录器消耗的内容兼容。raw 仅包含文本的消息。将省略级别、PID、日期、时间、进程名称和系统名称。此格式旨在在容器中使用或在开发期间使用,其中严重性仅取决于使用的文件描述符(stdout/stderr)。<ranges> 用于标识要采样的日志的逗号分隔范围列表。用于平衡发送到日志服务器的日志负载。范围的限制不能为 null。它们从 1 开始编号。样本的大小或周期(日志数)必须使用 <sample_size> 参数设置。<sample_size> 考虑用于平衡日志记录负载的样本大小(以日志数为单位)。它用于平衡发送到 syslog 服务器的日志负载。此大小必须大于或等于范围的高限的最大值(另请参阅 <ranges> 参数)。<facility> 必须是 24 个标准 syslog 设施之一: kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,对于“short”和“raw”格式,会忽略 facility,但仍然需要将其作为位置字段。在这种情况下,建议使用“daemon”以清楚地表明它仅供本地使用。可以指定可选级别来过滤传出的消息。默认情况下,发送所有消息。如果指定了最大级别,则只有严重性至少与该级别一样重要的消息才会被发送。可以指定可选的最小级别。如果设置了此级别,则严重性比此级别更高的日志将被限制在此级别。这用于避免在某些默认 syslog 配置上将“emerg”消息发送到所有终端。已知有八个级别: emerg alert crit err warning notice info debug
设置 syslog 报头中的 hostname 字段。如果设置了可选的 "string" 参数,则报头将设置为该字符串内容,否则使用系统的主机名。通常在不通过中间 syslog 服务器中继日志或仅为自定义日志中打印的主机名时使用。
log-tag <string>
将 syslog 报头中的 tag 字段设置为此字符串。它默认为从命令行启动的程序名,通常是 "haproxy"。有时,区分同一主机上运行的多个进程会很有用。另请参阅每个代理的 "log-tag" 指令。
lua-load <file>
此全局指令加载并执行一个 Lua 文件。此指令可以多次使用。
lua-prepend-path <string> [<type>]
在 Lua 的 package.<type> 变量前面加上给定的字符串,后跟一个分号。<type> 必须是“path”或“cpath”。如果未给出 <type>,则默认为“path”。Lua 的路径是由模式组成的分号分隔列表,这些模式指定 `require` 函数如何尝试查找库的源文件。模式中的问号 (?) 将被替换为模块名称。路径从左到右求值。这意味着稍后添加的路径将被更早地检查。例如,通过指定以下路径: lua-prepend-path /usr/share/haproxy-lua/?/init.lua lua-prepend-path /usr/share/haproxy-lua/?.lua 当调用 `require "example"` 时,Lua 将首先尝试加载 /usr/share/haproxy-lua/example.lua 脚本,如果该脚本不存在,则尝试加载 /usr/share/haproxy-lua/example/init.lua,如果这些都不存在,则尝试默认路径。有关 Lua 文档中的详细信息,请参阅 https://lua.ac.cn/pil/8.1.html。
master-worker [no-exit-on-failure]
主-工作者模式。它等同于命令行参数“-W”。此模式将启动一个“主进程”,该进程将监控“工作进程”。使用此模式,您可以通过向主进程发送 SIGUSR2 信号来直接重新加载 HAProxy。主-工作者模式与前台或守护进程模式兼容。建议在多进程和 systemd 环境下使用此模式。默认情况下,如果一个工作进程以错误的返回码退出,例如在发生段错误的情况下,所有工作进程都将被杀死,主进程将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用,以重新启动整个进程是很方便的。如果您不希望有此行为,则必须使用关键字“no-exit-on-failure”。另请参见管理指南中的“-W”。
在主-从模式下,此选项限制了工作进程可以承受的重载次数。如果工作进程在重载后没有退出,一旦其重载次数大于此数字,该工作进程将收到一个 SIGTERM 信号。此选项有助于控制工作进程的数量。另请参阅管理指南中的“show proc”。
nbproc <number>
创建 <number> 个进程以进入 daemon 模式。这需要“daemon”模式。默认情况下,只创建一个进程,这是推荐的操作模式。对于文件描述符数量有限的系统,可能需要派生多个守护进程。当设置为大于 1 的值时,线程会自动禁用。使用多个进程更难调试,并且强烈不推荐。另请参阅“daemon”和“nbthread”。
nbthread <number>
仅当启用了线程支持时,此设置才可用。它使 haproxy 在 <number> 个线程上运行。这与“nbproc”互斥。虽然“nbproc”在历史上是使用多个处理器唯一的方式,但它也带来了一些与进程之间缺乏同步相关的问题(健康检查、对等节点、stick-tables、stats 等),而这些问题不会影响线程。因此,强烈建议任何现代配置都从“nbproc”迁移到“nbthread”。“nbthread”在 HAProxy 以前台模式启动时也有效。在某些支持 CPU 亲和性的平台上,当未使用 nbproc 时,默认的“nbthread”值会自动设置为进程启动时绑定的 CPU 数量。这意味着可以通过“taskset”或“cpuset”等命令从调用进程轻松调整线程数。否则,此值默认为 1。“haproxy -vv”的输出中会报告默认值。另请参阅“nbproc”。
pidfile <pidfile>
将所有守护进程的 PID 写入文件 <pidfile>。此选项等同于“-p”命令行参数。该文件必须对启动进程的用户可访问。另请参阅“daemon”。
PROXY 协议 v2 实现中的一个错误存在于 HAProxy 2.1 之前的版本中,导致它为健康检查发出 PROXY 命令而不是 LOCAL 命令。这问题特别微小,但会混淆一些服务器的日志。遗憾的是,这个错误发现得很晚,并揭示出一些可能只针对 HAProxy 测试其 PROXY 协议实现的服务器无法正确处理 LOCAL 命令,并在 HAProxy 检查它们时永久保持在 "down" 状态。当这种情况发生时,可以启用此全局选项以恢复到旧的(错误的)行为,直到联系受影响组件的供应商并修复它们。此选项默认禁用,并作用于所有具有 "send-proxy-v2" 语句的服务器。
presetenv <name> <value>
将环境变量 <name> 设置为值 <value>。如果该变量已存在,则不会被覆盖。更改会立即生效,以便配置文件中的下一行可以看到新值。另请参阅 "setenv"、"resetenv" 和 "unsetenv"。
resetenv [<name> ...]
删除除参数中指定的环境变量之外的所有环境变量。它允许在使用 setenv 或 unsetenv 设置新值之前,使用一个干净受控的环境。请注意,一些内部函数可能会使用某些环境变量,例如时间操作函数,以及 OpenSSL 甚至外部检查。此命令必须极其小心使用,并且只能在完全验证后使用。更改会立即生效,因此配置文件中的下一行将看到新的环境。另请参阅 “setenv”、“presetenv” 和 “unsetenv”。
stats bind-process [ all | odd | even | <process_num>[-[process_num>]] ] ...
将统计套接字限制为一组特定的进程号。默认情况下,统计套接字绑定到所有进程,当 nbproc 大于 1 时会发出警告,因为连接时无法选择目标进程。但是,通过使用此设置,可以将统计套接字固定到一组特定的进程,通常是第一个进程。使用此设置后,无论使用多少个进程,警告都将自动禁用。最大进程 ID 取决于机器的字长(32 位或 64 位)。范围可以部分定义。可以省略上限。在这种情况下,它将被相应的最大值替换。一个更好的选择是在“stats socket”行的“process”设置中强制指定每行的进程。
server-state-base <directory>
指定目录前缀,该前缀将附加在所有不以“/”开头的服务器状态文件名前面。另请参阅 "server-state-file"、"load-server-state-from-file" 和 "server-state-file-name"。
指定包含服务器状态的文件路径。如果路径以斜杠('/')开头,则视为绝对路径,否则视为相对于使用 "server-state-base" 指定的目录(如果已设置)或当前目录。在重新加载 HAProxy 之前,可以使用统计命令 "show servers state" 保存服务器的当前状态。该命令的输出必须写入 <file> 指向的文件中。启动时,在处理流量之前,HAProxy 将读取、加载并应用文件中找到且在其当前运行配置中可用的每个服务器的状态。另请参阅 "server-state-base" 和 "show servers state"、"load-server-state-from-file" 和 "server-state-file-name"。
此选项默认最好禁用,并仅在开发人员请求时启用。如果已启用,仍可通过在其前面加上“no”关键字强制禁用。它对性能或稳定性没有影响,但会尽力重新启用可能已被文件大小限制 (ulimit -f)、核心大小限制 (ulimit -c) 或进程在更改 UID/GID 后(例如 Linux 上的 /proc/sys/fs/suid_dumpable)的“可转储性”所禁用的核心转储。核心转储仍可能受当前目录权限(检查文件是从哪个目录开始的)、chroot 目录权限(可能需要暂时禁用 chroot 指令或将其移动到专用可写位置)或任何其他系统特定约束的限制。例如,某些 Linux 发行版以替换默认核心文件为系统中未安装的可执行文件的路径而闻名(检查 /proc/sys/kernel/core_pattern)。通常,简单地写入“core”、“core.%p”或“/var/log/core/core.%p”可以解决问题。在尝试启用此选项以等待罕见问题再次出现时,通常最好先通过向“haproxy”进程发出例如“kill -11”来获取此类转储,并验证它在终止时会在预期位置留下一个核心文件。
setenv <name> <value>
将环境变量 <name> 设置为值 <value>。如果该变量存在,则会被覆盖。更改会立即生效,因此配置文件中的下一行将看到新的值。另请参阅 “presetenv”、“resetenv” 和 “unsetenv”。
仅当启用了 OpenSSL 支持时,此设置才可用。它设置了描述在 SSL/TLS 握手中为所有不明确定义密码套件的“bind”行协商的密码算法(“密码套件”)的默认字符串,直到 TLSv1.2。字符串的格式定义在 OpenSSL man 页的“man 1 ciphers”中。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/)。有关 TLSv1.3 密码配置,请参阅“ssl-default-bind-ciphersuites”关键字。有关更多信息,请参阅“bind”关键字。
仅当启用了 OpenSSL 支持并使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时,此设置才可用。它设置了描述在 TLSv1.3 握手中为所有不明确定义密码套件的“bind”行协商的密码算法(“密码套件”)的默认字符串。字符串的格式定义在 OpenSSL man 页的“ciphersuites”部分中。有关 TLSv1.2 及更早版本的密码配置,请参阅“ssl-default-bind-ciphers”关键字。此设置可能接受 TLSv1.2 密码套件,但这是一种未记录的行为,不推荐,因为它可能不一致或存在错误。OpenSSL 的默认 TLSv1.3 密码套件是:“TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”。TLSv1.3 只支持 5 个密码套件: - TLS_AES_128_GCM_SHA256 - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 - TLS_AES_128_CCM_SHA256 - TLS_AES_128_CCM_8_SHA256 有关更多信息,请参阅“bind”关键字。
示例
global ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256 ssl-default-bind-ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
仅当启用了 OpenSSL 支持时,此设置才可用。它设置了描述在与 ECDHE 进行 SSL/TLS 握手期间协商的椭圆曲线算法(“曲线套件”)的默认字符串。字符串的格式是冒号分隔的曲线名称列表。有关更多信息,请参阅“bind”关键字。
仅当启用了 OpenSSL 支持时,此设置才可用。它为所有“bind”行设置了要强制使用的默认 ssl-options。有关可用选项,请检查“bind”关键字。
示例
global ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
仅当启用了 OpenSSL 支持时,此设置才可用。它设置了描述在与服务器进行 SSL/TLS 握手中协商的密码算法的默认字符串,直到 TLSv1.2,适用于所有不明确定义其密码套件的“server”行。字符串的格式定义在 OpenSSL man 页的“man 1 ciphers”中。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/)。有关 TLSv1.3 密码配置,请参阅“ssl-default-server-ciphersuites”关键字。有关更多信息,请参阅“server”关键字。
仅当启用了 OpenSSL 支持并使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时,此设置才可用。它设置了描述在与服务器进行 TLSv1.3 握手中协商的密码算法的默认字符串,适用于所有不明确定义其密码套件的“server”行。字符串的格式定义在 OpenSSL man 页的“ciphersuites”部分中。有关 TLSv1.2 及更早版本的密码配置,请参阅“ssl-default-server-ciphers”关键字。有关更多信息,请参阅“server”关键字。
仅当启用了 OpenSSL 支持时,此设置才可用。它为所有不明确定义其 ssl-options 的“server”行强制设置默认的 ssl-options。有关可用选项,请参阅“server”关键字。
仅当启用了 OpenSSL 支持时,此设置才可用。它设置了用于在 SSL/TLS 握手中进行带外 Diffie-Hellman (DHE) 密钥交换的默认 DH 参数,适用于所有不明确定义其 DH 参数的“bind”行。如果证书文件中有自定义 DH 参数,它将被覆盖。如果未使用 ssl-dh-param-file 指定自定义 DH 参数,或者未在证书文件中直接设置它们,则将使用 tune.ssl.default-dh-param 指定大小的预生成 DH 参数。自定义参数已知更安全,因此建议使用它们。自定义 DH 参数可以通过使用 OpenSSL 命令“openssl dhparam <size>”生成,其中 size 至少应为 2048,因为 1024 位 DH 参数不应再被视为安全。
ssl-load-extra-files <none|all|bundle|sctl|ocsp|issuer|key>*
此设置会更改 HAProxy 在加载与“bind”行关联的 SSL 证书时查找未指定文件的行为。它不适用于“server”行上用于客户端身份验证的证书。默认情况下,HAProxy 会自动发现配置中未指定的许多文件,如果您想优化启动时间,可以禁用此行为。“none”:仅加载配置文件中指定的文件。如果文件不存在,则不会尝试加载证书捆绑包。对于目录,如果证书具有相同的基本名称,则不会尝试捆绑证书。“all”:这是默认行为,它会尝试加载所有内容,包括捆绑包、sctl、ocsp、issuer、key。“bundle”:当配置文件中指定的文件不存在时,HAProxy 会尝试加载证书捆绑包。这是通过查找 <basename>.rsa、.ecdsa 和 .dsa 来实现的。对于目录,HAProxy 会尝试将具有相同基本名称的文件收集到一个多证书捆绑包中。捆绑包是在 OpenSSL 1.0.2 中引入的,当时是加载具有相同 SNI 的 ECDSA 证书和 RSA 证书的唯一方法。自 OpenSSL 1.1.1 起,已不再推荐使用此方法,您可以在 bind 行上指定 ECDSA 和 RSA 文件。“sctl”:尝试为每个 crt 关键字加载“<basename>.sctl”。“ocsp”:尝试为每个 crt 关键字加载“<basename>.ocsp”。“issuer”:如果 PEM 文件中未提供 OCSP 文件的颁发者,则尝试加载“<basename>.issuer”。“key”:如果 PEM 文件未提供私钥,则尝试加载一个包含私钥的文件“<basename>.key”。默认行为是“all”。
示例
ssl-load-extra-files bundle sctl ssl-load-extra-files sctl ocsp issuer ssl-load-extra-files none
ssl-server-verify [none|required]
服务器端 SSL 验证的默认行为。如果指定为 'none',则不验证服务器证书。默认值为 'required',除非使用命令行选项 '-dV' 强制指定。
自签发 CA,即 x509 根 CA,是证书链验证的锚点:作为服务器发送它是无用的,客户端必须拥有它。标准配置需要不在 PEM 文件中包含此类 CA。此选项允许您在 PEM 文件中保留此类 CA 而不将其发送给客户端。用例是为 ocsp 提供颁发者,而无需“.issuer”文件,并能够与“issuers-chain-path”共享它。这涉及所有没有中间证书的证书。对于 BoringSSL 来说是无用的,.issuer 被忽略,因为 ocsp 位不需要它。至少需要 OpenSSL 1.0.2。
stats maxconn <connections>
默认情况下,统计套接字限制为 10 个并发连接。可以使用 "stats maxconn" 更改此值。
stats socket [<address:port>|<path>] [param*]
将 UNIX 套接字绑定到 <path> 或 TCPv4/v6 地址到 <address:port>。连接到此套接字将返回各种统计信息输出,甚至允许发出一些命令来更改一些运行时设置。有关详细信息,请参阅管理指南的第 9.3 节“Unix 套接字命令”。“bind”行支持的所有参数均可用于此,例如限制某些用户或其访问权限。有关更多信息,请参阅第 5.1 节。
stats timeout <timeout, in milliseconds>
统计套接字的默认超时时间设置为 10 秒。可以使用 "stats timeout" 更改此值。该值必须以毫秒为单位传递,或者带有时间单位后缀,如 { us, ms, s, m, h, d }。
当 setrlimit 失败时,使进程在启动时失败。HAProxy 会根据计算结果尝试设置最佳的 setrlimit。如果失败,它将发出警告。此选项旨在保证当这些限制失败时 HAProxy 明确失败。它默认启用。仍可通过在其前添加“no”关键字来强制禁用它。
uid <number>
将进程的用户 ID 更改为 <number>。建议将用户 ID 专用于 HAProxy 或一小组类似的守护进程。HAProxy 必须以超级用户权限启动才能切换到另一个用户 ID。另请参阅“gid”和“user”。
ulimit-n <number>
将每个进程的最大文件描述符数设置为 <number>。默认情况下,它是自动计算的,因此建议不要使用此选项。
unix-bind [ prefix <prefix> ] [ mode <mode> ] [ user <user> ] [ uid <uid> ] [ group <group> ] [ gid <gid> ]
修复了在“bind”语句中声明的 UNIX 套接字的一些常见设置。这主要用于简化这些 UNIX 套接字的声明,并降低出错风险,因为这些设置通常是必需的,但也是进程特定的。<prefix> 设置可用于强制所有套接字路径相对于该目录。为了访问另一个组件的 chroot,可能需要这样做。请注意,这些路径在 haproxy chroot 之前解析,因此它们是绝对路径。“<mode>”、“<user>”、“<uid>”、“<group>”和“<gid>”的含义与它们在“bind”语句中使用时的含义相同。如果同时指定了两者,“bind”语句具有优先级,这意味着“unix-bind”设置可以被视为进程范围的默认设置。
unsetenv [<name> ...]
删除参数中指定的环境变量。这对于隐藏某些操作期间偶尔从用户环境中继承的一些敏感信息很有用。不存在的变量会被静默忽略,因此操作后可以确定这些变量都不再存在。更改会立即生效,因此配置文件中的下一行将看不到这些变量。另请参阅 “setenv”、“presetenv” 和 “resetenv”。
user <user name>
类似于“uid”,但它使用 /etc/passwd 中用户名为 <user name> 的用户的 UID。另请参阅“uid”和“group”。
node <name>
只允许字母、数字、连字符和下划线,与 DNS 名称类似。此语句在 HA 配置中很有用,其中两个或多个进程或服务器共享相同的 IP 地址。通过在所有节点上设置不同的节点名称,可以轻松地立即发现哪个服务器正在处理流量。
设置 WURFL User-Agent 缓存大小。为了更快地查找,已处理的用户代理会保存在 LRU 缓存中:- “0”:不使用缓存。- <size>:lru 缓存的大小(以元素为单位)。请注意,此选项仅在 HAProxy 编译时带有 USE_WURFL=1 时可用。
wurfl-data-file <file path>
提供设备检测服务的 WURFL 数据文件路径。该文件应由 HAProxy 访问,并具有相关权限。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
wurfl-information-list [<capability>]*
WURFL 功能、虚拟功能、我们计划在注入的标头中使用的属性名称的空格分隔列表。功能和虚拟功能名称的完整列表可在 Scientiamobile 网站上找到:https://www.scientiamobile.com/wurflCapability 有效的 WURFL 属性包括:- wurfl_id 包含匹配设备的设备 ID。- wurfl_root_id 包含匹配设备的根设备 ID。- wurfl_isdevroot 告诉匹配设备是否为根设备。可能的值为“TRUE”或“FALSE”。- wurfl_useragent 此特定 Web 请求附带的原始 useragent。- wurfl_api_version 包含表示当前使用的 Libwurfl API 版本的字符串。- wurfl_info 包含有关已解析的 wurfl.xml 及其完整路径的信息的字符串。- wurfl_last_load_time 包含 WURFL 最后一次成功加载的 Unix 时间戳。- wurfl_normalized_useragent 规范化的 useragent。请注意,仅当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
用于分隔包含 WURFL 结果的响应标头中值的字符。如果未设置,则默认使用逗号 (',')。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
wurfl-patch-file [<file path>]
WURFL 补丁文件路径列表。请注意,补丁是在启动时加载的,因此在 chroot 之前加载。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。

3.2. 性能调优

在某些情况下,尤其是在处理支持可变频率处理器的低延迟或在虚拟机中运行时,进程每次使用 poller 等待 I/O 时,处理器会睡眠或长时间被提供给另一个 VM,这会导致过高的延迟。此选项提供了一种防止处理器睡眠的解决方案,方法是始终对 poller 使用空超时。这会导致延迟显著降低(观察到 30 到 100 微秒),但会增加处理器过热的风险。它甚至可以与线程一起使用,在这种情况下,不正确绑定的线程可能会发生严重冲突,导致性能下降,“show info”输出中的 CPU 占用率值偏高,指示哪些线程配置错误。使用此选项时,切勿让进程与网络中断运行在同一处理器上。最好避免在共享同一核心的多个 CPU 线程上使用它。此选项默认禁用。如果已启用,仍然可以通过在前面加上“no”关键字来强制禁用它。它会被“select”和“poll” poller 忽略。在无缝重新加载期间,旧进程的此选项会自动禁用;它避免了当多个进程在一段时间内等待当前连接结束时过多的 CPU 冲突。
max-spread-checks <delay in milliseconds>
默认情况下,haproxy 会尝试将健康检查的开始时间分散到服务器场中所有服务器的最小健康检查间隔内。其原理是避免对同一服务器上运行的服务进行密集检查。但是当使用较大的检查间隔(10 秒或更长)时,服务器场中的最后几个服务器需要一些时间才能开始被测试,这可能是一个问题。此参数用于强制设置第一个和最后一个检查之间的延迟上限,即使服务器的检查间隔较大。当服务器以较短的间隔运行时,它们的间隔仍将得到尊重。
设置 HAProxy 在停止新请求的压缩或降低当前请求的压缩级别之前可以达到的最大 CPU 使用率。它的工作方式类似于“maxcomprate”,但测量的是 CPU 使用率而不是传入数据带宽。该值以 HAProxy 使用的 CPU 百分比表示。值 100 表示禁用限制。默认值为 100。设置较低的值将防止压缩工作减慢整个进程的速度并引入高延迟。
maxcomprate <number>
将每个进程的最大输入压缩速率设置为 <number> 千字节/秒。对于每个会话,如果达到最大值,会话期间的压缩级别将降低。如果在会话开始时达到最大值,该会话将完全不压缩。如果未达到最大值,压缩级别将增加到 tune.comp.maxlevel。值为零表示没有限制,这是默认值。
maxconn <number>
将每个进程的并发连接数最大值设置为 <number>。它等同于命令行参数“-n”。当达到此限制时,代理将停止接受连接。“ulimit-n”参数会根据此值自动调整。另请参阅“ulimit-n”。注意:在某些平台上,“select”轮询器无法可靠地使用超过 1024 个文件描述符。如果您的平台仅支持 select 并在启动时报告“select FAILED”,您需要减少 maxconn 直到它正常工作(通常略低于 500)。如果未设置此值,它将根据“ulimit -n”命令报告的当前文件描述符限制自动计算,如果强制执行内存限制,可能会根据缓冲区大小、分配给压缩的内存、SSL 缓存大小以及是否使用 SSL 和相关的 maxsslconn(也可以是自动的)而减少到一个较低的值。
maxconnrate <number>
将每个进程每秒的最大连接数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
maxpipes <number>
将每个进程的最大管道数设置为 <number>。目前,管道仅由基于内核的 tcp 拼接使用。由于一个管道包含两个文件描述符,"ulimit-n" 值将相应增加。默认值为 maxconn/4,这对于大多数重度使用情况来说似乎已经足够了。拼接代码动态分配和释放管道,并且可以回退到标准复制,因此将此值设置得太低可能只会影响性能。
maxsessrate <number>
将每个进程每秒的最大会话数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
maxsslconn <number>
将每个进程的并发 SSL 连接的最大数量设置为 <number>。默认情况下,没有 SSL 特定限制,这意味着全局 maxconn 设置将适用于所有连接。设置此限制可避免 openssl 使用过多内存而崩溃(因为不幸的是,它不能可靠地检查此类条件)。请注意,此限制同时适用于传入和传出连接,因此一个解密然后加密的连接算作 2 个 SSL 连接。如果未设置此值,但强制执行了内存限制,则此值将根据内存限制、maxconn、缓冲区大小、分配给压缩的内存、SSL 缓存大小以及在前端、后端或两者中使用的 SSL 自动计算。如果内存限制未指定 maxconn 或 maxsslconn,haproxy 将自动调整这些值,以便 100% 的连接可以安全地通过 SSL 进行,并考虑启用它的方面(前端、后端、两者)。
maxsslrate <number>
将每个进程每秒的最大 SSL 会话数设置为 <number>。当达到此限制时,SSL 侦听器将停止接受连接。它可以用来限制全局 SSL CPU 使用率,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。同样重要的是要注意,会话是在进入 SSL 堆栈之前而不是之后计算的,这也保护了堆栈免受不良握手的影响。此外,降低 tune.maxaccept 可以提高公平性。
maxzlibmem <number>
设置 zlib 每个进程可用的最大 RAM 量(以兆字节为单位)。当达到最大量时,只要 RAM 不可用,将来的会话将不会压缩。当设置为 0 时,没有限制。默认值为 0。该值在 UNIX 套接字上以字节为单位可用,通过 "show info" 命令的 "MaxZlibMemUsage" 行显示,zlib 使用的内存为 "ZlibMemUsage"(以字节为单位)。
禁用在 Linux 上使用 "epoll" 事件轮询系统。它等同于命令行参数 "-de"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
在源自 Solaris 10 及更高版本的 SunOS 系统上禁用事件端口(event ports)事件轮询系统的使用。它等同于命令行参数“-dv”。下一个使用的轮询系统通常是“poll”。另请参阅“nopoll”。
禁用使用 getaddrinfo(3) 进行名称解析。它等同于命令行参数 "-dG"。将使用已弃用的 gethostbyname(3)。
禁用在 BSD 上使用 "kqueue" 事件轮询系统。它等同于命令行参数 "-dk"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
禁用“poll”事件轮询系统的使用。它等同于命令行参数“-dp”。下一个使用的轮询系统将是“select”。通常不需要禁用“poll”,因为它在 HAProxy 支持的所有平台上都可用。另请参阅“nokqueue”、“noepoll”和“noevports”。
禁用 SO_REUSEPORT 的使用 - 请参阅 socket(7)。它等同于命令行参数 "-dR"。
禁用在 Linux 上使用内核在套接字之间进行 tcp 拼接。它等同于命令行参数 "-dS"。数据将使用传统的、更具可移植性的 recv/send 调用进行复制。内核 tcp 拼接仅限于一些非常近期的内核 2.6 实例。大多数 2.6.25 到 2.6.28 之间的版本都有错误,会转发损坏的数据,因此不得使用。此选项使得在有疑问时可以轻松地全局禁用内核拼接。另请参阅 "option splice-auto"、"option splice-request" 和 "option splice-response"。
profiling.tasks { auto | on | off }
启用('on')或禁用('off')每个任务的 CPU 分析。当设置为 'auto' 时,当线程开始遭受平均延迟 1000 微秒或更高(如“avg_loop_us”活动字段中报告的)时,分析会自动开启该线程,当延迟返回到 990 微秒以下时,会自动关闭(此值是过去 1024 次循环的平均值,因此它不会快速变化,并且倾向于显著平滑短时间的峰值)。它还可能在系统过载、容器或虚拟机中,或者在系统交换时(负载均衡器上绝不能发生这种情况)自发触发。每个任务的 CPU 分析对于报告时间花在哪里以及哪些请求对哪些其他请求产生什么影响非常方便。启用它通常会影响整体性能不到 1%,因此建议将其保留为默认的“auto”值,以便它仅在识别到问题时运行。此功能需要支持具有 clock_gettime(2) 系统调用和 CLOCK_MONOTONIC 和 CLOCK_THREAD_CPUTIME_ID 时钟标识符的系统,否则报告的时间将为零。可以使用 CLI 上的“set profiling”在运行时更改此选项。
spread-checks <0..50, in percent>
有时,希望避免以精确的间隔向服务器发送代理和健康检查,例如当许多逻辑服务器位于同一物理服务器上时。借助此参数,可以在检查间隔中添加 0 到 +/- 50% 之间的随机性。2 到 5 之间的值似乎效果很好。默认值仍为 0。
ssl-engine <name> [algo <comma-separated list of algorithms>]
将 OpenSSL 引擎设置为 <name>。可以使用命令“openssl engine”获取 <name> 的有效值列表。此语句可以多次使用,它只会启用多个加密引擎。引用不支持的引擎将导致 haproxy 无法启动。请注意,许多引擎将导致 HTTPS 性能低于最新处理器上的纯软件。可选命令“algo”使用 OPENSSL 函数 ENGINE_set_default_string() 设置 ENGINE 将提供的默认算法。值为“ALL”时,引擎用于所有加密操作。如果未指定 algo 列表,则使用“ALL”的值。可以指定由不同算法组成的逗号分隔列表,包括:RSA、DSA、DH、EC、RAND、CIPHERS、DIGESTS、PKEY、PKEY_CRYPTO、PKEY_ASN1。这与 openssl 配置文件使用的格式相同:https://www.openssl.org/docs/man1.0.2/apps/config.html
将 SSL_MODE_ASYNC 模式添加到 SSL 上下文。如果使用支持异步的 SSL 引擎,这将启用异步 TLS I/O 操作。当前实现最多支持 32 个引擎。Openssl ASYNC API 不支持移动读/写缓冲区,并且不兼容 haproxy 的缓冲区管理。因此,异步模式在读/写操作时被禁用(它仅在初始握手和重新协商握手期间启用)。
为每个进程可能分配的缓冲区设置硬限制。默认值为零,表示无限制。非零的最小值将始终大于“tune.buffers.reserve”,并且理想情况下应大约是其两倍。强制设置此值可能特别有助于限制进程可能占用的内存量,同时保持合理的行为。当达到此限制时,需要缓冲区的会话将等待另一个会话释放。由于缓冲区是动态分配和释放的,等待时间非常短且不易察觉,前提是限制保持合理。实际上,有时减小限制甚至可以通过提高 CPU 缓存的效率来提高性能。测试表明,对于平均 HTTP 流量,将限制设置为预期全局 maxconn 设置的 1/10,可以获得良好的结果,同时显着降低内存使用量。内存节省来自于这样一个事实:一些连接不会分配 2*tune.bufsize。最好不要更改此值,除非 haproxy 核心开发人员建议这样做。
设置预分配并保留的缓冲区数量,仅在内存分配失败导致的内存短缺情况下使用。最小值为 2,也是默认值。用户没有理由更改此值,它主要针对 haproxy 核心开发人员。
tune.bufsize <number>
将缓冲区大小设置为此大小(以字节为单位)。较低的值允许更多会话共存于相同数量的 RAM 中,而较高的值允许某些具有非常大 cookie 的应用程序工作。默认值为 16384,可以在构建时更改。强烈建议不要从默认值更改此值,因为非常低的值会破坏某些服务(如统计信息),而大于默认大小的值会增加内存使用量,可能导致系统内存不足。至少,全局 maxconn 参数应按此参数增加的相同比例减小。此外,HTTP/2 的使用要求此值必须为 16384 或更高。如果 HTTP 请求大于(tune.bufsize - tune.maxrewrite),haproxy 将返回 HTTP 400 (Bad Request) 错误。同样,如果 HTTP 响应大于此大小,haproxy 将返回 HTTP 502 (Bad Gateway)。请注意,使用此参数设置的值将在 32 位机器上自动向上舍入到下一个 8 的倍数,在 64 位机器上向上舍入到下一个 16 的倍数。
tune.chksize <number> (已弃用)
此选项已弃用并被忽略。
设置最大压缩级别。压缩级别影响压缩期间的 CPU 使用率。此值影响压缩期间的 CPU 使用率。每个使用压缩的会话都使用此值初始化压缩算法。默认值为 1。
如果使用 DEBUG_FAIL_ALLOC 编译,则给出分配尝试失败的百分比几率。必须介于 0(无失败)和 100(无成功)之间。这对于调试和确保内存故障得到妥善处理非常有用。
tune.fd.edge-triggered { on | off } [ 实验性 ]
为支持它的文件描述符(FD)启用('on')或禁用('off')边缘触发轮询模式。目前仅在 epoll 下支持。在某些情况下,它可能会显著减少 epoll_ctl() 调用的数量并略微提高性能。这仍然是实验性的,如果仍然存在错误,可能会导致连接冻结,并且默认禁用。
设置 HTTP/2 动态头表大小。默认为 4096 字节,不能大于 65536 字节。较大的值可能有助于某些客户端发送更紧凑的请求,具体取决于它们的能力。每个 HTTP/2 连接都会消耗此数量的内存。建议不要更改它。
设置 HTTP/2 的初始窗口大小,即客户端在等待 haproxy 确认之前可以上传的字节数。此设置仅影响有效负载内容(即 POST 请求的正文),而不影响标头。默认值为 65535,在大约 100 毫秒的 ping 时间的网络上,每位客户端的上传带宽约为 5 Mbps,在 1 毫秒的本地网络上约为 500 Mbps。增加此值以允许更快的上传,或在处理多个客户端时减小此值以增加公平性是有意义的。它不影响资源使用。
设置每个连接的 HTTP/2 最大并发流数(即单个连接上的未完成请求数)。默认值为 100。在具有高延迟的网络上访问时,更大的值可能会略微改善复杂站点的页面加载时间,但会增加单个客户端可能分配的资源量。值为零会禁用限制,因此单个客户端可以创建 haproxy 可分配的任意数量的流。强烈建议不要更改此值。
设置 haproxy 向其对等节点宣告愿意接收的最大帧大小。默认值是 16384 和缓冲区大小 (tune.bufsize) 之间的较大者。在任何情况下,haproxy 都不会宣告支持大于缓冲区的帧大小。此设置的主要目的是在配置大缓冲区时允许限制最大帧大小。过大的帧大小可能会影响性能或导致某些对等节点行为异常。强烈建议不要更改此值。
设置捕获的 cookie 的最大长度。"capture cookie xxx len yyy" 允许的最大值将是此值,任何更高的值都将自动截断为此值。重要的是不要设置太高的值,因为所有 cookie 捕获无论其配置值如何都会分配此大小(它们共享一个池)。此值是每个请求每个响应的,因此每个连接分配的内存是此值的两倍。如果未指定,限制设置为 63 个字符。建议不要更改此值。
设置日志中请求 URI 的最大长度。这可以防止在日志行中截断带有有价值查询字符串的长请求 URI。这与 syslog 的限制无关。如果增加此限制,您可能还需要增加 'log ... len yyy' 参数。您的 syslog 守护进程可能也需要特定的配置指令。默认值为 1024。
设置请求中的最大报头数。当请求的报头数(包括第一行)大于此值时,它将被拒绝,并返回 "400 Bad Request" 状态码。同样,过大的响应将被阻止,并返回 "502 Bad Gateway"。默认值为 101,对于所有用途来说已经足够,考虑到广泛部署的 Apache 服务器也使用相同的限制。有时可以进一步提高此限制,以便在修复错误的应用程序之前临时允许其工作。可接受的范围是 1..32767。请记住,每个新报头都会为每个会话消耗 32 位的内存,因此不要将此限制设置得太高。
启用('on')或禁用('off')同一服务器的空闲连接池在线程间的共享。默认是共享它们,以最小化到服务器的持久连接数,并优化连接重用率。但为了帮助调试或当怀疑 HAProxy 在连接重用方面存在错误时,强制禁用多线程间的空闲池共享,并将此选项设置为 "off" 可能很方便。默认是 on。强烈建议在禁用此选项时,不要为所有依赖连接重用以实现高性能的服务器设置一个保守的“pool-low-conn”值,否则随着线程数的增加,连接可能会被频繁关闭。
tune.idletimer <timeout>
设置 haproxy 将认为空缓冲区可能与空闲流关联的时间。这用于在转发大量和小数据时优化某些数据包大小。使用 splice() 或在 SSL 中发送大缓冲区进行数据的决定受此参数的调节。该值以毫秒为单位,在 0 到 65535 之间。值为零表示 haproxy 不会尝试检测空闲流。默认值为 1000,它似乎能正确检测最终用户暂停(例如,在点击之前阅读页面)。没有理由更改此值。请查看下面的 tune.ssl.maxrecord。
启用('on')或禁用('off')侦听器的多队列接受,该接受会将传入流量分散到“bind”行允许运行的所有线程,而不是将它们全部自己占用。这提供了更平滑的流量分布,并且可扩展性更好,特别是在线程可能因外部活动(例如,网络中断与某个线程冲突)而不均匀加载的环境中。此选项默认启用,但可以强制禁用以进行故障排除,或在估计操作系统已提供足够好的分布且连接寿命极短的情况下使用。
该指令强制 Lua 引擎每执行 <number> 条指令就执行一次让出(yield)。这允许中断一个长时间运行的脚本,并让 HAProxy 调度器处理其他任务,如接受连接或转发流量。默认值为 10000 条指令。如果 HAProxy 经常执行一些 Lua 代码但需要更高的响应性,可以降低这个值。如果 Lua 代码相当长,并且其结果对于处理数据是绝对必需的,可以增加这个 <number>。
设置 Lua 每个进程可用的最大 RAM 量(以兆字节为单位)。默认情况下为零,表示无限制。设置限制很重要,以确保脚本中的错误不会导致系统内存耗尽。
这是 Lua 会话的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
这是 Lua 服务的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
目的与 "tune.lua.session-timeout" 相同,但此超时专用于任务。默认情况下,此超时未设置,因为任务可能在 HAProxy 的整个生命周期内保持活动状态。例如,用于检查服务器的任务。
设置一个进程在切换到其他工作之前可以连续接受的最大连接数。在单进程模式下,较高的数字在高连接率下性能更好。然而,在多进程模式下,在进程之间保持一点公平性通常能更好地提高性能。此值单独应用于每个侦听器,以便考虑到侦听器绑定的进程数。此值默认为 64。在多进程模式下,它除以侦听器绑定的进程数的两倍。将此值设置为 -1 将完全禁用此限制。通常不需要调整此值。
设置一次调用轮询系统可以处理的最大事件量。默认值根据操作系统进行调整。已经注意到,将其降低到 200 以下会略微降低延迟,但会牺牲网络带宽,而将其增加到 200 以上则会以延迟换取略微增加的带宽。
将保留的缓冲区空间设置为此大小(以字节为单位)。保留空间用于报头重写或追加。套接字上的第一次读取永远不会超过 bufsize-maxrewrite。历史上,它默认为 bufsize 的一半,但这没有太大意义,因为很少有大量的报头需要添加。设置得太高会妨碍处理大的请求或响应。设置得太低会妨碍向已有的较大请求或 POST 请求添加新报头。通常明智的做法是将其设置为大约 1024。如果大于 bufsize 的一半,它会自动调整为 bufsize 的一半。这意味着您在更改 bufsize 时不必担心它。
将模式查找缓存的大小设置为 <number> 个条目。这是一个 LRU 缓存,用于记住以前的查找及其结果。它由 ACL 和 maps 在慢模式查找中使用,即使用“sub”、“reg”、“dir”、“dom”、“end”、“bin”匹配方法以及不区分大小写的字符串。它适用于模式表达式,这意味着它能够记住配置行(包括从文件中加载的所有模式)上所有指定模式的查找结果。它会自动使通过 HTTP 操作或 CLI 更新的条目失效。默认缓存大小设置为 10000 个条目,这将其占用空间限制在每个进程/线程约 5 MB(32 位系统)和每个进程/线程约 8 MB(64 位系统),因为缓存是线程/进程本地的。此缓存中发生冲突的风险非常低,约为缓存大小除以 2^64。通常,在每秒 10000 个请求且默认缓存大小为 10000 个条目的情况下,暴力攻击导致单个冲突的概率在 60 年后为 1%,在 6 年后为 0.1%。这被认为远低于老化组件引起的内存损坏风险。如果这不可接受,可以通过将此参数设置为 0 来禁用缓存。
tune.pipesize <number>
将内核管道缓冲区大小设置为此大小(以字节为单位)。默认情况下,管道是系统的默认大小。但有时在使用 TCP 拼接时,增加管道大小可以提高性能,特别是在怀疑管道未被填满且执行了许多 splice() 调用时。这对内核的内存占用有影响,因此如果影响不明确,则不应更改此值。
此设置设置了haproxy全局使用的文件描述符数量(百分比)与haproxy可以使用但在此之前我们将开始在无法重用连接且必须创建新连接时杀死空闲连接的最大文件描述符数量之间的比率。默认值为25(四分之一的文件描述符意味着大约一半的最大前端连接可以保留一个空闲连接,超出此范围在一般情况下目标是连接重用时意义不大)。
此设置设置了haproxy全局使用的文件描述符数量(百分比)与haproxy可以使用但在此之前我们将停止将连接放入空闲池进行重用的最大文件描述符数量之间的比率。默认值为20。
强制将客户端或服务器端的内核套接字接收缓冲区大小设置为指定的字节值。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小(0)让内核根据可用内存量自动调整此值。但是,有时将其设置为非常低的值(例如 4096)有助于节省内核内存,因为它阻止内核缓冲过多的接收数据。不过,较低的值会显著增加 CPU 使用率。
HAProxy 使用一些提示来检测短读是否表示套接字缓冲区的末尾。其中之一是读取返回的字节数超过 <recv_enough>,默认为 10136(7 个 1448 字节的段)。此默认值可以通过此设置更改,以更好地处理涉及大量短消息的工作负载,例如 telnet 或 SSH 会话。
在运行任务时,设置一次可以处理的任务的最大数量。默认值为 200。增加它可能会在处理 I/O 时增加延迟,而使其太小可能会产生额外的开销。在尝试使用大得多的值时,启用 tune.sched.low-latency 以将最大延迟限制在尽可能低的范围内可能很有用。
启用('on')或禁用('off')低延迟任务调度程序。默认情况下,haproxy 按顺序一次处理几个类别的任务,因为这效率最高。但在使用较大的 tune.runqueue-depth 值运行时,这可能会对请求或连接延迟产生可衡量的影响。当启用此低延迟设置时,如果存在较低优先级的任务,它们将始终在其他任务之前执行。这将有助于降低在大流量中新请求或连接所经历的最大延迟,但代价是影响大流量的程度更高。对于常规用法,最好将其关闭。默认值为 off。
将客户端或服务器端的内核套接字发送缓冲区大小强制设置为指定的字节数。此值适用于所有TCP/HTTP前端和后端。通常不应设置它,默认大小(0)允许内核根据可用内存量自动调整此值。但是,有时将其设置为非常小的值(例如4096)可以通过阻止内核缓冲过多的接收数据来节省内核内存。然而,较低的值将显著增加CPU使用率。另一种用例是防止由于内核等待缓冲区的大部分被读取然后再次通知haproxy而导致的极慢客户端的写入超时。
将全局 SSL 会话缓存的大小设置为块数。一个块足够大,可以包含一个没有对端证书的编码会话。带有对端证书的编码会话根据对端证书的大小存储在多个块中。一个块使用大约 200 字节的内存(基于 `sizeof(struct sh_ssl_sess_hdr) + SHSESS_BLOCK_MIN_SIZE` 计算,用于 `shctx_init` 函数)。默认值可以在构建时强制设置,否则默认为 20000。当缓存已满时,最不活动的条目将被清除并重新分配。较高的值会减少此类清除的发生次数,从而通过确保所有用户尽可能长时间地保留其会话来减少 CPU 密集型 SSL 握手的次数。所有条目在启动时预分配,并且如果“nbproc”大于 1 时,这些条目会在所有进程之间共享。将此值设置为 0 会禁用 SSL 会话缓存。
设置用于捕获客户端 hello 密码列表、扩展列表、椭圆曲线列表和椭圆曲线点格式的缓冲区的最大大小。如果值为 0(默认值),则禁用捕获,否则将为每个 SSL/TLS 连接分配一个缓冲区。
在 DHE 密钥交换的情况下,设置用于生成临时/临时 Diffie-Hellman 密钥的 Diffie-Hellman 参数的最大大小。最终大小将尝试匹配服务器的 RSA(或 DSA)密钥的大小(例如,对于 2048 位 RSA 密钥,使用 2048 位临时 DH 密钥),但不会超过此最大值。只允许 1024 或更高的值。较高的值会增加 CPU 负载,而大于 1024 位的值不受 Java 7 及更早版本的客户端支持。如果直接在证书文件中或通过使用 ssl-dh-param-file 参数提供了静态 Diffie-Hellman 参数,则不使用此值。如果既没有定义 default-dh-param 也没有定义 ssl-dh-param-file,并且给定前端的服务器 PEM 文件没有指定其自己的 DH 参数,则 DHE 密码将对此前端不可用。
此选项禁用所有进程之间的 SSL 会话缓存共享。通常不应使用它,因为它会由于客户端命中随机进程而强制进行许多重新协商。但在某些操作系统上可能需要它,因为这些操作系统上可能无法使用任何 SSL 缓存同步方法。在这种情况下,在 SSL 层之前添加第一层基于哈希的负载均衡可能会限制缺少会话共享的影响。
tune.ssl.keylog { on | off }
此选项激活 TLS 密钥的日志记录。应谨慎使用,因为它会消耗每个 SSL 会话更多的内存,并可能降低性能。默认情况下禁用此功能。这些样本提取应与用于生成解密 wireshark 流量所需的 SSLKEYLOGFILE 一起使用。https://mdn.org.cn/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format SSLKEYLOG 是一系列行,格式如下:<Label> <space> <ClientRandom> <space> <Secret> ClientRandom 由 %[ssl_fc_client_random,hex] 样本提取提供,Secret 和 Label 可以在下面的数组中找到。您需要生成一个包含此数组中所有标签的 SSLKEYLOGFILE。以下样本提取是十六进制字符串,无需转换。SSLKEYLOGFILE 标签 | Secret 的样本提取 --------------------------------|----------------------------------------- CLIENT_EARLY_TRAFFIC_SECRET | %[ssl_fc_client_early_traffic_secret] CLIENT_HANDSHAKE_TRAFFIC_SECRET | %[ssl_fc_client_handshake_traffic_secret] SERVER_HANDSHAKE_TRAFFIC_SECRET | %[ssl_fc_server_handshake_traffic_secret] CLIENT_TRAFFIC_SECRET_0 | %[ssl_fc_client_traffic_secret_0] SERVER_TRAFFIC_SECRET_0 | %[ssl_fc_server_traffic_secret_0] EXPORTER_SECRET | %[ssl_fc_exporter_secret] EARLY_EXPORTER_SECRET | %[ssl_fc_early_exporter_secret] 仅当使用 OpenSSL 1.1.1 时可用,并且对于 TLS1.3 会话很有用。如果您想生成 TLS < 1.3 的 SSLKEYLOGFILE 内容,您只需要以下行:“CLIENT_RANDOM %[ssl_fc_client_random,hex] %[ssl_fc_session_key,hex]”
设置缓存的 SSL 会话可以保持有效的时长。此时间以秒为单位表示,默认为 300(5 分钟)。重要的是要理解,这并不保证会话会持续那么长时间,因为如果缓存已满,最长时间空闲的会话将被清除,尽管它们配置了生命周期。此设置的真正用处是防止会话被使用太长时间。
设置一次传递给 SSL_write() 的最大字节数。默认值 0 表示没有限制。通过 SSL/TLS,客户端只有在接收到完整的记录后才能解密数据。对于大记录,这意味着客户端可能需要下载多达 16kB 的数据才能开始处理它们。限制该值可以改善位于高延迟或低带宽网络上的浏览器的页面加载时间。建议找到适合 1 或 2 个 TCP 段(在以太网上启用 TCP 时间戳时通常为 1448 字节,禁用时间戳时为 1460 字节)的最佳值,同时记住 SSL/TLS 会增加一些开销。测试期间,1419 和 2859 的典型值取得了良好结果。使用“strace -e trace=write”来找到最佳值。HAProxy 在检测到空闲流后将自动切换到此设置(请参阅上面的 tune.idletimer)。
将用于存储生成证书的缓存大小设置为 <number> 个条目。这是一个 LRU 缓存。因为动态生成 SSL 证书的开销很大,所以它们被缓存起来。默认缓存大小设置为 1000 个条目。
这五个 tune 参数有助于管理变量系统使用的内存总量。“global”限制了所有作用域可用的内存总量。“proc”限制了进程作用域的内存,“sess”限制了会话作用域的内存,“txn”用于事务作用域,而“reqres”限制了每个请求或响应处理的内存。内存计数是分层的,这意味着更粗粒度的限制包括更细粒度的限制:“proc”包含“sess”,“sess”包含“txn”,“txn”包含“reqres”。例如,当“tune.vars.sess-max-size”限制为 100 时,“tune.vars.txn-max-size”和“tune.vars.reqres-max-size”也不能超过 100。如果我们创建一个包含 100 字节的变量“txn.var”,则所有可用空间都会被消耗。请注意,在运行时超出限制不会导致错误消息,但值可能会被截断或损坏。因此,请务必准确规划存储所有变量所需的空间量。
为每个会话在 zlib 初始化中设置 memLevel 参数。它定义了应为内部压缩状态分配多少内存。值为 1 使用最少的内存,但速度慢且压缩率降低;值为 9 使用最大的内存以获得最佳速度。可以是 1 到 9 之间的值。默认值为 8。
为每个会话在 zlib 初始化中设置窗口大小(历史缓冲区的大小)。此参数的较大值会以内存使用为代价带来更好的压缩效果。可以是 8 到 15 之间的值。默认值为 15。

3.3. 调试

debug (已弃用)
启用调试模式,将所有交换信息转储到标准输出,并禁止 fork 到后台。它等同于命令行参数 "-d"。它绝不应在生产配置中使用,因为它可能会阻止系统完全启动。
启动期间不显示任何消息。它等同于命令行参数 "-q"。
当设置此选项时,如果处理配置时发出任何警告,haproxy 将拒绝启动。强烈建议在不经常更改的配置上设置此选项,因为它有助于检测细微的错误,并使配置保持清晰和前向兼容。请注意,“haproxy -c”在这种情况下也会报告错误。此选项等同于命令行参数“-dW”。

3.4. 用户列表

可以通过仅允许经过身份验证和授权的用户来控制对前端/后端/侦听部分或 http 统计信息的访问。为此,需要创建至少一个用户列表并定义用户。
userlist <listname>
创建名为 <listname> 的新用户列表。可以使用许多独立的用户列表来存储独立客户的身份验证和授权数据。
group <groupname> [users <user>,<user>,(...)]
将组 <groupname> 添加到当前用户列表。也可以通过使用逗号分隔的名称列表(前面有 "users" 关键字)将用户附加到此组。
user <username> [password|insecure-password <password>] [groups <group>,<group>,(...)]
将用户 <username> 添加到当前用户列表中。可以使用安全(加密)和不安全(未加密)的密码。加密密码使用 crypt(3) 函数进行评估,因此取决于系统的功能,支持不同的算法。例如,现代基于 Glibc 的 Linux 系统支持 MD5、SHA-256、SHA-512,当然还有经典的基于 DES 的加密密码方法。注意:请注意,使用加密密码可能会显著增加 CPU 使用率,具体取决于请求数量和使用的算法。对于任何哈希变体,每个请求的密码都必须通过选定的算法进行处理,然后才能与配置文件中指定的值进行比较。大多数当前算法故意设计成计算成本高昂,以抵抗暴力攻击。它们不是一次性加盐/哈希明文密码,而是成千上万次。这可能很快成为 haproxy 总体 CPU 消耗的一个主要因素!
示例
userlist L1 group G1 users tiger,scott group G2 users xdb,scott user tiger password $6$k6y3o.eP$JlKBx9za9667qe4(...)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.5. 对等节点

可以在多个 haproxy 实例之间通过 TCP 连接以多主方式传播粘性表中的任何数据类型的条目。每个实例将其本地更新和插入推送到远程对等节点。推送的值会覆盖远程值,而不进行聚合。中断的交换会自动检测并从最后一个已知点恢复。此外,在软重启期间,旧进程使用这样的 TCP 连接连接到新进程,以在新进程尝试连接其他对等节点之前推送其所有条目。这确保了在重新加载期间的快速复制,即使对于大型表,通常也只需要几分之一秒。请注意,服务器 ID 用于远程识别服务器,因此重要的是配置看起来相似,或者至少在所有参与者上对每个服务器强制使用相同的 ID。
peers <peersect>
创建名为 <peersect> 的新对等节点列表。它是一个独立的部分,由一个或多个粘性表引用。
bind [<地址>]:端口 [参数*]
bind /<路径> [参数*]
定义此“peers”部分中本地对等节点的绑定参数。在同一个“peers”部分中,此类行不支持与“peer”行同时使用。
禁用一个对等节点部分。它会禁用与此部分相关的侦听和任何同步。这用于禁用粘性表的同步,而无需注释掉所有 "peers" 引用。
default-bind [参数*]
定义本地对等节点的绑定参数,但不包括其地址。
default-server [参数*]
更改“peers”部分中服务器的默认选项。
参数
<param*> 是此服务器的参数列表。“default-server”关键字接受大量选项,并有一个专门介绍它的部分。在 peers 部分,支持 default-server 行的传输参数。请参阅第 5 节以获取更多详细信息,以及本节下面的 server 关键字以获取一些限制。
此选项重新启用一个先前通过“disabled”关键字禁用的 peers 部分。
log <address> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]
peers”部分支持与代理相同的“log”关键字,用于记录有关“peers”侦听器的信息。请参阅代理的“log”选项以获取更多详细信息。
peer <peername> [<address>]:port [param*]
peer <peername> /<path> [param*]
在 peers 部分内定义一个 peer。如果 <peername> 设置为本地 peer 名称(默认为主机名,或通过“-L”命令行选项或“localpeer”全局配置设置强制设置),则 HAproxy 将在该地址上侦听传入的远程 peer 连接。否则,该地址定义了连接到哪里以加入远程 peer,而 <peername> 在协议级别用于标识和验证服务器端的远程 peer。在软重新启动期间,旧实例会使用本地 peer 地址连接新实例,并启动完整的复制(教学过程)。强烈建议所有 peer 使用完全相同的 peers 声明,并且仅依赖“-L”命令行参数或“localpeer”全局配置设置来更改本地 peer 名称。这使得跨所有 peer 维护一致的配置文件更加容易。您可能需要引用地址参数中的某些环境变量,有关环境变量的信息,请参阅第 2.3 节。注意:“peer”关键字可以被“server”关键字透明地替换(请参阅下面的“server”关键字解释)。
server <peername> [<address>:<port>] [param*]
server <peername> [/<path>] [param*]
如前所述,“peer”关键字可以被“server”关键字替换,支持 5.2 段中与传输设置相关的“server”参数。如果底层 peer 是本地的,则地址参数不得存在;它必须在“bind”行上提供(请参阅本节的“peers”部分中的“bind”关键字)。一些“server”参数与“peers”部分无关。Peer 本质上不支持动态主机名解析或运行状况检查,因此“init_addr”、“resolvers”、“check”、“agent-check”或“track”等参数不受支持。同样,没有负载均衡也没有粘性,因此“weight”或“cookie”等参数无效。
示例
 # 旧方法。 peers mypeers peer haproxy1 192.168.0.1:1024 peer haproxy2 192.168.0.2:1024 peer haproxy3 10.2.0.1:1024 backend mybackend mode tcp balance roundrobin stick-table type ip size 20k peers mypeers stick on src server srv1 192.168.0.30:80 server srv2 192.168.0.31:80 示例: peers mypeers bind 192.168.0.1:1024 ssl crt mycerts/pem default-server ssl verify none server haproxy1 #本地对等节点 server haproxy2 192.168.0.2:1024 server haproxy3 10.2.0.1:1024
table <tablename> type {ip | integer | string [len <length>] | binary [len <length>]} size <size> [expire <expire>] [nopurge] [store <data_type>]*
为当前部分配置粘性表。此行解析方式与“stick-table”关键字在其他部分中的解析方式相同,只是“peers”参数在此处不是必需的,并且有一个额外的强制性第一个参数来指定粘性表。与其他部分不同,peers 部分可能有多行“table”(另请参阅“stick-table”关键字)。还要注意,“peers”部分有自己的粘性表命名空间,以避免在不同“peers”部分中具有相同名称的粘性表之间发生冲突。这通过在粘性表名称前加上“peers”部分名称,然后加上“/”字符来内部处理。如果在配置文件的其他地方必须引用在“peers”部分声明的此类粘性表,则必须使用带前缀的粘性表名称,如下所示:peers mypeers peer A ... peer B ... table t1 ... frontend fe1 tcp-request content track-sc0 src table mypeers/t1 这也是用于通过 CLI 引用在“peers”部分声明的粘性表的带前缀的粘性表名称。关于“peers”协议,由于同一部分的“peers”才能相互通信,因此无需进行此类区分。多个“peers”部分可能声明同名的粘性表。这是在网络上发送的粘性表名称的较短版本。只有一个“/”字符作为前缀,以避免在声明为后端的粘性表与在“peers”部分中声明的粘性表之间发生名称冲突,如下面这种奇怪但支持的配置所示:peers mypeers peer A ... peer B ... table t1 type string size 10m store gpc0 backend t1 stick-table type string size 10m store gpc0 peers mypeers 在这里,“mypeers”部分声明的“t1”表具有“mypeers/t1”的全局名称。“t1”表声明为后端,其全局名称为“t1”。但在此对端协议级别,前者表名为“/t1”,后者表名仍为“t1”。

3.6. 邮件发送器

当服务器状态发生变化时,可以发送电子邮件警报。如果配置了电子邮件警报,则会发送到邮件发送器部分中配置的每个邮件发送器。电子邮件使用 SMTP 发送给邮件发送器。
mailers <mailersect>
创建名为 <mailersect> 的新邮件发送器列表。它是一个独立的部分,由一个或多个代引用。
mailer <mailername> <ip>:<port>
在邮件发送器部分内定义一个邮件发送器。
示例
mailers mymailers mailer smtp1 192.168.0.1:587 mailer smtp2 192.168.0.2:587 backend mybackend mode tcp balance roundrobin email-alert mailers mymailers email-alert from test1@horms.org email-alert to test2@horms.org server srv1 192.168.0.30:80 server srv2 192.168.0.31:80
timeout mail <时间>
定义可用于建立邮件/连接并发送到邮件服务器的时间。如果未定义,默认值为 10 秒。为了允许在初始 TCP 握手期间至少发送两个 SYN-ACK 数据包,建议将此值保持在 4 秒以上。
示例
mailers mymailers timeout mail 20s mailer smtp1 192.168.0.1:587

3.7. 程序

在 master-worker 模式下,可以与 master 一起启动外部二进制文件,这些进程称为程序。这些程序的启动和管理方式与 worker 相同。在 HAProxy 重载期间,这些进程将经历与 worker 相同的序列: - master 被重新执行 - master 向程序发送一个 SIGUSR1 信号 - 如果没有禁用“option start-on-reload”,master 将启动一个新的程序实例 在停止或重启期间,会向程序发送一个 SIGTERM 信号。
program <名称>
这是一个新的程序部分,此部分将创建一个名为 <name> 的实例,该实例在 master CLI 的 "show proc" 中可见。(请参阅管理指南中的 "9.4. Master CLI")。
command <命令> [参数*]
定义要启动的命令及可选参数。如果命令不包含绝对路径,则会在当前 PATH 中查找。这是 program 部分的一个强制选项。包含空格的参数必须用单引号或双引号括起来,或者以反斜杠为前缀。
user <用户名>
将执行的命令用户 ID 更改为 /etc/passwd 中的 <用户名>。另请参阅“group”。
group <组名>
将执行的命令组 ID 更改为 /etc/group 中的 <组名>。另请参阅“user”。
在 master 重载时启动(或不启动)程序的新实例。默认是启动新实例。此选项只能在 program 部分使用。

3.8. HTTP 错误

可以全局声明多个 HTTP 错误组,以便之后在任何代理部分中导入。同一个组可以在多个地方被引用,并且可以全部或部分导入。
http-errors <名称>
创建一个名为 <name> 的新 http-errors 组。它是一个独立的部分,可以由一个或多个代理通过其名称引用。
errorfile <代码> <文件>
将文件内容与一个 HTTP 错误码关联起来。
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、425、429、500、502、503 和 504 的代码。<file> 指定一个包含完整 HTTP 响应的文件。建议遵循将“.http”附加到文件名上的常见做法,以便人们不会将响应与 HTML 错误页面混淆,并使用绝对路径,因为文件是在执行任何 chroot 之前读取的。
请参考第 4 节中的“errorfile”关键字以获取详细信息。
示例
http-errors website-1 errorfile 400 /etc/haproxy/errorfiles/site1/400.http errorfile 404 /etc/haproxy/errorfiles/site1/404.http errorfile 408 /dev/null # 解决 Chrome 预连接错误 http-errors website-2 errorfile 400 /etc/haproxy/errorfiles/site2/400.http errorfile 404 /etc/haproxy/errorfiles/site2/404.http errorfile 408 /dev/null # 解决 Chrome 预连接错误

3.9. 环形缓冲区

可以全局声明环形缓冲区,用作日志服务器或跟踪的目标。
ring <ringname>
创建一个名为 <ringname> 的新环形缓冲区。
description <文本>
描述是环形缓冲区的可选描述字符串。它将出现在 CLI 中。默认情况下,<name> 会被重用以填充此字段。
format <格式>
用于将事件存储到环形缓冲区的格式。
参数
<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一: iso 包含仅 ISO 日期,后跟文本的消息。省略 PID、进程名和系统名。此格式旨在与本地日志服务器一起使用。 raw 仅包含文本的消息。省略级别、PID、日期、时间、进程名和系统名。此格式旨在在容器内或开发过程中使用,其中严重性仅取决于使用的文件描述符(stdout/stderr)。这是默认设置。 rfc3164 RFC3164 syslog 消息格式。这是默认设置。(https://tools.ietf.org/html/rfc3164) rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424) short 包含仅在尖括号内的级别的消息,例如“<3>”,后跟文本。省略 PID、日期、时间、进程名和系统名。此格式旨在与本地日志服务器一起使用。此格式与 systemd 日志记录器使用的格式兼容。 timed 包含仅在尖括号内的级别的消息,例如“<3>”,后跟 ISO 日期和文本的消息。省略 PID、进程名和系统名。此格式旨在与本地日志服务器一起使用。
maxlen <长度>
存储在环形缓冲区中的事件消息的最大长度,包括格式化的头部。如果事件消息长于 <length>,它将被截断为此长度。
server <名称> <地址> [参数*]
用于配置 syslog tcp 服务器以转发来自 ring buffer 的消息。它支持 5.2 段中找到的所有“server”参数。其中一些参数对于“ring”部分是不相关的。重要提示:将一个 ring 添加到多个服务器上的原因很少,因为所有服务器都将收到完全相同的 ring 内容副本,因此 ring 将以最慢服务器的速度前进。如果一个服务器无响应,它将阻止旧消息被清除,并可能阻止新消息被插入 ring。将消息发送到多个服务器的正确方法是为每个日志服务器使用一个单独的 ring,而不是将多个服务器连接到同一个 ring。请注意,特定的服务器指令“log-proto”用于设置用于发送消息的协议。
size <大小>
这是环形缓冲区的可选大小,以字节为单位。默认值设置为 BUFSIZE。
设置等待服务器连接尝试成功的最大时间。
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
设置待处理数据在输出缓冲区中停留的最长时间。
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
示例
global log ring@myring local7 ring myring description "我的本地缓冲区" format rfc3164 maxlen 1200 size 32764 timeout connect 5s timeout server 10s server mysyslogsrv 127.0.0.1:6514 log-proto octet-count
代理配置可以位于以下部分集合中: - defaults [<name>] - frontend <name> - backend <name> - listen <name> “defaults”部分设置其声明之后所有其他部分的默认参数。这些默认参数将被下一个“defaults”部分重置。有关可以在“defaults”部分中设置的参数列表,请参见下文。名称是可选的,但为了提高可读性,鼓励使用名称。“frontend”部分描述了一组接受客户端连接的侦听套接字。“backend”部分描述了一组代理将连接以转发传入连接的服务器。“listen”部分在一个部分中定义了其前端和后端部分结合在一起的完整代理。它通常对纯 TCP 流量有用。所有代理名称必须由大写和小写字母、数字、“-”(连字符)、“_”(下划线)、“.”(点)和“:”(冒号)组成。ACL 名称区分大小写,这意味着“www”和“WWW”是两个不同的代理。历史上,所有代理名称都可以重叠,这只会导致日志中的问题。自内容切换引入以来,具有重叠功能(前端/后端)的两个代理必须具有不同的名称。但是,前端和后端仍然可以共享相同的名称,因为这种配置似乎很常见。目前,支持两种主要的代理模式:“tcp”,也称为第 4 层,以及“http”,也称为第 7 层。在第 4 层模式下,HAProxy 仅在前后端两侧之间转发双向流量。在第 7 层模式下,HAProxy 分析协议,并可以通过允许、阻止、切换、添加、修改或删除请求或响应中的任意内容来与之交互,具体取决于任意标准。在 HTTP 模式下,对流经连接的请求和响应所应用的处理取决于前端的 HTTP 选项和后端的组合。HAProxy 支持 3 种连接模式: - KAL:keep alive(“option http-keep-alive”),这是默认模式:所有请求和响应都已处理,连接保持打开状态,但在响应和新请求之间处于空闲状态。 - SCL:server close(“option http-server-close”):在收到响应的结束时关闭面向服务器的连接,但面向客户端的连接保持打开状态。 - CLO:close(“option httpclose”):连接在响应结束时关闭,并在两个方向上都附加“Connection: close”。有效模式将应用于通过前端和后端连接的连接,这些模式可由两个代理模式根据以下矩阵确定,但简而言之,模式是对称的,keep-alive 是最弱的选项,close 是最强的。后端模式 | KAL | SCL | CLO ----+-----+-----+---- KAL | KAL | SCL | CLO ----+-----+-----+---- mode SCL | SCL | SCL | CLO ----+-----+-----+---- CLO | CLO | CLO | CLO

4.1. 代理关键字矩阵

支持以下关键字列表。它们中的大多数只能在有限的段落类型中使用。其中一些被标记为“已弃用”,因为它们继承自一个可能令人困惑或功能有限的旧语法,并且有新的推荐关键字来替换它们。 标有“(*)”的关键字可以选择性地使用“no”前缀进行反转,例如“no option contstats”。当该选项默认启用并且必须为特定实例禁用时,这样做是有意义的。此类选项也可以使用“default”前缀,以便恢复默认设置,而不管之前的“defaults”段落中指定了什么。
关键字defaultsfrontendlistenbackend
acl XXX
backlogXXX 
balanceX XX
bind XX 
bind-processXXXX
capture cookie XX 
capture request header XX 
capture response header XX 
compressionXXXX
cookieX XX
declare capture XX 
default-serverX XX
default_backendXXX 
description XXX
disabledXXXX
dispatch  XX
email-alert fromXXXX
email-alert levelXXXX
email-alert mailersXXXX
email-alert myhostnameXXXX
关键字defaultsfrontendlistenbackend
email-alert toXXXX
enabledXXXX
errorfileXXXX
errorfilesXXXX
errorlocXXXX
errorloc302XXXX
errorloc303XXXX
force-persist  XX
filter XXX
fullconnX XX
graceXXXX
hash-typeX XX
http-after-response XXX
http-check commentX XX
http-check connectX XX
http-check disable-on-404X XX
http-check expectX XX
http-check sendX XX
http-check send-stateX XX
http-check set-varX XX
关键字defaultsfrontendlistenbackend
http-check unset-varX XX
http-errorXXXX
http-request XXX
http-response XXX
http-reuseX XX
http-send-name-headerX XX
id XXX
ignore-persist  XX
load-server-state-from-fileX XX
(*)logXXXX
log-formatXXX 
log-format-sdXXX 
log-tagXXXX
max-keep-alive-queueX XX
max-session-srv-connsXXX 
maxconnXXX 
modeXXXX
monitor fail XX 
monitor-netXXX 
monitor-uriXXX 
关键字defaultsfrontendlistenbackend
(*)option abortoncloseX XX
(*)option accept-invalid-http-requestXXX 
(*)option accept-invalid-http-responseX XX
(*)option allbackupsX XX
(*)option checkcacheX XX
(*)option clitcpkaXXX 
(*)option contstatsXXX 
(*)option disable-h2-upgradeXXX 
(*)option dontlog-normalXXX 
(*)option dontlognullXXX 
option forwardforXXXX
(*)option h1-case-adjust-bogus-clientXXX 
(*)option h1-case-adjust-bogus-serverX XX
(*)option http-buffer-requestXXXX
(*)option http-ignore-probesXXX 
(*)option http-keep-aliveXXXX
(*)option http-no-delayXXXX
(*)option http-pretend-keepaliveX XX
option http-restrict-req-hdr-namesXXXX
(*)option http-server-closeXXXX
关键字defaultsfrontendlistenbackend
(*)option http-use-proxy-headerXXX 
option httpchkX XX
(*)option httpcloseXXXX
option httplogXXX 
(*)option http_proxyXXXX
(*)option independent-streamsXXXX
option ldap-checkX XX
option external-checkX XX
(*)option log-health-checksX XX
(*)option log-separate-errorsXXX 
(*)option logasapXXX 
option mysql-checkX XX
(*)option nolingerXXXX
option originaltoXXXX
(*)option persistX XX
option pgsql-checkX XX
(*)option prefer-last-serverX XX
(*)option redispatchX XX
option redis-checkX XX
option smtpchkX XX
关键字defaultsfrontendlistenbackend
(*)option socket-statsXXX 
(*)option splice-autoXXXX
(*)option splice-requestXXXX
(*)option splice-responseXXXX
option spop-checkX XX
(*)option srvtcpkaX XX
option ssl-hello-chkX XX
option tcp-checkX XX
(*)option tcp-smart-acceptXXX 
(*)option tcp-smart-connectX XX
option tcpkaXXXX
option tcplogXXXX
(*)option transparentX XX
external-check commandX XX
external-check pathX XX
persist rdp-cookieX XX
rate-limit sessionsXXX 
redirect XXX
retriesX XX
retry-onX XX
关键字defaultsfrontendlistenbackend
server  XX
server-state-file-nameX XX
server-template  XX
sourceX XX
stats admin XXX
stats authXXXX
stats enableXXXX
stats hide-versionXXXX
stats http-request XXX
stats realmXXXX
stats refreshXXXX
stats scopeXXXX
stats show-descXXXX
stats show-legendsXXXX
stats show-nodeXXXX
stats uriXXXX
stick match  XX
stick on  XX
stick store-request  XX
stick store-response  XX
关键字defaultsfrontendlistenbackend
stick-table XXX
tcp-check commentX XX
tcp-check connectX XX
tcp-check expectX XX
tcp-check sendX XX
tcp-check send-lfX XX
tcp-check send-binaryX XX
tcp-check send-binary-lfX XX
tcp-check set-varX XX
tcp-check unset-varX XX
tcp-request connection XX 
tcp-request content XXX
tcp-request inspect-delay XXX
tcp-request session XX 
tcp-response content  XX
tcp-response inspect-delay  XX
timeout checkX XX
timeout clientXXX 
timeout client-finXXX 
timeout connectX XX
关键字defaultsfrontendlistenbackend
timeout http-keep-aliveXXXX
timeout http-requestXXXX
timeout queueX XX
timeout serverX XX
timeout server-finX XX
timeout tarpitXXXX
timeout tunnelX XX
(已弃用)transparentX XX
unique-id-formatXXX 
unique-id-headerXXX 
use_backend XX 
use-fcgi-app  XX
use-server  XX

4.2. 按字母排序的关键字参考

本节提供了每个关键字及其用法的描述。
acl <aclname> <criterion> [flags] [operator] <value> ...
声明或完成一个访问控制列表。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
示例
acl invalid_src src 0.0.0.0/7 224.0.0.0/3 acl invalid_src src_port 0:1023 acl local_dst hdr(host) -i localhost
有关 ACL 的用法,请参见第 7 节
backlog <conns>
向系统提供关于期望的监听队列(backlog)大致大小的提示。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<conns> 是待处理连接的数量。根据操作系统的不同,它可能表示已确认的连接数、未确认的连接数或两者之和。
为了防范 SYN 洪水攻击,一种解决方案是增加系统的 SYN 队列大小。根据系统的不同,有时它只能通过系统参数进行调整,有时根本无法调整,有时系统依赖于应用程序在调用 listen() 系统调用时给出的提示。默认情况下,HAProxy 将前端的 maxconn 值传递给 listen() 系统调用。在可以利用此值的系统上,有时能够指定一个不同的值会很有用,因此有了这个 backlog 参数。在 Linux 2.4 上,该参数被系统忽略。在 Linux 2.6 上,它被用作一个提示,系统最多接受不小于该值的最小的 2 的幂次方,并且永远不会超过某些限制(通常是 32768)。
balance <algorithm> [ <arguments> ]
balance url_param <param> [check_post]
定义在后端中使用的负载均衡算法。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<algorithm> 是在进行负载平衡时用于选择服务器的算法。这仅在没有可用持久性信息或连接被重新调度到另一台服务器时适用。<algorithm> 可以是以下之一: roundrobin 根据其权重轮流使用每台服务器。当服务器的处理时间保持平均分配时,这是最平滑、最公平的算法。此算法是动态的,这意味着可以随时调整服务器权重,例如用于慢启动。它在设计上限制为每个后端最多 4095 台活动服务器。请注意,在某些大型集群中,当一台服务器在短暂宕机后恢复正常时,可能需要几百个请求才能将其重新集成到集群中并开始接收流量。虽然很少见,但这是正常的。在此处指明,以防您有机会观察到它,以免您担心。 static-rr 根据其权重轮流使用每台服务器。此算法与 roundrobin 非常相似,只是它是静态的,这意味着随时更改服务器权重将无效。另一方面,它对服务器数量没有设计限制,并且当服务器启动时,在完全重新计算映射后,它总是会立即重新集成到集群中。它运行也使用稍少的 CPU(约 -1%)。 leastconn 连接数最少的服务器接收连接。在相同负载的服务器组之间执行轮循,以确保所有服务器都被使用。建议在预期会话时间很长的情况下使用此算法,例如 LDAP、SQL、TSE 等……但不太适合使用短会话协议(如 HTTP)的场景。此算法是动态的,这意味着可以随时调整服务器权重,例如用于慢启动。 first 具有可用连接槽的第一台服务器接收连接。服务器按从最低数字标识符到最高数字标识符(请参阅服务器参数“id”),默认为服务器在集群中的位置)进行选择。一旦服务器达到其 maxconn 值,就会使用下一台服务器。不设置 maxconn 而使用此算法没有意义。此算法的目的是始终使用最少数量的服务器,以便在非高峰时段关闭额外的服务器。此算法忽略服务器权重,并且比 HTTP 更适合 RDP 或 IMAP 等长会话,尽管它在那里也可能有用。为了有效地使用此算法,建议云控制器定期检查服务器使用情况,在未使用时关闭服务器,并在集群膨胀时定期检查后端队列以启动新服务器。或者,使用“http-check send-state”可能会通知服务器的负载情况。 source 源 IP 地址被哈希并除以运行服务器的总权重,以指定哪台服务器将接收请求。只要没有服务器宕机或启动,这就能确保同一客户端 IP 地址始终到达同一台服务器。如果由于运行服务器数量的变化导致哈希结果发生变化,许多客户端将被定向到不同的服务器。此算法通常在不支持插入 cookie 的 TCP 模式下使用。它也可以在 Internet 上使用,为拒绝会话 cookie 的客户端提供尽力而为的粘性。此算法默认是静态的,这意味着随时更改服务器权重将无效,但可以使用“hash-type”进行更改。 uri 该 URI 的左侧部分(在问号之前)或整个 URI(如果存在“whole”参数)被哈希,并除以运行服务器的总权重。结果指定哪台服务器将接收请求。这用于代理缓存和防病毒代理,以最大化缓存命中率。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着随时更改服务器权重将无效,但可以使用“hash-type”进行更改。此算法支持两个可选参数“len”和“depth”,后面都跟一个正整数。当需要仅基于 URI 的开头来平衡服务器时,这些选项可能很有用。“len”参数表示算法仅考虑 URI 开头的字符数来计算哈希。请注意,“len”设置为 1 很少有意义,因为大多数 URI 都以斜杠“/”开头。“depth”参数表示用于计算哈希的最大目录深度。对于请求中的每个斜杠,算作一个级别。如果同时指定了这两个参数,则在达到任一参数时停止评估。“path-only”参数表示哈希键从路径的第一个“/”开始。这可用于忽略绝对 URI 的主机部分,并确保 HTTP/1 和 HTTP/2 URI 提供相同的哈希。 url_param 将在参数中指定的 URL 参数会在每个 HTTP GET 请求的查询字符串中查找。如果使用了“check_post”修改器,则当参数在 URL 的问号(“?”)之后未在查询字符串中找到时,会搜索 HTTP POST 请求实体。消息正文将在收到广告的数据量或请求缓冲区已满后开始分析。在极少数情况下使用分块编码时,仅扫描第一个块。由块边界分隔的参数值可能会被随机平衡(如果存在)。此关键字过去支持一个可选的 <max_wait> 参数,现在已被忽略。如果找到该参数后跟等号(“=”)和值,则对该值进行哈希处理并除以运行服务器的总权重。结果指定哪台服务器将接收请求。这用于跟踪请求中的用户标识符,并确保相同的用户 ID 只要服务器不出现宕机或启动,就会始终发送到同一台服务器。如果未找到值或未找到参数,则应用轮循算法。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着随时更改服务器权重将无效,但可以使用“hash-type”进行更改。 hdr(<name>) HTTP 标头 <name> 将在每个 HTTP 请求中查找。与等效的 ACL 'hdr()' 函数一样,括号中的标头名称不区分大小写。如果标头不存在或不包含任何值,则改为应用 roundrobin 算法。提供了一个可选的“use_domain_only”参数,用于将哈希算法缩小到主域部分,对于某些特定标头(如“Host”)来说。例如,在主机值“haproxy.1wt.eu”中,只考虑“1wt”。此算法默认是静态的,这意味着随时更改服务器权重将无效,但可以使用“hash-type”进行更改。 random random(<draws>) 将使用一个随机数作为一致性哈希函数的键。这意味着服务器的权重会得到尊重,动态权重更改会立即生效,新服务器的添加也会如此。随机负载平衡在大型集群或服务器频繁添加或删除的情况下可能很有用,因为它可能会避免在此情况下由 roundrobin 或 leastconn 引起的敲击效应。hash-balance-factor 指令可用于进一步提高负载平衡的公平性,特别是在服务器显示高度可变的响应时间的情况下。当存在参数 <draws> 时,它必须是大于等于 1 的整数值,表示在选择这些服务器中负载最低的服务器之前进行的抽样次数。事实上,已经证明选择两台服务器中负载最低的服务器足以显著提高算法的公平性,因为它总是避免选择集群中最加载的服务器,并消除一致列表分布不均可能引起的任何偏差。较高的值 N 将以性能为代价,剔除 N-1 台负载最高的服务器。对于非常高的值,算法将收敛到 leastconn 的结果,但速度慢得多。默认值为 2,通常显示非常好的分布和性能。此算法也称为“两次随机选择的强大性”,并在以下位置进行了描述:http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf rdp-cookie rdp-cookie(<name>) RDP cookie <name>(如果省略则为“mstshash”)将在每个传入的 TCP 请求中查找并进行哈希处理。与等效的 ACL 'req.rdp_cookie()' 函数一样,名称不区分大小写。此机制用作降级的持久性模式很有用,因为它可以使相同的用户(或相同的会话 ID)始终发送到同一台服务器。如果未找到 cookie,则改为使用正常的轮循算法。请注意,要使其正常工作,前端必须确保请求缓冲区中已存在 RDP cookie。为此,您必须使用“tcp-request content accept”规则并结合“req.rdp_cookie_cnt”ACL。此算法默认是静态的,这意味着随时更改服务器权重将无效,但可以使用“hash-type”进行更改。 <arguments> 是某些算法可能需要的可选参数列表。目前,只有“url_param”和“uri”支持可选参数。
当没有设置其他算法、模式或选项时,后端的负载均衡算法被设置为 roundrobin。每个后端只能设置一次算法。对于需要相同连接的认证方案(如 NTLM),不得使用基于 URI 的算法,因为它们会导致后续请求被路由到不同的后端服务器,从而破坏 NTLM 所依赖的无效假设。
示例
balance roundrobin balance url_param userid balance url_param session_id check_post 64 balance hdr(User-Agent) balance hdr(host) balance hdr(Host) use_domain_only
注意:使用“check_post”扩展与“url_param”的以下注意事项和限制必须予以考虑: - 所有 POST 请求都有资格被考虑,因为无法确定参数是位于主体还是可能包含二进制数据的实体中。因此,可能需要另一种方法来限制对主体中没有 URL 参数的 POST 请求的考虑。(请参阅 acl http_end) - 使用大于请求缓冲区大小的 <max_wait> 值没有意义且无用。缓冲区大小在构建时设置,默认为 16 kB。 - 不支持 Content-Encoding,参数搜索可能会失败;负载平衡将回退到 Round Robin。 - 不支持 Expect: 100-continue,负载平衡将回退到 Round Robin。 - Transfer-Encoding (RFC7230 3.3.1) 仅在第一个块中受支持。如果参数的完整值不在第一个块中,则服务器的选择是不确定的(实际上,由第一个块中实际出现的多少决定)。 - 此功能不支持生成 100、411 或 501 响应。 - 在某些情况下,请求“check_post”可能会尝试扫描消息主体的全部内容。扫描通常在找到线性空白字符或控制字符时终止,这表明 URL 参数列表可能已结束。对于 SGML 类型消息主体,这可能不是问题。
bind [<address>]:<port_range> [, ...] [param*]
bind /<path> [, ...] [param*]
在前端(frontend)中定义一个或多个监听地址和/或端口。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<address> 是可选的,可以是主机名、IPv4 地址、IPv6 地址或“*”。它指定了前端将侦听的地址。如果未设置,则将侦听系统的所有 IPv4 地址。“*”或系统的特殊地址“0.0.0.0”也将执行此操作。 IPv6 等效项是 '::'。可选地,可以在地址前使用地址族前缀来强制使用该地址族,无论地址格式如何,这对于使用不带斜杠(“/”)的路径指定 Unix 套接字很有用。当前支持的前缀是: - 'ipv4@' -> 地址始终为 IPv4 - 'ipv6@' -> 地址始终为 IPv6 - 'unix@' -> 地址是本地 Unix 套接字的路径 - 'abns@' -> 地址在抽象命名空间(仅限 Linux)。注意:由于抽象套接字不能“重新绑定”,因此它们在软重启期间与多进程模式配合不佳,因此最好避免在 nbproc 大于 1 时使用它们。其效果是,如果新进程启动失败,只有旧进程之一能够重新绑定到套接字。 - 'fd@<n>' -> 使用从父进程继承的文件描述符 <n>。fd 必须已绑定,并且可能已在侦听,也可能没有。 - 'sockpair@<n>'-> 类似于 fd@,但您必须使用已连接的 Unix 套接字或套接字对的 fd。bind 等待通过 Unix 套接字接收 FD,并将其用作 accept() 的 FD。应谨慎使用。您可能希望在地址参数中引用某些环境变量,请参阅 第 2.3 节关于环境变量。 <port_range> 是一个唯一的 TCP 端口,或者是一个端口范围,代理将接受指定 IP 地址的连接。对于 TCP 侦听器,端口是必需的。请注意,在 IPv6 地址的情况下,端口始终是最后一个冒号 (':') 之后的数字。范围可以是: - 数值端口(例如:'80') - 以连字符分隔的端口范围,明确说明下限和上限(例如:'2000-2100'),这些端口包含在范围内。必须特别注意端口范围,因为每个 <address:port> 对都会消耗一个套接字(=一个文件描述符),因此很容易通过一个简单的范围消耗大量描述符,并耗尽套接字。此外,每个 <address:port> 对在同一系统上运行的所有实例中必须只使用一次。请注意,绑定到低于 1024 的端口通常需要特定的权限才能启动程序,这独立于 'uid' 参数。 <path> 是以斜杠 ('/') 开头的 UNIX 套接字路径。这是 TCP 侦听端口的替代方案。然后 HAProxy 将在位于该位置的套接字上接收 UNIX 连接。路径必须以斜杠开头,并且默认是绝对路径。它可以相对于全局部分中由“unix-bind”定义的目录。请注意,目录前缀和套接字路径的总长度不能超过 UNIX 套接字的一些系统限制,这些限制通常设置为 107 个字符。 <param*> 是同一行中声明的所有套接字的参数列表。这些众多参数取决于操作系统和构建选项,并且有一个专门的部分用于它们。请参阅 第 5 节了解更多详情。
可以指定由逗号分隔的地址:端口组合列表。然后前端将侦听所有这些地址。前端可以侦听的地址和端口数量没有固定限制,前端中的“bind”语句的数量也没有限制。
示例
listen http_proxy bind :80,:443 bind 10.0.0.1:10080,10.0.0.1:10443 bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy listen http_https_proxy bind :80 bind :443 ssl crt /etc/haproxy/site.pem listen http_https_proxy_explicit bind ipv6@:80 bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen external_bind_app1 bind "fd@${FD_APP1}"
注意:关于 Linux 的抽象命名空间套接字,HAProxy 使用整个 sun_path 长度作为地址长度。其他一些程序,如 socat,默认只使用字符串长度。在 socat 中对任何抽象套接字定义传递选项 ",unix-tightsocklen=0",以使其与 HAProxy 兼容。
bind-process [ all | odd | even | <进程号>[-[<进程号>]] ] ...
将一个实例的可见性限制在特定的进程号集合中。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
all 所有进程都将看到此实例。这是默认设置。它可用于覆盖默认值。 odd 此实例将在进程 1、3、5、...、63 上启用。此选项可与其他数字组合使用。 even 此实例将在进程 2、4、6、...、64 上启用。此选项可与其他数字组合使用。如果进程少于 2 个,请不要使用它,否则某些实例可能会在所有进程中都缺失。 process_num 此实例将在此进程号或范围内启用,其值必须全部在 1 到 32 或 64 之间,具体取决于机器的字长。范围可以部分定义。可以省略上限。在这种情况下,它将被相应的最大值替换。如果一个代理被绑定到大于配置的 global.nbproc 的进程号,如果指定了单个进程,它将被强制到进程 #1,否则将被强制到所有进程。
此关键字限制某些实例绑定到某些进程。这对于避免过多的进程侦听同一端口很有用。例如,在双核机器上,可以在全局部分设置 'nbproc 2',然后将侦听器分配给 'odd' 和 'even' 实例。目前,无法使用此关键字引用超过 32 或 64 个进程,但这对于大多数设置来说应该足够了。请注意,'all' 实际上意味着所有进程,无论机器的字长如何,并且不限于前 32 或 64 个。每个“bind”行可能进一步限制为代理进程的子集,请参阅 第 5.1 节中的“process”bind 关键字。当前端没有显式的“bind-process”行时,它会尝试绑定到其“bind”行引用的所有进程。这意味着前端可以轻松适应其侦听器的进程。如果某些后端被绑定到其他进程的前端引用,则后端会自动继承前端的进程。
示例
listen app_ip1 bind 10.0.0.1:80 bind-process odd listen app_ip2 bind 10.0.0.2:80 bind-process even listen management bind 10.0.0.3:80 bind-process 1 2 3 4 listen management bind 10.0.0.4:80 bind-process 1-4
capture cookie <name> len <length>
在请求和响应中捕获并记录一个 cookie。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<name> 是要捕获的 cookie 名称的开头。为了精确匹配名称,只需在名称后加上一个等号('=')。完整的名称将出现在日志中,这对于会同时调整 cookie 名称和值的应用服务器(例如 ASPSESSIONXXX)很有用。<length> 是日志中报告的最大字符数,包括 cookie 名称、等号和值,全部采用标准的 "name=value" 格式。如果字符串超过 <length>,它将被从右侧截断。
仅捕获第一个 cookie。将监视“cookie”请求标头和“set-cookie”响应标头。这对于检查导致用户之间会话交叉或窃取的应用程序错误特别有用,因为通常用户的 cookie 只能在登录页面上更改。当客户端未提供 cookie 时,关联的日志列将报告“-”。当请求未导致服务器分配 cookie 时,响应列中将报告“-”。捕获仅在前端执行,因为日志格式对于给定前端根据后端保持不变是必要的。这将来可能会更改。请注意,前端中只能有一个“capture cookie”语句。最大捕获长度由全局“tune.http.cookielen”设置确定,默认为 63 个字符。无法在“defaults”部分中指定捕获。
示例
capture cookie ASPSESSION len 32
capture request header <name> len <length>
捕获并记录指定请求头的最后一次出现。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在请求中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <length>,它将被从右侧截断。
捕获最后一个标头的完整值。该值将以花括号 ('{}') 包围添加到日志中。如果捕获了多个标头,它们将用竖线 ('|') 分隔,并按照它们在配置中声明的顺序出现。不存在的标头将仅记录为空字符串。请求标头捕获的常见用途包括:虚拟托管环境中的“Host”字段,“Content-length”(当支持上传时),“User-agent”(以快速区分真实用户和机器人),以及代理环境中的“X-Forwarded-For”(以查找请求的来源)。请注意,在捕获“User-agent”等标头时,可能会记录一些空格,从而使日志分析更加困难。因此,如果您知道您的日志解析器不够智能,无法依赖花括号,请谨慎记录您记录的内容。对捕获的请求标头数量及其长度没有限制,但最好保持较低的限制以限制每个会话的内存使用。为了保持同一前端的日志格式一致,标头捕获只能在前端声明。无法在“defaults”部分中指定捕获。
示例
capture request header Host len 15 capture request header X-Forwarded-For len 15 capture request header Referer len 15
capture response header <name> len <length>
捕获并记录指定响应头的最后一次出现。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在响应中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <length>,它将被从右侧截断。
捕获该头最后一次出现的完整值。结果将在捕获的请求头之后,添加在日志中的大括号 ('{}') 之间。如果捕获了多个头,它们将由竖线 ('|') 分隔,并按照它们在配置中声明的相同顺序出现。不存在的头将被记录为空字符串。响应头捕获的常见用途包括 "Content-length" 头,它指示预计将返回多少字节,以及 "Location" 头,用于跟踪重定向。捕获的响应头数量及其长度没有限制,但明智的做法是保持它们较低以限制每个会话的内存使用。为了保持同一前端的日志格式一致,头捕获只能在前端声明。不能在 "defaults" 配置段中指定捕获。
示例
capture response header Content-length len 9 capture response header Location len 15
compression algo <algorithm> ...
compression type <mime type> ...
启用 HTTP 压缩。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
algo 后面是支持的压缩算法列表。type 后面是将要被压缩的 MIME 类型列表。offload 使 haproxy 仅作为压缩卸载器工作(见说明)。
当前支持的算法包括: identity 这主要是为了调试,并且在开发压缩功能时很有用。Identity 不对数据进行任何更改。 gzip 应用 gzip 压缩。此设置仅在构建时支持 zlib 或 libslz 时可用。 deflate 与“gzip”相同,但使用 deflate 算法和 zlib 格式。请注意,此算法在许多浏览器上的支持存在歧义,并且最新浏览器完全不支持。强烈建议不要将其用于除实验以外的任何用途。此设置仅在构建时支持 zlib 或 libslz 时可用。 raw-deflate 与“deflate”相同,但没有 zlib 包装器,并且在浏览器需要“deflate”时用作替代。所有主流浏览器都理解它,尽管违反了标准,但它比“deflate”效果更好,至少在 MSIE 和某些版本的 Safari 上是如此。请勿将其与“deflate”结合使用,只能选择其中一种,因为它们都对相同的 Accept-Encoding 令牌做出反应。此设置仅在构建时支持 zlib 或 libslz 时可用。压缩将根据 Accept-Encoding 请求标头激活。使用 identity 时,它不考虑该标头。如果后端服务器支持 HTTP 压缩,这些指令将不起作用:haproxy 将看到压缩响应,而不会再次压缩。如果后端服务器不支持 HTTP 压缩且请求中存在 Accept-Encoding 标头,则 haproxy 将压缩匹配的响应。“offload”设置使 haproxy 删除 Accept-Encoding 标头,以防止后端服务器压缩响应。强烈建议不要这样做,因为这意味着所有压缩工作都将在 haproxy 所在的一个点上完成。然而,在某些部署场景中,haproxy 可能安装在有缺陷的网关前面,该网关具有无法关闭的损坏的 HTTP 压缩实现。在这种情况下,haproxy 可用于防止该网关发出无效的有效负载。在这种情况下,仅仅在配置中删除标头不起作用,因为它在标头被解析之前就应用了,因此阻止了 haproxy 进行压缩。在这种情况下,应使用“offload”设置。注意:目前,“offload”设置在 defaults 部分设置时将被忽略。压缩将被禁用,原因如下: * 请求不在“Accept-Encoding”标头中声明受支持的压缩算法 * 响应消息不是 HTTP/1.1 或更高版本 * HTTP 状态码不是 200、201、202 或 203 之一 * 响应既不包含“Content-Length”标头也不包含“Transfer-Encoding”,其最后一个值为“chunked” * 响应包含“Content-Type”标头,其第一个值以“multipart”开头 * 响应在“Cache-control”标头中包含“no-transform”值 * User-Agent 匹配“Mozilla/4”,除非它是带有 XP SP2 的 MSIE 6,或 MSIE 7 及更高版本 * 响应包含“Content-Encoding”标头,指示响应已压缩(请参阅压缩卸载) * 响应包含无效的“ETag”标头或多个 ETag 标头注意:压缩不发出 Warning 标头。
示例
compression algo gzip compression type text/html text/plain
cookie <名称> [ rewrite | insert | prefix ] [ indirect ] [ nocache ] [ postonly ] [ preserve ] [ httponly ] [ secure ] [ domain <域名> ]* [ maxidle <空闲时间> ] [ maxlife <生命周期> ] [ dynamic ] [ attr <值> ]*
在后端启用基于 cookie 的持久性。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<name> 是要监控、修改或插入以实现持久性的 cookie 的名称。此 cookie 通过响应中的“Set-Cookie”标头发送到客户端,并在所有请求中通过“Cookie”标头由客户端带回。应特别注意选择一个不会与任何可能的应用程序 cookie 冲突的名称。此外,如果相同的后端将由相同的客户端使用(例如 HTTP/HTTPS),则应注意在所有后端之间使用不同的 cookie 名称,除非希望在它们之间实现持久性。rewrite 此关键字表示 cookie 将由服务器提供,并且 haproxy 将必须修改其值以在其内设置服务器标识符。当“Set-cookie”和“Cache-control”标头等复杂组合的管理留给应用程序处理时,此模式非常方便。然后,应用程序可以决定是否发出持久性 cookie 是合适的。由于应监控所有响应,因此此模式在 HTTP 隧道模式下不起作用。除非应用程序行为非常复杂和/或损坏,否则建议在新部署时不要从此模式开始。此关键字与“insert”和“prefix”不兼容。insert 此关键字表示,如果客户端尚未拥有允许其访问该服务器的 cookie,则 haproxy 将必须将持久性 cookie 插入服务器响应中。当未使用“preserve”选项使用时,如果服务器发出具有相同名称的 cookie,它将在处理前被删除。因此,此模式可用于升级以“rewrite”模式运行的现有配置。cookie 将仅成为一个会话 cookie,不会存储在客户端的磁盘上。默认情况下,除非添加了“indirect”选项,否则服务器将看到客户端发出的 cookie。由于缓存效果,通常明智的做法是添加“nocache”或“postonly”关键字(见下文)。“insert”关键字与“rewrite”和“prefix”不兼容。prefix 此关键字表示,不是依赖于专用的持久性 cookie,而是将完成一个现有的 cookie。在某些不支持单个 cookie 的特定环境中,并且应用程序已需要它时,这可能是必需的。在这种情况下,每当服务器设置一个名为 <name> 的 cookie 时,它都会被服务器标识符和一个分隔符前缀。前缀将从所有客户端请求中删除,以便服务器仍然找到它发出的 cookie。由于所有请求和响应都可能被修改,因此此模式在隧道模式下不起作用。“prefix”关键字与“rewrite”和“insert”不兼容。注意:强烈建议不要将“indirect”与“prefix”一起使用,否则服务器 cookie 更新将不会发送给客户端。indirect 当指定此选项时,不会向已拥有该服务器的有效 cookie 的客户端发出 cookie。如果服务器本身设置了此类 cookie,它将被删除,除非还设置了“preserve”选项。在“insert”模式下,这还将从传输到服务器的请求中删除 cookie,从而使持久性机制从应用程序的角度完全透明。注意:强烈建议不要将“indirect”与“prefix”一起使用,否则服务器 cookie 更新将不会发送给客户端。nocache 此选项建议与 insert 模式结合使用,当客户端和 HAProxy 之间存在缓存时,因为它确保可缓存响应将被标记为不可缓存,如果需要插入 cookie。这很重要,因为如果所有持久性 cookie 都添加到例如可缓存的主页上,那么所有客户将从外部缓存中获取页面,并将共享相同的持久性 cookie,导致一个服务器接收比其他服务器更多的流量。另请参阅“insert”和“postonly”选项。postonly 此选项确保 cookie 插入仅在对 POST 请求的响应中执行。它是“nocache”选项的替代方案,因为 POST 响应是不可缓存的,因此这确保了持久性 cookie 永远不会被缓存。由于大多数网站在第一个 POST(通常是登录请求)之前不需要任何类型的持久性,因此这是一种优化缓存而不会冒在缓存中找到持久性 cookie 的风险的高效方法。另请参阅“insert”和“nocache”选项。preserve 此选项只能与“insert”和/或“indirect”一起使用。它允许服务器本身发出持久性 cookie。在这种情况下,如果在响应中找到 cookie,haproxy 将保持不变。这对于在注销请求后结束持久性很有用。为此,服务器只需发出一个无效值(例如,空)或一个过去日期的 cookie。通过将此机制与“disable-on-404”检查选项结合使用,可以执行完全优雅的关闭,因为用户在注销后肯定会离开服务器。httponly 此选项指示 haproxy 在插入 cookie 时添加“HttpOnly”cookie 属性。此属性用于防止用户代理与非 HTTP 组件共享 cookie。有关此属性的更多信息,请查阅 RFC6265。secure 此选项指示 haproxy 在插入 cookie 时添加“Secure”cookie 属性。此属性用于防止用户代理通过不安全的通道发出此 cookie,这意味着带有此标志学习到的 cookie 将仅在 SSL/TLS 连接上呈现。有关此属性的更多信息,请查阅 RFC6265。domain 此选项允许指定插入 cookie 的域。它需要一个参数:一个有效的域名。如果域以点开头,则允许浏览器将其用于以该名称结尾的任何主机。也可以通过多次调用此选项来指定多个域名。某些浏览器可能对域名数量有限制,因此请谨慎使用。为了记录,将 10 个域发送到 MSIE 6 或 Firefox 2 可以按预期工作。maxidle 此选项允许在一段时间闲置后忽略插入的 cookie。它仅适用于 insert-mode cookie。当 cookie 发送给客户端时,也会发送发出该 cookie 的日期。在进一步呈现此 cookie 时,如果日期比参数指示的延迟(以秒为单位)更旧,则将被忽略。否则,在将响应发送给客户端时,如有必要,将刷新它。这对于防止从不关闭浏览器的用户在同一服务器上停留过长时间(例如,在农场大小更改后)特别有用。设置此选项时,如果没有日期的 cookie,它总是被接受,但在响应中刷新。这使得管理员能够访问他们的站点。未来 24 小时以上的日期 cookie 将被忽略。这样做可以使管理员在不冒将用户踢出站点风险的情况下修复时区问题。maxlife 此选项允许在一段时间后忽略插入的 cookie,无论它们是否在使用中。它仅适用于 insert 模式 cookie。当 cookie 首次发送到客户端时,也会发送发出该 cookie 的日期。在进一步呈现此 cookie 时,如果日期比参数指示的延迟(以秒为单位)更旧,则将被忽略。如果请求中的 cookie 没有日期,则接受它并将设置日期。未来 24 小时以上的日期 cookie 将被忽略。这样做可以使管理员在不冒将用户踢出站点风险的情况下修复时区问题。与 maxidle 不同,此值不会刷新,只有第一次访问日期才算。maxidle 和 maxlife 都可以在此时使用。这对于防止从不关闭浏览器的用户在同一服务器上停留过长时间(例如,在农场大小更改后)特别有用。这比 maxidle 方法更强,因为它强制在某个绝对延迟后重新分发。dynamic 激活动态 cookie。使用时,将根据服务器的 IP 和端口以及在“dynamic-cookie-key”后端指令中指定的密钥,为每个服务器动态创建一个会话 cookie。每次 IP 地址更改时,cookie 都将重新生成,并且仅为 IPv4/IPv6 生成。attr 此选项指示 haproxy 在插入 cookie 时添加一个额外的属性。属性值可以包含除控制字符或“;”之外的任何字符。此选项可以重复。
<name> 是现有 http-errors 部分的名称。<code> 是一个 HTTP 状态码。可以列出多个状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、413、425、429、500、502、503 和 504 的代码。
示例
cookie JSESSIONID prefix cookie SRV insert indirect nocache cookie SRV insert postonly indirect cookie SRV insert indirect nocache maxidle 30m maxlife 8h
declare capture [ request | response ] len <length>
声明一个捕获槽。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<length> 是允许捕获的长度。
此声明仅在 frontend 或 listen 配置段中可用,但保留的槽可以在 backend 中使用。“request”关键字分配一个用于请求中的捕获槽,“response”分配一个用于响应中的捕获槽。
更改后端中服务器的默认选项。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<param*> 是此服务器的参数列表。“default-server”关键字接受大量选项,并有专门的完整章节介绍。更多详情请参阅 第 5 节
示例
default-server inter 1000 weight 13
default_backend <backend>
指定在没有匹配到“use_backend”规则时使用的后端。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<backend> 是要使用的后端的名称。
在使用“use_backend”关键字在前端和后端之间进行内容切换时,指明在没有规则匹配时将使用哪个后端通常很有用。这通常是动态后端,它将捕获所有未确定的请求。
示例
use_backend dynamic if url_dyn use_backend static if url_css url_img extension_img default_backend dynamic
description <string>
描述一个 listen、frontend 或 backend。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
参数: string
允许添加一句话来在 HAProxy HTML 统计页面中描述相关对象。该描述将打印在其所描述对象名称的右侧。<string> 参数中的空格无需使用反斜杠转义。
禁用一个 proxy、frontend 或 backend。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
disabled”关键字用于禁用实例,主要目的是释放监听端口或临时禁用服务。实例仍将被创建,其配置将得到检查,但它将被创建为“stopped”状态,并在统计信息中显示为这样。它不会接收任何流量,也不会发送任何健康检查或日志。通过在“defaults”部分添加“disabled”关键字,可以同时禁用多个实例。
dispatch <address>:<port>
设置一个默认服务器地址

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
dispatch”关键字指定一个默认服务器,用于在没有其他服务器可以接收连接时使用。过去,它被用来将非持久性连接转发到一个辅助负载均衡器。由于其语法简单,它也被用于简单的 TCP 中继。为了更清晰,建议不要使用它,而是使用“server”指令。
dynamic-cookie-key <字符串>
为后端设置动态 cookie 的密钥。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数: 要使用的密钥。
当启用动态 cookie 时(参见 cookie 的 "dynamic" 指令),会为每个服务器创建一个动态 cookie(除非在“server”行上明确指定了一个),使用服务器的 IP 地址、TCP 端口和密钥的哈希值。这样,我们可以确保跨多个负载均衡器的会话持久性,即使服务器是动态添加或删除的。
启用一个 proxy、frontend 或 backend。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
enabled”关键字用于显式启用一个实例,当 defaults 设置为“disabled”时。这很少使用。
errorfile <code> <file>
返回文件内容以替代 HAProxy 生成的错误

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、413、425、429、500、502、503 和 504 的代码。<file> 指定一个包含完整 HTTP 响应的文件。建议遵循将“.http”附加到文件名上的常见做法,以便人们不会将响应与 HTML 错误页面混淆,并使用绝对路径,因为文件在执行任何 chroot 之前就被读取。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测到并返回的错误。这就是为什么支持的错误列表仅限于一小部分。代码 200 是响应匹配“monitor-uri”规则的请求而生成的。文件在 HAProxy 启动时解析,并且必须根据 HTTP 规范有效。它们不应超过配置的缓冲区大小(BUFSIZE),通常为 16 kB,否则将返回内部错误。明智的做法是不包含任何对本地内容的引用(例如图像),以避免在所有服务器都关闭时客户端和 HAProxy 之间的循环,导致返回错误而不是图像。最后,响应不能超过(tune.bufsize - tune.maxrewrite),以便“http-after-response”规则仍有操作空间(请参阅“tune.maxrewrite”)。文件在配置解析时读取并保存在内存中。因此,即使进程被 chroot,错误也会继续返回,并且在进程运行时不会考虑文件更改。开发这些文件的一个简单方法是将它们与 403 状态码关联,并查询一个被阻止的 URL。
示例
errorfile 400 /etc/haproxy/errorfiles/400badreq.http errorfile 408 /dev/null # 解决 Chrome 预连接的 bug errorfile 403 /etc/haproxy/errorfiles/403forbid.http errorfile 503 /etc/haproxy/errorfiles/503sorry.http
errorfiles <名称> [<状态码> ...]
全部或部分导入在 <name> http-errors 区域中定义的错误文件。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<name> 是一个现有的 http-errors 部分的名称。<code> 是一个 HTTP 状态码。可以列出多个状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、413、425、429、500、502、503 和 504 的代码。
在 http-errors 部分中以名称 <name> 定义的错误将被导入到当前代理中。如果未指定状态码,则 http-errors 部分的所有错误文件都将被导入。否则,只有与所列状态码关联的错误文件才会被导入。这些错误文件会覆盖代理已定义的自定义错误。并且它们可能会被后续的错误文件覆盖。从功能上讲,这与使用 “errorfile” 指令手动声明所有错误文件完全相同。
示例
errorfiles generic errorfiles site-1 403 404
errorloc <code> <url>
errorloc302 <code> <url>
返回一个到某个 URL 的 HTTP 重定向,以替代 HAProxy 生成的错误

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、413、425、429、500、502、503 和 504 的代码。<url> 是“Location”标头中的确切内容。它可以包含指向同一站点上错误页面的相对 URI,或者指向另一个站点上错误页面的绝对 URI。对于相对 URI,应给予特别关注,以避免重定向循环,如果 URI 本身可能会生成相同的错误(例如 500)。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 302 状态码,它告诉客户端使用相同的 HTTP 方法获取指定的 URL。对于非 GET 方法(如 POST),这可能会很有问题,因为发送给客户端的 URL 可能不允许 GET 以外的方法。要解决此问题,请使用“errorloc303”,它会发送 HTTP 303 状态码,指示客户端必须使用 GET 请求获取该 URL。
errorloc303 <code> <url>
返回一个到某个 URL 的 HTTP 重定向,以替代 HAProxy 生成的错误

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、413、425、429、500、502、503 和 504 的代码。<url> 是“Location”标头中的确切内容。它可以包含指向同一站点上错误页面的相对 URI,或者指向另一个站点上错误页面的绝对 URI。对于相对 URI,应给予特别关注,以避免重定向循环,如果 URI 本身可能会生成相同的错误(例如 500)。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 303 状态码,它告诉客户端使用相同的 HTTP GET 方法获取指定的 URL。这解决了与“errorloc”和 302 状态码相关的常见问题。一些在 HTTP/1.1 之前设计的非常旧的浏览器可能不支持它,但到目前为止还没有报告过此类问题。
email-alert from <emailaddr>
声明用于电子邮件警报的信封和头部的发件人电子邮件地址。这是发送电子邮件警报的来源地址。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<emailaddr> 是发送电子邮件警报时使用的发件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明将发送电子邮件警报的消息的最大日志级别。这充当发送电子邮件警报的过滤器。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<level> 8 个 syslog 级别之一:emerg alert crit err warning notice info debug 以上 syslog 级别从低到高排序。
默认级别是 alert。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。在以下情况下会发送警报: * 一个未暂停的服务器被标记为 down 且 <level> 是 alert 或更低 * 一个已暂停的服务器被标记为 down 且 <level> 是 notice 或更低 * 一个服务器被标记为 up 或进入 drain 状态且 <level> 是 notice 或更低 * 启用了“option log-health-checks”,<level> 是 info 或更低,并且发生了健康检查状态更新
email-alert mailers <mailersect>
声明发送电子邮件警报时要使用的邮件程序

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<mailersect> 是用于发送电子邮件警报的邮件程序部分的名称。
还需要设置“email-alert from”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明与邮件程序通信时要使用的主机名地址。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<hostname> 是与邮件程序通信时使用的主机名
默认使用系统的主机名。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
email-alert to <emailaddr>
声明邮件警报信封中的收件人地址和邮件头中的 to 地址。这是邮件警报发送到的地址。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<emailaddr> 是发送电子邮件警报时使用的收件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
force-persist { if | unless } <condition>
声明一个条件以强制在宕机服务器上保持持久性

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
默认情况下,请求不会分发到宕机服务器。可以使用“option persist”强制执行此操作,但它是无条件的,并且在设置了“option redispatch”的情况下会重新分发到有效服务器。这留下了很少的可能性来强制某些请求到达一个被人为标记为宕机以进行维护操作的服务器。“force-persist”语句允许声明各种基于 ACL 的条件,当满足这些条件时,将导致请求忽略服务器的宕机状态并仍然尝试连接到它。这使得可以启动一个服务器,它仍然对健康检查返回错误,并运行一个特制的浏览器来测试服务。在方便的方法中,可以使用特定的源 IP 地址或特定的 cookie。cookie 的另一个优点是可以轻松地从测试页面添加到/从浏览器中删除。一旦服务得到验证,就可以通过对健康检查返回有效响应来向全世界开放服务。当满足“if”条件时,将启用强制持久性,或者除非满足“unless”条件。使用此选项时,最终的重新分发始终是禁用的。
filter <名称> [参数*]
将过滤器 <name> 添加到附加到代理的过滤器列表中。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
参数
<name> 是过滤器的名称。官方支持的过滤器在第 9 节中引用。<param*> 是过滤器 <name> 接受的参数列表。这些参数的解析是过滤器的责任。有关支持的参数的所有详细信息,请参阅相应过滤器(第 9 节)的文档。
对于同一个代理,可以多次使用 filter 行。如果需要,可以多次引用同一个过滤器。
示例
listen bind *:80 filter trace name BEFORE-HTTP-COMP filter compression filter trace name AFTER-HTTP-COMP compression algo gzip compression offload server srv1 192.168.0.1:80
fullconn <conns>
指定后端负载达到何种程度时服务器将达到其 maxconn

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<conns> 是后端上的连接数,该连接数将使服务器使用最大连接数。
当服务器指定了“maxconn”参数时,意味着其并发连接数永远不会超过该值。此外,如果它有“minconn”参数,则表示一个动态限制,遵循后端的负载。然后,服务器将始终至少接受 <minconn> 个连接,永远不超过 <maxconn> 个连接,并且当后端具有少于 <conns> 个并发连接时,限制将在这两个值之间爬升。这使得可以在正常负载下限制服务器上的负载,但在后端负载较高时可以将其进一步推高,而不会在异常负载期间使服务器过载。由于很难获得正确的值,haproxy 会自动将其设置为可能分支到此后端的 HAPROXY 的所有前端的最大连接数之和的 10%(基于“use_backend”和“default_backend”规则)。这样,即使不设置它也是安全的。但是,涉及动态名称的“use_backend”不被计算在内,因为无法知道它们是否匹配。
示例
# 服务器将接受 100 到 1000 个并发连接 # 当后端达到 10000 个连接时,将达到 1000 的最大值。 backend dynamic fullconn 10000 server srv1 dyn1:80 minconn 100 maxconn 1000 server srv2 dyn2:80 minconn 100 maxconn 1000
grace <time>
在软停止后,维持代理在一段时间内可操作

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<time> 是当通过 SIGUSR1 信号接收到软停止时,实例将保持可操作且前端套接字仍在监听的时间(默认为毫秒)。
这可以用来确保服务按特定顺序消失。它被设计成这样,专用于外部设备监控的前端会立即失败,而其他前端则会保持运行,直到设备检测到故障所需的时间。请注意,目前使用此参数的好处非常小,实际上它可能会使软重新配置过程复杂化,而不是简化它。
指定有界负载一致性哈希的平衡因子

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

no

yes
参数
<factor> 是控制发送到服务器的最大并发请求数的参数,表示为所有活动服务器上平均并发请求数的百分比。
为具有“hash-type consistent”的服务器指定“hash-balance-factor”会启用一种算法,该算法可以防止任何一个服务器一次获取过多的请求,即使某些哈希存储桶接收的请求比其他存储桶多得多。将 <factor> 设置为 0(默认值)会禁用该功能。否则,<factor> 是一个大于 100 的百分比。例如,如果 <factor> 为 150,则任何服务器的负载都不会超过平均值的 1.5 倍。如果使用了服务器权重,它们将得到尊重。如果第一个选择的服务器被取消资格,算法将根据请求的哈希选择另一个服务器,直到找到一个具有额外容量的服务器。较高的 <factor> 允许服务器之间的不平衡度更大,而较低的 <factor> 意味着平均而言会检查更多的服务器,从而影响性能。合理的值范围是 125 到 200。此设置也由“balance random”使用,它内部依赖于一致性哈希机制。
hash-type <method> <function> <modifier>
指定一种将哈希值映射到服务器的方法

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<method> 是用于从 <function> 计算的哈希中选择服务器的方法:map-based 哈希表是一个包含所有活动服务器的静态数组。哈希将非常平滑,会考虑权重,但会是静态的,这意味着当服务器处于运行状态时权重更改将被忽略。这意味着将没有慢启动。另外,由于服务器是根据其在数组中的位置选择的,因此当服务器计数更改时,大多数映射都会更改。这意味着当服务器启动或关闭,或者当服务器添加到集群时,大多数连接将被重新分发到不同的服务器。这对于缓存等情况可能不方便。consistent 哈希表是一个填充了服务器多个实例的树。查找哈希键并在树中选择最近的服务器。此哈希是动态的,支持在服务器运行时更改权重,因此与慢启动功能兼容。它的优点是当服务器启动或关闭时,只有它的关联被移动。当服务器添加到集群时,只有一小部分映射被重新分发,这使其成为缓存的理想方法。然而,由于其原理,分布永远不会非常平滑,有时可能需要调整服务器的权重或 ID 以获得更均衡的分布。为了在多个负载均衡器上获得相同的分布,所有服务器具有完全相同的 ID 很重要。注意:如果未指定哈希函数,一致性哈希将使用 sdbm 和 avalanche。<function> 是要使用的哈希函数:sdbm 此函数最初是为 sdbm(ndbm 的公共域重新实现)数据库库创建的。它被发现能够很好地打乱位,从而更好地分布键并减少分裂。它也恰好是一个很好的通用哈希函数,具有良好的分布,除非总服务器权重是 64 的倍数,在这种情况下,应用 avalanche 修饰符可能会有帮助。djb2 此函数由 Dan Bernstein 多年前在 comp.lang.c 上提出。研究表明,对于某些工作负载,此函数比 sdbm 提供更好的分布。它通常适用于基于文本的输入,尽管它在纯数字输入时表现极差,或者当总服务器权重是 33 的倍数时,除非也使用了 avalanche 修饰符。wt6 此函数是在过去测试其他函数时为 haproxy 设计的。它不如其他函数平滑,但对输入数据集或服务器数量的敏感度较低。它可以用作一致性哈希或对数字数据(如源 IP 地址或 URL 参数中的访问者标识符)进行哈希时 sdbm+avalanche 或 djb2+avalanche 的替代方案。crc32 这是以太网、gzip、PNG 等中使用的最常见的 CRC32 实现。它比其他实现慢,但在对字符串进行哈希时可能提供更好的分布或更不可预测的结果。<modifier> 指示在对键进行哈希之后应用的可选方法:avalanche 此指令表示上述哈希函数的 the result 不会以原始形式使用,而是首先应用一个 4 字节的 full avalanche hash。此步骤的目的是混合前一个哈希的结果位,以避免在输入包含某些受限值或服务器数量是哈希分量(SDBM 为 64,DJB2 为 33)的倍数时产生任何不良影响。启用 avalanche 倾向于使结果更不可预测,但它也不如使用原始函数那样平滑。可能需要对某些工作负载进行一些测试。此哈希是由 Bob Jenkins 提出的众多哈希之一。
默认的哈希类型是“map-based”,建议在大多数情况下使用。默认的函数是“sdbm”,函数的选择应基于被哈希值的范围。
http-after-response <动作> <选项...> [ { if | unless } <条件> ]
对所有第 7 层响应(服务器、小程序/服务和内部响应)进行访问控制。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
http-after-response 语句定义了一组应用于第 7 层处理的规则。规则在它们被声明的顺序中进行评估,当它们在 frontend、listen 或 backend 部分遇到时。任何规则都可以选择性地跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时才会对其进行评估。由于这些规则应用于响应,因此 backend 规则首先应用,然后是 frontend 的规则。与 http-response 规则不同,这些规则应用于所有响应,包括服务器响应以及 HAProxy 生成的所有响应。这些规则在响应分析结束时,在数据转发之前进行评估。第一个关键字是规则的 action。支持的 actions 如下所述。每个实例的 http-after-response 语句的数量没有限制。
示例
http-after-response set-header Strict-Transport-Security "max-age=31536000" http-after-response set-header Cache-Control "no-store,no-cache,private" http-after-response set-header Pragma "no-cache"
http-after-response add-header <name> <fmt> [ { if | unless } <condition> ]
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由遵循日志格式规则的 <fmt> 定义(参见 第 8.2.4 节中的自定义日志格式)。例如,这可用于向客户端发送 cookie,或传递一些内部信息。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
http-after-response allow [ { if | unless } <condition> ]
此操作停止规则的评估,并让响应通过检查。不再评估任何后续的“http-after-response”规则。
http-after-response del-header <name> [ -m <meth> ] [ { if | unless } <condition> ]
此操作移除所有名称在 <name> 中指定的 HTTP 标头字段。<meth> 是应用于标头名称的匹配方法。支持的匹配方法有“str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子串匹配)和“reg”(正则表达式匹配)。如果未指定,则使用精确匹配方法。
http-after-response replace-header <name> <regex-match> <replace-fmt> [ { if | unless } <condition> ]
此操作的工作方式类似于“http-response replace-header”。
示例
http-after-response replace-header Set-Cookie (C=[^;]*);(.*) \1;ip=%bi;\2 # 应用于: Set-Cookie: C=1; expires=Tue, 14-Jun-2016 01:40:45 GMT # 输出: Set-Cookie: C=1;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT # 假设后端 IP 是 192.168.1.20。
http-after-response replace-value <name> <regex-match> <replace-fmt> [ { if | unless } <condition> ]
此操作的工作方式类似于“http-response replace-value”。
示例
http-after-response replace-value Cache-control ^public$ private # 应用于: Cache-Control: max-age=3600, public # 输出: Cache-Control: max-age=3600, private
http-after-response set-header <name> <fmt> [ { if | unless } <condition> ]
这与 "add-header" 的作用相同,只是如果头名称已存在,会先将其删除。当向服务器传递安全信息,且该头不能被外部用户操纵时,这很有用。
http-after-response set-status <status> [reason <str>] [ { if | unless } <condition> ]
这将用 <status> 替换响应状态码,该值必须是 100 到 999 之间的整数。可以选择性地提供由 <str> 定义的自定义原因文本,否则将使用指定状态码的默认原因作为后备。
示例
# 返回 "431 Request Header Fields Too Large" http-response set-status 431 # 返回 "503 Slow Down",自定义原因 http-response set-status 503 reason "Slow Down"
<a class="anchor" name="http-after-response set-var"></a><a href="#4.2-http-after-response%20set-var">http-after-response set-var</a>(<span style="color: #080"><var-name></span>) <span style="color: #080"><expr></span> <span style="color: #008">[ <span style="color: #800">{ if | unless }</span> <span style="color: #080"><condition></span> ]</span>
此操作用于设置变量的内容。变量是内联声明的。
参数
<var-name> 变量名以其作用域的指示开头。允许的作用域有: “proc”:变量与整个进程共享 “sess”:变量与整个会话共享 “txn”:变量与事务(请求和响应)共享 “req”:变量仅在请求处理期间共享 “res”:变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。 <expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
http-after-response set-var(sess.last_redir) res.hdr(location)
这将为后续规则启用或禁用严格重写模式。它不影响在其之前声明的规则,并且仅适用于对响应执行重写的规则。当启用严格模式时,任何重写失败都会触发内部错误。否则,此类错误将被静默忽略。严格重写模式的目的是使一些重写是可选的,而另一些则必须执行才能继续响应处理。默认情况下,严格重写模式是启用的。其值在规则集评估结束时也会被重置。因此,例如,如果您在后端更改了模式,当 HAProxy 开始前端规则评估时,会恢复默认模式。
http-after-response unset-var(<var-name>) [ { if | unless } <condition> ]
这用于取消设置一个变量。有关 <var-name> 的详细信息,请参见“http-after-response set-var”。
示例
http-after-response unset-var(sess.last_redir)
http-check comment <字符串>
为接下来的 http-check 规则定义一条注释,如果检查失败,该注释将在日志中报告。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<string> 是如果以下 http-check 规则失败时要在日志中添加的注释消息。
它仅适用于 connect、send 和 expect 规则。这对于进行用户友好的错误报告很有用。
http-check connect [default] [port <表达式>] [addr <ip>] [send-proxy] [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger] [proto <名称>] [comment <消息>]
打开一个新连接以执行 HTTP 健康检查

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义一个在规则评估失败时报告的消息。default 使用服务器行的默认选项进行健康检查。仅当未重新定义时才使用服务器选项。port <expr> 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 连接到哪里。<port> 必须是一个有效的 TCP 端口源整数,范围从 1 到 65535 或一个 sample-fetch 表达式。addr <ip> 定义进行健康检查的 IP 地址。send-proxy 使用 socks4 代理发送 PROXY 协议字符串启用出站健康检查。ssl 打开一个加密连接。sni <sni> 指定要用于 SSL 健康检查的 SNI。alpn <alpn> 定义要使用 ALPN 声明的协议。协议列表由逗号分隔的协议名称组成,例如:“h2,http/1.1”。如果未设置,则使用服务器 ALPN。proto <name> 强制用于此连接的多路复用器协议。它必须是 HTTP MUX 协议,并且必须在后端端可用。可用协议列表在 haproxy -vv 中报告。linger 干净地关闭连接而不是使用单个 RST。
就像 tcp-check 健康检查一样,可以配置用于执行 HTTP 健康检查的连接。此指令也应用于描述涉及多个请求/响应交换的场景,可能在不同的端口上或与不同的服务器。当服务器行上既没有配置 TCP 端口,也没有服务器端口指令时,http-check 序列的第一步必须是使用 “http-check connect” 指定端口。在一个 http-check 规则集中,'connect' 是必需的,并且也必须以 'connect' 规则开始规则集。目的是确保管理员知道他们在做什么。当一个 connect 必须开始规则集时,它前面仍然可以有 set-var、unset-var 或 comment 规则。
示例
# 检查服务器上的 HTTP 和 HTTPs 服务。 # 首先通过服务器行端口指令打开端口 80,然后 # tcp-check 打开端口 443,加密并在其上运行请求: option httpchk http-check connect http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu http-check expect status 200-399 http-check connect port 443 ssl sni haproxy.1wt.eu http-check send meth GET uri / ver HTTP/1.1 hdr host haproxy.1wt.eu http-check expect status 200-399 server www 10.0.0.1 check port 80
在对健康检查响应 HTTP/404 时启用维护模式

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当设置此选项时,返回 HTTP 404 状态码的服务器将从进一步的负载均衡中排除,但仍会接收持久连接。这为 Web 管理员提供了一种非常方便的方法来优雅地关闭他们的服务器。同样重要的是要注意,在此模式下被检测为失败的服务器不会生成警报,只会生成一个通知。如果服务器再次响应 2xx 或 3xx,它将立即被重新插入到服务器组中。在统计页面上,处于此模式的服务器状态报告为“NOLB”。重要的是要注意,此选项仅与“httpchk”选项一起使用。如果此选项与“http-check expect”一起使用,则它优先于后者,因此 404 响应仍将被视为软停止。
http-check expect [min-recv <整数>] [comment <消息>] [ok-status <状态>] [error-status <状态>] [tout-status <状态>] [on-success <格式>] [on-error <格式>] [status-code <表达式>] [!] <匹配> <模式>
使 HTTP 健康检查考虑响应内容或特定状态码

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义一个在规则评估失败时报告的消息。min-recv 是可选的,并且可以定义评估当前 expect 规则所需的最少数据量。如果接收的字节数低于此限制,则检查将等待更多数据。此选项可用于解决一些歧义匹配规则或避免在已知内容仍不完整的情况下执行昂贵的正则表达式匹配。如果使用精确字符串,则使用字符串长度和此参数之间的最小值。如果此参数设置为 -1,则忽略它。如果 expect 规则不匹配,检查将等待更多数据。如果设置为 0,则评估结果始终是决定性的。ok-status <st> 是可选的,并且可用于在 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则时设置检查状态。支持“L7OK”、“L7OKC”、“L6OK”和“L4OK”:- L7OK:检查在第 7 层通过 - L7OKC:检查在第 7 层有条件通过,例如 404(带 disable-on-404) - L6OK:检查在第 6 层通过 - L4OK:检查在第 4 层通过 默认使用“L7OK”。error-status <st> 是可选的,并且可用于在 expect 规则评估期间发生错误时设置检查状态。支持“L7RSP”、“L7STS”、“L6RSP”和“L4CON”:- L7RSP:第 7 层无效响应 - 协议错误 - L7STS:第 7 层响应错误,例如 HTTP 5xx - L6RSP:第 6 层无效响应 - 协议错误 - L4CON:第 1-4 层连接问题 默认使用“L7RSP”。tout-status <st> 是可选的,并且可用于在 expect 规则评估期间发生超时时设置检查状态。支持“L7TOUT”、“L6TOUT”和“L4TOUT”:- L7TOUT:第 7 层(HTTP/SMTP)超时 - L6TOUT:第 6 层(SSL)超时 - L4TOUT:第 1-4 层超时 默认使用“L7TOUT”。on-success <fmt> 是可选的,并且可用于在 expect 规则成功评估并且它是 tcp-check 规则集中的最后一条规则时自定义日志中报告的信息性消息。<fmt> 是一个 log-format 字符串。on-error <fmt> 是可选的,并且可用于在 expect 规则评估期间发生错误时自定义日志中报告的信息性消息。<fmt> 是一个 log-format 字符串。<match> 是一个关键字,指示如何在响应中查找特定模式。该关键字可以是“status”、“rstatus”、“hdr”、“fhdr”、“string”或“rstring”之一。该关键字前面可以有一个感叹号(“!”)来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参阅下文。<pattern> 是要查找的模式。它可以是字符串、正则表达式或包含多个参数的更复杂的模式。如果字符串模式包含空格,则必须使用常规反斜杠(‘\’)进行转义。
默认情况下,“option httpchk”认为 2xx 和 3xx 的响应状态码是有效的,而其他状态码是无效的。当使用“http-check expect”时,它定义了什么被认为是有效或无效。一个后端最多支持一个“http-check”语句。如果服务器未能响应或超时,检查显然会失败。可用的匹配项是:status <codes>:测试从解析 <codes> 字符串中找到的状态码。它必须是逗号分隔的状态码或范围码列表。如果响应的状态码与列表中的任何状态码匹配或在任何范围之内,则健康检查响应将被视为有效。如果“status”关键字前带有“!”,则当状态码匹配时,响应将被视为无效。rstatus <regex>:测试 HTTP 状态码的正则表达式。如果响应的状态码与表达式匹配,则健康检查响应将被视为有效。如果“rstatus”关键字前带有“!”,则当状态码匹配时,响应将被视为无效。这主要用于检查多个状态码。hdr { name | name-lf } [ -m <meth> ] <name> [ { value | value-lf } [ -m <meth> ] <value>:测试 HTTP 响应头中的指定头模式。名称模式是必需的,但值模式是可选的。如果未指定,则仅验证头是否存在。<meth> 是匹配方法,应用于头名称或头值。支持的匹配方法有“str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子字符串匹配)或“reg”(正则表达式匹配)。如果未指定,则使用精确匹配方法。如果使用“name-lf”参数,则 <name> 被评估为日志格式字符串。如果使用“value-lf”参数,则 <value> 被评估为日志格式字符串。这些参数不能与正则表达式匹配方法一起使用。最后,头值被视为逗号分隔的列表。请注意,头名称的匹配不区分大小写。fhdr { name | name-lf } [ -m <meth> ] <name> [ { value | value-lf } [ -m <meth> ] <value>:测试 HTTP 响应头中的指定完整头模式。它的功能与“hdr”关键字完全相同,只是测试的是完整的头值,逗号不被视为分隔符。string <string>:测试 HTTP 响应体中的精确字符串匹配。如果响应体包含此精确字符串,则健康检查响应将被视为有效。如果“string”关键字前带有“!”,则当响应体包含此字符串时,响应将被视为无效。这可用于查找动态页面末尾的强制单词,或在检查页面中出现特定错误(例如堆栈跟踪)时检测失败。rstring <regex>:测试 HTTP 响应体中的正则表达式。如果响应体与表达式匹配,则健康检查响应将被视为有效。如果“rstring”关键字前带有“!”,则当响应体与表达式匹配时,响应将被视为无效。这可用于查找动态页面末尾的强制单词,或在检查页面中出现特定错误(例如堆栈跟踪)时检测失败。string-lf <fmt>:测试 HTTP 响应体中的日志格式字符串匹配。如果响应体包含通过评估 <fmt> 产生的字符串(遵循日志格式规则),则健康检查响应将被视为有效。如果前面带有“!”,则当响应体包含该字符串时,响应将被视为无效。需要注意的是,响应将被限制在全局“tune.bufsize”选项定义的特定大小内,该选项默认为 16384 字节。因此,过大的响应在使用“string”或“rstring”时可能不包含强制模式。如果绝对需要大响应,可以通过设置全局变量来更改默认最大大小。但是,要记住,解析非常大的响应可能会浪费一些 CPU 周期,尤其是在使用正则表达式时,而且最好将检查集中在较小的资源上。在 http-check 规则集中,最后一个 expect 规则可能是隐式的。如果在最后一个“http-check send”之后没有指定 expect 规则,则会定义一个隐式 expect 规则来匹配 2xx 或 3xx 状态码。这意味着即使根本没有“http-check”规则,只有“option httpchk”被设置时,也会定义此规则。最后,如果“http-check expect”与“http-check disable-on-404”结合使用,则当服务器响应 404 时,后者具有优先权。
示例
# 只接受状态码 200 为有效 http-check expect status 200,201,300-310 # 确保设置了 sessid cookie http-check expect header name "set-cookie" value -m beg "sessid=" # 将 SQL 错误视为错误 http-check expect ! string SQL\ Error # 仅将 5xx 状态码视为错误 http-check expect ! rstatus ^5 # 检查在 /html 之前是否有正确的十六进制标签 http-check expect rstring <!--tag:[0-9a-f]*--></html>
http-check send [meth <method>] [{ uri <uri> | uri-lf <fmt> }>] [ver <version>] [hdr <name> <fmt>]* [{ body <string> | body-lf <fmt> }] [comment <msg>]
在 HTTP 健康检查期间,向发送的请求添加可能的头信息列表和/或一个主体。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义一条消息,如果规则评估失败则报告。meth <method> 是与请求一起使用的可选 HTTP 方法。未设置时,使用“OPTIONS”方法,因为它通常需要较少的服务器处理,并且易于从日志中过滤掉。可以使用任何方法,但不建议使用非标准方法。uri <uri> 是可选的,并将 HTTP 请求中引用的 URI 设置为字符串 <uri>。它默认为“/”,几乎所有服务器都默认可访问,但可以更改为任何其他 URI。允许使用查询字符串。uri-lf <fmt> 是可选的,并使用日志格式字符串 <fmt> 设置 HTTP 请求中引用的 URI。它默认为“/”,几乎所有服务器都默认可访问,但可以更改为任何其他 URI。允许使用查询字符串。ver <version> 是可选的 HTTP 版本字符串。它默认为“HTTP/1.0”,但某些服务器在 HTTP 1.0 下行为可能不正确,因此将其切换为 HTTP/1.1 有时可能有所帮助。请注意,HTTP/1.1 中 Host 字段是必需的,请使用“hdr”参数添加。hdr <name> <fmt> 添加 HTTP 头字段,其名称在 <name> 中指定,其值由 <fmt> 定义,后者遵循日志格式规则。body <string> 将由 <string> 定义的请求体添加到 HTTP 健康检查期间发送的请求中。如果定义了,则“Content-Length”头会自动添加到请求中。body-lf <fmt> 将由日志格式字符串 <fmt> 定义的请求体添加到 HTTP 健康检查期间发送的请求中。如果定义了,则“Content-Length”头会自动添加到请求中。
除了“option httpchk”指令定义的请求行之外,这是在 HTTP 健康检查期间发送的请求中添加一些头和可选体的一种有效方式。如果定义了体,则会自动添加关联的“Content-Length”头。因此,此头或“Transfer-encoding”头不应出现在“http-check send”提供的请求中。如果出现,将被忽略。“http-check send”之后在版本字符串上添加头的旧技巧现在已弃用。此外,“http-check send”不支持 HTTP 持久连接。请注意,它会自动附加“Connection: close”头,除非通过 hdr 条目已配置了 Connection 头。请注意,Host 头和请求的 authority(当两者都定义时)会自动同步。这意味着当发送 HTTP 请求时,当 Host 被插入请求中时,请求的 authority 会相应更新。因此,如果 Host 头的值覆盖了配置的请求 authority,请不要惊讶。另请注意,目前在 HTTP/1.1 或更高版本的请求中不会自动添加 Host 头。您应该显式添加它。
启用在 HTTP 健康检查中发送状态头

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当设置此选项时,haproxy 将系统地发送一个特殊的头“X-Haproxy-Server-State”,其中包含一组参数,指示每个服务器如何被 haproxy 看到。例如,当一个服务器在没有访问 haproxy 的情况下被操作,并且操作员需要知道 haproxy 是否仍然认为它在线,或者服务器是否是集群中的最后一个时,可以使用此选项。该头由分号分隔的字段组成,第一个字段是一个单词(“UP”、“DOWN”、“NOLB”),可能后跟一个数字,表示在转换之前有效检查的总数,正如在统计界面中显示的那样。接下来的头形式为“<variable>=<value>”,按任意顺序表示统计界面中可用的一些值:- 变量“address”,包含后端服务器的地址。这对应于服务器声明中的 <address> 字段。对于 unix 套接字,它将读取“unix”。- 变量“port”,包含后端服务器的端口。这对应于服务器声明中的 <port> 字段。对于 unix 套接字,它将读取“unix”。- 变量“name”,包含后端名称,后跟斜杠(“/”)然后是服务器名称。当服务器在多个后端中进行检查时,可以使用此变量。- 变量“node”包含 haproxy 节点的名称,如全局“node”变量中设置的,否则为未指定的系统主机名。- 变量“weight”指示服务器的权重,一个斜杠(“/”)和集群的总权重(仅计算可用服务器)。这有助于在当前服务器失败时了解是否有其他服务器可用以处理负载。- 变量“scur”指示服务器上当前的并发连接数,后跟一个斜杠(“/”)然后是同一后端所有服务器上的总连接数。- 变量“qcur”指示服务器队列中当前请求数。应用程序服务器收到的头示例:>>> X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \ scur=13/22; qcur=0
<a class="anchor" name="http-check set-var"></a><a href="#4.2-http-check%20set-var">http-check set-var</a>(<span style="color: #080"><var-name></span>) <span style="color: #080"><expr></span>
此操作设置变量的内容。变量是内联声明的。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量的名称以其范围的指示开头。http-check 允许的范围是:“proc”:变量与整个进程共享。“sess”:变量与 tcp-check 会话共享。“check”:变量为 tcp-check 的生命周期声明。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '-'。<expr> 是一个样本抓取表达式,后面可能跟着转换器。
示例
http-check set-var(check.port) int(1234)
在其作用域内释放对变量的引用。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量的名称以其作用域的指示开头。http-check 允许的作用域有: “proc”:变量在整个进程中共享。 “sess”:变量在 tcp-check 会话中共享。 “check”:变量在 tcp-check 的生命周期内声明。 此前缀后跟一个名称。分隔符是‘.’。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '-'。
示例
http-check unset-var(check.port)
http-error status <code> [content-type <type>] [ { default-errorfiles | errorfile <file> | errorfiles <name> | file <file> | lf-file <file> | string <str> | lf-string <fmt> } ] [ hdr <name> <fmt> ]*
定义一个自定义错误消息,以替代 HAProxy 生成的错误。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
status <code> 是 HTTP 状态码。它必须指定。目前,HAProxy 能够生成 200、400、401、403、404、405、407、408、410、413、425、429、500、502、503 和 504 的状态码。content-type <type> 是响应内容类型,例如“text/plain”。当配置了 errorfile 或负载为空时,此参数将被忽略并应省略。否则,必须定义它。default-errorfiles 重置当前代理先前为状态码 <code> 定义的错误消息。如果用于后端,则使用前端错误消息(如果已定义)。如果用于前端,则使用默认错误消息。errorfile <file> 指定一个包含完整 HTTP 响应的文件。建议遵循将“.http”附加到文件名上的常见做法,以便人们不会将响应与 HTML 错误页面混淆,并使用绝对路径,因为文件在执行任何 chroot 之前被读取。errorfiles <name> 指定要使用的 http-errors 部分,以导入状态码 <code> 的错误消息。如果找不到此类消息,则考虑代理的错误消息。file <file> 指定用作响应负载的文件。如果文件不为空,则必须将其 content-type 设置为“content-type”的参数,否则将忽略任何“content-type”参数。<file> 被视为原始字符串。string <str> 指定用作响应负载的原始字符串。content-type 必须始终设置为“content-type”的参数。lf-file <file> 指定用作响应负载的文件。如果文件不为空,则必须将其 content-type 设置为“content-type”的参数,否则将忽略任何“content-type”参数。<file> 被评估为日志格式字符串。lf-string <str> 指定用作响应负载的日志格式字符串。content-type 必须始终设置为“content-type”的参数。hdr <name> <fmt> 将 HTTP 头字段添加到响应中,其名称在 <name> 中指定,其值由 <fmt> 定义,后者遵循日志格式规则。如果使用 errorfile,则忽略此参数。
此指令可用于代替“errorfile”来定义自定义错误消息。与“errorfile”指令一样,它用于 HAProxy 检测并返回的错误。如果定义了 errorfile,则在 HAProxy 启动时进行解析,并且必须根据 HTTP 标准有效。生成的响应不得超过配置的缓冲区大小(BUFFSIZE),否则将返回内部错误。最后,如果您考虑使用一些 http-after-response 规则来重写这些错误,则应可用预留的缓冲区空间(参见“tune.maxrewrite”)。文件在配置读取时同时读取并保存在内存中。因此,即使在进程被 chroot 之后,错误也会继续返回,并且在进程运行时不考虑文件更改。
http-request <action> [options...] [ { if | unless } <condition> ]
第 7 层请求的访问控制

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
http-request 语句定义了一组适用于第 7 层处理的规则。当在 frontend、listen 或 backend 部分遇到规则时,将按声明顺序对其进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有在条件为真时才会对其进行评估。第一个关键字是规则的操作。支持的操作如下所述。每个实例的 http-request 语句数量没有限制。
示例
acl nagios src 192.168.129.3 acl local_net src 192.168.0.0/16 acl auth_ok http_auth(L1) http-request allow if nagios http-request allow if local_net auth_ok http-request auth realm Gimme if local_net auth_ok http-request deny
示例
acl key req.hdr(X-Add-Acl-Key) -m found acl add path /addacl acl del path /delacl acl myhost hdr(Host) -f myhost.lst http-request add-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key add http-request del-acl(myhost.lst) %[req.hdr(X-Add-Acl-Key)] if key del
示例
acl value req.hdr(X-Value) -m found acl setmap path /setmap acl delmap path /delmap use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found } http-request set-map(map.lst) %[src] %[req.hdr(X-Value)] if setmap value http-request del-map(map.lst) %[src] if delmap
http-request add-acl(<file-name>) <key fmt> [ { if | unless } <condition> ]
此操作用于向 ACL 中添加一个新条目。ACL 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集新条目的内容。它在插入前会先在 ACL 中进行查找,以避免重复(或更多)的值。此查找通过线性搜索完成,对于大列表可能会很耗费资源!它等同于 stats socket 中的“add acl”命令,但可以由 HTTP 请求触发。
http-request add-header <name> <fmt> [ { if | unless } <condition> ]
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循日志格式规则(请参阅 第 8.2.4 节 中的自定义日志格式)。这对于向服务器传递特定于连接的信息(例如,客户端的 SSL 证书)或将多个头部合并为一个特别有用。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
http-request allow [ { if | unless } <condition> ]
这会停止规则的评估,并允许请求通过检查。不再评估其他“http-request”规则。
http-request auth [realm <realm>] [ { if | unless } <condition> ]
这会停止规则的评估,并立即以 HTTP 401 或 407 错误代码响应,以提示用户提供有效的用户名和密码。不再评估任何进一步的“http-request”规则。支持可选的“realm”参数,它设置响应中返回的认证域(通常是应用程序的名称)。使用相应的代理错误消息。可以使用“errorfile”或“http-error”指令进行自定义。对于 401 响应,所有 WWW-Authenticate 头都将被删除,并替换为一个带有基本认证挑战的新头,用于域“<realm>”。对于 407 响应,Proxy-Authenticate 头上执行相同的操作。如果错误消息不应被修改,请考虑使用“http-request return”规则而不是。
示例
acl auth_ok http_auth_group(L1) G1 http-request auth unless auth_ok
http-request cache-use <name> [ { if | unless } <condition> ]
请参阅关于缓存设置的第 6.2 节
http-request capture <sample> [ len <length> | id <id> ] [ { if | unless } <condition> ]
这会从请求缓冲区捕获样本表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。结果字符串存储在下一个请求的“capture”槽中,因此它可能会出现在一些捕获的 HTTP 头旁边。它将自动出现在日志中,并且可以使用样本获取规则将其提取出来以馈送到头或任何其他地方。长度应受限制,因为在整个会话生命周期中,每个捕获都将分配此大小。请查看 第 7.3 节(获取样本)和“capture request header”以获取更多信息。如果使用“id”关键字而不是“len”,则操作会尝试将捕获的字符串存储在先前声明的捕获槽中。这对于在后端运行捕获很有用。槽 id 可以由之前的指令“http-request capture”或使用“declare capture”关键字声明。在后端使用此操作时,请仔细检查相关的前端是否具有所需的捕获槽,否则,此规则将在运行时被忽略。由于 HAProxy 能够动态解析后端名称,因此无法在配置解析时检测到这一点。
http-request del-acl(<file-name>) <key fmt> [ { if | unless } <condition> ]
此操作用于从 ACL 中删除一个条目。ACL 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集要删除的条目的内容。它等同于 stats socket 中的“del acl”命令,但可以由 HTTP 请求触发。
http-request del-header <name> [ -m <meth> ] [ { if | unless } <condition> ]
此操作移除所有名称在 <name> 中指定的 HTTP 标头字段。<meth> 是应用于标头名称的匹配方法。支持的匹配方法有“str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子串匹配)和“reg”(正则表达式匹配)。如果未指定,则使用精确匹配方法。
http-request del-map(<file-name>) <key fmt> [ { if | unless } <condition> ]
此操作用于从 MAP 中删除一个条目。MAP 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集要删除的条目的内容。它接受一个参数:“file name”。它等同于 stats socket 中的“del map”命令,但可以由 HTTP 请求触发。
http-request deny [deny_status <status>] [ { if | unless } <condition> ]
http-request deny [ { status | deny_status } <code>] [content-type <type>] [ { default-errorfiles | errorfile <file> | errorfiles <name> | file <file> | lf-file <file> | string <str> | lf-string <fmt> } ] [ hdr <name> <fmt> ]* [ { if | unless } <condition> ]
这会停止规则的评估,并立即拒绝请求。默认情况下,返回 HTTP 403 错误。但是,可以使用与“http-request return”规则相同的语法来自定义响应。因此,请参阅“http-request return”以获取详细信息。为了兼容性,当没有定义参数,或仅定义“deny_status”时,则隐含“default-errorfiles”参数。这意味着“http-request deny [deny_status <status>]”是“http-request deny [status <status>] default-errorfiles”的别名。不再评估任何进一步的“http-request”规则。另请参阅“http-request return”。
http-request disable-l7-retry [ { if | unless } <condition> ]
此操作会禁止任何因连接失败以外的原因而重试请求的尝试。例如,这对于确保 POST 请求在失败时不会被重试非常有用。
http-request do-resolve(<var>,<resolvers>,[ipv4,ipv6]) <expr>
此操作对 <expr> 的输出执行 DNS 解析,并将结果存储在变量 <var> 中。它使用由 <resolvers> 指向的 DNS 解析器部分。可以使用可选参数 'ipv4' 或 'ipv6' 选择解析偏好。执行 DNS 解析时,客户端连接会暂停,等待解析结束。如果能找到 IP 地址,它将被存储到 <var> 中。如果发生任何类型的错误,则 <var> 不会被设置。可以使用此操作在运行时根据请求中的信息(即 Host 头部)发现服务器 IP 地址。如果此操作用于查找服务器的 IP 地址(使用 "set-dst" 操作),则后端中的服务器 IP 地址必须设置为 0.0.0.0。do-resolve 操作接受一个仅主机参数,任何端口都必须从字符串中移除。
示例
resolvers mydns nameserver local 127.0.0.53:53 nameserver google 8.8.8.8:53 timeout retry 1s hold valid 10s hold nx 3s hold other 3s hold obsolete 0s accepted_payload_size 8192 frontend fe bind 10.42.0.1:80 http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower,regsub(:[0-9]*$,) http-request capture var(txn.myip) len 40 # 当变量未设置时返回 503, # 这意味着 DNS 解析错误 use_backend b_503 unless { var(txn.myip) -m found } default_backend be backend b_503 # 用于返回 503 的虚拟后端。 # 可以使用 errorfile 指令向最终用户发送一个漂亮的 # 503 错误页面 backend be # 阻止 HAProxy 重新连接到服务以防止本地网络(伪造的 DNS 名称用于扫描网络)的规则 http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 } http-request set-dst var(txn.myip) server clear 0.0.0.0:0
注意:不要忘记设置“保护”规则,以确保 HAProxy 不会被用于扫描网络,或更糟糕的是,不会循环访问自身……
http-request early-hint <name> <fmt> [ { if | unless } <condition> ]
此操作用于在任何其他响应之前构建一个 HTTP 103 Early Hints 响应。此操作向此响应附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循日志格式规则(请参阅 第 8.2.4 节 中的自定义日志格式)。这对于向客户端传递一些 Link 头部以预加载渲染 HTML 文档所需的资源特别有用。更多信息请参阅 RFC 8297。
http-request redirect <规则> [ { if | unless } <条件> ]
此操作基于重定向规则执行 HTTP 重定向。这与“redirect”语句完全相同,只是它插入一个重定向规则,该规则可以在其他“http-request”规则中间进行处理,并且这些规则使用“log-format”字符串。有关规则的语法,请参见“redirect”关键字。
http-request reject [ { if | unless } <条件> ]
这会停止规则的评估,并立即关闭连接而不发送任何响应。它的作用类似于“tcp-request content reject”规则。强制关闭 HTTP/2 连接可能很有用。
http-request replace-header <名称> <匹配正则表达式> <替换格式> [ { if | unless } <条件> ]
此操作将头部字段 <名称> 的所有出现的值与 <匹配正则表达式> 进行匹配。匹配是区分大小写的。匹配的值将被 <替换格式> 完全替换。在 <替换格式> 中允许使用格式化字符,其工作方式类似于“http-request add-header”中的 <fmt> 参数。支持使用反斜杠 ('\') 后跟数字的标准后向引用。此操作作用于整个头部行,无论它们可能包含多少个值。因此,它非常适合处理值中自然包含逗号的头部,例如 If-Modified-Since。包含逗号分隔值列表的头部,例如 Accept,应使用“http-request replace-value”进行处理。
示例
http-request replace-header Cookie foo=([^;]*);(.*) foo=\1;ip=%bi;\2 # 应用于: Cookie: foo=foobar; expires=Tue, 14-Jun-2016 01:40:45 GMT; # 输出: Cookie: foo=foobar;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT; # 假设后端 IP 是 192.168.1.20 http-request replace-header User-Agent curl foo # 应用于: User-Agent: curl/7.47.0 # 输出: User-Agent: foo
http-request replace-path <匹配正则表达式> <替换格式> [ { if | unless } <条件> ]
此操作的工作方式类似于“replace-header”,但它作用于请求的路径组件而不是头部。路径组件从可选的协议+授权之后第一个'/'开始,到问号之前结束。因此,替换不会修改协议、授权和查询字符串。值得注意的是,正则表达式的评估可能比某些 ACL 更昂贵,因此对于罕见的替换,使用条件来避免在不匹配时执行评估可能会更有利。
示例
# 在 /foo 前加上前缀:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-path (.*) /foo\1 # 去除 /foo:将 /foo/bar?q=1 变为 /bar?q=1 http-request replace-path /foo/(.*) /\1 # 或者如果只有部分请求匹配,这样更高效: http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }
http-request replace-pathq <匹配正则表达式> <替换格式> [ { if | unless } <条件> ]
此操作与“http-request replace-path”相同,只是路径中包含了查询字符串(如果存在)。因此,路径和查询字符串都会被替换。
示例
# 在路径后添加后缀 /foo:将 /bar?q=1 变为 /bar/foo?q=1: http-request replace-pathq ([^?]*)(\?(.*))? \1/foo\2
http-request replace-uri <匹配正则表达式> <替换格式> [ { if | unless } <条件> ]
此功能与“replace-header”类似,但它作用于请求的 URI 部分而不是头。URI 部分可能包含可选的协议、权威或查询字符串。这些被视为要匹配的值的一部分。值得注意的是,正则表达式的评估成本可能比某些 ACL 更高,因此稀疏替换可能受益于条件,以避免执行评估(如果它不匹配)。重要提示:历史上在 HTTP/1.x 中,浏览器发送的大多数请求都使用“原始形式”,它与“绝对形式”不同,因为它在 URI 部分不包含协议或权威。主要是发送给代理的请求、手工伪造的请求以及某些应用程序发出的请求使用绝对形式。因此,“replace-uri”在 HTTP/1.x 中通常可以正常工作,规则以“/”开头。但是,在 HTTP/2 中,鼓励客户端仅发送绝对 URI,它们看起来像 HTTP/1 客户端与代理通信时使用的 URI。这样的部分 replace-uri 规则在 HTTP/2 中可能失败,而在 HTTP/1 中有效。规则需要进行调整以可选地匹配协议和权威,或者应使用 replace-path。
示例
# 将所有 "http" 绝对请求重写为 "https": http-request replace-uri ^http://(.*) https://\1 # 添加前缀 /foo:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2
http-request replace-value <名称> <匹配正则表达式> <替换格式> [ { if | unless } <条件> ]
此操作的工作方式类似于“replace-header”,但它将正则表达式与头部字段 <名称> 的每个逗号分隔的值进行匹配,而不是整个头部。这适用于所有允许携带多个值的头部。例如 Accept 头部。
示例
http-request replace-value X-Forwarded-For ^192\.168\.(.*)$ 172.16.\1 # 应用于: X-Forwarded-For: 192.168.10.1, 192.168.13.24, 10.0.0.37 # 输出: X-Forwarded-For: 172.16.10.1, 172.16.13.24, 10.0.0.37
http-request return [status <代码>] [content-type <类型>] [ { default-errorfiles | errorfile <文件> | errorfiles <名称> | file <文件> | lf-file <文件> | string <字符串> | lf-string <格式> } ] [ hdr <名称> <格式> ]* [ { if | unless } <条件> ]
这会停止规则的评估并立即返回响应。默认使用的状态码是 200。它可以作为“status”的参数可选地指定。响应内容类型也可以作为“content-type”的参数指定。最后,可以定义响应本身。它可以是一个完整的 HTTP 响应,指定要使用的 errorfile,或者一个响应负载,指定要使用的文件或字符串。遵循以下规则创建响应:* 如果没有定义 errorfile 或要使用的负载,则返回一个虚拟响应。仅考虑“status”参数。它可以是 [200, 599] 范围内的任何代码。“content-type”参数(如果有)将被忽略。* 如果设置了“default-errorfiles”参数,则考虑代理的 errorfiles。如果定义了“status”参数,它必须是 haproxy 处理的状态码之一(200、400、403、404、405、408、410、413、425、429、500、502、503 和 504)。“content-type”参数(如果有)将被忽略。* 如果定义了特定的 errorfile,并带有“errorfile”参数,则返回包含完整 HTTP 响应的相应文件。仅考虑“status”参数。它必须是 haproxy 处理的状态码之一(200、400、403、404、405、408、410、413、425、429、500、502、503 和 504)。“content-type”参数(如果有)将被忽略。* 如果定义了 http-errors 部分,并带有“errorfiles”参数,则返回指定 http-errors 部分中的相应文件,该文件包含完整的 HTTP 响应。仅考虑“status”参数。它必须是 haproxy 处理的状态码之一(200、400、403、404、405、408、410、413、425、429、500、502、503 和 504)。“content-type”参数(如果有)将被忽略。* 如果指定了“file”或“lf-file”参数,则文件的内容将用作响应负载。如果文件不为空,则必须将其 content-type 设置为“content-type”的参数。否则,将忽略任何“content-type”参数。“lf-file”参数的文件内容被评估为日志格式字符串。“file”参数的文件内容被视为原始内容。* 如果指定了“string”或“lf-string”参数,则定义的字符串将用作响应负载。content-type 必须始终设置为“content-type”的参数。“lf-string”参数的字符串被评估为日志格式字符串。“string”参数的字符串被视为原始字符串。当响应不基于 errorfile 时,可以使用“hdr”参数向响应添加 HTTP 头字段。否则,所有“hdr”参数都将被忽略。对于每个参数,头名称在 <name> 中指定,其值由 <fmt> 定义,后者遵循日志格式规则。请注意,生成的响应必须小于缓冲区。为了避免任何警告,当加载 errorfile 或原始文件时,为头重写保留的缓冲区空间也应可用。不再评估任何进一步的“http-request”规则。
示例
http-request return errorfile /etc/haproxy/errorfiles/200.http \ if { path /ping } http-request return content-type image/x-icon file /var/www/favicon.ico \ if { path /favicon.ico } http-request return status 403 content-type text/plain \ lf-string "Access denied. IP %[src] is blacklisted." \ if { src -f /etc/haproxy/blacklist.lst }
http-request sc-inc-gpc0(<sc-id>) [ { if | unless } <条件> ]
http-request sc-inc-gpc1(<sc-id>) [ { if | unless } <条件> ]
此操作根据由 <sc-id> 指定的粘性计数器来递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估继续。
http-request sc-set-gpt0(<sc-id>) { <整数> | <表达式> } [ { if | unless } <条件> ]
此操作根据由 <sc-id> 指定的粘性计数器和 <int>/<expr> 的值来设置 32 位无符号 GPT0 标签。预期结果为布尔值。如果发生错误,此操作将静默失败,并继续评估操作。
http-request set-dst <表达式> [ { if | unless } <条件> ]
此操作用于将目标 IP 地址设置为指定表达式的值。当 HAProxy 前面的代理重写了目标 IP,但在 HTTP 标头中提供了正确的 IP 时,或者您想为隐私目的屏蔽 IP 时,这很有用。如果要连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
http-request set-dst hdr(x-dst) http-request set-dst dst,ipmask(24)
在可能的情况下,只要地址族允许,set-dst 会保留原始目标端口,否则目标端口将被设置为 0。
http-request set-dst-port <表达式> [ { if | unless } <条件> ]
此操作用于将目标端口地址设置为指定表达式的值。如果要连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
http-request set-dst-port hdr(x-port) http-request set-dst-port int(4000)
在可能的情况下,只要地址族支持端口,set-dst-port 就会保留原始目标地址,否则它会在重写端口之前将目标地址强制设置为 IPv4 "0.0.0.0"。
http-request set-header <名称> <格式> [ { if | unless } <条件> ]
此操作与“http-request add-header”相同,只是如果头部名称已存在,则会首先删除它。这在向服务器传递安全信息时很有用,因为此时头部不应被外部用户操纵。请注意,新值是在删除之前计算的,因此可以将一个值连接到现有头部。
示例
http-request set-header X-Haproxy-Current-Date %T http-request set-header X-SSL %[ssl_fc] http-request set-header X-SSL-Session_ID %[ssl_fc_session_id,hex] http-request set-header X-SSL-Client-Verify %[ssl_c_verify] http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn] http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)] http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn] http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore] http-request set-header X-SSL-Client-NotAfter %{+Q}[ssl_c_notafter]
http-request set-log-level <级别> [ { if | unless } <条件> ]
这用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 个 syslog 级别(参见“log”关键字),加上特殊级别“silent”,它禁用此请求的日志记录。此规则不是最终规则,因此最后一个匹配的规则获胜。此规则可用于禁用来自其他设备的健康检查。
http-request set-map(<文件名>) <键格式> <值格式> [ { if | unless } <条件> ]
此操作用于向 MAP 中添加一个新条目。MAP 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它需要 2 个参数:<键格式>,它遵循日志格式规则,用于收集 MAP 键;以及 <值格式>,它遵循日志格式规则,用于收集新条目的内容。它在插入前会进行一次 MAP 查找,以避免重复(或更多)的值。此查找通过线性搜索完成,对于大型列表可能会很耗时!它等同于 stats 套接字中的“set map”命令,但可以由 HTTP 请求触发。
http-request set-mark <标记> [ { if | unless } <条件> ]
在支持的平台上,此操作将 Netfilter MARK 设置为传递给 <mark> 的值,该值将发送到客户端的所有数据包上。该值是一个无符号 32 位值,netfilter 和路由表都可以匹配。它可以表示为十进制或十六进制格式(以“0x”为前缀)。这对于强制某些数据包采用不同的路由(例如,更便宜的批量下载网络路径)非常有用。这适用于 Linux 内核 2.6.32 及更高版本,并且需要管理员权限。
http-request set-method <格式> [ { if | unless } <条件> ]
此操作使用格式化字符串 <fmt> 的求值结果来重写请求方法。这样做应该有极少数的正当理由,因为它更有可能破坏某些东西而不是修复它。
http-request set-nice <nice值> [ { if | unless } <条件> ]
这会设置正在处理的当前请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级越低。较低的值会使请求比其他请求更重要。这有助于提高某些请求的速度,或降低不重要请求的优先级。未经事先试验而使用此设置可能会导致一些严重的减速。
http-request set-path <格式> [ { if | unless } <条件> ]
此操作用格式字符串 <格式> 的评估结果重写请求路径。查询字符串(如果存在)保持不变。如果在路径之前找到协议和授权,它们也保持不变。如果请求没有路径(“*”),则此路径将被格式替换。例如,这可用于在路径前添加一个目录组件。另请参见“http-request set-query”和“http-request set-uri”。
示例
# 在路径前添加主机名 http-request set-path /%[hdr(host)]%[path]
http-request set-pathq <格式> [ { if | unless } <条件> ]
此操作与“http-request set-path”相同,只是查询字符串也会被重写。它可用于移除查询字符串,包括问号(使用“http-request set-query”是无法做到的)。
http-request set-priority-class <表达式> [ { if | unless } <条件> ]
此操作用于设置当前请求的队列优先级类别。该值必须是一个样本表达式,其转换结果为 -2047 到 2047 范围内的整数。超出此范围的结果将被截断。优先级类别决定了排队请求的处理顺序。值越低,优先级越高。
http-request set-priority-offset <表达式> [ { if | unless } <条件> ]
此操作用于设置当前请求的队列优先级时间戳偏移量。该值必须是一个样本表达式,其转换结果为 -524287 到 524287 范围内的整数。超出此范围的结果将被截断。当一个请求进入队列时,它首先按优先级类别排序,然后按当前时间戳加上给定的偏移量(以毫秒为单位)进行排序。值越低,优先级越高。请注意,结果时间戳的跟踪精度仅足以表示 524,287 毫秒(8 分 44 秒 287 毫秒)。如果请求排队时间足够长,以至于调整后的时间戳超过此值,它将被错误地识别为最高优先级。因此,将“timeout queue”设置为一个值,使其与偏移量相加后不超过此限制,这一点很重要。
http-request set-query <格式> [ { if | unless } <条件> ]
此操作用格式字符串 <格式> 的评估结果重写请求的查询字符串,即第一个问号(“?”)之后的部分。问号之前的部分保持不变。如果请求不包含问号且新值不为空,则在 URI 的末尾添加一个问号,后跟新值。如果问号已存在,即使值为空,它也永远不会被删除。这可用于从查询字符串中添加或删除参数。另请参见“http-request set-query”和“http-request set-uri”。
示例
# 在查询字符串中将“%3D”替换为“=” http-request set-query %[query,regsub(%3D,=,g)]
http-request set-src <表达式> [ { if | unless } <条件> ]
此操作用于将源 IP 地址设置为指定表达式的值。当 HAProxy 前面的代理重写了源 IP,但在 HTTP 标头中提供了正确的 IP 时,或者您想为隐私目的屏蔽源 IP 时,这很有用。所有后续对“src”的提取调用都将返回此值(见示例)。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
另请参阅“option forwardfor”。
示例
http-request set-src hdr(x-forwarded-for) http-request set-src src,ipmask(24) # 经过掩码处理后,这将根据最后字节为零的 IP 地址来跟踪连接。 http-request track-sc0 src
在可能的情况下,只要地址族允许,set-src 会保留原始源端口,否则源端口将被设置为 0。
http-request set-src-port <表达式> [ { if | unless } <条件> ]
此操作用于将源端口地址设置为指定表达式的值。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
http-request set-src-port hdr(x-port) http-request set-src-port int(4000)
在可能的情况下,只要地址族支持端口,set-src-port 就会保留原始源地址,否则它会在重写端口之前将源地址强制设置为 IPv4 "0.0.0.0"。
http-request set-tos <tos> [ { if | unless } <条件> ]
此操作用于在支持此功能的平台上,将发送给客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中传递的值。此值代表 IP TOS 字段的全部 8 位,可以用十进制或十六进制格式(以“0x”为前缀)表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的两位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474, 2597, 3260 和 4594。
http-request set-uri <格式> [ { if | unless } <条件> ]
这会使用格式字符串 <fmt> 的评估结果重写请求 URI。scheme、authority、path 和 query string 会同时被替换。这可以用于在代理前面重写主机,或对 URI 进行复杂修改,例如在 path 和 query string 之间移动部分。另请参阅 "http-request set-path" 和 "http-request set-query"。
http-request set-var(<var-name>) <expr> [ { if | unless } <condition> ]
此操作用于设置变量的内容。变量是内联声明的。
参数
<var-name> 变量的名称以作用域指示符开头。允许的作用域有:"proc" : 变量在整个进程中共享 "sess" : 变量在整个会话中共享 "txn" : 变量在整个事务(请求和响应)中共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 该前缀后跟一个名称。分隔符是"."。名称只能包含字符 'a-z', 'A-Z', '0-9' 和 '_'。 <expr> 是一个标准的 HAProxy 表达式,由一个 sample-fetch 后跟一些转换器组成。
示例
http-request set-var(req.my_var) req.fhdr(user-agent),lower
http-request send-spoe-group <引擎名称> <组名称> [ { if | unless } <条件> ]
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
参数
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
http-request silent-drop [ { if | unless } <condition> ]
这会停止规则的评估,并使用一种依赖于系统的方式使面向客户端的连接突然消失,该方式试图阻止客户端被通知。效果是客户端仍然看到一个已建立的连接,而在 HAProxy 端则没有。其目的是实现与“tarpit”类似的效果,但它不使用 HAProxy 运行的机器上的任何本地资源。它可以抵抗比“tarpit”高得多的负载,并且可以减缓更强大的攻击者。理解使用此机制的影响非常重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持连接,并可能因此受此操作的影响。在具有足够权限运行的现代 Linux 系统上,TCP_REPAIR 套接字选项用于阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 被减至 1,以便 TCP 重置不会通过第一个路由器,尽管它仍然会被传递到本地网络。除非您完全理解其工作原理,否则请勿使用它。
此操作为后续规则启用或禁用严格重写模式。它不影响在其之前声明的规则,并且仅适用于对请求执行重写的规则。当启用严格模式时,任何重写失败都会触发内部错误。否则,此类错误将被静默忽略。严格重写模式的目的是使某些重写是可选的,而其他重写必须执行才能继续请求处理。默认情况下,严格重写模式是启用的。当规则集评估结束时,其值也会被重置。因此,例如,如果您在前端更改模式,当 HAProxy 开始后端规则评估时,默认模式将被恢复。
http-request tarpit [deny_status <状态码>] [ { if | unless } <条件> ]
http-request tarpit [ { status | deny_status } <code>] [content-type <type>] [ { default-errorfiles | errorfile <file> | errorfiles <name> | file <file> | lf-file <file> | string <str> | lf-string <fmt> } ] [ hdr <name> <fmt> ]* [ { if | unless } <condition> ]
这会停止规则的评估,并立即根据“timeout tarpit”或(如果前者未设置)“timeout connect”指定的延迟来阻止请求。延迟之后,如果客户端仍然连接,则会返回响应,以便客户端不会怀疑它已被 tarpit。日志将报告标志“PT”。tarpit 规则的目标是在攻击期间减慢机器人的速度,当它们受限于并发请求的数量时。对于非常愚蠢的机器人来说,它可能非常有效,并且与 deny 规则相比,将显着减少防火墙的负载。但是,当面对“正确”开发的机器人时,它可能会使情况变得更糟,因为它会迫使 haproxy 和前端防火墙支持大量并发连接。默认情况下,返回 HTTP 错误 500。但是,可以使用与“http-request return”规则相同的语法来自定义响应。因此,请参阅“http-request return”以获取详细信息。为了兼容性,当没有定义参数,或仅定义“deny_status”时,则隐含“default-errorfiles”参数。这意味着“http-request tarpit [deny_status <status>]”是“http-request tarpit [status <status>] default-errorfiles”的别名。不再评估任何进一步的“http-request”规则。另请参阅“http-request return”和“http-request silent-drop”。
http-request track-sc0 <键> [table <表>] [ { if | unless } <条件> ]
http-request track-sc1 <键> [table <表>] [ { if | unless } <条件> ]
http-request track-sc2 <键> [table <表>] [ { if | unless } <条件> ]
此操作启用从当前请求跟踪粘性计数器。这些规则不会停止评估,也不会改变默认操作。同一连接可同时跟踪的计数器数量在构建时由 MAX_SESS_STKCTR 设置(在 haproxy -vv 中报告),默认为 3,因此 track-sc 的编号在 0 和 (MAX_SESS_STKCTR-1) 之间。执行的第一个“track-sc0”规则启用对指定表的计数器的跟踪作为第一组。执行的第一个“track-sc1”规则启用对指定表的计数器的跟踪作为第二组。执行的第一个“track-sc2”规则启用对指定表的计数器的跟踪作为第三组。建议的做法是使用第一组计数器用于每个前端的计数器,第二组用于每个后端的计数器。但这只是一个指导方针,所有计数器都可以在任何地方使用。
参数
<键> 是强制性的,并且是第 7.3 节中描述的样本表达式规则。它描述了将要分析、提取、组合和用于选择更新哪个表条目计数器的传入请求或连接的元素。 <表> 是一个可选的表,用于替代默认表,默认表是在当前代理中声明的粘性表。然后,所有匹配和更新键的计数器都将在该表中执行,直到会话结束。
一旦执行了“track-sc*”规则,将在表中查找该键,如果未找到,则会为其分配一个条目。然后,在整个会话生命周期内都会保留一个指向该条目的指针,并且该条目的计数器会尽可能频繁地更新,即每当会话的计数器更新时,以及在会话结束时系统性地更新。计数器只为跟踪开始后发生的事件更新。作为一个例外,连接计数器和请求计数器会系统性地更新,以反映有用的信息。如果该条目跟踪并发连接计数器,只要该条目被跟踪,就会计为一个连接,并且在此期间该条目不会过期。跟踪计数器相比仅检查键值还提供了性能优势,因为对于所有使用它的 ACL 检查,都只执行一次表查找。
http-request unset-var(<变量名>) [ { if | unless } <条件> ]
此操作用于取消设置一个变量。有关 <变量名> 的详细信息,请参见上文。
示例
http-request unset-var(req.my_var)
http-request use-service <服务名称> [ { if | unless } <条件> ]
该指令执行配置的 HTTP 服务以响应请求,并停止规则的评估。HTTP 服务可以选择通过发送任何有效的 HTTP 响应来回复,或者可以立即关闭连接而不发送任何响应。除了原生服务,例如 Prometheus 导出器,还可以用 Lua 编写自己的服务。不再评估更多的“http-request”规则。
参数
<service-name> 是必需的。它是要调用的服务。
示例
http-request use-service prometheus-exporter if { path /metrics }
http-request wait-for-handshake [ { if | unless } <条件> ]
这会延迟请求的处理,直到 SSL 握手完成。这主要用于延迟处理早期数据,直到我们确定它们是有效的。
http-response <action> <options...> [ { if | unless } <condition> ]
第 7 层响应的访问控制

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
http-response 语句定义了一组适用于第 7 层处理的规则。当在前端、listen 或后端部分遇到规则时,它们将按声明顺序进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时,它才会被评估。由于这些规则适用于响应,因此后端规则首先应用,然后是前端的规则。第一个关键字是规则的操作。支持的操作如下所述。每个实例的 http-response 语句数量没有限制。
示例
acl key_acl res.hdr(X-Acl-Key) -m found acl myhost hdr(Host) -f myhost.lst http-response add-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl http-response del-acl(myhost.lst) %[res.hdr(X-Acl-Key)] if key_acl
示例
acl value res.hdr(X-Value) -m found use_backend bk_appli if { hdr(Host),map_str(map.lst) -m found } http-response set-map(map.lst) %[src] %[res.hdr(X-Value)] if value http-response del-map(map.lst) %[src] if ! value
http-response add-acl(<文件名>) <键格式> [ { if | unless } <条件> ]
这用于将新条目添加到 ACL 中。ACL 必须从文件中加载(即使是空的虚拟文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能会很昂贵!它等同于 stats socket 的 "add acl" 命令,但可以由 HTTP 响应触发。
http-response add-header <名称> <格式> [ { if | unless } <条件> ]
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由遵循日志格式规则的 <fmt> 定义(参见 第 8.2.4 节中的自定义日志格式)。例如,这可用于向客户端发送 cookie,或传递一些内部信息。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
http-response allow [ { if | unless } <条件> ]
此操作停止规则的评估,并让响应通过检查。当前部分不再评估更多的“http-response”规则。
http-response cache-store <名称> [ { if | unless } <条件> ]
请参阅关于缓存设置的第 6.2 节
http-response capture <样本> id <id> [ { if | unless } <条件> ]
此命令捕获响应缓冲区中的样本表达式 <sample>,并将其转换为字符串。生成的字符串存储在下一个请求的“capture”槽中,因此它可能会与某些捕获的 HTTP 标头并列出现。然后它将自动出现在日志中,并且可以使用样本提取规则进行提取,以将其馈送到标头或其他地方。有关更多信息,请参阅 7.3 节(提取样本)和“捕获响应标头”。关键字“id”是用于存储字符串的捕获槽的 ID。捕获槽必须在关联的前端中定义。这对于在后端运行捕获很有用。槽 ID 可以通过之前的指令“http-response capture”或使用关键字“declare capture”来声明。在后端使用此操作时,请仔细检查相关前端是否具有所需的捕获槽,否则,此规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析后端名称,因此在配置解析时无法检测到这一点。
http-response del-acl(<文件名>) <键格式> [ { if | unless } <条件> ]
这用于从 ACL 中删除条目。ACL 必须从文件中加载(即使是空的虚拟文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它等同于 stats socket 的 "del acl" 命令,但可以由 HTTP 响应触发。
http-response del-header <名称> [ -m <方法> ] [ { if | unless } <条件> ]
此操作移除所有名称在 <name> 中指定的 HTTP 标头字段。<meth> 是应用于标头名称的匹配方法。支持的匹配方法有“str”(精确匹配)、“beg”(前缀匹配)、“end”(后缀匹配)、“sub”(子串匹配)和“reg”(正则表达式匹配)。如果未指定,则使用精确匹配方法。
http-response del-map(<文件名>) <键格式> [ { if | unless } <条件> ]
这用于从 MAP 中删除条目。MAP 必须从文件中加载(即使是空的虚拟文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它接受一个参数:"文件名" 它等同于 stats socket 的 "del map" 命令,但可以由 HTTP 响应触发。
http-response deny [deny_status <状态码>] [ { if | unless } <条件> ]
http-response deny [ { status | deny_status } <code>] [content-type <type>] [ { default-errorfiles | errorfile <file> | errorfiles <name> | file <file> | lf-file <file> | string <str> | lf-string <fmt> } ] [ hdr <name> <fmt> ]* [ { if | unless } <condition> ]
这会停止规则的评估并立即拒绝响应。默认情况下,会返回 HTTP 502 错误。但可以使用与“http-response return”规则相同的语法来自定义响应。因此,有关详细信息,请参阅“http-response return”。为了兼容性,当没有定义参数或只定义了“deny_status”时,会隐含参数“default-errorfiles”。这意味着“http-response deny [deny_status <status>]”是“http-response deny [status <status>] default-errorfiles”的别名。不再评估其他“http-response”规则。另请参阅“http-response return”。
http-response redirect <规则> [ { if | unless } <条件> ]
此操作基于重定向规则执行 HTTP 重定向。它支持与“http-request redirect”规则类似的格式字符串,但例外是响应上只可能进行“location”类型的重定向。有关规则的语法,请参见“redirect”关键字。当在响应期间应用重定向规则时,与服务器的连接将被关闭,以便无法将任何数据从服务器转发到客户端。
http-response replace-header <名称> <正则匹配> <替换格式> [ { if | unless } <条件> ]
此操作的工作方式类似于“http-request replace-header”,但它作用于服务器的响应而不是客户端的请求。
示例
http-response replace-header Set-Cookie (C=[^;]*);(.*) \1;ip=%bi;\2 # 应用于: Set-Cookie: C=1; expires=Tue, 14-Jun-2016 01:40:45 GMT # 输出: Set-Cookie: C=1;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT # 假设后端 IP 是 192.168.1.20。
http-response replace-value <名称> <正则匹配> <替换格式> [ { if | unless } <条件> ]
此操作的工作方式类似于“http-request replace-value”,但它作用于服务器的响应而不是客户端的请求。
示例
http-response replace-value Cache-control ^public$ private # 应用于: Cache-Control: max-age=3600, public # 输出: Cache-Control: max-age=3600, private
http-response return [status <代码>] [content-type <类型>] [ { default-errorfiles | errorfile <文件> | errorfiles <名称> | file <文件> | lf-file <文件> | string <字符串> | lf-string <格式> } ] [ hdr <名称> <值> ]* [ { if | unless } <条件> ]
这会停止规则的评估并立即返回响应。响应的默认状态码为 200。可以作为“status”的参数可选地指定它。“content-type”的响应内容类型也可以作为“content-type”的参数指定。最后,可以定义响应本身。它可以是指定错误文件的完整 HTTP 响应,或者指定文件或字符串的响应有效负载。遵循这些规则来创建响应:* 如果未定义错误文件或要使用的有效负载,则返回一个虚拟响应。仅考虑“status”参数。它可以是 [200, 599] 范围内的任何代码。“content-type”参数(如果有)将被忽略。* 如果设置了“default-errorfiles”参数,则考虑代理的错误文件。如果定义了“status”参数,则它必须是 haproxy 处理的状态码之一(200、400、403、404、405、408、410、413、425、429、500、502、503 和 504)。“content-type”参数(如果有)将被忽略。* 如果使用“errorfile”参数定义了特定的错误文件,将返回包含完整 HTTP 响应的相应文件。仅考虑“status”参数。它必须是 haproxy 处理的状态码之一(200、400、403、404、405、408、410、413、425、429、500、502、503 和 504)。“content-type”参数(如果有)将被忽略。* 如果使用“errorfiles”参数定义了 http-errors 部分,将返回指定 http-errors 部分中包含完整 HTTP 响应的相应文件。仅考虑“status”参数。它必须是 haproxy 处理的状态码之一(200、400、403、404、405、408、410、413、425、429、500、502、503 和 504)。“content-type”参数(如果有)将被忽略。* 如果指定了“file”或“lf-file”参数,则将文件的内容用作响应有效负载。如果文件不为空,则其 content-type 必须设置为“content-type”参数。否则,“content-type”参数将被忽略。使用“lf-file”参数时,文件的内容被评估为日志格式字符串。使用“file”参数时,它被视为原始内容。* 如果指定了“string”或“lf-string”参数,则将定义的字符串用作响应有效负载。content-type 必须始终设置为“content-type”参数。使用“lf-string”参数时,字符串被评估为日志格式字符串。使用“string”参数时,它被视为原始字符串。当响应不基于错误文件时,可以使用“hdr”参数将 HTTP 标头字段附加到响应。否则,所有“hdr”参数都将被忽略。对于每个参数,标头名称在 <name> 中指定,其值由后面的 <fmt> 定义,它遵循日志格式规则。请注意,生成的响应必须小于缓冲区。并且为了避免任何警告,当加载错误文件或原始文件时,为标头重写保留的缓冲区空间也应该为空。不再评估其他“http-response”规则。
示例
http-response return errorfile /etc/haproxy/errorfiles/200.http \ if { status eq 404 } http-response return content-type text/plain \ string "This is the end !" \ if { status eq 500 }
http-response sc-inc-gpc0(<sc-id>) [ { if | unless } <条件> ]
http-response sc-inc-gpc1(<sc-id>) [ { if | unless } <条件> ]
此操作根据 <sc-id> 指定的粘性计数器递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并继续评估操作。
http-response sc-set-gpt0(<sc-id>) { <整数> | <表达式> } [ { if | unless } <条件> ]
此操作根据由 <sc-id> 指定的粘性计数器和 <int>/<expr> 的值来设置 32 位无符号 GPT0 标签。预期结果为布尔值。如果发生错误,此操作将静默失败,并继续评估操作。
http-response send-spoe-group <引擎名称> <组名称> [ { if | unless } <条件> ]
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
参数
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
http-response set-header <name> <fmt> [ { if | unless } <condition> ]
这与 "add-header" 的作用相同,只是如果头名称已存在,会先将其删除。当向服务器传递安全信息,且该头不能被外部用户操纵时,这很有用。
http-response set-log-level <level> [ { if | unless } <condition> ]
这用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 个 syslog 级别(参见“log”关键字),加上特殊级别“silent”,它禁用此请求的日志记录。此规则不是最终规则,因此最后一个匹配的规则获胜。此规则可用于禁用来自其他设备的健康检查。
http-response set-map(<file-name>) <key fmt> <value fmt>
这用于将新条目添加到 MAP 中。MAP 必须从文件中加载(即使是空的虚拟文件)。要更新的 MAP 的文件名在括号中传递。它接受 2 个参数:<key fmt>,遵循 log-format 规则,用于收集 MAP 键,以及 <value fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能会很昂贵!它等同于 stats socket 的 "set map" 命令,但可以由 HTTP 响应触发。
http-response set-mark <mark> [ { if | unless } <condition> ]
在支持的平台上,此操作将 Netfilter MARK 设置为传递给 <mark> 的值,该值将发送到客户端的所有数据包上。该值是一个无符号 32 位值,netfilter 和路由表都可以匹配。它可以表示为十进制或十六进制格式(以“0x”为前缀)。这对于强制某些数据包采用不同的路由(例如,更便宜的批量下载网络路径)非常有用。这适用于 Linux 内核 2.6.32 及更高版本,并且需要管理员权限。
http-response set-nice <nice> [ { if | unless } <condition> ]
这会设置正在处理的当前请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级越低。较低的值会使请求比其他请求更重要。这有助于提高某些请求的速度,或降低不重要请求的优先级。未经事先试验而使用此设置可能会导致一些严重的减速。
http-response set-status <status> [reason <str>] [ { if | unless } <condition> ]
这将用 <status> 替换响应状态码,该值必须是 100 到 999 之间的整数。可以选择性地提供由 <str> 定义的自定义原因文本,否则将使用指定状态码的默认原因作为后备。
示例
# 返回“431 Request Header Fields Too Large” http-response set-status 431 # 返回“503 Slow Down”,自定义原因 http-response set-status 503 reason "Slow Down".
http-response set-tos <tos> [ { if | unless } <condition> ]
此操作用于在支持此功能的平台上,将发送给客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中传递的值。此值代表 IP TOS 字段的全部 8 位,可以用十进制或十六进制格式(以“0x”为前缀)表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的两位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474, 2597, 3260 和 4594。
http-response set-var(<var-name>) <expr> [ { if | unless } <condition> ]
此操作用于设置变量的内容。变量是内联声明的。
参数
<var-name> 变量名以其作用域的指示开头。允许的作用域有: “proc”:变量与整个进程共享 “sess”:变量与整个会话共享 “txn”:变量与事务(请求和响应)共享 “req”:变量仅在请求处理期间共享 “res”:变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。 <expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
http-response set-var(sess.last_redir) res.hdr(location)
http-response silent-drop [ { if | unless } <condition> ]
这会停止规则的评估,并使用一种依赖于系统的方式使面向客户端的连接突然消失,该方式试图阻止客户端被通知。效果是客户端仍然看到一个已建立的连接,而在 HAProxy 端则没有。其目的是实现与“tarpit”类似的效果,但它不使用 HAProxy 运行的机器上的任何本地资源。它可以抵抗比“tarpit”高得多的负载,并且可以减缓更强大的攻击者。理解使用此机制的影响非常重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持连接,并可能因此受此操作的影响。在具有足够权限运行的现代 Linux 系统上,TCP_REPAIR 套接字选项用于阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 被减至 1,以便 TCP 重置不会通过第一个路由器,尽管它仍然会被传递到本地网络。除非您完全理解其工作原理,否则请勿使用它。
这将为后续规则启用或禁用严格重写模式。它不影响在其之前声明的规则,并且仅适用于对响应执行重写的规则。当启用严格模式时,任何重写失败都会触发内部错误。否则,此类错误将被静默忽略。严格重写模式的目的是使一些重写是可选的,而另一些则必须执行才能继续响应处理。默认情况下,严格重写模式是启用的。其值在规则集评估结束时也会被重置。因此,例如,如果您在后端更改了模式,当 HAProxy 开始前端规则评估时,会恢复默认模式。
http-response track-sc0 <key> [table <table>] [ { if | unless } <condition> ]
http-response track-sc1 <key> [table <table>] [ { if | unless } <condition> ]
http-response track-sc2 <key> [table <table>] [ { if | unless } <condition> ]
此操作用于跟踪当前响应的粘性计数器。请参阅 "http-request track-sc" 以获取完整描述。与 "http-request track-sc" 的唯一区别是 <key> 样本表达式只能使用响应中的样本(例如,res.*、status 等)以及第 6 层以下的样本(例如,SSL 相关样本,请参阅 第 7.3.4 节)。如果样本不支持,haproxy 在解析配置时将失败并发出警告。
http-response unset-var(<var-name>) [ { if | unless } <condition> ]
这用于取消设置变量。有关 <var-name> 的详细信息,请参阅 "http-response set-var"。
示例
http-response unset-var(sess.last_redir)
http-reuse { never | safe | aggressive | always }
声明空闲的 HTTP 连接如何在请求之间共享

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
默认情况下,HAProxy 与后端服务器建立的、可安全重用的连接会移回服务器的空闲连接池,以便其他请求可以使用它。这是下面的“safe”策略。该参数指示所需的连接重用策略:-“never”:空闲连接永远不会在会话之间共享。此模式可能用于取消从 defaults 部分继承的不同策略或进行故障排除。例如,如果旧的错误应用程序认为同一连接上的多个请求来自同一客户端,并且无法修复该应用程序,则可能需要在单个后端中禁用连接共享。此类应用程序的一个示例可能是使用隧道模式下的 cookie 插入且不检查第一个请求之后的任何请求的旧 HAProxy。-“safe”:这是默认且推荐的策略。会话的第一个请求始终通过自己的连接发送,只有后续请求才能在其他现有连接上分派。这确保了在服务器关闭连接时发送请求,浏览器可以决定静默重试。由于它与常规的 keep-alive 完全等效,因此不应有任何副作用。-“aggressive”:此模式可能在webservices环境中使用,其中并非所有服务器都必然已知,并且通过现有连接分派大多数第一个请求将是可取的。在这种情况下,第一个请求仅通过至少重用一次的现有连接发送,这证明服务器正确支持连接重用。仅当确定客户端可以偶尔重试失败的请求,并且积极连接重用的好处明显超过罕见的连接失败的缺点时,才应使用它。-“always”:此模式仅在已知通往服务器的路径在释放现有连接后不会很快中断时才推荐使用。它允许将会话的第一个请求发送到现有连接。当后端是缓存场时,这可以比“safe”策略带来显著的性能提升,因为此类组件倾向于表现出一致的行为,并且将受益于连接共享。建议在此模式下保持“http-keep-alive”超时较低,以免任何死连接保持可用。在大多数情况下,这将带来与“aggressive”相同的性能提升,但风险更大。仅当它优于“aggressive”时才应使用它。启用 HTTP 连接共享时,会非常小心地遵守连接属性和兼容性。具体来说:- 使用“usesrc”后跟客户端相关值(“client”、“clientip”、“hdr_ip”)建立的连接将被标记为私有,并且永远不会共享;- 发送到带有 TLS SNI 扩展的服务器的连接将被标记为私有,并且永远不会共享;- 具有某些依赖于连接的错误身份验证方案(如 NTLM)的连接会被检测到,如果可能,会被标记为私有,并且永远不会共享。然而,在使用具有多路复用能力的协议并使用大于默认“safe”策略的重用模式级别值时,情况并非如此,因为在这种情况下,没有任何东西可以阻止连接已经被共享。连接池会涉及,并且可以通过“pool-max-conn”进行配置。注意:连接重用提高了“server maxconn”设置的准确性,因为在有可用空闲连接的情况下,几乎不会建立新连接。这一点在“always”策略下尤其明显。决定保持空闲连接打开或在处理后关闭它的规则也受“tune.pool-low-fd-ratio”(默认值:20%)和“tune.pool-high-fd-ratio”(默认值:25%)的约束。这些分别对应于空闲连接所占文件描述符总数的百分比,高于该百分比时,HAProxy 将分别避免在响应后保持连接打开,并主动终止空闲连接。一些使用非常高比例空闲连接的设置,无论是由于全局“maxconn”值过低,还是由于前端大量 HTTP/2 或 HTTP/3 流量(连接少)但后端为 HTTP/1 连接,可能会观察到较低的重用率,因为保持打开的连接太少。在这种情况下,可能希望调整这些阈值或简单地增加全局“maxconn”值。类似地,当显式启用线程组时,重要的是要理解空闲连接只能在同一组的线程之间使用。因此,可能会出现组之间负载不均导致需要更多空闲连接,从而导致重用率降低的情况。然后可以应用相同的解决方案(增加全局“maxconn”或增加池比例)。
将服务器名称添加到请求中。使用由 <header> 给出的头字符串。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<header> 用于发送服务器名称的头字符串。
http-send-name-header”语句会使名为 <header> 的标头字段在请求即将通过线路发送时设置为目标服务器的名称。任何现有的该标头实例都将被删除。在重试和重新分派时,标头字段将被更新,以始终反映正在尝试连接的服务器。鉴于此标头在连接设置的后期被修改,它可能对已修改的标头产生意外影响。例如,将其与传输层标头(如 connection、content-length、transfer-encoding 等)一起使用,很可能会导致发送到服务器的请求无效。此外,据报道,此指令目前正被用作覆盖传出请求中 Host 标头字段的方法;虽然此技巧作为该功能的一项副作用已存在一段时间,但它不受官方支持,并且在未来的版本中可能会因该功能带来的技术难度而不再有效。长期解决方案是修复需要此技巧的应用程序,使其绑定到正确的服务器名称。
id <value>
为代理设置一个持久 ID。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
参数:
为代理设置一个持久 ID。此 ID 必须是唯一的正数。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
ignore-persist { if | unless } <condition>
声明一个忽略持久性的条件

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
默认情况下,当启用 cookie 持久性时,每个包含该 cookie 的请求都是无条件持久的(假设目标服务器正常运行)。"ignore-persist" 语句允许声明各种基于 ACL 的条件,当满足这些条件时,请求将忽略持久性。这有时对于负载均衡静态文件的请求很有用,因为这些文件通常不需要持久性。这也可以用于完全禁用特定 User-Agent 的持久性(例如,某些网络爬虫机器人)。 当 "if" 条件满足时,或者除非 "unless" 条件满足时,持久性将被忽略。
示例
acl url_static path_beg /static /images /img /css acl url_static path_end .gif .png .jpg .css .js ignore-persist if url_static
load-server-state-from-file { global | local | none }
允许 HAProxy 的无缝重载

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
此指令将 HAProxy 指向一个文件,其中保存了先前运行进程的服务器状态。这样,在启动时,在处理流量之前,新进程可以将旧状态应用于服务器,就像没有发生重新加载一样。“load-server-state-from-file”指令的目的是告诉 haproxy 使用哪个文件。目前,只有两个参数,它们可以防止加载状态或从包含所有后端和服务器的文件加载状态。状态文件可以通过在 stats socket 上运行“show servers state”命令并将输出重定向来生成。文件格式是版本化的,并且非常特定。要理解它,请阅读“show servers state”命令的文档(管理指南的第 9.3 章)。
参数
global 加载由名为 "server-state-file" 的全局指令指向的文件的内容。 local 如果设置了 "server-state-file-name" 指令,则加载其指向的文件的内容。如果未设置,则使用后端名称作为文件名。 none 不为此后端加载任何状态
注意:- 默认情况下,服务器的 IP 地址在重载时会保留,但顺序可以通过服务器的“init-addr”设置来更改。这意味着在运行时通过 CLI 执行的 IP 地址更改将被保留,并且对本地解析器(例如 /etc/hosts)的任何更改可能不会有任何效果(如果正在使用状态文件)。- 除非在前一个和新的配置文件之间发生了变化,否则将应用前一个运行进程的服务器权重。
示例
最小配置
global stats socket /tmp/socket server-state-file /tmp/server_state defaults load-server-state-from-file global backend bk server s1 127.0.0.1:22 check weight 11 server s2 127.0.0.1:22 check weight 12
然后可以运行: socat /tmp/socket - <<< "show servers state" > /tmp/server_state 文件 /tmp/server_state 的内容将如下所示: 1 # <文档示例中省略了字段名称> 1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0 1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0
示例
最小配置
global stats socket /tmp/socket server-state-base /etc/haproxy/states defaults load-server-state-from-file local backend bk server s1 127.0.0.1:22 check weight 11 server s2 127.0.0.1:22 check weight 12
然后可以运行: socat /tmp/socket - <<< "show servers state bk" > /etc/haproxy/states/bk 文件 /etc/haproxy/states/bk 的内容将如下所示: 1 # <文档示例中省略了字段名称> 1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0 1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0
log <address> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]
启用事件和流量的每个实例日志记录。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
前缀:当必须清除记录器列表时,应使用 no。例如,如果您不想从默认记录器列表继承。此前缀不允许有参数。
参数
global 应在实例的日志参数与全局参数相同时使用。这是最常见的用法。“global”会替换 <address>、<facility> 和 <level> 为“global”部分中的日志条目的那些。每个实例只能使用一个“log global”语句,并且此形式不带其他参数。<address> 指示将日志发送到何处。它的格式与“global”部分的日志相同,可以是以下之一:- IPv4 地址,可选地后跟冒号(':')和 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- IPv6 地址,后跟冒号(':')和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- 指向 UNIX 域套接字的操作系统路径,同时注意 chroot 的考虑(确保路径在 chroot 内可访问)和 uid/gid(确保路径具有适当的可写权限)。- 文件描述符编号,形式为“fd@<number>”,它可以指向管道、终端或套接字。在这种情况下,将使用无缓冲日志,并且每次日志执行一次 writev() 调用。这有点昂贵,但对大多数工作负载来说是可以接受的。以这种方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,“DroppedLogs”计数器将增加。writev() 调用对于大小不超过 PIPE_BUF 的消息(POSIX 建议至少为 512,在大多数现代操作系统上为 4096 字节)即使在管道上也是原子的。任何更大的消息可能会与其他进程的消息交错。调试目的的文件描述符也可以指向文件,但这会大大降低 haproxy 的速度,因为会忽略非阻塞调用。此外,在不重新启动进程的情况下,将无法清除或轮换此文件。请注意,已配置的 syslog 格式将被保留,因此输出适用于 TCP syslog 服务器。另请参阅下面的“short”和“raw”格式。-“stdout”/“stderr”,它们分别是“fd@1”和“fd@2”的别名,请参阅上文。- 形式为“ring@<name>”的环形缓冲区,它将对应于可以通过 CLI 使用“show events”命令访问的内存环形缓冲区,该命令还将列出现有环形缓冲区及其大小。此类缓冲区在重新加载或重启时会丢失,但当作为补充使用时,可以通过让日志即时可用来帮助故障排除。您可能希望在地址参数中引用一些环境变量,有关环境变量的详细信息,请参阅 2.3 节。<length> 是可选的最大行长度。大于此值的日志行将在发送前被截断。原因是 syslog 服务器对日志行长度的处理不同。所有服务器都支持 1024 的默认值,但有些服务器会丢弃较大的行,而另一些服务器则会记录它们。如果服务器支持长行,则在此处设置此值以避免截断长行可能是有意义的。类似地,如果服务器丢弃长行,最好在发送之前截断它们。接受的值为 80 到 65535(含)。1024 的默认值对于所有标准用法来说通常都可以。一些长捕获或 JSON 格式日志的特定情况可能需要较大的值。<ranges> 要识别要采样的日志的逗号分隔范围列表。这用于平衡发送到日志服务器的日志负载。范围的限制不能为 null。它们从 1 开始编号。样本的大小或周期(日志数量)必须使用 <sample_size> 参数设置。<sample_size> 在平衡日志发送到 syslog 服务器的负载时要考虑的样本大小(日志数量)。此大小必须大于或等于范围的高限制的最大值。(另请参阅 <ranges> 参数)。<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一:rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164)rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424)short 包含角度括号之间的级别(如“<3>”)以及文本的消息。PID、日期、时间、进程名称和系统名称将被省略。这旨在与本地日志服务器一起使用。此格式与 systemd 日志记录器使用的格式兼容。raw 仅包含文本的消息。级别、PID、日期、时间、进程名称和系统名称将被省略。这旨在用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。<facility> 必须是 24 个标准 syslog 设施之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,“short”和“raw”格式会忽略 facility,但仍需要作为位置字段。在这种情况下,建议使用“daemon”以使其清楚它仅用于本地。<level> 是可选的,可以指定以过滤传出的消息。默认情况下,所有消息都会发送。如果指定了级别,则只发送具有至少与此级别一样重要的严重性的消息。可以指定可选的最小级别。如果设置了此级别,则具有比此级别更高级别发出的日志将被限制为此级别。这用于避免在某些默认 syslog 配置上将“emerg”消息发送到所有终端。已知有八个级别:emerg alert crit err warning notice info debug
重要的是要记住,是由前端决定要从连接中记录什么,并且在内容切换的情况下,来自后端的日志条目将被忽略。连接以 "info" 级别记录。然而,后端日志声明定义了服务器状态更改将如何以及在何处被记录。级别 "notice" 将用于指示服务器启动,"warning" 将用于终止信号和最终的服务终止,而 "alert" 将用于服务器宕机时。 注意:根据 RFC3164,消息在发出前会被截断为 1024 字节。
示例
log global log stdout format short daemon # 发送日志到 systemd log stdout format raw daemon # 发送所有内容到 stdout log stderr format raw daemon notice # 将重要事件发送到 stderr log 127.0.0.1:514 local0 notice # 只发送重要事件 log 127.0.0.1:514 local0 notice notice # 相同,但限制输出级别 log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器
log-format <string>
指定用于流量日志的日志格式字符串

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
此指令指定了将用于所有通过此行所在前端的流量产生的日志的日志格式字符串。如果在 defaults 部分使用此指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍日志格式字符串的第 8.2.4 节。"log-format" 指令会覆盖之前的 "option tcplog"、"log-format" 和 "option httplog" 指令。
log-format-sd <string>
指定 RFC5424 结构化数据日志格式字符串

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
此指令指定了 RFC5424 结构化数据日志格式字符串,该字符串将用于所有通过此行所在前端的流量产生的日志。如果在 defaults 部分使用此指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍日志格式字符串的第 8.2.4 节。有关 RFC5424 结构化数据部分的更多信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3。 注意:此日志格式字符串仅用于将日志格式设置为 "rfc5424" 的记录器。
示例
log-format-sd [exampleSDID@1234\ bytes=\"%B\"\ status=\"%ST\"]
log-tag <string>
指定用于所有传出日志的日志标签

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
将 syslog 标头中的 tag 字段设置为此字符串。默认情况下,它设置为全局部分的 log-tag,否则设置为从命令行启动的程序名称,通常是“haproxy”。有时区分同一主机上运行的多个进程,或区分同一进程中运行的客户机实例会很有用。在后端,关于服务器上下线的日志将使用此 tag。作为提示,可以在 defaults 部分设置与托管客户机相关的 log-tag,然后将该客户机的所有前端和后端放在一起,然后开始一个新的 defaults 部分中的另一个客户机。另请参阅全局“log-tag”指令。
设置用于维护 keep-alive 连接的最大服务器队列大小

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
HTTP keep-alive 尝试在可能的情况下重用相同的服务器连接,但有时可能会适得其反,例如,如果一个服务器有很多连接而其他服务器是空闲的。这对于静态服务器尤其如此。此设置的目的是在 HAProxy 停止尝试重用同一服务器并更倾向于查找另一台服务器的排队连接数上设置一个阈值。默认值 -1 表示没有限制。值为零表示 keep-alive 请求永远不会排队。对于延迟低且不敏感于中断 keep-alive 的非常近的服务器,建议使用较低的值(例如,本地静态服务器可以使用 10 或更少的值)。对于高延迟的远程服务器,可能需要较高的值来弥补延迟和/或选择不同服务器的成本。请注意,这对响应没有影响,这些响应在 401 响应后会保留给同一服务器。它们仍将转到同一服务器,即使它们需要排队。
设置对于给定的客户端会话,我们可以保持空闲的最大传出连接数。默认值为 5(它精确等于构建时定义的 MAX_SRV_LIST)。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
maxconn <conns>
固定前端的最大并发连接数

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
如果系统支持,在高负载网站上将此限制提高到非常高的值可能很有用,这样 HAProxy 就可以管理连接队列,而不是让客户端遇到连接尝试失败。此值不应超过全局 maxconn。此外,请记住,一个连接包含两个 tune.bufsize(默认为 16kB)的缓冲区,以及其他一些数据,导致每个已建立连接消耗大约 33 kB 的 RAM。这意味着一台配备 1GB RAM 的中型系统如果经过适当调优,可以承受大约 20000-25000 个并发连接。此外,当 <conns> 设置为较大的值时,服务器可能尺寸不足以接受此类负载,因此通常最好为它们分配一些合理的连接限制。当此值设置为零(默认值)时,将使用全局“maxconn”值。
mode { tcp|http|health }
设置实例的运行模式或协议

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
tcp 该实例将以纯 TCP 模式工作。将在客户端和服务器之间建立全双工连接,并且不会执行任何第 7 层检查。这是默认模式。应将其用于 SSL、SSH、SMTP 等。http 该实例将以 HTTP 模式工作。在连接到任何服务器之前,将深入分析客户端请求。任何不符合 RFC 的请求都将被拒绝。将可能进行第 7 层过滤、处理和交换。这就是 HAProxy 带来大部分价值的模式。health 该实例将以“health”模式工作。它只会回复传入连接的“OK”并关闭连接。或者,如果设置了“httpchk”选项,则将发送“HTTP/1.0 200 OK”而不是。在这两种情况下都不会记录任何内容。此模式用于回复外部组件的健康检查。此模式已弃用,不应再使用,因为可以通过结合 TCP 或 HTTP 模式与“monitor”关键字来实现相同甚至更好的效果。
在进行内容切换时,前端和后端必须处于相同的模式(通常是 HTTP),否则配置将被拒绝。
示例
defaults http_instances mode http
monitor fail { if | unless } <condition>
添加一个条件以向监控 HTTP 请求报告失败。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
if <cond> 如果条件满足,监控请求将失败,否则将成功。该条件应描述一个组合测试,如果所有条件都满足,则必须导致失败,例如后端及其备份中的服务器数量都很少。 unless <cond> 只有当条件满足时,监控请求才会成功,否则将失败。这样的条件可以基于对后端列表中最小活动服务器数量的存在的测试。
此语句添加一个条件,该条件可以强制对监视请求的响应报告失败。默认情况下,当外部组件查询专用于监视的 URI 时,将返回 200 响应。当满足上述条件之一时,haproxy 将返回 503 而不是 200。这对于向可能基于可用性(由 haproxy 报告)在多个站点之间进行路由广告的外部组件报告站点故障非常有用。在这种情况下,将依赖于涉及“nbsrv”标准的 ACL。请注意,“monitor fail”仅在 HTTP 模式下有效。如果需要,可以通过“errorfile”或“errorloc”进行调整。
示例
frontend www mode http acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor-uri /site_alive monitor fail if site_dead
monitor-net <source>
声明一个仅限于监控请求的源网络

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<source> 是源 IPv4 地址或网络,该网络只能对任何请求获取监控响应。它可以是 IPv4 地址、主机名或后跟斜杠('/')和掩码的地址。
在 TCP 模式下,来自与 <source> 匹配的源的任何连接都将立即关闭,而不会进行任何日志记录。这允许其他设备探测端口并验证它是否仍在监听,而无需将连接转发到远程服务器。在 HTTP 模式下,来自与 <source> 匹配的源的连接将被接受,在等待请求之前将发送以下响应,然后连接将关闭:“HTTP/1.0 200 OK”。这通常足以让任何前端 HTTP 探测检测到服务正常运行,而无需将请求转发到后端服务器。请注意,此响应以原始格式发送,没有任何转换。这一点很重要,因为它意味着它不会在 SSL 监听器上进行 SSL 加密。监视请求在很早的时候就会被处理,紧随 tcp-request 连接 ACL 之后,而 tcp-request 连接 ACL 是唯一能够阻止它们的。这些连接寿命很短,并且从不等待来自客户端的任何数据。它们不能被记录,并且这是预期的目的。它们仅用于向上层组件报告 HAProxy 的运行状况,仅此而已。请注意,“monitor fail”规则不适用于被“monitor-net”截获的连接。最后,请注意,前端只能指定一个“monitor-net”语句。如果发现多个,则只有最后一个将被考虑。
示例
# 地址 .252 和 .253 只是在探测我们。 frontend www monitor-net 192.168.0.252/31
拦截外部组件监控请求使用的 URI

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
当在前端收到引用 <uri> 的 HTTP 请求时,HAProxy 不会转发它,也不会记录它,而是根据“monitor fail”定义的失败条件返回“HTTP/1.0 200 OK”或“HTTP/1.0 503 Service unavailable”。这通常足以让任何前端 HTTP 探测检测到服务正常运行,而无需将请求转发到后端服务器。请注意,HTTP 方法、版本和所有标头都将被忽略,但请求至少必须在 HTTP 级别上有效。此关键字只能与 HTTP 模式的前端一起使用。监视请求在非常早的时候就被处理,就在请求解析之后,甚至在任何“http-request”之前。唯一在此之前应用的规则集是 tcp-request 规则集。它们也不能被记录,并且这是预期的目的。只能配置一个 URI 进行监视;当存在多个“monitor-uri”语句时,最后一个将定义要使用的 URI。它们仅用于向上的组件报告 HAProxy 的运行状况,仅此而已。然而,可以使用任意数量的条件与“monitor fail”和 ACL 结合使用,以便结果可以根据可以想象到的任何检查进行调整(最常见的是后端中可用服务器的数量)。注意:如果 <uri> 以斜杠 ('/') 开头,则匹配会针对请求的路径而不是请求的 uri 进行。这是一个变通方法,允许 HTTP/2 请求匹配 monitor-uri。事实上,在 HTTP/2 中,鼓励客户端仅发送绝对 URI。
示例
# 使用 /haproxy_test 来报告 haproxy 的状态 frontend www mode http monitor-uri /haproxy_test
启用或禁用对队列中待处理的已中止请求的提前丢弃。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
在高负载情况下,服务器响应需要一些时间。每个实例的连接队列会膨胀,响应时间会随着队列大小乘以平均每会话响应时间而增加。当客户端等待几秒钟以上时,它们通常会点击浏览器上的“STOP”按钮,在队列中留下一个无用的请求,并减慢其他用户的速度,同时也会减慢服务器的速度,因为请求最终会被服务,然后在传递响应期间遇到第一个错误时中止。由于无法区分客户端方面的完整 STOP 和简单的输出关闭,HTTP 代理应保守行事,并认为客户端在等待响应时可能只关闭了其输出通道。然而,这会带来拥塞的风险(当大量用户执行相同操作时),并且如今是完全没有用的,因为可能没有任何客户端会在等待响应时关闭会话。某些 HTTP 代理支持此行为(Squid、Apache、HAProxy),而其他代理不支持(TUX、大多数基于硬件的负载均衡器)。因此,关闭的输入通道代表用户点击“STOP”按钮的概率接近 100%,并且成为唯一破坏罕见但有效流量的组件的风险极低,这增加了在不污染服务器的情况下,在仍未服务时及早中止会话的诱惑。在 HAProxy 中,用户可以使用“abortonclose”选项来选择所需行为。默认情况下(不带选项),行为符合 HTTP 标准,中止的请求将被服务。但是,当指定了该选项时,对于传入通道关闭的会话,将在可能的情况下中止,无论是在连接队列中等待连接槽,还是在服务器尚未确认连接请求期间。这极大地减小了队列大小以及当用户倾向于单击 STOP 时饱和服务器上的负载,从而减少了其他用户的响应时间。如果在“defaults”部分启用了此选项,则可以通过在前面加上“no”关键字来在特定实例中禁用它。
启用或禁用放宽 HTTP 请求解析

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,HAProxy 在消息解析方面符合 RFC7230。这意味着在标头名称中不允许使用非法字符,否则会导致返回错误给客户端。这是期望的行为,因为这些禁止的字符实质上用于构建利用服务器漏洞并绕过安全过滤器的攻击。有时,有问题的浏览器或服务器会因任何原因(配置、实现)发出非法的标头名称,并且问题不会立即修复。在这种情况下,可以通过指定此选项来放宽 HAProxy 的标头名称解析器,以接受任何字符,即使这没有意义。同样,URI 中允许出现的字符列表由 RFC3986 明确定义,并且字符 0-31、32(空格)、34(") 、60(<)、62(>)、92(\)、94(^)、96(`)、123({)、124(|)、125(})、127(delete)以及所有大于 127 的字符都是完全不允许的。HAProxy 始终会阻止其中一些字符(0..32, 127)。其余字符默认会被阻止,除非启用了此选项。此选项还会放宽对 HTTP 版本的要求,它允许 HTTP/0.9 请求通过(未指定版本),并且允许主版本和次版本包含多个数字。最后,此选项还允许传入的 URL 包含片段引用(路径后的 '#')。此选项永远不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。它仅应在确认问题后部署。启用此选项后,请求中的错误标头名称仍将被接受,但将捕获完整的请求,以便使用 UNIX 统计套接字上的“show errors”命令进行后续分析。同样,包含 URI 部分中非法字符的请求将被记录。这样做也有助于确认问题已得到解决。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用或禁用放宽 HTTP 响应解析

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
默认情况下,HAProxy 在消息解析方面符合 RFC7230。这意味着在标头名称中不允许使用非法字符,否则会导致返回错误给客户端。这是期望的行为,因为这些禁止的字符实质上用于构建利用服务器漏洞并绕过安全过滤器的攻击。有时,有问题的浏览器或服务器会因任何原因(配置、实现)发出非法的标头名称,并且问题不会立即修复。在这种情况下,可以通过指定此选项来放宽 HAProxy 的标头名称解析器,以接受任何字符,即使这没有意义。此选项还会放宽对 HTTP 版本格式的要求,它允许主版本和次版本包含多个数字。此选项永远不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。它仅应在确认问题后部署。启用此选项后,响应中的错误标头名称仍将被接受,但将捕获完整的响应,以便使用 UNIX 统计套接字上的“show errors”命令进行后续分析。这样做也有助于确认问题已得到解决。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
一次使用所有备用服务器,或仅使用第一个

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
默认情况下,当所有正常服务器都宕机时,第一个可用的备用服务器将获得所有流量。有时,可能希望一次使用多个备用服务器,因为一个可能不够用。当启用 "option allbackups" 时,当所有正常服务器都不可用时,将在所有备用服务器之间执行负载均衡。将使用相同的负载均衡算法,并遵守服务器的权重。因此,备用服务器之间将不再有任何优先级顺序。此选项主要用于专用于在应用程序完全离线时返回“抱歉”页面的静态服务器群。 如果此选项已在 "defaults" 部分中启用,可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
分析所有服务器响应并阻止带有可缓存 cookie 的响应

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
一些高级框架会在所有地方设置应用程序 cookie,并且并不总是为开发人员提供足够的控制来管理响应的缓存方式。当缓存对象上返回会话 cookie 时,用户在同一缓存之间穿行时存在会话交叉或窃取的风险。在某些情况下,阻止响应比让一些敏感会话信息泄露更好。“checkcache”选项启用对所有服务器响应的深度检查,以严格遵守 HTTP 规范中的可缓存性。它会仔细检查服务器响应中的“Cache-control”、“Pragma”和“Set-cookie”标头,以检查在客户端代理上缓存 cookie 的风险。启用此选项后,只能将以下响应传递给客户端:- 所有没有“Set-Cookie”标头的响应;- 所有返回码不是 200、203、204、206、300、301、404、405、410、414、501 的响应,前提是服务器没有设置“Cache-control: public”标头字段;- 所有由 GET、HEAD、OPTIONS、TRACE 方法以外的请求产生的响应,前提是服务器没有设置“Cache-Control: public”标头字段;- 带有“Pragma: no-cache”标头的响应;- 带有“Cache-control: private”标头的响应;- 带有“Cache-control: no-store”标头的响应;- 带有“Cache-control: max-age=0”标头的响应;- 带有“Cache-control: s-maxage=0”标头的响应;- 带有“Cache-control: no-cache”标头的响应;- 带有“Cache-control: no-cache="set-cookie"”标头的响应;- 带有“Cache-control: no-cache="set-cookie,"”标头的响应(允许 set-cookie 之后有其他字段);如果不符合这些要求,响应将被阻止,就像来自“http-response deny”规则一样,返回“HTTP 502 bad gateway”。会话状态显示“PH--”,表示代理在标头处理过程中阻止了响应。此外,还会向日志发送警报,以便管理员了解需要修复的问题。由于对应用程序影响很大,因此在生产环境中部署前应深入测试应用程序。在测试期间始终激活它也是一个好习惯,即使它不在生产环境中使用,因为它会报告潜在的危险应用程序行为。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用或禁用在客户端发送 TCP keepalive 数据包

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且协议涉及具有长时间空闲周期的非常长的会话(例如远程桌面)时,存在一个风险,即其中一个中间组件决定终止已空闲太长时间的会话。启用套接字级别的 TCP keep-alive 会使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并且取决于操作系统及其调优参数。重要的是要理解,keep-alive 数据包既不在应用程序级别发出,也不在应用程序级别接收。只有网络堆栈会看到它们。因此,即使代理的一侧已经使用 keep-alive 来保持其连接处于活动状态,这些 keep-alive 数据包也不会被转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用“clitcpka”选项可在连接的客户端一侧启用 TCP keep-alive 探测的发出,这在 HAProxy 与客户端之间的会话过期时会有所帮助。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用连续流量统计更新

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,用于统计计算的计数器仅在会话完成时递增。处理小型对象时效果很好,但处理大型对象(例如大型图像或存档)或 A/V 流时,从 haproxy 计数器生成的图看起来会像刺猬。启用此选项后,计数器会频繁地在会话期间递增,通常每 5 秒一次,这足以生成清晰的图表。重新计数直接触及热路径,因此默认情况下不启用它,因为它可能会导致会话计数非常大的情况下大量唤醒并导致性能略有下降。
启用或禁用从 HTTP/1.x 客户端连接的隐式 HTTP/2 升级。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,如果来自给定 HTTP 连接的第一个请求与 HTTP/2 连接前导符(即字符串 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")匹配,HAProxy 能够隐式地将 HTTP/1.x 客户端连接升级为 HTTP/2 连接。这样,就可以在非 SSL 连接上支持 HTTP/1.x 和 HTTP/2 客户端。必须使用此选项来禁用隐式升级。请注意,此隐式升级仅支持 HTTP 代理,因此此选项也一样。另请注意,可以通过在 bind 行上指定 "proto h2" 来强制在清晰连接上使用 HTTP/2。如果此选项已在 "defaults" 部分中启用,则可以通过在其前面加上 "no" 关键字来禁用它在特定实例中的行为。
启用或禁用对正常、成功连接的日志记录

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
有些大型网站每秒处理数千个连接,日志记录对它们来说是一个主要的痛点。其中一些甚至被迫关闭日志,无法调试生产问题。设置此选项可确保正常的连接,即那些没有经历错误、超时、重试或重新分派的连接,将不会被记录。这为异常情况留下了磁盘空间。在 HTTP 模式下,会检查响应状态码,返回码为 5xx 的仍将被记录。 强烈建议不要使用此选项,因为大多数情况下,复杂问题的关键在于正常的日志中,而这些日志在这里不会被记录。如果您需要分离日志,请改用 "log-separate-errors" 选项。
启用或禁用对空连接的日志记录

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
在某些环境中,有些组件会定期连接到各种系统,以确保它们仍然存活。这可能是来自另一个负载均衡器以及监控系统的情况。默认情况下,即使是简单的端口探测或扫描也会产生一条日志。如果这些连接过多地污染了日志,可以启用选项“dontlognull”,以指示没有传输任何数据的连接将不会被记录,这通常对应于那些探测。请注意,错误仍将返回给客户端并在统计信息中计算。如果这不是期望的,可以使用 http-ignore-probes 选项。通常建议不要在不受控制的环境(例如互联网)中使用此选项,否则扫描和其他恶意活动将不会被记录。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字来在特定实例中禁用它。
option forwardfor [ except <network> ] [ header <name> ] [ if-none ]
启用向发送到服务器的请求中插入 X-Forwarded-For 头部

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<network> 是一个可选参数,用于对匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Forwarded-For" 头部名称。
由于 HAProxy 以反向代理模式运行,服务器将其 IP 地址视为其客户端地址。当服务器日志中期望客户端 IP 地址时,这有时会很麻烦。为了解决这个问题,众所周知的 HTTP 标头“X-Forwarded-For”可以由 HAProxy 添加到发送到服务器的所有请求中。此标头包含一个代表客户端 IP 地址的值。由于此标头始终附加到现有标头列表的末尾,因此必须配置服务器仅使用此标头的最后一个实例。请参阅服务器的手册,了解如何启用此标准标头的使用。请注意,只能使用该标头的最后一个实例,因为实际上客户端可能已经带了一个。可以使用关键字“header”来提供一个不同的标头名称来替换默认的“X-Forwarded-For”。当您可能已经从不同的应用程序(例如 stunnel)获取了“X-Forwarded-For”标头,并且需要保留它时,这很有用。另外,如果您的后端服务器不使用“X-Forwarded-For”标头并且需要不同的标头(例如,Zeus Web Servers 需要“X-Cluster-Client-IP”)。有时,同一个 HAProxy 实例可能由直接客户端访问和反向代理访问共享(例如,当使用 SSL 反向代理来解密 HTTPS 流量时)。可以通过添加“except”关键字后跟网络地址来禁用为已知源地址或网络添加标头。在这种情况下,任何匹配网络的源 IP 都不会导致添加此标头。最常见的用法是私有网络或 127.0.0.1。或者,关键字“if-none”表示仅当该标头不存在时才添加该标头。这仅应在完全受信任的环境中使用,因为如果到达 haproxy 的标头受到最终用户的控制,这可能会导致安全问题。仅支持 IPv4 地址。“http-request add-header”或“http-request set-header”规则可用于解决此限制。此选项可以在前端或后端指定。如果其中至少一个使用了它,则会添加标头。请注意,如果前端和后端都定义了标头子参数,则后端设置的标头子参数优先。对于“if-none”参数,如果前端或后端至少有一个没有指定它,它希望强制添加,因此它会获胜。
示例
# 公共 HTTP 地址,也由同一台机器上的 stunnel 使用 frontend www mode http option forwardfor except 127.0.0.1 # stunnel 已经添加了该标头 # 这些服务器希望在 X-Client 中获取 IP 地址 backend www mode http option forwardfor header X-Client
启用或禁用对发送给有问题的客户端的 HTTP/1 头部的大小写调整

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
标头名称没有标准的区分大小写,因为如 RFC7230 所述,它们是大小写不敏感的。因此,应用程序必须以大小写不敏感的方式处理它们。但一些有问题的应用程序违反了标准,并错误地依赖于浏览器最常用的区分大小写。这个问题在 HTTP/2 中变得至关重要,因为所有标头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。无论 HTTP 版本如何,所有标头名称都将以小写形式发送给客户端和服务器。当 HAProxy 收到 HTTP/1 响应时,其标头名称会被转换为小写并以这种方式处理和发送给客户端。如果已知客户端违反 HTTP 标准,并且无法处理来自 HAProxy 的响应,则可以通过启用此选项并通过全局指令“h1-case-adjust”或“h1-case-adjust-file”指定要重新格式化的标头列表,在格式化响应并将其发送给客户端时,将小写标头名称转换为不同的格式。这只能作为临时解决方法,直到客户端修复为止,因为需要此类解决方法的客户端可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准规定的客户端。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用或禁用对发送给有问题的服务器的 HTTP/1 头部的大小写调整

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
标头名称没有标准的区分大小写,因为如 RFC7230 所述,它们是大小写不敏感的。因此,应用程序必须以大小写不敏感的方式处理它们。但一些有问题的应用程序违反了标准,并错误地依赖于浏览器最常用的区分大小写。这个问题在 HTTP/2 中变得至关重要,因为所有标头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。无论 HTTP 版本如何,所有标头名称都将以小写形式发送给客户端和服务器。当 HAProxy 收到 HTTP/1 请求时,其标头名称会被转换为小写并以这种方式处理和发送给服务器。如果已知服务器违反 HTTP 标准,并且无法处理来自 HAProxy 的请求,则可以通过启用此选项并通过全局指令“h1-case-adjust”或“h1-case-adjust-file”指定要重新格式化的标头列表,在格式化请求并将其发送给服务器时,将小写标头名称转换为不同的格式。这只能作为临时解决方法,直到服务器修复为止,因为需要此类解决方法的服务器可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准规定的服务器。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用或禁用在处理前等待整个 HTTP 请求体

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
有时,在做出决定之前等待 HTTP 请求的主体是可取的。例如,“balance url_param”就是这样做的。第一个用例是在连接到服务器之前缓冲来自慢速客户端的请求。另一个用例是基于请求主体的内容做出路由决策。此选项放置在前端或后端中,强制 HTTP 处理等待直到接收到整个主体或请求缓冲区已满。它可能与一些滥用 HTTP 的应用程序产生不希望的副作用,这些应用程序期望前端和后端之间有无缓冲的传输,因此绝对不应默认使用。
启用或禁用空连接和请求超时的日志记录

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
最近一些浏览器开始实现“预连接”功能,即猜测性地连接到一些最近访问过的网站,以防用户想要访问它们。这会导致与网站建立许多连接,最终在超时首先发生时返回 408 Request Timeout,或在浏览器首先决定关闭它们时返回 400 Bad Request。这些连接会污染日志并增加错误计数器。已经有“option dontlognull”,但这在这种情况下不够。相反,此选项执行以下操作:- 如果在连接关闭前未收到任何数据,则阻止将任何 400/408 消息发送给客户端;- 阻止在此情况下发出任何日志;- 阻止任何错误计数器增加。这样,空连接将被静默忽略。请注意,最好不要使用此选项,除非清楚它确实需要,因为它会隐藏真实问题。在没有收到请求并看到 408 的最常见原因是客户端与中间元素(如 VPN)之间的 MTU 不一致,该元素会阻止过大的数据包。这些问题通常在 POST 请求以及带有大 cookie 的 GET 请求中看到。日志通常是检测它们的唯一方法。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用或禁用从客户端到服务器的 HTTP/1.x 连接的 HTTP keep-alive

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,HAProxy 在持久 HTTP/1.x 连接方面以 keep-alive 模式运行:对于每个连接,它会处理每个请求和响应,并在两侧将连接保持空闲状态。此模式可以通过多个选项来更改,例如“option http-server-close”或“option httpclose”。此选项允许恢复到 keep-alive 模式,当在 defaults 部分使用了其他模式时,这可能很有用。设置“option http-keep-alive”可在客户端和服务器端启用 HTTP keep-alive 模式。这在客户端(慢速网络)上提供了最低的延迟,并在服务器端实现了最快的会话重用,但代价是维护与服务器的空闲连接。总的来说,使用此选项可以比“http-server-close”选项在处理小型对象时实现大约两倍的请求速率。此选项主要在以下两种情况下有用:- 当服务器不符合 HTTP 标准并对连接进行身份验证而不是请求时(例如,NTLM 身份验证);- 当与服务器建立连接的成本与从服务器检索关联对象所需的成本相比很高时。后一种情况可能发生在服务器是快速静态服务器或缓存时。目前,日志不会显示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束时间,请求时间对应于等待新请求所花费的时间。keep-alive 请求时间仍然受限于“timeout http-keep-alive”或(如果未设置)“timeout http-request”定义的超时。此选项会禁用并替换任何先前的“option httpclose”或“option http-server-close”。
指示系统在 HTTP 中优先考虑低交互延迟而非性能

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
在 HTTP 中,每个有效负载都是单向的,没有交互的概念。任何代理都被期望以相对低的延迟对数据进行排队。有一些非常罕见的服务器到服务器应用程序滥用 HTTP 协议,并期望有效负载阶段高度交互,在单个请求中在两个方向上有很多交错的数据块。这完全不被 HTTP 规范支持,并且在大多数代理或服务器上无法正常工作。当这些应用程序尝试通过 haproxy 进行此类操作时,它会起作用,但由于网络优化(通过指示系统等待足够的数据可用以仅发送完整数据包来提高性能)而会导致延迟很高。典型的延迟大约是每个往返 200 毫秒。请注意,这仅发生在异常使用时。正常的用法,如 CONNECT 请求或 WebSockets,不受影响。当“option http-no-delay”存在于连接使用的前端或后端时,所有此类优化都将被禁用,以使交换尽可能快。当然,这并不保证功能正常,因为它可能在任何其他地方中断。但如果它通过 HAProxy 工作,它将以尽可能快的速度工作。此选项永远不应默认使用,除非发现此类有问题的应用程序,否则永远不应使用。使用此选项的影响是增加了带宽使用量和 CPU 使用量,这可能会显著降低高延迟环境中的性能。
定义 HAProxy 是否向服务器宣告 HTTP/1.x 连接的 keepalive

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当运行“option http-server-close”或“option httpclose”时,HAProxy 会向发送到服务器的 HTTP/1.x 请求添加“Connection: close”标头。不幸的是,当某些服务器看到此标头时,它们会自动放弃使用分块编码响应未知长度的内容,而这完全无关。其效果是客户端或缓存可能会收到一个不完整的响应而不知道,并认为响应已完成。通过设置“option http-pretend-keepalive”,haproxy 将使服务器相信它将保持连接处于活动状态。然后,服务器将不会回退到上述异常的不期望的行为。当 haproxy 收到完整的响应后,它将关闭与服务器的连接,就像它使用“option httpclose”时一样。这样,客户端将收到一个正常的响应,并且连接在服务器端正确关闭。建议不要默认启用此选项,因为大多数服务器会在最后一个数据包之后更有效地自行关闭连接,并稍微提前释放其缓冲区。此外,网络上添加的数据包可能会稍微降低整体峰值性能。然而,值得注意的是,当启用此选项时,haproxy 的工作量会略微减少。因此,如果 haproxy 是整个架构的瓶颈,启用此选项可能会节省一些 CPU 周期。此选项可以在 backend 和 listen 部分设置。在 frontend 部分使用它将被忽略,并在启动时报告警告。这是一个与 backend 相关的选项,因此在 frontend 上设置它没有实际意义。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
option http-restrict-req-hdr-names { preserve | delete | reject }
设置 HAProxy 关于包含 "[a-zA-Z0-9-]" 字符集之外字符的 HTTP 请求头名称的策略

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
preserve 禁用过滤。这是没有配置 FastCGI 应用程序的 HTTP 代理的默认模式。 delete 删除名称中包含 "[a-zA-Z0-9-]" 字符集之外字符的请求头部。这是配置了 FastCGI 应用程序的 HTTP 后端的默认模式。 reject 如果请求包含名称中含有 "[a-zA-Z0-9-]" 字符集之外字符的头部,则以 403-Forbidden 响应拒绝该请求。
此选项可用于将请求头部名称限制为字母数字和连字符字符 ([A-Za-z0-9-])。这对于与无法处理头部名称中某些字符的非 HTTP 兼容服务器互操作可能是必需的。对于 FastCGI 应用程序也可能是必需的,因为头部名称中的所有非字母数字字符都会被下划线 ('_') 替换。因此,很容易混淆头部名称并绕过一些规则。例如,"X-Forwarded-For" 和 "X_Forwarded-For" 头部在 FastCGI 中都被转换为 "HTTP_X_FORWARDED_FOR"。请注意,此选项是按代理评估的,并且在 http-request 规则评估之后。
启用或禁用服务器端的 HTTP/1.x 连接关闭

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,HAProxy 在持久 HTTP/1.x 连接方面以 keep-alive 模式运行:对于每个连接,它会处理每个请求和响应,并在两侧将连接保持空闲状态。此模式可以通过多个选项来更改,例如“option http-server-close”或“option httpclose”。设置“option http-server-close”可在服务器端启用 HTTP 连接关闭模式,同时保留在客户端支持 HTTP keep-alive 和流水线的能力。这在客户端(慢速网络)上提供了最低的延迟,并在服务器端实现了最快的会话重用,以节省服务器资源,类似于“option httpclose”。它还允许将不支持 keepalive 的服务器以 keep-alive 模式提供给客户端,前提是它们符合 RFC7230 的要求。请注意,当某些服务器在请求中看到“Connection: close”时,它们并不总是符合这些要求。效果是 keep-alive 永远不会被使用。一种变通方法是启用“option http-pretend-keepalive”。目前,日志不会显示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束时间,请求时间对应于等待新请求所花费的时间。keep-alive 请求时间仍然受限于“timeout http-keep-alive”或(如果未设置)“timeout http-request”定义的超时。此选项可以在 frontend 和 backend 中设置。如果持有连接的 frontend 或 backend 中至少有一个启用了它,则它将被启用。它会禁用并替换任何先前的“option httpclose”或“option http-keep-alive”。请检查第 4 节(“代理”)以了解当 frontend 和 backend 选项不同时此选项如何与其他选项结合使用。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
使用非标准的 Proxy-Connection 标头代替 Connection

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
虽然 RFC7230 明确规定 HTTP/1.1 代理必须使用 Connection 标头来指示其对持久或非持久连接的意愿,但浏览器和代理都会忽略代理连接的此标头,而是使用未记录的非标准 Proxy-Connection 标头。当尝试将负载均衡器置于浏览器和此类代理之间时,问题就开始出现,因为 haproxy 的理解与客户端和代理的约定之间会存在差异。通过在前段设置此选项,haproxy 可以在看到代理请求时自动切换到使用该非标准标头。代理请求在此处定义为 URI 不以 '/' 或 '*' 开头的请求。这与 HTTP 隧道模式不兼容。请注意,此选项只能在前段指定,并且将影响请求的整个生命周期。此外,当设置此选项时,需要身份验证的请求将自动切换到使用代理身份验证标头,如果它本身是代理请求的话。这使得在现有代理前面检查或强制执行身份验证成为可能。此选项通常永远不应使用,除非是在代理前面。
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
启用 HTTP 协议来检查服务器健康状况

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<method> 是与请求一起使用的可选 HTTP 方法。如果未设置,则使用 "OPTIONS" 方法,因为它通常需要较低的服务器处理能力,并且易于从日志中过滤掉。可以使用任何方法,但不建议发明非标准方法。<uri> 是 HTTP 请求中引用的 URI。它默认为 " / ",几乎所有服务器默认都可以访问,但可以更改为任何其他 URI。允许查询字符串。<version> 是可选的 HTTP 版本字符串。它默认为 "HTTP/1.0",但某些服务器可能在 HTTP 1.0 中行为不正确,因此将其更改为 HTTP/1.1 有时会有帮助。请注意,Host 字段在 HTTP/1.1 中是强制性的,请使用 "http-check send" 指令来添加它。
默认情况下,服务器运行状况检查仅包括尝试建立 TCP 连接。当指定“option httpchk”时,一旦建立了 TCP 连接,就会发送一个完整的 HTTP 请求,并将 2xx 和 3xx 响应视为有效,而所有其他响应都表示服务器失败,包括缺乏任何响应。与“http-check”指令结合使用时,可以自定义 HTTP 健康检查期间发送的请求或响应的匹配规则。还可以配置发送/期望序列,就像使用“tcp-check”指令进行 TCP 健康检查一样。服务器配置默认用于打开连接以执行 HTTP 健康检查。但也可以使用“http-check connect”规则覆盖服务器参数。“httpchk”选项不一定需要 HTTP 后端,它也适用于纯 TCP 后端。这对于使用 inetd 守护进程检查绑定到特定端口的简单脚本特别有用。但是,它始终会在内部依赖于 HTX 复用器。因此,这意味着请求格式化和响应解析将是严格的。注意:一段时间以来,无法在用于 HTTP 健康检查的请求中添加标头或正文。因此,一种解决方法是将其隐藏在版本字符串的末尾,并在版本后加上“\r\n”。现在已弃用。应改用“http-check send”指令。
示例
# 将 HTTPS 流量中继到 Apache 实例,并使用 HTTP 请求 "OPTIONS * HTTP/1.1" # 在端口 80 上检查服务可用性。 backend https_relay mode tcp option httpchk OPTIONS * HTTP/1.1 http-check send hdr Host www server apache1 192.168.1.1:443 check port 80
启用或禁用 HTTP/1.x 连接关闭

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,HAProxy 在持久 HTTP/1.x 连接方面以 keep-alive 模式运行:对于每个连接,它会处理每个请求和响应,并在两侧将连接保持空闲状态。此模式可以通过多个选项来更改,例如“option http-server-close”或“option httpclose”。如果设置了“option httpclose”,HAProxy 将关闭客户端或服务器连接,具体取决于选项的设置位置。只有 frontend 会被考虑用于客户端连接,而 frontend 和 backend 会被考虑用于服务器连接。在这种情况下,如果持有连接的 frontend 或 backend 中至少有一个启用了该选项,则该选项将被启用。如果选项设置在监听器上,它将同时应用于客户端和服务器连接。它将检查每个方向是否已设置“Connection: close”标头,如果缺少则会添加一个。此选项还可以与“option http-pretend-keepalive”结合使用,后者将禁用发送“Connection: close”请求标头,但仍会导致在收到完整响应后关闭连接。它会禁用并替换任何先前的“option http-server-close”或“option http-keep-alive”。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在特定实例中禁用它。
启用 HTTP 请求、会话状态和计时器的日志记录

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
clf 如果添加了“clf”参数,则输出格式将是 CLF 格式,而不是 HAProxy 的默认 HTTP 格式。当您需要将 HAProxy 的日志输入到只支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。
默认情况下,日志输出格式非常简陋,只包含源地址和目标地址以及实例名称。通过指定 "option httplog",每条日志行都会变成一种更丰富的格式,包括但不限于 HTTP 请求、连接计时器、会话状态、连接数、捕获的头部和 cookie、前端、后端和服务器名称,当然还有源地址和端口。仅指定 "option httplog" 将自动清除默认设置的 'clf' 模式。"option httplog" 会覆盖任何先前的 "log-format" 指令。
启用或禁用纯 HTTP 代理模式

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
有时人们需要一个纯粹的 HTTP 代理,它能理解基本的代理请求,而不需要缓存或任何花哨的功能。在这种情况下,设置一个启用了 "option http_proxy" 的 HAProxy 实例可能是值得的。在这种模式下,不声明任何服务器,连接被转发到 URL 中 "http://" 方案后的 IP 地址和端口。不执行主机地址解析,因此这仅在传递纯 IP 地址时有效。由于此选项的使用范围相当有限,它可能只会被那些知道自己确切需要它的专家使用。这与 HTTP 隧道模式不兼容。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
示例
# 此后端理解 HTTP 代理请求并直接转发它们。 backend direct_forward option httpclose option http_proxy
启用或禁用对两个方向的独立超时处理

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,当通过套接字发送数据时,该套接字的写入超时和读取超时都会被刷新,因为我们认为该套接字上有活动,并且我们没有其他方法来猜测是否应该接收数据。虽然这种默认行为对几乎所有应用程序都是可取的,但存在一种情况,即希望禁用它,并且仅在有传入数据时刷新读取超时。这种情况发生在具有长超时和少量交换数据(如 telnet 会话)的会话中。如果服务器突然消失,输出数据会累积在系统的套接字缓冲区中,两个超时都会被正确刷新,并且无法知道服务器未收到它们,因此我们不会超时。然而,当底层协议始终回显发送的数据时,仅凭此就可以使用读取超时来检测问题。请注意,对于更冗长的协议,不会发生此问题,因为数据不会长时间累积在套接字缓冲区中。当此选项在前段设置时,它将禁用对发送到客户端的数据的读取超时更新。这种情况可能很少有用。当该选项在 backend 设置时,它将禁用对发送到服务器的数据的读取超时更新。这样做通常会中断来自慢速线路的大型 HTTP POST 请求,因此请谨慎使用。
使用 LDAPv3 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
可以测试服务器是否正确地使用 LDAPv3 通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 LDAPv3 匿名简单绑定消息,并分析响应以查找 LDAPv3 绑定响应消息。只有当 LDAP 响应包含成功 resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9) 时,服务器才被认为是有效的。绑定请求的日志记录取决于服务器,请参阅您的文档如何配置它。
示例
option ldap-check
使用外部进程进行服务器健康检查

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
可以使用外部命令测试服务器的健康状况。这是通过运行使用 "external-check command" 设置的可执行文件来实现的。需要设置全局的 "external-check"。
启用或禁用健康检查状态更新的日志记录

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
默认情况下,如果服务器处于 UP 状态,则记录失败的健康检查;如果服务器处于 DOWN 状态,则记录成功的健康检查,因此额外的信息量是有限的。启用此选项后,健康检查状态或服务器健康状况的任何变化都将被记录,这样就可以知道服务器在崩溃前偶尔会检查失败,或者确切知道它何时未能响应有效的 HTTP 状态,然后端口何时开始拒绝连接,以及服务器何时完全停止响应。请注意,此选项有意不记录非健康检查引起的状态变化(例如,在 CLI 上启用/禁用)。
更改非完全成功连接的日志级别

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
有时在日志中查找错误并不容易。此选项使 haproxy 提高包含潜在有趣信息(如错误、超时、重试、重新分派或 HTTP 状态码 5xx)的日志级别。级别从 "info" 变为 "err"。这使得可以使用大多数 syslog 守护进程将它们单独记录到不同的文件中。注意不要将它们从原始文件中删除,否则你会丢失提供非常重要信息的顺序。使用此选项,处理每秒数千个连接的大型站点可以将正常流量记录到循环缓冲区中,并只归档较小的错误日志。
启用或禁用早期日志记录。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,当日志格式字符串定义中使用的所有日志格式变量和采样提取都返回值,或者会话终止时,会发出日志。这使得内置的日志格式字符串可以考虑传输时间或日志消息中的字节数。处理长时间连接(如大文件传输或 RDP)时,请求或连接可能需要一段时间才能显示在日志中。使用“logasap 选项”,一旦服务器连接在 tcp 模式下建立,或者一旦服务器在 http 模式下发送完整标头,就会立即创建日志消息。日志中缺失的信息将是总字节数(仅指示消息创建之前的传输数据量)和总时间(不考虑连接生命周期或传输时间的剩余部分)。对于 HTTP,捕获 Content-Length 响应标头是一个好习惯,这样日志至少可以指示预期传输的字节数。
示例
listen http_proxy 0.0.0.0:80 mode http option httplog option logasap log 192.168.2.200 local3 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \ "GET /image.iso HTTP/1.0"
option mysql-check [ user <username> [ { post-41 | pre-41 } ] ]
使用 MySQL 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<username> 这是连接到 MySQL 服务器时将使用的用户名。 post-41 发送与 v4.1 后客户端兼容的检查(默认) pre-41 发送与 v4.1 前客户端兼容的检查
如果指定了用户名,则检查包括发送两个 MySQL 数据包:一个客户端身份验证数据包和一个 QUIT 数据包,以正确关闭 MySQL 会话。然后,我们解析 MySQL 握手初始化数据包和/或错误数据包。这是一个基本但有用的测试,它不会在服务器上产生错误或中止连接。但是,它需要一个未锁定的授权用户,没有密码。要在 MySQL 中创建一个基本受限用户,并带有可选的资源限制:CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>' /*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */ /*M!100201 MAX_STATEMENT_TIME 0.0001 */; 如果不指定用户名(已弃用且不推荐),则检查仅包括解析 MySQL 握手初始化数据包或错误数据包,在此模式下我们不发送任何内容。有报告称,如果检查过于频繁和/或流量不足,可能会导致锁定。实际上,在这种情况下,您需要检查 MySQL 的“max_connect_errors”值,因为如果在先前的连接中断后,在少于 MySQL 的“max_connect_errors”次尝试内成功建立连接,则该主机的错误计数将清除为零。如果 HAProxy 的服务器被阻止,则“FLUSH HOSTS”语句是唯一可以解除阻止的方法。请记住,这不会检查数据库是否存在或数据库一致性。要做到这一点,您可以使用 xinetd 等外部检查。该检查需要 MySQL >=3.22,对于旧版本,请使用 TCP 检查。通常,传入的 MySQL 服务器需要查看客户端的 IP 地址,以用于各种目的,包括 IP 特权匹配和连接日志记录。在可能的情况下,在使用“source”关键字的“usesrc”参数连接到服务器时,通常明智的做法是假装客户端的 IP 地址,这需要编译透明代理功能,并且 MySQL 服务器需要通过托管 haproxy 的机器路由客户端。
启用或禁用关闭后立即清理会话资源

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当客户端或服务器以不正常的方式中止连接时(例如,它们被物理断开),会话超时会被触发,并且会话会关闭。但是,它会在系统中一段时间内保持 FIN_WAIT1 状态,占用一些资源,并可能限制建立新连接的能力。当这种情况发生时,可以激活“nolinger 选项”,它强制系统在关闭时立即删除任何套接字的挂起数据。因此,会话会立即从系统表中清除。这通常会产生副作用,例如 TCP 重置数量增加,因为旧的重传会立即被拒绝。一些防火墙有时也会对此抱怨。因此,除非绝对必要,否则不建议使用此选项。当您发现系统中存在数千个 FIN_WAIT1 会话时(TIME_WAIT 的不计在内),就知道您需要它。此选项可用于前端和后端,具体取决于它所需的一侧。对客户端使用前端,对服务器使用后端。如果此选项已在“defaults”部分启用,则可以通过在前面加上“no”关键字来在特定实例中禁用它。
option originalto [ except <network> ] [ header <name> ]
启用向发送到服务器的请求插入 X-Original-To 标头

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<network> 是一个可选参数,用于为匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Original-To" 标头名称。
由于 HAProxy 可以以透明模式工作,因此来自客户端的每个请求都可以重定向到代理,而 HAProxy 本身可以将所有请求代理到复杂的 SQUID 环境,并且 SO_ORIGINAL_DST 的目标主机将丢失。当您希望基于目标 IP 地址的访问规则时,这会很麻烦。为了解决这个问题,HAProxy 可能会将一个新的 HTTP 标头“X-Original-To”添加到发送到服务器的所有请求中。此标头包含一个值,表示原始目标 IP 地址。由于必须始终仅使用此标头的最后一个实例进行配置。请注意,必须仅使用标头的最后一个实例,因为客户端可能已经带了一个。可以使用“header”关键字提供不同的标头名称来替换默认的“X-Original-To”。当您可能已经有一个来自不同应用程序的“X-Original-To”标头并且需要保留它时,这很有用。同样,如果您的后端服务器不使用“X-Original-To”标头并且需要不同的标头。有时,同一个 HAProxy 实例可能在直接客户端访问和反向代理访问之间共享(例如,当使用 SSL 反向代理来解密 HTTPS 流量时)。可以通过添加“except”关键字后跟网络地址来禁用为已知源地址或网络添加标头。在这种情况下,任何匹配网络的源 IP 都不会导致添加此标头。最常见的用途是私有网络或 127.0.0.1。仅支持 IPv4 地址。“http-request add-header”或“http-request set-header”规则可用于解决此限制。此选项可以在前端或后端指定。如果其中至少一个使用它,则将添加标头。请注意,如果同时定义了前端和后端的标头子参数,则后端设置的标头子参数优先于前端。
示例
# 原始目标地址 frontend www mode http option originalto except 127.0.0.1 # 这些服务器希望在 X-Client-Dst 中获取 IP 地址 backend www mode http option originalto header X-Client-Dst
启用或禁用对故障服务器的强制持久性

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当 HTTP 请求到达一个带有引用故障服务器的 cookie 的后端时,默认情况下它会被重新分派到另一台服务器。如果绝对需要,可以使用 "option persist" 强制将请求首先发送到故障服务器。一个常见的用例是当服务器处于极端负载下并不断地出现状态切换时。在这种情况下,用户仍将被导向到他们打开会话的服务器,希望他们能得到正确的服务。建议将 "option redispatch" 与此选项结合使用,以便在无法连接到服务器的情况下(服务器确定故障),客户端最终将被重定向到另一台有效的服务器。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 PostgreSQL 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<username> 这是连接到 PostgreSQL 服务器时将使用的用户名。
此检查发送一个 PostgreSQL StartupMessage 并等待认证请求或 ErrorResponse 消息。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。此检查与 "mysql-check" 相同。
允许多个负载均衡的请求保留在同一台服务器上

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当使用的负载均衡算法不是确定性的,并且先前的请求被发送到 haproxy 仍有连接的服务器时,有时希望同一会话中的后续请求尽可能地去到同一台服务器。请注意,这与持久性不同,因为我们只指示了一个首选项,haproxy 会尝试应用它,但不提供任何形式的保证。实际用途是发送到服务器的 keep-alive 连接。使用此选项时,haproxy 将尝试重用附加到服务器的同一连接,而不是重新均衡到另一台服务器,从而导致连接关闭。这对于静态文件服务器来说是有意义的。与哈希算法结合使用此选项没有多大意义。请注意,haproxy 已经自动尝试坚持发送 401 的服务器或发送 407(需要身份验证)的代理,当负载均衡算法不是确定性的时候。这对于与有缺陷的 NTLM 身份验证挑战一起使用是强制性的,并且在排除一些有故障的应用程序时有显著帮助。在这种环境中,prefer-last-server 选项也可能是可取的,以避免在每次响应后重新分发流量。如果此选项已在“defaults”部分启用,则可以通过在前面加上“no”关键字来在特定实例中禁用它。
启用或禁用连接失败时的会话重新分发

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<interval> 可选的整数值,用于控制重试连接时重新分发的频率。正值 P 表示希望在每第 P 次重试时进行重新分发,负值 N 表示希望在最后一次重试前的第 N 次重试时进行重新分发。例如,默认值 -1 保留了在最后一次重试时重新分发的历史行为,正值 1 表示每次重试都重新分发,正值 3 表示每三次重试重新分发一次。您可以使用值 0 禁用重新分发。
在 HTTP 模式下,如果由 cookie 指定的服务器出现故障,客户端可能会永久地坚持使用它,例如在使用“persist 选项”或“force-persist”时,因为它们无法刷新 cookie,因此它们将无法再访问该服务。指定“redispatch 选项”将允许代理中断 cookie 或基于一致性哈希的持久性,并将它们重新分发到工作的服务器。活动服务器从可用服务器列表中选择一个子集。非停机或非维护状态的活动服务器(即,其运行状况未被检查或已被检查为“up”)将按以下顺序选择:1. 任何活动的、非备份的服务器(如果有);或 2. 如果未设置“allbackups 选项”,则列表中的第一台备份服务器;或 3. 如果设置了“allbackups 选项”,则任何备份服务器。当发生重试时,HAProxy 会尝试选择一台不同于上次的服务器。新服务器从当前服务器列表中选择。有时,如果列表在重试之间更新(例如,如果发生多次重试,并且持续时间比检查服务器是否已停机、将其从列表中删除并回退到备份服务器列表所需的时间长),连接可能会被重定向到备份服务器,尽管如此。它还允许在多次连接失败的情况下重试连接到另一台服务器。当然,这需要将“retries”设置为非零值。如果此选项已在“defaults”部分启用,则可以通过在前面加上“no”关键字来在特定实例中禁用它。
使用 Redis 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
可以测试服务器是否正确地使用 REDIS 协议通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 PING redis 命令,并分析响应以查找 "+PONG" 响应消息。
示例
option redis-check
option smtpchk <hello> <domain>
使用 SMTP 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<hello> 是一个可选参数。它是要使用的“hello”命令。它可以是“HELO”(用于 SMTP)或“EHLO”(用于 ESMTP)。所有其他值都将转换为默认命令(“HELO”)。<domain> 是要呈现给服务器的域名。只有在指定了 hello 命令时才能指定(并且是强制性的)。默认情况下,使用“localhost”。
当设置了“smtpchk 选项”时,运行状况检查将包括 TCP 连接,然后是一个 SMTP 命令。默认情况下,此命令是“HELO localhost”。将分析服务器的返回代码,只有以“2”开头的返回代码才会被视为有效。所有其他响应,包括无响应,都将构成错误,并指示服务器已死。此测试适用于 SMTP 服务器或中继。根据请求,某些服务器可能不会记录每次连接尝试,因此您可能需要进行试验以改善行为。使用 telnet 端口 25 通常比调整配置更容易。通常,传入的 SMTP 服务器需要查看客户端的 IP 地址,以用于各种目的,包括垃圾邮件过滤、防欺骗和日志记录。在可能的情况下,在使用“source”关键字的“usesrc”参数连接到服务器时,通常明智的做法是假装客户端的 IP 地址,这需要编译透明代理功能。
示例
option smtpchk HELO mydomain.org
启用或禁用为每个套接字收集并提供单独的统计信息。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
启用或禁用双向套接字上的自动内核加速

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当此选项在前端或后端启用时,haproxy 将自动评估使用内核 TCP 拼接在客户端和服务器之间转发数据的机会,无论是哪个方向。HAProxy 使用启发式方法来估计内核拼接是否可能提高性能。两个方向都独立处理。请注意,所使用的启发式方法不太激进,以限制拼接的过度使用。此选项需要在编译时启用拼接,并且可以使用全局选项“nosplice”进行全局禁用。由于 splice 使用管道,因此使用它需要有足够的备用管道。重要提示:基于内核的 TCP 拼接是一项特定于 Linux 的功能,首次出现在内核 2.6.25 中。它提供基于内核的加速,可在不将数据复制到用户空间的情况下在套接字之间传输数据,从而提供可观的性能提升和 CPU 周期节省。由于许多早期实现存在错误、数据损坏和/或效率低下,因此默认情况下不启用此功能,并且应谨慎使用。虽然无法检测到实现的正确性,但 2.6.29 是第一个提供正常工作实现的版本。如有疑问,可以使用全局“nosplice”关键字全局禁用拼接。
示例
option splice-auto
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用请求套接字上的自动内核加速

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当在前台或后台启用此选项时,haproxy 将尽可能使用内核 TCP 拼接来转发从客户端到服务器的数据。如果没有备用管道,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于 splice 使用管道,使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅 "option splice-auto"。
示例
option splice-request
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用响应套接字上的自动内核加速

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当在前台或后台启用此选项时,haproxy 将尽可能使用内核 TCP 拼接来转发从服务器到客户端的数据。如果没有备用管道,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于 splice 使用管道,使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅 "option splice-auto"。
示例
option splice-response
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 SPOP 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
可以测试服务器是否正确地使用 SPOP 协议进行通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,HAProxy 和服务器之间会执行 HELLO 握手,并分析响应以检查是否报告了错误。
示例
option spop-check
启用或禁用在服务器端发送 TCP keepalive 数据包

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及非常长的会话且空闲时间很长时(例如,远程桌面),则存在中间组件决定使长时间空闲的会话过期的风险。启用套接字级别的 TCP keep-alive 会使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并且取决于操作系统及其调优参数。重要的是要理解 keep-alive 数据包既不在应用程序级别发出,也不在应用程序级别接收。只有网络堆栈会看到它们。因此,即使代理的一侧已经使用 keep-alive 来保持其连接活跃,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用“srvtcpka 选项”会在连接的服务器端启用 TCP keep-alive 探测的发出,这应该有助于在 HAProxy 和服务器之间注意到会话过期。如果此选项已在“defaults”部分启用,则可以通过在前面加上“no”关键字来在特定实例中禁用它。
使用 SSLv3 客户端 hello 健康检查进行服务器测试

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
当一些基于 SSL 的协议在 TCP 模式下通过 HAProxy 中继时,可以测试服务器是否正确地使用 SSL 通信,而不仅仅是测试它是否接受 TCP 连接。设置 "option ssl-hello-chk" 后,一旦与服务器建立连接,就会发送纯 SSLv3 客户端 hello 消息,并分析响应以查找 SSL 服务器 hello 消息。只有当响应包含此服务器 hello 消息时,服务器才被认为是有效的。到目前为止测试的所有服务器都能正确回复 SSLv3 客户端 hello 消息,并且大多数测试的服务器甚至不记录仅包含 hello 消息的请求,这是值得赞赏的。请注意,即使 haproxy 未内置 SSL 支持,此检查也能正常工作,因为它会伪造 SSL 消息。当 SSL 支持可用时,最好使用原生 SSL 健康检查而不是这个。
使用 tcp-check 发送/期望序列执行健康检查

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
此运行状况检查方法旨在与“tcp-check”命令列表结合使用,以支持发送/接收类型的运行状况检查序列。TCP 检查当前支持 4 种操作模式:- 未指定“tcp-check”指令:运行状况检查仅包括连接尝试,这是默认模式。- 仅提及“tcp-check send”或“tcp-check send-binary”:这用于在打开连接时 along with a string。对于某些协议,例如发送“QUIT”消息,可以防止服务器为每次运行状况检查记录连接错误。检查结果仍基于打开连接的能力。- 仅提及“tcp-check expect”:这用于测试横幅。连接将打开,haproxy 将等待服务器显示一些内容,这些内容必须满足某些规则。检查结果将基于内容和规则之间的匹配。这适用于 POP、IMAP、SMTP、FTP、SSH、TELNET。- 同时提及“tcp-check send”和“tcp-check expect”:这用于测试问候类型协议。HAProxy 发送消息,服务器响应,并分析其响应。检查结果将基于响应内容和规则之间的匹配。这通常适用于需要绑定或请求/响应模型的协议。LDAP、MySQL、Redis 和 SSL 是此类协议的示例,尽管它们都已具有更深入地了解各自协议的专用检查。在此模式下,可以发送许多问题并分析许多答案。可以使用第五种模式在脚本的不同步骤中插入注释。对于您创建的每个 tcp-check 规则,您可以添加一个“comment”指令,后跟一个字符串。此字符串将在调试模式下的日志和 stderr 中报告。它有助于用户友好的错误报告。“comment”当然是可选的。在运行状况检查期间,可以使用“tcp-check set-var”操作在变量作用域中存储数据样本。可以使用“tcp-check unset-var”来释放这些变量。
示例
# 执行 POP 检查(仅分析服务器的横幅) option tcp-check tcp-check expect string +OK\ POP3\ ready comment POP\ protocol # 执行 IMAP 检查(仅分析服务器的横幅) option tcp-check tcp-check expect string *\ OK\ IMAP4\ ready comment IMAP\ protocol # 在确保它能很好地说话后,查找 Redis 主服务器 # Redis 协议,然后它正常退出。 # (发送命令然后分析响应 3 次) option tcp-check tcp-check comment PING\ phase tcp-check send PING\r\n tcp-check expect string +PONG tcp-check comment role\ check tcp-check send info\ replication\r\n tcp-check expect string role:master tcp-check comment QUIT\ phase tcp-check send QUIT\r\n tcp-check expect string +OK 伪造 HTTP 请求,然后分析响应(在分析之前发送许多标头) option tcp-check tcp-check comment forge\ and\ send\ HTTP\ request tcp-check send HEAD\ /\ HTTP/1.1\r\n tcp-check send Host:\ www.mydomain.com\r\n tcp-check send User-Agent:\ HAProxy\ tcpcheck\r\n tcp-check send \r\n tcp-check expect rstring HTTP/1\..\ (2..|3..) comment check\ HTTP\ response
启用或禁用在接受序列期间节省一个 ACK 数据包

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
当 HTTP 连接请求进来时,系统会代表 HAProxy 确认它,然后客户端立即发送其请求,系统也会确认它,同时通知 HAProxy 新连接。然后 HAProxy 读取请求并响应。这意味着我们有一个由系统发送的无用 TCP ACK,因为当 HAProxy 发送其响应时,请求可以被它确认。因此,在 HTTP 模式下,HAProxy 会自动请求系统避免发送此无用的 ACK(在支持的平台上,目前至少有 Linux)。这不会引起任何问题,因为如果响应花费的时间超过预期,系统仍会在 40 毫秒后发送它。在复杂的网络调试会话期间,可能希望禁用此优化,因为延迟的 ACK 会使在识别数据包延迟的位置时进行故障排除变得更加复杂。然后可以通过指定“no option tcp-smart-accept”来恢复到正常行为。通过简单地指定“option tcp-smart-accept”来强制非 HTTP 代理使用它也是可能的。例如,对于某些服务(如 SMTP),服务器先说话,这可能是有意义的。建议避免在 defaults 部分强制使用此选项。如有疑问,请考虑将其设置回自动值,方法是在前面加上“default”关键字,或使用“no”关键字将其禁用。
启用或禁用在连接序列期间节省一个 ACK 数据包

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
在某些系统(至少是 Linux)上,HAProxy 可以请求内核在收到连接请求时不立即发送一个空的 ACK,而是直接发送带有数据的请求。这可以在网络上节省一个数据包,从而提高性能。这对某些服务器也很有用,因为它们可以立即随传入连接一起获取请求。当在后端设置了 "option tcp-smart-connect" 时,此功能被启用。默认情况下不启用,因为它会使网络故障排除变得更加复杂。只在客户端先说话的协议(如 HTTP)中启用它才有意义。在其他情况下,如果没有数据可以代替 ACK 发送,则会发送一个正常的 ACK。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用在两侧发送 TCP keepalive 数据包

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
当客户端和服务器之间存在防火墙或任何会话感知组件时,并且当协议涉及非常长的会话且空闲时间很长时(例如,远程桌面),则存在中间组件决定使长时间空闲的会话过期的风险。启用套接字级别的 TCP keep-alive 会使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并且取决于操作系统及其调优参数。重要的是要理解 keep-alive 数据包既不在应用程序级别发出,也不在应用程序级别接收。只有网络堆栈会看到它们。因此,即使代理的一侧已经使用 keep-alive 来保持其连接活跃,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用“tcpka 选项”会在连接的客户端和服务器端发出 TCP keep-alive 探测。请注意,这仅在“defaults”或“listen”部分有意义。如果在前端使用此选项,则只有客户端才会获得 keep-alive;如果在后端使用此选项,则只有服务器端才会获得 keep-alive。因此,强烈建议在前端和后端之间拆分配置时,显式使用“clitcpka 选项”和“srvtcpka 选项”。
启用包含会话状态和计时器的 TCP 连接高级日志记录

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数:
默认情况下,日志输出格式非常简陋,只包含源地址和目标地址以及实例名称。通过指定 "option tcplog",每条日志行都会变成一种更丰富的格式,包括但不限于连接计时器、会话状态、连接数、前端、后端和服务器名称,当然还有源地址和端口。此选项对于纯 TCP 代理很有用,以便找出是客户端还是服务器断开连接或超时。对于普通的 HTTP 代理,最好使用 "option httplog",它甚至更完整。"option tcplog" 会覆盖任何先前的 "log-format" 指令。
启用客户端透明代理

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
引入此选项是为了给第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力,将针对远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一台设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。请注意,与普遍看法相反,此选项不会使 HAProxy 在建立连接时向服务器呈现客户端的 IP。
执行外部检查时要运行的可执行文件

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<command> 是要运行的外部命令
传递给命令的参数是:<proxy_address> <proxy_port> <server_address> <server_port> <proxy_address> 和 <proxy_port> 来自第一个 IPv4、IPv6 或 UNIX 套接字监听器。在 UNIX 套接字监听器的情况下,proxy_address 将是套接字路径,而 <proxy_port> 将是字符串“NOT_USED”。在 backend 部分,无法确定监听器,并且 <proxy_address> 和 <proxy_port> 都将是字符串值“NOT_USED”。一些值也通过环境变量提供。环境变量:HAPROXY_PROXY_ADDR 第一个绑定地址(如果可用)(如果不可用则为空,例如在“backend”部分)。HAPROXY_PROXY_ID 后端 ID。HAPROXY_PROXY_NAME 后端名称。HAPROXY_PROXY_PORT 第一个绑定端口(如果可用)(如果不可用则为空,例如在“backend”部分或对于 UNIX 套接字)。HAPROXY_SERVER_ADDR 服务器地址。HAPROXY_SERVER_CURCONN 服务器上的当前连接数。HAPROXY_SERVER_ID 服务器 ID。HAPROXY_SERVER_MAXCONN 服务器最大连接数。HAPROXY_SERVER_NAME 服务器名称。HAPROXY_SERVER_PORT 服务器端口(如果可用,或对于 UNIX 套接字为空)。PATH PATH 环境变量在使用执行命令时可以使用“external-check path”进行设置。有关其他变量,请参阅“2.3. 环境变量”。如果执行的命令退出状态为零,则认为检查通过,否则认为检查失败。
示例
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<path> 是执行外部命令时使用的路径
默认路径为 ""。
示例
external-check path "/usr/bin:/bin"
启用基于 RDP cookie 的持久性

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<name> 是要检查的可选 RDP cookie 的名称。如果省略,将使用默认的 cookie 名称 "msts"。目前没有更改此名称的有效理由。
此语句启用基于 RDP cookie 的持久性。RDP cookie 包含在已知服务器列表中找到服务器所需的所有信息。因此,当在后端中设置此选项时,将分析请求,如果找到 RDP cookie,则会对其进行解码。如果它与仍然 UP 的已知服务器匹配(或者如果设置了 "option persist"),则连接将被转发到此服务器。请注意,这仅在 TCP 后端中有意义,但要使其工作,前端必须等待足够长的时间以确保 RDP cookie 存在于请求缓冲区中。这与 "rdp-cookie" 负载均衡方法的要求相同。因此,强烈建议将所有语句放在一个 "listen" 部分中。此外,重要的是要理解,终端服务器只有在配置为 "令牌重定向模式" 时才会发出此 RDP cookie,这意味着 "IP 地址重定向" 选项被禁用。
示例
listen tse-farm bind :3389 # 在请求中等待 RDP cookie 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # 应用 RDP cookie 持久性 persist rdp-cookie # 如果服务器未知,让我们在相同的 cookie 上进行负载均衡。 # 或者,"balance leastconn" 也可能有用。 balance rdp-cookie server srv1 1.1.1.1:3389 server srv2 1.1.1.2:3389
设置前端每秒接受的新会话数限制

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<rate> <rate> 参数是一个整数,指定前端每秒接受的最大新会话数。
当前端达到每秒指定的新会话数时,它将停止接受新连接,直到速率再次降至限制以下。在此期间,挂起的会话将保留在套接字的后备队列中(在系统缓冲区中),haproxy 甚至不会意识到会话正在挂起。当在高度负载的服务上应用非常低的限制时,使用“backlog”关键字增加套接字的后备队列可能会有益。此功能特别擅长阻止基于连接的攻击或对脆弱服务器的服务滥用。由于会话速率每毫秒测量一次,因此它非常精确。此外,限制会立即应用,不需要任何延迟即可检测到阈值。
示例
将 SMTP 的连接速率限制为最大每秒 10 个
listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025
注意:当达到最大速率时,前端的状态不会改变,但如果启用了 "socket-stats" 选项,其套接字在统计信息中将显示为 "WAITING"。
redirect location <loc> [code <code>] <option> [{if | unless} <condition>]
redirect prefix <pfx> [code <code>] <option> [{if | unless} <condition>]
redirect scheme <sch> [code <code>] <option> [{if | unless} <condition>]
如果/除非条件匹配,则返回 HTTP 重定向

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
如果/除非条件匹配,HTTP 请求将导致重定向响应。如果未指定条件,则重定向无条件适用。
参数
<loc> 使用“redirect location”时,<loc> 中的确切值将放入 HTTP “Location”标头。在“http-request”规则中使用时,<loc> 值遵循 log-format 规则,并且可以包含一些动态值(请参阅 第 8.2.4 节中的自定义日志格式)。<pfx> 使用“redirect prefix”时,“Location”标头将由 <pfx> 与完整的 URI 路径(包括查询字符串)的连接构成,除非指定了“drop-query”选项(见下文)。作为特例,如果 <pfx> 等于“/”,则不在原始 URI 前插入任何内容。这允许重定向到同一个 URL(例如,插入 cookie)。在“http-request”规则中使用时,<pfx> 值遵循 log-format 规则,并且可以包含一些动态值(请参阅 第 8.2.4 节中的自定义日志格式)。<sch> 使用“redirect scheme”时,“Location”标头将通过连接 <sch>、“://”然后是“Host”标头的第一个实例,然后是 URI 路径(包括查询字符串,除非指定了“drop-query”选项(见下文))来构建。如果没有找到路径或路径为“*”,则使用“/”代替。如果没有找到“Host”标头,则将返回一个空主机组件,大多数现代浏览器将其解释为重定向到同一主机。此指令主要用于将 HTTP 重定向到 HTTPS。在“http-request”规则中使用时,<sch> 值遵循 log-format 规则,并且可以包含一些动态值(请参阅 第 8.2.4 节中的自定义日志格式)。<code> 代码是可选的。它指示所需的 HTTP 重定向类型。仅支持 301、302、303、307 和 308 代码,默认情况下,如果未指定代码,则使用 302。301 表示“永久移动”,浏览器可以缓存 Location。302 表示“临时移动”,意味着浏览器不应缓存重定向。303 相当于 302,只是浏览器将使用 GET 方法获取位置。307 就像 302,但明确表示必须重用相同的方法。同样,如果必须使用相同的方法,308 将替换 301。<option> 有几种选项可以指定以调整重定向的预期行为:-“drop-query” 当此关键字用于基于前缀的重定向时,Location 将设置为不带任何可能的查询字符串,这对于将用户定向到非安全页面非常有用。它对 location 类型重定向没有影响。-“append-slash” 此关键字可与“drop-query”结合使用,将使用不以“/”结尾的 URL 的用户重定向到带有“/”的同一 URL。这有助于确保搜索引擎只看到一个 URL。为此,优选返回码 301。-“set-cookie NAME[=value]” 将在响应中添加一个“Set-Cookie”标头(可选加上“=value”)。这有时用于指示用户已被看到,例如以防范某些类型的 DoS 攻击。不添加其他 cookie 选项,因此 cookie 将是会话 cookie。请注意,对于浏览器,单独的 cookie 名称(没有等号)与带等号的 cookie 不同。-“clear-cookie NAME[=]” 将在 cookie 中添加一个“Set-Cookie”标头(可选加上“=”),但将“Max-Age”属性设置为零。这将告诉浏览器删除此 cookie。例如,这对于注销页面很有用。需要注意的是,清除 cookie“NAME”不会删除使用“NAME=value”设置的 cookie。您必须清除 cookie“NAME=”才能实现这一点,因为浏览器有所区别。
示例
仅将登录 URL 移动到 HTTPS。
acl clear dst_port 80 acl secure dst_port 8080 acl login_page url_beg /login acl logout url_beg /logout acl uid_given url_reg /login?userid=[^&]+ acl cookie_set hdr_sub(cookie) SEEN=1 redirect prefix https://mysite.com set-cookie SEEN=1 if !cookie_set redirect prefix https://mysite.com if login_page !secure redirect prefix http://mysite.com drop-query if login_page !uid_given redirect location http://mysite.com/ if !login_page secure redirect location / clear-cookie USERID= if logout
示例
为不带 '/' 的文章请求发送重定向。
acl missing_slash path_reg ^/article/[^/]*$ redirect code 301 prefix / drop-query append-slash if missing_slash
示例
当 SSL 由 haproxy 处理时,将所有 HTTP 流量重定向到 HTTPS。
redirect scheme https if !{ ssl_fc }
示例
在所有没有 'www.' 前缀的主机前添加该前缀
http-request redirect code 301 location \ http://www.%[hdr(host)]%[capture.req.uri] \ unless { hdr_beg(host) -i www }
有关 ACL 的用法,请参见第 7 节
retries <value>
设置发生故障后对服务器执行的重试次数

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<value> 是在服务器失败后,请求或连接尝试应重试的次数。
默认情况下,重试仅适用于新的连接尝试。但是,当使用“retry-on”指令时,其他条件可能会触发重试(例如,空响应、不期望的状态代码),并且其中每一个都会算作一次尝试,当总尝试次数达到此处的值时,将返回错误。为了避免立即重新连接到正在重新启动的服务器,将在同一服务器上重试之前应用一个周转计时器,该计时器为 min(“timeout connect”、“一秒钟”)。当设置了“redispatch 选项”时,即使 cookie 引用了不同的服务器,也可能会在另一台服务器上执行一些重试。默认情况下,这仅是最后一次重试,除非向“redispatch 选项”传递了参数。
retry-on [以空格分隔的关键字列表]
指定何时尝试自动重试失败的请求。此设置仅在 "mode" 设置为 http 时有效,否则将被静默忽略。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<keywords> 是一个由空格分隔的关键词或 HTTP 状态码列表,每个都代表一个希望重试请求的失败事件类型。在更改此设置之前,请阅读底部的说明。支持以下关键词: none 永不重试 conn-failure 在连接或 SSL 握手失败且请求无法发送时重试。这是默认值。 empty-response 在发送了部分请求后服务器连接关闭,且未收到服务器任何响应时重试。此类型的失败可能由服务器端的请求超时、糟糕的网络状况,或服务器在处理请求时崩溃或重启引起。 junk-response 在服务器返回看起来不完整的 HTTP 响应时重试。这包括部分响应头以及非 HTTP 内容。在这种情况下重试通常是不明智的,这可能由配置问题(错误的服务器端口)或请求对服务器有害(例如缓冲区溢出攻击)引起。 response-timeout 在等待服务器响应请求时服务器超时。这可能由糟糕的网络状况、已过时的空闲连接重用,或请求处理成本极高引起。在处理大量数据库请求(如全扫描等)的服务器上重试此类事件通常是不明智的,因为它可能放大拒绝服务攻击。 0rtt-rejected 在通过早期数据发送并被服务器拒绝的请求时重试。这些请求通常被认为是安全的重试对象。 <status> "404" (未找到), "408" (请求超时), "425" (过早), "500" (服务器错误), "501" (未实现), "502" ( bad gateway), "503" (服务不可用), "504" (网关超时) 中的任意 HTTP 状态码。 all-retryable-errors 重试所有被认为是可重试错误的请求。目前激活 "conn-failure", "empty-response", "junk-response", "response-timeout", "0rtt-rejected", "500", "502", "503", 和 "504"。
使用此指令将用新设置替换任何先前设置;它不是累积的。请注意,使用 "none" 和 "conn-failure" 以外的任何值都需要分配一个缓冲区并将整个请求复制到其中,因此会影响内存和性能。无法放入单个缓冲区的请求将永远不会被重试(参见全局 tune.bufsize 设置)。您必须确保应用程序内置了重放保护机制,例如在请求中传递的唯一事务 ID,或者重放同一请求没有后果,否则使用 "conn-failure" 和 "none" 以外的任何 retry-on 值都非常危险。静态文件服务器和缓存通常被认为是安全的,不受任何重试类型的影响。使用状态码可以快速跳过出现异常行为(内存不足、文件系统问题等)的服务器,但在这种情况下,最好立即将连接重新分派到另一台服务器(请参阅 "option redispatch")。最后,重要的是要理解,大多数失败的原因是请求本身,而重试导致服务器行为异常的请求通常会使该服务器的情况变得更糟,或者在重新分派的情况下使整个服务变得更糟。除非您确切地知道应用程序如何处理重放的请求,否则不应使用此指令。默认值为 "conn-failure"。
示例
retry-on 503 504
server <name> <address>[:[port]] [param*]
在后端中声明一个服务器

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<name> 是分配给此服务器的内部名称。此名称将出现在日志和警报中。如果设置了 "http-send-name-header",它将被添加到发送到服务器的请求头中。 <address> 是服务器的 IPv4 或 IPv6 地址。或者,也支持可解析的主机名,但此名称将在启动时解析。地址 "0.0.0.0" 或 "*" 具有特殊含义。它表示连接将被转发到与客户端连接相同的 IP 地址。这对于透明代理架构非常有用,其中客户端的连接被拦截,haproxy 必须转发到原始目标地址。这或多或少是 "transparent" 关键字的作用,除了使用服务器可以限制并发性和报告统计信息。可选地,可以在地址前面使用地址族前缀来强制指定地址族,而忽略地址格式,这在指定没有斜杠 ('/') 的 unix 套接字路径时非常有用。目前支持的前缀是: - 'ipv4@' -> 地址始终为 IPv4 - 'ipv6@' -> 地址始终为 IPv6 - 'unix@' -> 地址是本地 unix 套接字的路径 - 'abns@' -> 地址在抽象命名空间 (仅限 Linux) - 'sockpair@' -> 地址是已连接的 unix 套接字或套接字对的 FD。在连接期间,后端创建一个套接字对,并将其中一个通过 FD 传递。绑定部分将使用接收到的套接字作为客户端 FD。应谨慎使用。您可能希望在地址参数中引用某些环境变量,请参阅 第 2.3 节关于环境变量的内容。" init-addr" 设置可用于修改启动时 IP 地址的解析方式。 <port> 是一个可选的端口规范。如果设置,所有连接都将发送到此端口。如果未设置,将使用客户端连接的相同端口。端口也可以用 "+" 或 "-" 前缀。在这种情况下,服务器的端口将通过将此值加到客户端端口来确定。 <param*> 是此服务器的参数列表。"server" 关键词接受大量选项,并有一个专门的章节介绍。有关更多详细信息,请参阅 第 5 节
示例
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server transp ipv4@ server backup "${SRV_BACKUP}:1080" backup server www1_dc1 "${LAN_DC1}.101:80" server www1_dc2 "${LAN_DC2}.101:80"
注意:关于 Linux 的抽象命名空间套接字,HAProxy 使用整个 sun_path 长度作为地址长度。其他一些程序,如 socat,默认只使用字符串长度。在 socat 中对任何抽象套接字定义传递选项 ",unix-tightsocklen=0",以使其与 HAProxy 兼容。
server-state-file-name [ { use-backend-name | <file> } ]
设置要读取、加载并应用于此后端中可用服务器的服务器状态文件。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
它仅在指令 "load-server-state-from-file" 设置为 "local" 时适用。当未提供 <file> 时,如果使用了 "use-backend-name" 或未设置此指令,则使用后端名称。如果 <file> 以斜杠 '/' 开头,则它被视为绝对路径。否则,<file> 将与全局指令 "server-state-base" 连接。
示例
下面的最小配置将使 HAProxy 查找状态服务器文件 '/etc/haproxy/states/bk'
global server-state-file-base /etc/haproxy/states backend bk load-server-state-from-file
server-template <prefix> <num | range> <fqdn>[:<port>] [params*]
设置一个模板来初始化具有共享参数的服务器。这些服务器的名称由 <prefix> 和 <num | range> 参数构建。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<prefix> 用于生成服务器名称的前缀。 <num | range> 如果提供了 <num>,此模板将初始化 <num> 个服务器,其服务器名称后缀从 1 到 <num>。也可以使用数字范围 <num_low>-<num_high> 来使用 <num_low> 到 <num_high> 作为服务器名称后缀。 <fqdn> 此模板初始化的所有服务器的 FQDN。 <port> 与 "server" <port> 参数的含义相同(请参阅 "server" 关键词)。 <params*> 剩余的服务器参数,包括 "server" 关键词支持的所有参数。
示例
# 初始化 3 个服务器,名称分别为 srv1、srv2 和 srv3, # FQDN 为 google.com,并启用了健康检查。 server-template srv 1-3 google.com:80 check # 或 server-template srv 3 google.com:80 check # 将等同于: server srv1 google.com:80 check server srv2 google.com:80 check server srv3 google.com:80 check
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<port>] [interface <name>]
设置出站连接的源地址

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<addr> 是 HAProxy 在连接到服务器之前将绑定的 IPv4 地址。此地址也用作健康检查的源。默认值 0.0.0.0 表示系统将选择最适合访问目标的地址。可选地,可以在地址前面使用地址族前缀来强制指定地址族,而忽略地址格式,这在指定没有斜杠 ('/') 的 unix 套接字路径时非常有用。目前支持的前缀是: - 'ipv4@' -> 地址始终为 IPv4 - 'ipv6@' -> 地址始终为 IPv6 - 'unix@' -> 地址是本地 unix 套接字的路径 - 'abns@' -> 地址在抽象命名空间 (仅限 Linux) 您可能希望在地址参数中引用某些环境变量,请参阅 第 2.3 节关于环境变量的内容。 <port> 是一个可选端口。通常不需要,但在某些非常特殊的情况下可能有用。默认值零表示系统将选择一个空闲端口。请注意,后端不支持端口范围。如果您想强制使用端口范围,必须在每个 "server" 行上指定它们。 <addr2> 在连接以完全透明代理模式转发时要呈现给服务器的 IP 地址。目前仅在某些已修补的 Linux 内核上支持。当指定此地址时,连接到服务器的客户端将看到此地址,而健康检查仍将使用 <addr> 地址。 <port2> 在连接以完全透明代理模式转发时要呈现给服务器的可选端口(参见上面的 <addr2>)。默认值零表示系统将选择一个空闲端口。 <hdr> 是用于获取绑定 IP 的 HTTP 头名称。这是逗号分隔的头列表名称,可以包含多个 IP 地址。默认情况下,使用最后一个出现的值。此功能旨在与 X-Forwarded-For 头配合使用,并自动绑定到由先前代理看到的客户端 IP 地址,通常是 Stunnel。为了使用最后一个值以外的其他值,请参阅下面的 <occ> 参数。当找不到头(或出现项)时,不执行绑定,因此使用代理的默认 IP 地址。还要记住,头名称不区分大小写,就像任何 HTTP 头一样。 <occ> 是要用于多值头的值的出现次数。这需要与 "hdr_ip(<hdr>)" 结合使用,以指定要用于源 IP 地址的出现次数。正值表示从第一个出现项开始的位置,1 表示第一个。负值表示相对于最后一个出现项的位置,-1 表示最后一个。这对于 X-Forwarded-For 头在基础设施入口处设置,并且必须在多个代理层之后使用的情况很有用。当未指定此值时,假定为 -1。传递零将禁用此功能。 <name> 是要绑定到出站流量的可选接口名称。在支持此功能的系统上(目前仅限 Linux),这允许将所有到服务器的流量绑定到此接口,即使它不是系统根据路由表选择的接口。应极其谨慎地使用此选项。请注意,使用此选项需要 root 权限。
source” 关键字在复杂环境中很有用,因为在这些环境中只允许特定的地址连接到服务器。当必须通过公共网关使用私有地址时,可能需要此关键字,并且已知系统无法自行确定适当的源地址。通过可选关键字 "usesrc" 可以使用某些已修补的 Linux 内核上的扩展。它使得可以使用不属于系统本身的 IP 地址连接到服务器。这被称为 "完全透明代理模式"。为此,目标服务器必须将其流量路由回此地址,并且通常需要在运行 HAProxy 的机器上启用 IP 转发。在此 "完全透明代理模式" 下,可以强制向服务器呈现特定的 IP 地址。实际上很少使用此功能。更常见的用途是告诉 HAProxy 呈现客户端的 IP 地址。为此,有两种方法: - 呈现客户端的 IP 和端口地址。这是最透明的模式,但如果启用了 IP 连接跟踪,可能会导致问题,因为同一个连接可能被看到两次,状态不同。然而,此解决方案的巨大优点是不限制系统使用 64k 个出站地址+端口对,因为可以使用所有客户端范围。 - 只呈现客户端的 IP 地址并选择一个备用端口。此解决方案仍然相当优雅,但透明度略低(下游防火墙日志将与上游不匹配)。它还有一个缺点,即将并发连接的数量限制为通常的 64k 个端口。然而,由于上游和下游端口不同,机器上的本地 IP 连接跟踪不会因重复使用同一会话而受到影响。此选项设置后端所有服务器的默认源。它也可以在 "defaults" 部分指定。通过服务器级别的 "source" 服务器选项可以进行更精细的源地址指定。有关更多信息,请参阅 第 5 节。为了使 "usesrc" 生效,需要 root 权限。
示例
backend private # 使用我们的 192.168.1.200 源地址连接到服务器 source 192.168.1.200 backend transparent_ssl1 # 从客户端源地址连接到 SSL Farm source 192.168.1.200 usesrc clientip backend transparent_ssl2 # 从客户端源地址和端口连接到 SSL Farm # 如果本地机器上有 IP conntrack,不推荐使用。 source 192.168.1.200 usesrc client backend transparent_ssl3 # 从客户端源地址连接到 SSL Farm。 # 它对 conntrack 更友好。 source 192.168.1.200 usesrc clientip backend transparent_smtp # 使用客户端源地址/端口连接到 SMTP Farm # 使用 Tproxy v4。 source 0.0.0.0 usesrc clientip backend transparent_http # 使用先前代理看到的客户端 IP 连接到服务器。 source 0.0.0.0 usesrc hdr_ip(x-forwarded-for,-1)
stats admin { if | unless } <cond>
如果/除非条件匹配,则启用统计信息管理级别

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
此语句在满足 if/unless 条件时启用统计信息的管理员级别。管理员级别允许从 Web 界面启用/禁用服务器。默认情况下,出于安全原因,统计信息页面是只读的。注意:在多进程模式(nbproc > 1)下,请谨慎使用此功能,除非您了解其作用:进程之间不共享内存,这可能导致行为不确定。目前,POST 请求受限于缓冲区大小减去预留的缓冲区空间,这意味着如果服务器列表太长,请求将不会被处理。建议一次修改少数服务器。
示例
# 仅对 localhost 启用统计信息管理级别 backend stats_localhost stats enable stats admin if LOCALHOST
示例
# 由于身份验证,统计信息管理级别始终启用 backend stats_auth stats enable stats auth admin:AdMiN123 stats admin if TRUE
示例
# 统计信息管理级别取决于经过身份验证的用户 userlist stats-auth group admin users admin user admin insecure-password AdMiN123 group readonly users haproxy user haproxy insecure-password haproxy backend stats_auth stats enable acl AUTH http_auth(stats-auth) acl AUTH_ADMIN http_auth_group(stats-auth) admin stats http-request auth unless AUTH stats admin if AUTH_ADMIN
stats auth <user>:<passwd>
启用带身份验证的统计信息,并为一个账户授予访问权限

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<user> 是要授予访问权限的用户名 <passwd> 是与此用户关联的明文密码
此语句启用具有默认设置的统计信息,并将访问限制为仅声明的用户。可以根据需要重复此语句,以允许任意数量的用户。当用户尝试在没有有效帐户的情况下访问统计信息时,将返回 "401 Forbidden" 响应,以便浏览器提示用户提供有效的用户名和密码。将返回给浏览器的真实身份可使用 "stats realm" 进行配置。由于身份验证方法是 HTTP Basic Authentication,密码会在网络上以明文形式传输。因此,决定配置文件也将使用明文密码,以提醒用户这些密码不应敏感,也不应与任何其他帐户共享。还可以使用 "stats scope" 来缩小报告中出现的代理范围。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置,以避免依赖不直观的默认参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
使用默认设置启用统计报告

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
此语句使用构建时定义的默认设置启用统计报告。除非另有说明,否则将使用以下设置:- stats uri : /haproxy?stats - stats realm : "HAProxy Statistics" - stats auth : 无身份验证 - stats scope : 无限制 尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
启用统计信息并隐藏 HAProxy 版本报告

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
默认情况下,统计页面会报告一些有用的状态信息以及统计数据。其中包括 HAProxy 的版本。但是,通常认为向任何人报告精确的版本是危险的,因为它可能帮助他们利用已知弱点进行特定攻击。“stats hide-version”语句从统计报告中移除版本信息。建议对公共站点或任何具有弱登录名/密码的站点使用此功能。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stats http-request { allow | deny | auth [realm <realm>] } [ { if | unless } <condition> ]
统计信息的访问控制

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
与 "http-request" 类似,这组选项允许精确控制对统计信息的访问。每个选项后面可以跟 if/unless 和 acl。第一个匹配条件(或没有条件的选项)的选项是最终的。对于 "deny",将返回 403 错误;对于 "allow",将执行正常处理;对于 "auth",将返回 401/407 错误代码,以便客户端被要求输入用户名和密码。每个实例的 http-request 语句数量没有固定限制。
stats realm <realm>
启用统计信息并设置身份验证领域

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<realm> 是报告给浏览器的 HTTP 基本认证领域的名称。浏览器用它在弹出窗口中显示,邀请用户输入有效的用户名和密码。
领域被读取为单个词,因此其中的任何空格都应使用反斜杠('\')进行转义。此语句仅在与“stats auth”结合使用时才有用,因为它只与身份验证相关。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
启用带自动刷新的统计信息

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<delay> 是建议的刷新延迟,以秒为单位指定,它将返回给查看报告页面的浏览器。虽然浏览器可以自由应用任何延迟,但通常会遵守它并每隔这么多秒刷新一次页面。刷新间隔可以用任何其他非默认的时间单位指定,方法是在值后面加上单位后缀,如本文档开头所述。
此语句在监控显示器上非常有用,可以永久显示报告负载均衡器活动的页面。设置后,HTML 报告页面将包含一个“刷新”/“停止刷新”的链接,以便用户可以选择是否希望页面自动刷新。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stats scope { <name> | "." }
启用统计信息并限制访问范围

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<name> 是要报告的 listen、frontend 或 backend 部分的名称。特殊名称“.”(一个点)表示该语句所在的节。
指定此语句后,只有使用此语句枚举的部分才会出现在报告中。所有其他部分都将被隐藏。如果需要报告多个部分,此语句可以根据需要出现多次。请注意,名称检查是作为简单的字符串比较执行的,并且从不检查给定的部分名称是否真的存在。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stats show-desc [ <desc> ]
在统计页面上启用描述的报告。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
<desc> 是一个可选的要报告的描述。如果未指定,则自动使用全局部分的描述。此语句对于向客户提供共享服务的用户非常有用,其中每个客户的节点或描述应该不同。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认情况下不显示描述。
示例
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-desc Master node for Europe, Asia, Africa stats uri /admin?stats stats refresh 5s
在统计页面上启用额外信息的报告

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数:
在统计信息页面上启用报告附加信息: - cap: 功能(代理) - mode: tcp, http 或 health 之一(代理) - id: SNMP ID(代理、套接字、服务器) - IP(套接字、服务器) - cookie(后端、服务器) 尽管仅此语句就足以启用统计信息报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认行为是不显示此信息。
stats show-node [ <name> ]
在统计页面上启用主机名的报告。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<name> 是一个可选的要报告的名称。如果未指定,则自动使用全局部分的节点名称。
此语句对于向其客户提供共享服务的用户非常有用,在为每个客户提供的统计页面上,节点或描述可能会有所不同。默认行为是不显示主机名。虽然仅此语句就足以启用统计报告,但建议设置所有其他设置,以避免依赖于默认的不明显参数。
示例
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-node Europe-1 stats uri /admin?stats stats refresh 5s
stats uri <prefix>
启用统计信息并定义访问它们的 URI 前缀

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<prefix> 是任何将被重定向到统计信息的 URI 的前缀。此前缀可能包含一个问号('?')以指示查询字符串的一部分。
统计 URI 在中继流量上被拦截,因此它作为正常应用程序的一部分页面显示。强烈建议确保所选 URI 永远不会出现在应用程序中,否则将永远无法在应用程序中访问它。haproxy 中编译的默认 URI 是 "/haproxy?stats",但这可以在构建时更改,因此最好在此处始终明确指定。通常在 URI 中包含问号是一个好主意,这样中间代理就不会缓存结果。此外,由于以该前缀开头的任何字符串都将被接受为统计请求,问号有助于确保没有有效的 URI 会以相同的单词开头。有时使用 "/" 作为 URI 前缀并将此语句放在其自身的 "listen" 实例中非常方便。这使得可以轻松地将一个地址或端口专门用于统计信息。尽管此语句本身足以启用统计信息报告,但建议设置所有其他设置,以避免依赖不直观的默认参数。
示例
# 公共访问(仅限于此后端) backend public_www server srv1 192.168.0.1:80 stats enable stats hide-version stats scope . stats uri /admin?stats stats realm HAProxy\ Statistics stats auth admin1:AdMiN123 stats auth admin2:AdMiN321 # 内部监控访问(无限制) backend private_monitoring stats enable stats uri /admin?stats stats refresh 5s
stick match <pattern> [table <table>] [{if | unless} <cond>]
定义一个请求模式匹配条件,以将用户粘滞到一台服务器上

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<pattern> 是 第 7.3 节 中描述的样本表达式规则。它描述了将分析传入请求或连接的哪些元素,以期在粘性表中找到匹配的条目。此规则是强制性的。 <table> 是一个可选的粘性表名称。如果未指定,则使用相同后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是一个可选的匹配条件。它使得仅在满足(或不满足)其他条件时才对某个标准进行匹配成为可能。例如,它可以用于匹配源 IP 地址,除非请求通过一个已知的代理,在这种情况下,我们将匹配包含该 IP 地址的头。
某些协议或应用程序需要复杂的粘性规则,并且不能总是简单地依赖 cookie 或哈希。"stick match" 语句描述了一条规则,用于从传入的请求或连接中提取粘性标准。有关可能的模式和转换规则的完整列表,请参阅 第 7 节。该表必须使用 "stick-table" 语句声明。它必须是与模式兼容的类型。默认情况下,它是同一后端中存在的表。可以通过使用 "table" 关键字引用来与其他后端共享表。如果引用了另一个表,则使用后端中的服务器 ID。默认情况下,每个后端中的所有服务器 ID 都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其 "id" 设置强制设置服务器 ID。可以使用 "if" 或 "unless" 后跟条件来限制 "stick match" 语句适用的条件。有关基于 ACL 的条件,请参阅 第 7 节。"stick match" 语句的数量没有限制。第一个适用的并匹配的语句将导致请求被定向到用于创建条目的请求所使用的相同服务器。这样,可以使用多个匹配作为回退。粘性规则在持久性 cookie 之后进行检查,因此如果已经使用了 cookie 来选择服务器,它们不会影响粘性。这样,可以轻松地插入 cookie 并按 IP 地址匹配,以在 HTTP 和 HTTPS 之间保持粘性。注意:在多进程模式 (nbproc > 1) 下使用此功能时请谨慎,除非您知道自己在做什么:进程之间不共享内存,这可能导致随机行为。
示例
# 将 SMTP 用户转发到他们在过去 30 分钟内 # 刚刚用于 POP 的同一台服务器 backend pop mode tcp balance roundrobin stick store-request src stick-table type ip size 200k expire 30m server s1 192.168.1.1:110 server s2 192.168.1.1:110 backend smtp mode tcp balance roundrobin stick match src table pop server s1 192.168.1.1:25 server s2 192.168.1.1:25
stick on <pattern> [table <table>] [{if | unless} <condition>]
定义一个请求模式,将用户与服务器关联起来

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
注意:此形式等同于 "stick match" 后跟 "stick store-request",所有参数相同。请参考这两个关键字了解详情。它仅为方便编写更易于维护的配置而提供。注意:在多进程模式(nbproc > 1)下,请谨慎使用此功能,除非您了解其作用:进程之间不共享内存,这可能导致行为不确定。
示例
# 以下形式... stick on src table pop if !localhost # ...与此形式完全等价: stick match src table pop if !localhost stick store-request src table pop if !localhost # 对 HTTP 使用 cookie 持久性,对 HTTPS 以及 # 没有 cookie 的 HTTP 使用源地址粘滞。在两种访问之间共享同一个表。 backend http mode http balance roundrobin stick on src table https cookie SRV insert indirect nocache server s1 192.168.1.1:80 cookie s1 server s2 192.168.1.1:80 cookie s2 backend https mode tcp balance roundrobin stick-table type ip size 200k expire 30m stick on src server s1 192.168.1.1:443 server s2 192.168.1.1:443
stick store-request <pattern> [table <table>] [{if | unless} <condition>]
定义一个用于在粘滞表中创建条目的请求模式

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<pattern> 是 第 7.3 节 中描述的样本表达式规则。它描述了在选择服务器后,将分析、提取并存储在表中的传入请求或连接的哪些元素。 <table> 是一个可选的粘性表名称。如果未指定,则使用相同后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是一个可选的存储条件。它使得仅在满足(或不满足)某些条件时才存储某些标准成为可能。例如,它可以用于存储源 IP 地址,除非请求通过一个已知的代理,在这种情况下,我们将存储一个包含该 IP 地址的头的转换形式。
某些协议或应用程序需要复杂的粘性规则,并且不能总是简单地依赖 cookie 或哈希。"stick store-request" 语句描述了一条规则,用于决定从请求中提取什么以及何时提取,以便将其存储到粘性表中,供后续请求使用 "stick match" 语句进行匹配。显然,提取的部分必须有意义并且有机会在后续请求中匹配。例如,存储客户端的 IP 地址通常是有意义的。存储 URL 参数中的 ID 也有意义。存储源端口几乎没有意义,因为它是随机匹配的。有关可能的模式和转换规则的完整列表,请参阅 第 7 节。该表必须使用 "stick-table" 语句声明。它必须是与模式兼容的类型。默认情况下,它是同一后端中存在的表。可以通过使用 "table" 关键字引用来与其他后端共享表。如果引用了另一个表,则使用后端中的服务器 ID。默认情况下,每个后端中的所有服务器 ID 都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其 "id" 设置强制设置服务器 ID。可以使用 "if" 或 "unless" 后跟条件来限制 "stick store-request" 语句适用的条件。在解析请求时将评估此条件,因此可以使用任何标准。有关基于 ACL 的条件,请参阅 第 7 节。"stick store-request" 语句的数量没有限制,但每个请求或响应同时存储的数量限制为 8 个。这使得最多可以存储 8 个标准,所有这些标准都可以从请求或响应中提取,而不管规则的数量如何。只有匹配的前 8 个将被保留。使用此功能,可以一次填充多个表,以增加在其他协议或访问方法上识别用户的机会。可以使用多个 store-request 规则与同一个表,并通过按降序排列的偏好顺序来查找最可靠的标准。对于给定的表,只会存储第一个提取的标准。所有后续引用相同表的 store-request 规则将被跳过,并且它们的 ACL 将不会被评估。 "store-request" 规则在服务器连接建立后进行评估,因此表将包含处理请求的实际服务器。注意:在多进程模式 (nbproc > 1) 下使用此功能时请谨慎,除非您知道自己在做什么:进程之间不共享内存,这可能导致随机行为。
示例
# 将 SMTP 用户转发到他们在过去 30 分钟内 # 刚刚用于 POP 的同一台服务器 backend pop mode tcp balance roundrobin stick store-request src stick-table type ip size 200k expire 30m server s1 192.168.1.1:110 server s2 192.168.1.1:110 backend smtp mode tcp balance roundrobin stick match src table pop server s1 192.168.1.1:25 server s2 192.168.1.1:25
stick-table type {ip | integer | string [len <length>] | binary [len <length>]} size <size> [expire <expire>] [nopurge] [peers <peersect>] [store <data_type>]*
为当前部分配置粘滞表

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
参数
ip 声明为 "type ip" 的表将只存储 IPv4 地址。这种形式非常紧凑(每个条目约 50 字节),并且允许非常快速的条目查找和存储,开销几乎为零。这主要用于存储客户端源 IP 地址。 ipv6 声明为 "type ipv6" 的表将只存储 IPv6 地址。这种形式非常紧凑(每个条目约 60 字节),并且允许非常快速的条目查找和存储,开销几乎为零。这主要用于存储客户端源 IP 地址。 integer 声明为 "type integer" 的表将存储 32 位整数,例如可以代表请求中找到的客户端标识符。 string 声明为 "type string" 的表将存储最多 <len> 个字符的子字符串。如果模式提取器提供的字符串长度大于 <len>,将在存储前被截断。匹配时,表中的字符串和提取的模式之间最多比较 <len> 个字符。未指定时,字符串自动限制为 32 个字符。 binary 声明为 "type binary" 的表将存储 <len> 字节的二进制块。如果模式提取器提供的块长度大于 <len>,将在存储前被截断。如果样本表达式提供的块短于 <len>,它将用 0 填充。未指定时,块自动限制为 32 字节。 <length> 是存储在 "string" 类型表中的最大字符数(参见上面的 "string" 类型)。或 "binary" 类型表中的块字节数。更改此参数时要小心,因为内存使用量将成比例增加。 <size> 是可以放入表中的最大条目数。此值直接影响内存使用量。每个条目约计算 50 字节,加上字符串的大小(如果有)。size 支持 "k"、"m"、"g" 后缀,分别表示 2^10、2^20 和 2^30 因子。 [nopurge] 表示当表已满时,我们拒绝清除旧条目。未指定时,当 haproxy 想要在表中存储条目但表已满时,它将刷新一些最旧的条目以释放一些空间供新条目使用。这通常是期望的行为。在某些特定情况下,拒绝新条目而不是清除旧条目可能是可取的。当要存储的数据量远超硬件限制,并且我们宁愿不提供对新客户端的访问,而不是拒绝已连接的客户端时,可能会发生这种情况。使用此参数时,请务必正确设置 "expire" 参数(见下文)。 <peersect> 是用于复制的 peers 部分的名称。将键与服务器 ID 关联的条目将与此部分中声明的远程对等节点同步。所有条目在软重新启动期间也会自动从本地对等节点(旧进程)学习。注意:每个 peers 部分只能被属于同一唯一进程的表引用。 <expire> 定义了条目在表中自上次创建、使用 'track-sc' 刷新或使用 'stick match' 或 'stick on' 规则匹配以来的最大持续时间。过期延迟使用标准时间格式定义,类似于各种超时。最大持续时间略高于 24 天。有关更多信息,请参阅 第 2.4 节。如果未指定此延迟,则会话不会自动过期,但表满时会删除旧条目。请确保不要使用 "nopurge" 参数,如果未指定过期延迟。注意:'table_*' 转换器执行查找但不更新过期时间,因为它们不需要 'track-sc'。 <data_type> 用于在 stick-table 中存储附加信息。这可能被 ACL 用于控制与匹配 stick-table 的客户端活动相关的各种标准。对于此处指定的每个项目,每个条目的大小将增加,以便附加数据可以容纳。多个数据类型可以与一个条目一起存储。多个数据类型可以用逗号分隔的列表在 "store" 关键字后指定。或者,可以重复 "store" 关键字后跟一个或多个数据类型。除了 "server_id" 类型(自动检测并启用)之外,所有数据类型都必须显式声明才能存储。如果 ACL 引用了未存储的数据类型,ACL 将简单地不匹配。某些数据类型需要一个参数,该参数必须在类型后面用括号传递。有关支持的数据类型及其参数,请参阅下文。
可存储在条目中的数据类型如下:- server_id:这是一个整数,用于保存请求分配到的服务器的数字 ID。它被“stick match”、“stick store”和“stick on”规则使用。当被引用时,它会自动启用。- gpc0:第一个通用计数器。它是一个正的 32 位整数,可用于任何目的。大多数情况下,它将用于为某些条目打上特殊标签,例如,用于指出检测到特定的行为,并且在未来的匹配中必须知道。- gpc0_rate(<period>):第一个通用计数器在一段时间内的递增速率。它是一个正的 32 位整数,可用于任何目的。与 <gpc0> 类似,它计算事件,但它维护计数器递增的速率,而不是保持累积数量。大多数情况下,它将用于衡量特定事件(例如,对特定 URL 的请求)的发生频率。- gpc1:第二个通用计数器。它是一个正的 32 位整数,可用于任何目的。大多数情况下,它将用于为某些条目打上特殊标签,例如,用于指出检测到特定的行为,并且在未来的匹配中必须知道。- gpc1_rate(<period>):第二个通用计数器在一段时间内的递增速率。它是一个正的 32 位整数,可用于任何目的。与 <gpc1> 类似,它计算事件,但它维护计数器递增的速率,而不是保持累积数量。大多数情况下,它将用于衡量特定事件(例如,对特定 URL 的请求)的发生频率。- gpt0:第一个通用标签。它是一个正的 32 位整数,可用于任何目的。大多数情况下,它将用于为某些条目打上特殊标签,例如,用于指出检测到特定的行为,并且在未来的匹配中必须知道。- conn_cnt:连接计数。这是一个正的 32 位整数,用于计算来自匹配此条目的客户端的已接收连接的总数。这并不意味着连接已被接受,只是它们已被接收。- conn_cur:当前连接。这是一个正的 32 位整数,用于存储条目的并发连接计数。当一个入站连接匹配此条目时,它会增加,当连接离开时,它会减少。这样,就可以随时知道条目的确切并发连接数。- conn_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内平均入站连接速率,单位为“每周期连接数”。结果是一个整数,可以使用 ACL 进行匹配。- sess_cnt:会话计数。这是一个正的 32 位整数,用于计算来自匹配此条目的客户端的已接收会话的总数。会话是由第 4 层规则接受的连接。- sess_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内平均入站会话速率,单位为“每周期会话数”。结果是一个整数,可以使用 ACL 进行匹配。- http_req_cnt:HTTP 请求计数。这是一个正的 32 位整数,用于计算来自匹配此条目的客户端的已接收 HTTP 请求的总数。请求是否有效无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。- http_req_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内平均 HTTP 请求速率,单位为“每周期请求数”。结果是一个整数,可以使用 ACL 进行匹配。请求是否有效无关紧要。请注意,当客户端使用 keep-alive 时,这与会话不同。- http_err_cnt:HTTP 错误计数。这是一个正的 32 位整数,用于计算由匹配此条目的客户端引起的已接收 HTTP 请求错误的Số lượng。错误被计入无效和截断的请求,以及被拒绝或缓慢处理的请求,以及身份验证失败的请求。如果服务器响应 4xx,则该请求也被计为一个错误,因为它是由客户端触发的错误(例如,漏洞扫描)。- http_err_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内平均 HTTP 请求错误速率,单位为“每周期请求数”(上面 http_err_cnt 中已说明何种情况被视为错误)。结果是一个整数,可以使用 ACL 进行匹配。- bytes_in_cnt:客户端到服务器的字节计数。这是一个正的 64 位整数,用于计算从匹配此条目的客户端接收到的字节的累积数量。标题包含在计数中。这可能用于限制照片或视频服务器上上传功能的滥用。- bytes_in_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内平均入站字节速率,单位为“每周期字节数”。它可能用于检测上传过多过快(上传数据量)的用户。警告:对于大型上传,上传的数据量可能会在终止时被计算一次,从而导致平均传输速度出现峰值,而不是平滑的。虽然可以使用“option contstats”来部分平滑,但这还不完美。建议使用 byte_in_cnt 以获得更好的公平性。- bytes_out_cnt:服务器到客户端的字节计数。这是一个正的 64 位整数,用于计算发送到匹配此条目的客户端的字节的累积数量。标题包含在计数中。这可能用于限制机器人程序下载整个站点的滥用。- bytes_out_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示测量平均值的周期长度。它报告该周期内平均出站字节速率,单位为“每周期字节数”。它可能用于检测下载过多过快(传输数据量)的用户。警告:对于大型传输,传输的数据量可能会在终止时被计算一次,从而导致平均传输速度出现峰值,而不是平滑的。虽然可以使用“option contstats”来部分平滑,但这还不完美。建议使用 byte_out_cnt 以获得更好的公平性。每个代理只有一个 stick-table。在编写本文档时,拥有多个代理表似乎没有用。如果需要,只需创建一个带有 stick-table 的虚拟后端并引用它。重要的是要理解,基于学习信息的粘性有一些限制,包括在没有正确配置对等方来在重启时传输这些信息(推荐)的情况下,所有学习到的关联都会在重启时丢失。总的来说,它可以作为补充,但不能总是作为独占的粘性。最后,内存需求可能很重要,尤其是在存储多种数据类型时。事实上,在每个条目中同时存储所有上述指标需要每个条目 116 字节,或者对于 100 万个条目的表需要 116 MB。这绝对是不可忽视的。
示例
# 在 5 分钟内跟踪多达 100 万个 IP 地址的计数器 # 并存储一个通用计数器和在 30 秒滑动窗口上计算的 # 平均连接速率。 stick-table type ip size 1m expire 5m store gpc0,conn_rate(30s)
stick store-response <pattern> [table <table>] [{if | unless} <condition>]
定义一个用于在粘滞表中创建条目的响应模式

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<pattern> 是 第 7.3 节 中描述的样本表达式规则。它描述了在选择服务器后,将分析、提取并存储在表中的响应或连接的哪些元素。 <table> 是一个可选的粘性表名称。如果未指定,则使用相同后端的表。粘性表使用 "stick-table" 语句声明。 <cond> 是一个可选的存储条件。它使得仅在满足(或不满足)某些条件时才存储某些标准成为可能。例如,它可以用于仅在响应是 SSL 服务器 hello 时存储 SSL 会话 ID。
某些协议或应用程序需要复杂的粘性规则,并且不能总是简单地依赖 cookie 或哈希。 “stick store-response”语句描述了一个规则,用于决定从响应中提取什么以及何时提取,以便将其存储到粘性表中,以便后续请求使用“stick match”语句进行匹配。显然,提取的部分必须是有意义的,并且有机会在后续请求中匹配。存储响应头中找到的 ID 是有意义的。有关可能的模式和转换规则的完整列表,请参阅 第 7 节。表必须使用“stick-table”语句声明。它必须是与模式兼容的类型。默认情况下,它是存在于同一后端中的那个。可以通过使用“table”关键字来引用其他后端来与其他后端共享表。如果引用了另一个表,则使用后端中的服务器 ID。默认情况下,每个后端中的所有服务器 ID 都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其“id”设置强制指定服务器 ID。可以使用“if”或“unless”后跟一个条件来限制“stick store-response”语句适用的条件。在解析响应时将评估此条件,因此可以使用任何标准。有关基于 ACL 的条件,请参阅 第 7 节。“stick store-response”语句的数量没有限制,但每个请求或响应的并发存储限制为 8 个。这样,就可以存储多达 8 个标准,所有这些标准都从请求或响应中提取,而不管规则的数量。只有匹配的前 8 个标准将被保留。通过使用此功能,可以一次性填充多个表,以期增加识别另一协议或访问方法的用户的机会。使用具有相同表的多个 store-response 规则是可能的,并且可以通过按递减的偏好顺序排列规则来找到最可靠的标准。对于给定的表,将只存储第一个提取的标准。后续引用同一表的 store-response 规则将被跳过,并且其 ACL 将不会被评估。然而,即使 store-request 规则引用了一个表,store-response 规则也可以使用同一个表。这意味着每个表一次可以学习请求中的一个元素和响应中的一个元素。该表将包含处理请求的实际服务器。
示例
# 从请求和响应中学习 SSL 会话 ID 并创建关联。 backend https mode tcp balance roundrobin # 最大 SSL 会话 ID 长度为 32 字节。 stick-table type binary len 32 size 30k expire 30m acl clienthello req.ssl_hello_type 1 acl serverhello res.ssl_hello_type 2 # 使用 tcp content 接受来检测 ssl 客户端和服务器 hello。 tcp-request inspect-delay 5s tcp-request content accept if clienthello # 默认情况下,响应检查延迟没有超时。 tcp-response content accept if serverhello # SSL 会话 ID (SSLID) 可能存在于客户端或服务器 hello 中。 # 它的长度在偏移量 43 处以 1 字节编码,其值从 # 偏移量 44 处开始。 # 如果是客户端 hello,则在请求上匹配和学习。 stick on req.payload_lv(43,1) if clienthello # 如果是服务器 hello,则在响应上学习。 stick store-response resp.payload_lv(43,1) if serverhello server s1 192.168.1.1:443 server s2 192.168.1.1:443
tcp-check comment <字符串>
为接下来的 tcp-check 规则定义一个注释,如果失败,将在日志中报告。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<字符串> 是如果以下 tcp-check 规则失败时要在日志中添加的注释消息。
它仅适用于 connect、send 和 expect 规则。这对于进行用户友好的错误报告很有用。
tcp-check connect [default] [port <表达式>] [addr <ip>] [send-proxy] [via-socks4] [ssl] [sni <sni>] [alpn <alpn>] [linger] [proto <名称>] [comment <消息>]
打开一个新连接

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义一个消息,如果规则评估失败则报告。default 使用服务器行的默认选项来执行健康检查。仅当未重新定义时,才使用服务器选项。port <expr> 如果未设置,则使用端口或服务器端口。它告诉 HAProxy 在哪里建立连接。<port> 必须是一个有效的 TCP 端口源整数,范围从 1 到 65535,或一个 sample-fetch 表达式。addr <ip> 定义用于执行健康检查的 IP 地址。send-proxy 通过 socks4 发送 PROXY 协议字符串,启用使用上游 socks4 代理的出站健康检查。ssl 打开一个加密连接 sni <sni> 指定用于通过 SSL 执行健康检查的 SNI。alpn <alpn> 定义要使用 ALPN 宣告的协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不带引号)。如果未设置,则使用服务器 ALPN。proto <name> 强制连接要使用的复用器协议。它必须是 TCP 复用协议,并且必须可在后端侧使用。可用协议列表在 haproxy -vv 中报告。linger 清洁地关闭连接,而不是使用单个 RST。
当一个应用程序依赖于多个 TCP 端口,或者当 HAProxy 在一个后端中对许多服务进行负载均衡时,有必要在将服务器视为可运行之前单独探测所有服务。当服务器行上既没有配置 TCP 端口也没有 server port 指令时,那么 'tcp-check connect port <端口>' 必须是序列的第一步。在 tcp-check 规则集中,'connect' 是必需的,并且也必须用 'connect' 规则来开始规则集。目的是确保管理员知道他们在做什么。当一个 connect 必须开始规则集时,它前面仍然可以有 set-var、unset-var 或 comment 规则。
示例
# 检查服务器上的 HTTP 和 HTTPs 服务。 # 首先由于服务器行端口指令打开端口 80,然后 # tcp-check 打开端口 443,加密并在其上运行请求: option tcp-check tcp-check connect tcp-check send GET\ /\ HTTP/1.0\r\n tcp-check send Host:\ haproxy.1wt.eu\r\n tcp-check send \r\n tcp-check expect rstring (2..|3..) tcp-check connect port 443 ssl tcp-check send GET\ /\ HTTP/1.0\r\n tcp-check send Host:\ haproxy.1wt.eu\r\n tcp-check send \r\n tcp-check expect rstring (2..|3..) server www 10.0.0.1 check port 80 # 从单个服务器检查 POP 和 IMAP: option tcp-check tcp-check connect port 110 linger tcp-check expect string +OK\ POP3\ ready tcp-check connect port 143 tcp-check expect string *\ OK\ IMAP4\ ready server mail 10.0.0.1 check
tcp-check expect [min-recv <整数>] [comment <消息>] [ok-status <状态>] [error-status <状态>] [tout-status <状态>] [on-success <格式>] [on-error <格式>] [status-code <表达式>] [!] <匹配> <模式>
指定在通用健康检查期间要收集和分析的数据

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义一个消息,如果规则评估失败则报告。min-recv 是可选的,并且可以定义评估当前 expect 规则所需的最小数据量。如果接收到的字节数低于此限制,检查将等待更多数据。此选项可用于解决一些模糊的匹配规则,或避免对已知仍不完整的内容执行昂贵的正则表达式匹配。如果使用确切字符串(字符串或二进制),则使用字符串长度和此参数之间的最小值。如果此参数设置为 -1,则忽略它。如果 expect 规则不匹配,检查将等待更多数据。如果设置为 0,则评估结果始终是确定的。<match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是“string”、“rstring”、“binary”或“rbinary”之一。关键字前面可以加上感叹号(“!”)来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参阅下文。ok-status <st> 是可选的,并且可用于在 expect 规则成功评估并且它是 tcp-check 规则集中的最后一个规则时设置检查状态。支持“L7OK”、“L7OKC”、“L6OK”和“L4OK”:- L7OK:检查在第 7 层通过- L7OKC:检查在第 7 层有条件通过,例如 404 配合 disable-on-404- L6OK:检查在第 6 层通过- L4OK:检查在第 4 层通过默认使用“L7OK”。error-status <st> 是可选的,并且可用于在 expect 规则评估期间发生错误时设置检查状态。支持“L7RSP”、“L7STS”、“L6RSP”和“L4CON”:- L7RSP:第 7 层无效响应-协议错误- L7STS:第 7 层响应错误,例如 HTTP 5xx- L6RSP:第 6 层无效响应-协议错误- L4CON:第 1-4 层连接问题默认使用“L7RSP”。tout-status <st> 是可选的,并且可用于在 expect 规则评估期间发生超时时设置检查状态。支持“L7TOUT”、“L6TOUT”和“L4TOUT”:- L7TOUT:第 7 层(HTTP/SMTP)超时- L6TOUT:第 6 层(SSL)超时- L4TOUT:第 1-4 层超时默认使用“L7TOUT”。on-success <fmt> 是可选的,并且可用于在 expect 规则成功评估并且它是 tcp-check 规则集中的最后一个规则时自定义日志中报告的信息性消息。<fmt> 是一个日志格式字符串。on-error <fmt> 是可选的,并且可用于在 expect 规则评估期间发生错误时自定义日志中报告的信息性消息。<fmt> 是一个日志格式字符串。status-code <expr> 是可选的,并且可用于在成功或错误时设置日志中报告的检查状态码。<expr> 是一个标准的 HAProxy 表达式,由 sample-fetch 后跟一些转换器组成。<pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,则必须使用通常的反斜杠(“\”)进行转义。如果匹配设置为二进制,则模式必须以十六进制数字序列的形式传递,并且位数必须是偶数。每两个数字的序列代表一个字节。十六进制数字可以是大小写字母。
可用匹配项有意地与它们的 http-check 同类项相似:string <string>:测试响应缓冲区中的确切字符串匹配。如果响应缓冲区包含此确切字符串,则健康检查响应将被视为有效。如果“string”关键字前面带有“!”,则如果正文包含此字符串,响应将被视为无效。这可用于查找协议响应中的强制性模式,或在协议横幅中出现特定错误时检测失败。rstring <regex>:在响应缓冲区上测试正则表达式。如果响应缓冲区匹配此表达式,则健康检查响应将被视为有效。如果“rstring”关键字前面带有“!”,则如果正文匹配表达式,响应将被视为无效。string-lf <fmt>:在响应缓冲区中测试日志格式字符串匹配。如果响应缓冲区包含 <fmt> 求值结果的字符串(遵循日志格式规则),则健康检查响应将被视为有效。如果前面带有“!”,则如果缓冲区包含字符串,响应将被视为无效。binary <hexstring>:以十六进制形式测试响应缓冲区中的确切字符串匹配。如果响应缓冲区包含此确切的十六进制字符串,则健康检查响应将被视为有效。目的是匹配二进制协议上的数据。rbinary <regex>:在响应缓冲区上测试正则表达式,类似于“rstring”。但是,响应缓冲区被转换为其十六进制形式,包括 NUL 字节。这允许使用所有正则表达式引擎来匹配任何二进制内容。十六进制转换的大小是原始响应的两倍。因此,预期的模式最多应该在响应缓冲区大小的一半上工作。binary-lf <hexfmt>:在响应缓冲区中以十六进制形式测试日志格式字符串匹配。如果响应缓冲区包含 <fmt> 求值结果的十六进制字符串(遵循日志格式规则),则健康检查响应将被视为有效。如果前面带有“!”,则如果缓冲区包含十六进制字符串,响应将被视为无效。在匹配响应缓冲区之前,十六进制字符串被转换为二进制字符串。需要注意的是,响应将受到全局“tune.bufsize”选项定义的特定大小的限制,该选项默认为 16384 字节。因此,在“string”、“rstring”或 binary 选项时,过大的响应可能不包含必需的模式。如果绝对需要大型响应,可以通过设置全局变量来更改默认最大大小。但是,需要记住的是,解析非常大的响应可能会浪费一些 CPU 周期,尤其是在使用正则表达式时,并且始终最好将检查集中在较小的资源上。此外,在当前状态下,检查将在空字符之后找不到任何字符串或正则表达式。同样,无法请求匹配空字符。
示例
# 执行 POP 检查 option tcp-check tcp-check expect string +OK\ POP3\ ready # 执行 IMAP 检查 option tcp-check tcp-check expect string *\ OK\ IMAP4\ ready # 查找 redis 主服务器 option tcp-check tcp-check send PING\r\n tcp-check expect string +PONG tcp-check send info\ replication\r\n tcp-check expect string role:master tcp-check send QUIT\r\n tcp-check expect string +OK
tcp-check send <数据> [comment <消息>]
tcp-check send-lf <格式> [comment <消息>]
指定一个字符串或日志格式字符串,作为通用健康检查期间发送的问题

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义在规则评估失败时报告的消息。 <data> 是在通用健康检查会话期间将发送的字符串。 <fmt> 是在通用健康检查会话期间将发送的日志格式字符串(评估后)。
示例
# 查找 redis 主服务器 option tcp-check tcp-check send info\ replication\r\n tcp-check expect string role:master
tcp-check send-binary <十六进制字符串> [comment <消息>]
tcp-check send-binary-lf <十六进制格式> [comment <消息>]
指定一个十六进制数字字符串或十六进制数字日志格式字符串,作为原始 TCP 健康检查期间发送的二进制问题

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
comment <msg> 定义在规则评估失败时报告的消息。 <hexstring> 是在通用健康检查会话期间将发送的十六进制字符串(转换为二进制后)。 <hexfmt> 是在通用健康检查会话期间将发送的十六进制日志格式字符串(评估并转换为二进制后)。
示例
# 二进制 redis 检查 option tcp-check tcp-check send-binary 50494e470d0a # PING\r\n tcp-check expect binary 2b504F4e47 # +PONG
tcp-check set-var(<var-name>) <expr>
此操作设置变量的内容。变量是内联声明的。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量名的开头表示其作用域。tcp-check 允许的作用域是:"proc":变量与整个进程共享。"sess":变量与tcp-check会话共享。"check":变量在tcp-check的生命周期内声明。此前缀后跟一个名称。分隔符是"."。名称只能包含字符'a-z'、'A-Z'、'0-9'、'.'和'-'。<expr> 是一个sample-fetch表达式,后面可能跟着转换器。
示例
tcp-check set-var(check.port) int(1234)
tcp-check unset-var(<变量名>)
在其作用域内释放对变量的引用。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<var-name> 变量的名称以其作用域的指示开始。tcp-check 允许的作用域有: "proc":变量与整个进程共享。 "sess":变量与 tcp-check 会话共享。 "check":变量在 tcp-check 的生命周期内声明。 此前缀后跟一个名称。分隔符是 '.'。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '-'。
示例
tcp-check unset-var(check.port)
tcp-request connection <action> [{if | unless} <condition>]
根据第 4 层条件对传入连接执行操作

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的仅第 4 层的基于 ACL 的条件(见第 7 节)。
在接受新的入站连接后,可以立即评估某些条件,以决定是否必须接受或丢弃该连接,或跟踪其计数器。这些条件不能利用任何数据内容,因为连接尚未读取,缓冲区尚未分配。这用于非常快速地选择性地接受或丢弃来自各种源的连接,并且开销非常低。如果需要检查某些内容来做出决定,则必须改用“tcp-request content”语句。“tcp-request connection”规则按照其声明的顺序进行评估。如果没有规则匹配,或者根本没有规则,则默认操作是接受入站连接。可以插入的规则数量没有特定限制。支持四种类型的操作:- accept:如果条件为真(与“if”一起使用)或为假(与“unless”一起使用)则接受连接。执行的第一条此类规则会结束规则评估。- reject:如果条件为真(与“if”一起使用)或为假(与“unless”一起使用)则拒绝连接。执行的第一条此类规则会结束规则评估。拒绝的连接甚至不会成为会话,这就是为什么它们在统计信息中被单独计算为“denied connections”。它们不被计入会话速率限制,也不会被记录。原因是这些规则应该只用于过滤极高的连接速率,例如在大量 DDoS 攻击中遇到的情况。在这些极端情况下,记录每个事件的简单操作将导致系统崩溃,并大大降低过滤能力。如果确实需要记录,则应改用“tcp-request content”规则,因为“tcp-request session”规则也不会记录。- expect-proxy layer4:配置面向客户端的连接,在读取套接字中的任何字节之前接收 PROXY 协议头。这相当于在“bind”行上使用“accept-proxy”关键字,但使用 TCP 规则允许仅针对某些 IP 地址范围使用 ACL 来接受 PROXY 协议。当流量来自公共主机时,经过多层负载均衡器,这非常方便。- expect-netscaler-cip layer4:配置面向客户端的连接,在读取套接字中的任何字节之前接收 NetScaler 客户端 IP 插入协议头。这相当于在“bind”行上使用“accept-netscaler-cip”关键字,但使用 TCP 规则允许仅针对某些 IP 地址范围使用 ACL 来接受 PROXY 协议。当流量来自公共主机时,经过多层负载均衡器,这非常方便。- capture <sample> len <length>:这仅适用于“tcp-request content”规则。它从请求缓冲区捕获 sample 表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。生成的字符串将存储在下一个请求的“capture”槽中,因此它可能会出现在一些捕获的 HTTP 头部旁边。然后它会自动出现在日志中,并且可以通过 sample fetch 规则提取它以馈送到头部或其他任何地方。长度应该有限,因为此大小将为会话的整个生命周期中的每次捕获分配。有关更多信息,请参阅 第 7.3 节(Fetching samples)和“capture request header”。- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]:启用从当前连接跟踪粘性计数器。这些规则不会停止评估,也不会更改默认操作。同一连接可以同时跟踪的计数器数量在构建时由 MAX_SESS_STKCTR 设置(在 haproxy -vv 中报告),默认为 3,因此 track-sc 编号在 0 和 (MAX_SESS_STKCTR-1) 之间。执行的第一个“track-sc0”规则将指定表的计数器作为第一组进行跟踪。执行的第一个“track-sc1”规则将指定表的计数器作为第二组进行跟踪。执行的第一个“track-sc2”规则将指定表的计数器作为第三组进行跟踪。建议使用第一组计数器用于前端计数器,第二组用于后端计数器。但这只是一个指南,所有计数器都可以用在任何地方。这些操作接受一个或两个参数:<key> 是必需的,并且是一个 sample 表达式规则,如 第 7.3 节中所述。它描述了传入请求或连接的哪些元素将被分析、提取、组合并用于选择更新哪个表条目的计数器。请注意,“tcp-request connection”不能使用基于内容的 fetch。<table> 是一个可选的表,用于代替默认表,后者是当前代理中声明的 stick-table。然后,所有匹配和更新 key 的计数器都将在该表中执行,直到会话结束。一旦执行了“track-sc*”规则,就会在表中查找 key,如果找不到,则为其分配一个条目。然后,在会话的整个生命周期中都会保留指向该条目的指针,并且该条目的计数器会尽可能频繁地更新,每次会话计数器更新时,并且在会话结束时系统地更新。计数器仅为跟踪开始后发生的事件更新。例如,当跟踪第 7 层信息时,连接计数器不会被更新,因为连接事件发生在第 7 层信息被提取之前。如果条目跟踪并发连接计数器,则只要条目被跟踪,就会计算一个连接,并且该条目在此期间不会过期。跟踪计数器还提供了一个性能优势,与仅检查 key 相比,因为所有使用它的 ACL 检查只执行一次表查找。- sc-inc-gpc0(<sc-id>):“sc-inc-gpc0”根据粘性计数器 <sc-id> 递增 GPC0 计数器。如果发生错误,此操作将静默失败,并继续评估操作。- sc-inc-gpc1(<sc-id>):“sc-inc-gpc1”根据粘性计数器 <sc-id> 递增 GPC1 计数器。如果发生错误,此操作将静默失败,并继续评估操作。- sc-set-gpt0(<sc-id>) { <int> | <expr> }:此操作根据粘性计数器 <sc-id> 和 <int>/<expr> 的值设置 32 位无符号 GPT0 标签。预期结果是布尔值。如果发生错误,此操作将静默失败,并继续评估操作。- set-src <expr>:用于将源 IP 地址设置为指定表达式的值。如果您想隐藏源 IP 地址以保护隐私,则很有用。如果您想提供来自 HTTP 头部的 IP 地址,请使用“http-request set-src”。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
tcp-request connection set-src src,ipmask(24)
在可能的情况下,set-src 会保留原始源端口,只要地址系列允许,否则源端口设置为 0。- set-src-port <expr>:用于将源端口地址设置为指定表达式的值。
参数
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
示例
tcp-request connection set-src-port int(4000)
在可能的情况下,set-src-port 会保留原始源地址,只要地址系列支持端口,否则它会将源地址强制设置为 IPv4 "0.0.0.0",然后再重写端口。- set-dst <expr>:用于将目标 IP 地址设置为指定表达式的值。如果您想在日志中掩盖 IP 以保护隐私,则很有用。如果您想提供来自 HTTP 标头的 IP,请使用“http-request set-dst”。如果您想连接到新的地址/端口,请在后端使用“0.0.0.0:0”作为服务器地址。<expr> 是一个标准的 HAProxy 表达式,由样本提取后跟一些转换器组成。
示例
tcp-request connection set-dst dst,ipmask(24) tcp-request connection set-dst ipv4(10.0.0.1)
在可能的情况下,set-dst 会保留原始目标端口,只要地址系列允许,否则目标端口设置为 0。- set-dst-port <expr>:用于将目标端口地址设置为指定表达式的值。如果您想连接到新的地址/端口,请在后端使用“0.0.0.0:0”作为服务器地址。<expr> 是一个标准的 HAProxy 表达式,由样本提取后跟一些转换器组成。
示例
tcp-request connection set-dst-port int(4000)
在可能的情况下,set-dst-port 会保留原始目标地址,只要地址族支持端口,否则它会将目标地址强制为 IPv4 “0.0.0.0”,然后再重写端口。- “silent-drop”:这会停止规则的评估,并以系统依赖的方式突然删除面向客户端的连接,该方式试图阻止客户端收到通知。效果是客户端仍然看到一个已建立的连接,而 HAProxy 上实际上没有任何连接。目的是达到与“tarpit”类似的效果,除了它不使用 HAProxy 机器上的任何本地资源。它可以承受比“tarpit”高得多的负载,并减慢更强大的攻击者。了解使用此机制的影响很重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将在很长时间内保持已建立的连接,并可能因此操作而受到影响。在具有足够权限的现代 Linux 系统上,TCP_REPAIR 套接字选项用于阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 会减少到 1,这样 TCP 重置就不会经过第一个路由器,尽管它仍然会被传递到本地网络。除非您完全理解其工作原理,否则请勿使用它。请注意,“if/unless”条件是可选的。如果没有为操作设置条件,它将简单地无条件执行。这对于“track-sc*”操作以及更改默认操作为 reject 可能很有用。
示例
接受所有来自白名单主机的连接,拒绝过快的连接而不计数,并跟踪已接受的连接。这导致来自滥用来源的连接速率受到限制。
tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } tcp-request connection reject if { src_conn_rate gt 10 } tcp-request connection track-sc0 src
示例
接受所有来自白名单主机的连接,计算所有其他连接并拒绝过快的连接。这导致滥用者只要不减速就会被阻止。
tcp-request connection accept if { src -f /etc/haproxy/whitelist.lst } tcp-request connection track-sc0 src tcp-request connection reject if { sc0_conn_rate gt 10 }
示例
为来自所有已知代理的流量启用 PROXY 协议。
tcp-request connection expect-proxy layer4 if { src -f proxies.lst }
有关 ACL 的用法,请参见第 7 节
tcp-request content <action> [{if | unless} <condition>]
根据第 4-7 层条件对新会话执行操作

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
参数
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
请求的内容可以在请求处理的早期阶段进行分析,称为“TCP内容检查”。在此阶段,基于ACL的规则会在每次请求内容更新时进行评估,直到匹配到“accept”或“reject”规则,或者TCP请求检查延迟到期且没有匹配的规则。这些规则与“tcp-request connection”规则的第一个区别在于,“tcp-request content”规则可以利用内容来做出决策。大多数情况下,这些决策将考虑协议识别或有效性。第二个区别是,基于内容的规则可以在前端和后端使用。在与客户端进行HTTP keep-alive的情况下,所有tcp-request content规则都会被重新评估,因此haproxy会记录下由“tcp-request connection”规则与“tcp-request content”规则分配的粘性计数器,并在处理完HTTP请求后清除所有与内容相关的计数器,以便为下一个请求进行规则重新评估时再次评估。这一点在规则跟踪某些L7信息或由基于L7的ACL条件化时尤其重要,因为跟踪信息在请求之间可能会发生变化。基于内容的规则按照声明的确切顺序进行评估。如果没有规则匹配,或者根本没有规则,默认操作是接受内容。可以插入的规则数量没有特定限制。支持多种类型的操作:- accept:接受请求- do-resolve:执行DNS解析- reject:拒绝请求并关闭连接- capture:捕获指定的样本表达式- set-priority-class <expr> | set-priority-offset <expr>- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]- sc-inc-gpc0(<sc-id>)- sc-inc-gpc1(<sc-id>)- sc-set-gpt0(<sc-id>) { <int> | <expr>}- set-dst <expr>- set-dst-port <expr>- set-var(<var-name>) <expr>- unset-var(<var-name>)- silent-drop- send-spoe-group <engine-name> <group-name>- use-service <service-name>它们的意思与其在“tcp-request connection”中的对应项相同,请参考该部分以获得完整描述。有关“do-resolve”操作,请查看“http-request do-resolve”配置部分。虽然没有强制性要求,但建议在“tcp-request connection”规则中使用track-sc0,在前端的“tcp-request content”规则中使用track-sc1,在后端的“tcp-request content”规则中使用track-sc2,因为这使得配置更具可读性且易于排查,但这只是一个指导方针,所有计数器都可以在任何地方使用。请注意,“if/unless”条件是可选的。如果操作没有设置条件,则无条件执行。这对于“track-sc*”操作以及更改默认操作为拒绝都很有用。通过TCP代理使用“tcp-request content”规则匹配层7内容是完全可能的,因为HTTP特定的ACL匹配能够初步解析缓冲区内容,然后再提取所需数据。如果缓冲区内容无法解析为有效的HTTP消息,则ACL不匹配。这里涉及的解析器与所有其他HTTP处理的解析器完全相同,因此不存在解析差异的风险。在HTTP前端或HTTP后端,由于HTTP解析在连接处理的早期阶段(会话级别)执行,因此可以保证在首次评估规则时HTTP内容始终可用。但是对于这类代理,使用“http-request”规则更为自然且推荐。层7信息的跟踪也是可能的,前提是信息在规则处理时可用。规则处理引擎能够等待直到检查延迟到期,如果要跟踪的数据尚不可用。 “set-dst”和“set-dst-port”分别用于设置目标IP和端口。更多关于如何使用它的信息,请参见“http-request set-dst”。“set-var”用于设置变量的内容。变量是内联声明的。对于“tcp-request session”规则,只能使用会话级别的变量,没有任何层7内容。<var-name>变量名以其作用域的指示开始。允许的作用域为:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。<expr>是标准的HAProxy表达式,由样本获取(sample-fetch)后跟一些转换器(converters)组成。“unset-var”用于取消设置变量。有关<var-name>的详细信息,请参见上文。“set-priority-class”用于设置当前请求的队列优先级类。值必须是一个样本表达式,可以转换为-2047..2047范围内的整数。超出此范围的结果将被截断。优先级类决定了排队请求的处理顺序。值越小,优先级越高。“set-priority-offset”用于设置当前请求的队列优先级时间戳偏移量。值必须是一个样本表达式,可以转换为-524287..524287范围内的整数。超出此范围的结果将被截断。当请求入队时,它首先按优先级类排序,然后按当前时间戳(通过给定偏移量调整)排序(以毫秒为单位)。值越小,优先级越高。请注意,生成的时间戳仅以524,287毫秒(8分钟44秒287毫秒)的精度跟踪。如果请求排队时间过长,以至于调整后的时间戳超过此值,它将被误识别为最高优先级。因此,重要的是将“timeout queue”设置为一个值,该值与偏移量结合后不会超过此限制。“send-spoe-group”用于触发发送SPOE消息组。为此,必须定义用于发送消息的SPOE引擎,以及要发送的SPOE组。当然,SPOE引擎必须引用一个现有的SPOE过滤器。如果在SPOE过滤器行中未提供引擎名称,则必须使用SPOE代理名称。<engine-name> SPOE引擎名称。<group-name>引擎配置中指定的SPOE组名称。“use-service”用于执行TCP服务,该服务将回复请求并停止规则评估。该服务可以选择通过发送任何有效响应来回复,也可以立即关闭连接而不发送任何内容。除了原生服务,还可以用Lua编写自己的服务。不再评估其他“tcp-request”规则。
示例
tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst }
示例
tcp-request content set-var(sess.my_var) src tcp-request content unset-var(sess.my_var2)
示例
# 接受包含 Host 头部为 "example.com" 的 HTTP 请求 # 并拒绝所有其他请求。 acl is_host_com hdr(Host) -i example.com tcp-request inspect-delay 30s tcp-request content accept if is_host_com tcp-request content reject
示例
# 如果客户端先说话,则拒绝 SMTP 连接 tcp-request inspect-delay 30s acl content_present req.len gt 0 tcp-request content reject if content_present # 仅当客户端说话时才转发 HTTPS 连接 tcp-request inspect-delay 30s acl content_present req.len gt 0 tcp-request content accept if content_present tcp-request content reject
示例
# 跟踪 X-Forwarded-For 中的最后一个 IP(粘滞表类型为 string) tcp-request inspect-delay 10s tcp-request content track-sc0 hdr(x-forwarded-for,-1) # 或者跟踪 X-Forwarded-For 中的最后一个 IP(粘滞表类型为 ip|ipv6) tcp-request content track-sc0 req.hdr_ip(x-forwarded-for,-1)
示例
# 按“base”(Host+URL 的串联)跟踪请求计数 tcp-request inspect-delay 10s tcp-request content track-sc0 base table req-rate
示例
跟踪每个前端和每个后端的计数器,当后端检测到滥用(并标记 gpc0)时,在前端阻止滥用者。
frontend http # 在 SC0 中使用通用计数器 0 作为全局滥用计数器 # 保护我们所有的站点 stick-table type ip size 1m expire 5m store gpc0 tcp-request connection track-sc0 src tcp-request connection reject if { sc0_get_gpc0 gt 0 } ... use_backend http_dynamic if { path_end .php } backend http_dynamic # 如果某个来源对此动态站点发出的请求过快(由 # SC1 跟踪),则在前端全局阻止它。 stick-table type ip size 1m expire 5m store http_req_rate(10s) acl click_too_fast sc1_http_req_rate gt 10 acl mark_as_abuser sc0_inc_gpc0(http) gt 0 tcp-request content track-sc1 src tcp-request content reject if click_too_fast mark_as_abuser
有关 ACL 的用法,请参见第 7 节
设置在内容检测期间等待数据的最大允许时间

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
主要将haproxy用作TCP中继器的用户通常担心将任何类型的协议传递给服务器而不进行任何分析的风险。为了能够分析请求内容,我们必须先暂存数据,然后对其进行分析。此语句仅启用对数据暂存的最多指定时间。TCP内容检查在连接到达前端时非常早地应用,然后在连接转发到后端时也非常早地应用。这意味着如果前端和后端都有tcp-request规则,连接可能会在前端经历第一个延迟,然后在后端经历第二个延迟。请注意,在执行内容检查时,haproxy将评估每个新进入的数据块的整个规则,并考虑到这些数据是部分的。如果在上述延迟之前没有匹配的规则,则在延迟到期时会进行最后一次检查,这次将内容视为最终的。如果未设置延迟,haproxy将不会等待,并将根据可用信息立即做出裁决。显然,这不太可能有太大用处,甚至可能存在竞态条件,因此不建议进行此类设置。请注意,如果遇到连接错误或关闭,或者请求缓冲区已满,检查延迟会缩短。一旦匹配规则,请求将被释放并照常继续。如果超时到期且没有匹配的规则,默认策略将使其不受影响地通过。对于大多数协议,设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整的请求。增加3秒或更多时间以覆盖TCP重传,但仅此而已。对于某些协议,使用较大的值是有意义的,例如,为了确保客户端永远不在服务器之前通信(例如SMTP),或者在将数据传递给服务器之前等待客户端通信(例如SSL)。请注意,客户端超时至少必须覆盖检查延迟,否则它会先到期。如果客户端关闭连接或缓冲区已满,则延迟会立即到期,因为内容将不再改变。
tcp-response content <action> [{if | unless} <condition>]
根据第 4-7 层条件对会话响应执行操作

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
响应内容可以在响应处理的早期阶段进行分析,称为“TCP内容检查”。在此阶段,基于ACL的规则会在每次响应内容更新时进行评估,直到匹配到“accept”、“close”或“reject”规则,或者设置了TCP响应检查延迟并到期而没有匹配的规则。大多数情况下,这些决策将考虑协议识别或有效性。基于内容的规则按照声明的确切顺序进行评估。如果没有规则匹配,或者根本没有规则,默认操作是接受内容。可以插入的规则数量没有特定限制。支持多种类型的操作:- accept:如果条件为真(与“if”一起使用)或为假(与“unless”一起使用),则接受响应。第一个执行的此类规则将结束规则评估。- close:如果条件为真(与“if”一起使用)或为假(与“unless”一起使用),则立即与服务器关闭连接。第一个执行的此类规则将结束规则评估。此操作的主要目的是强制在交换后完成客户端和服务器之间的连接,当应用程序协议期望某些长超时先过去时。目的是消除在某些协议下占用服务器大量资源的空闲连接。- reject:如果条件为真(与“if”一起使用)或为假(与“unless”一起使用),则拒绝响应。被拒绝的会话将立即关闭。- set-var(<var-name>) <expr>:根据表达式设置变量。- unset-var(<var-name>):取消设置变量。- sc-inc-gpc0(<sc-id>):此操作根据<sc-id>指定的粘性计数器递增GPC0计数器。如果发生错误,此操作将静默失败,操作评估将继续。- sc-inc-gpc1(<sc-id>):此操作根据<sc-id>指定的粘性计数器递增GPC1计数器。如果发生错误,此操作将静默失败,操作评估将继续。- sc-set-gpt0(<sc-id>) { <int> | <expr> }:此操作根据<sc-id>指定的粘性计数器和<int>/<expr>的值设置32位无符号GPT0标签。预期结果为布尔值。如果发生错误,此操作将静默失败,操作评估将继续。- “silent-drop”:这会停止规则评估,并使面向客户端的连接突然消失,使用系统依赖的方式来尝试防止客户端收到通知。其效果是客户端仍然看到一个已建立的连接,而HAProxy上没有。目的是实现与“tarpit”类似的效果,但它不使用运行HAProxy的机器上的任何本地资源。它可以承受比“tarpit”高得多的负载,并减慢更强的攻击者。理解使用此机制的影响很重要。客户端和HAProxy之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持连接,并可能受到此操作的影响。在具有足够权限运行的现代Linux系统上,TCP_REPAIR套接字选项用于阻止TCP重置的发送。在其他系统上,套接字TTL被减小到1,以便TCP重置不会通过第一个路由器,但仍会传递到本地网络。除非您完全理解其工作原理,否则请勿使用它。- send-spoe-group <engine-name> <group-name>:发送一组SPOE消息。注意,“if/unless”条件是可选的。如果操作没有设置条件,则无条件执行。这对于更改默认操作为拒绝很有用。通过“tcp-response content”规则匹配层7内容是完全可能的,但重要的是要确保已缓冲完整的响应,否则任何内容都不会匹配。为了实现这一点,最佳解决方案是在检查期间检测HTTP协议。“set-var”用于设置变量的内容。变量是内联声明的。<var-name>变量名以其作用域的指示开始。允许的作用域为:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。<expr>是标准的HAProxy表达式,由样本获取(sample-fetch)后跟一些转换器(converters)组成。“unset-var”用于取消设置变量。有关<var-name>的详细信息,请参见上文。“send-spoe-group”用于触发发送SPOE消息组。为此,必须定义用于发送消息的SPOE引擎,以及要发送的SPOE组。当然,SPOE引擎必须引用一个现有的SPOE过滤器。如果在SPOE过滤器行中未提供引擎名称,则必须使用SPOE代理名称。<engine-name> SPOE引擎名称。<group-name>引擎配置中指定的SPOE组名称。请参阅第7节关于ACL用法。
tcp-request session <动作> [{if | unless} <条件>]
根据第 5 层条件对已验证的会话执行操作

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<动作> 定义了如果条件适用时要执行的动作。见下文。 <条件> 是一个标准的仅第 5 层的基于 ACL 的条件(见第 7 节)。
会话验证后(即所有握手完成后),可以评估某些条件来决定该会话是必须接受、丢弃还是跟踪其计数器。这些条件无法利用任何数据内容,因为此时尚未分配缓冲区,并且处理无法在此阶段等待。主要用例是将一些早期信息复制到变量(因为变量在会话中可访问),或者跟踪握手后收集的一些信息,例如SSL级别元素(SNI、密码套件、客户端证书的CN)或来自PROXY协议头的信息(例如,跟踪以这种方式转发的源)。提取的信息因此可以复制到变量或使用“track-sc”规则进行跟踪。当然,也可以决定接受/拒绝,与其他规则集一样。这里执行的大多数操作也可以在“tcp-request content”规则中执行,但HTTP中这些规则是针对每个新请求评估的,这可能并不总是可接受的。例如,一条规则可能会在每次评估时增加一个计数器。还可以通过地理位置解析出国家,分配给一个会话范围的变量,然后用HTTP头重写所有请求的源地址。如果需要在做出决定时检查某些内容,则必须使用“tcp-request content”语句。 “tcp-request session”规则按照声明的确切顺序进行评估。如果没有规则匹配,或者根本没有规则,默认操作是接受传入的会话。可以插入的规则数量没有特定限制。支持多种类型的操作:- accept:接受请求- reject:拒绝请求并关闭连接- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]- sc-inc-gpc0(<sc-id>)- sc-inc-gpc1(<sc-id>)- sc-set-gpt0(<sc-id>) { <int> | <expr>}- set-dst <expr>- set-dst-port <expr>- set-src <expr>- set-src-port <expr>- set-var(<var-name>) <expr>- unset-var(<var-name>)- silent-drop这些操作的意思与其在“tcp-request connection”和“tcp-request content”中的对应项相同,请参考这些部分以获得完整描述。请注意,“if/unless”条件是可选的。如果操作没有设置条件,则无条件执行。这对于“track-sc*”操作以及更改默认操作为拒绝都很有用。
示例
默认跟踪原始源地址,或者对于来自本地代理的连接,跟踪 PROXY 协议头中通告的地址。第一个连接级别的规则为这些连接启用了 PROXY 协议的接收,第二个规则跟踪我们在可选解码后决定保留的任何地址。
tcp-request connection expect-proxy layer4 if { src -f proxies.lst } tcp-request session track-sc0 src
示例
接受所有来自白名单主机的会话,拒绝过快的会话而不对其进行计数,并跟踪已接受的会话。这导致来自滥用来源的会话速率受到限制。
tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session reject if { src_sess_rate gt 10 } tcp-request session track-sc0 src
示例
接受所有来自白名单主机的会话,对所有其他会话进行计数,并拒绝过快的会话。这导致滥用会话被阻止,直到它们减速为止。
tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session track-sc0 src tcp-request session reject if { sc0_sess_rate gt 10 }
有关 ACL 的用法,请参见第 7 节
设置内容检测期间等待响应的最大允许时间

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
timeout check <timeout>
设置额外的检查超时,但仅在连接已经建立之后。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果设置了,haproxy将使用min(“timeout connect”、“inter”)作为检查的连接超时,以及“timeout check”作为额外的读取超时。“min”的目的是让运行*非常长*的“timeout connect”(例如,因为队列或tarpit需要它)的人不会减慢他们的检查速度。(另请注意,没有合理的原因来设置如此长的连接超时,因为“timeout queue”和“timeout tarpit”始终可以避免这种情况)。如果未设置“timeout check”,haproxy将使用“inter”作为完整的检查超时(连接+读取),与所有<1.3.15版本完全相同。在大多数情况下,检查请求比正常请求简单快捷得多,并且人们可能希望踢掉滞后的服务器,因此此超时应该小于“timeout server”。此参数特定于后端,但可以在“defaults”部分一次性指定。这实际上是最容易记住它的方法之一。
timeout client <timeout>
设置客户端侧的最大不活动时间。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于客户端需要确认或发送数据时。在HTTP模式下,此超时在第一阶段(客户端发送请求时)和响应阶段(客户端读取服务器发送的数据时)尤其重要。也就是说,对于第一阶段,最好设置“timeout http-request”以更好地保护HAProxy免受Slowloris类攻击。默认情况下,值以毫秒为单位指定,但如果数字后面带有单位,则可以是任何其他单位,如本文档顶部所述。在TCP模式下(以及在HTTP模式下程度较轻),强烈建议客户端超时等于服务器超时,以避免复杂的调试情况。通过指定比3秒的倍数稍长的超时(例如4或5秒)来覆盖一个或多个TCP数据包丢失是一个好习惯。如果将长时间运行的会话与短时间运行的会话混合(例如,WebSocket和HTTP),则值得考虑“timeout tunnel”,它会覆盖“timeout client”和“timeout server”对于隧道,以及“timeout client-fin”对于半关闭连接。此参数特定于前端,但可以在“defaults”部分一次性指定。这实际上是最容易记住它的方法之一。未设置的超时将导致无限超时,不推荐使用。接受并使用此类配置,但在启动时会报告警告,因为如果系统的超时未设置,可能会导致系统中的过期会话累积。
为半关闭连接设置客户端侧的不活动超时。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于客户端应确认或发送数据,而一端已关闭连接的情况。此超时与“timeout client”不同,因为它仅适用于单向关闭的连接。这对于避免在客户端未干净断开连接时,使连接长时间处于 FIN_WAIT 状态特别有用。此问题在 RDP 或 WebSocket 等长连接中尤其常见。请注意,当连接单向关闭时,此超时可能会覆盖“timeout tunnel”。它应用于已发送 GOAWAY 帧的空闲 HTTP/2 连接,通常表示连接将很快结束。此参数特定于前端,但可以在“defaults”部分统一指定。默认情况下未设置,因此半关闭的连接将使用其他超时(timeout.client 或 timeout.tunnel)。
timeout connect <timeout>
设置等待服务器连接尝试成功的最大时间。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果服务器与 haproxy 位于同一局域网内,连接应立即建立(毫秒级)。无论如何,通过设置略高于 3 秒倍数的超时(例如 4 或 5 秒)来涵盖一个或多个 TCP 数据包丢失是一种好习惯。默认情况下,如果未指定,连接超时还会将队列和弹坑超时设置为相同的值。此参数特定于后端,但可以在“defaults”部分统一指定。这实际上是最容易记住的解决方案之一。未指定的超时将导致无限超时,这是不推荐的。此类用法是可接受的并且可以正常工作,但在启动时会报告警告,因为它可能导致系统中的失败会话累积,除非系统的超时也已配置。
设置等待新 HTTP 请求出现的最大允许时间

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认情况下,在keep-alive情况下等待新请求的时间由“timeout http-request”设置。但这并不总是方便,因为有些人希望非常短的keep-alive超时以更快地释放连接,而另一些人则倾向于较长的超时,但在请求开始出现时仍然有较短的超时。“http-keep-alive”超时涵盖了这些需求。它将定义在发送响应后等待新HTTP请求开始到达的时间。一旦看到请求的第一个字节,就会使用“http-request”超时来等待完整的请求。请注意,新请求之前的空行不会刷新超时,也不计为新请求。这两个超时之间还有另一个区别:当连接在timeout http-keep-alive期间过期时,不会返回错误,连接只是关闭。如果连接在等待请求完成的“http-request”中过期,则在关闭连接之前会向客户端返回HTTP 408错误,除非在前端设置了“option http-ignore-probes”。通常,“timeout http-keep-alive”最适合防止客户端在看到大量短连接的站点上长时间保持空闲连接。这可以通过在HTTP/1.1中将值设置为几十到几百毫秒来实现。这将关闭连接,即使客户端请求了一个页面,而无需保持该连接打开以等待客户端的更多活动。在这种情况下,新的浏览器活动将导致TCP和/或SSL层的新握手。一个常见的用例是仅提供重定向到HTTPS页面的HTTP站点。最好不要长时间保持这些连接空闲,因为它们不会被重用,除非是为了获取favicon。另一个用例恰恰相反:一些站点希望允许客户端长时间(例如30秒到一分钟)重用空闲连接,但又不想为第一个请求等待那么长时间,以避免一个非常便宜的攻击向量。在这种情况下,http-keep-alive超时将被设置为一个较大的值,但http-request将保持较低(几秒钟)。当设置为非常小的值时,未流水线的额外请求很可能通过另一个连接处理,除非请求真正是流水线的,这在HTTP/1.1中非常罕见(请求是连续发送的,而不等待响应)。大多数HTTP/1.1实现会发送一个请求,等待响应,然后发送另一个请求。对于HTTP/1.1来说,这里的小值可能有利于减少具有数十万客户端的站点所使用的内存和套接字,但会增加握手计算成本。处理HTTP/2时,应特别注意小值。HTTP/2的性质是通过连接多路复用请求,以节省重新连接TCP和/或SSL层的开销。该协议还使用控制帧,这些帧对早期TCP连接关闭的处理不佳,在极少数情况下,当数据在离开HAProxy后丢失时(此时甚至无法记录错误),可能会导致响应截断。建议的HTTP/2连接的低起始值约为4秒。这将防止大多数现代keep-alive实现不必要地保持过时的连接打开,同时允许后续请求重用连接。然而,这应该根据需要进行调整,并且仅仅是一个起点。如果未设置此参数,则应用“http-request”超时,如果两者都未设置,则“timeout client”仍将在较低级别应用。它应在前端设置才能生效,除非前端处于TCP模式,在这种情况下将使用HTTP后端的超时。
设置等待完整 HTTP 请求的最大允许时间

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
为了提供DoS防护,可能需要降低接收完整HTTP请求的最大可接受时间,而不影响客户端超时。这有助于防止已建立连接但没有任何发送的情况。客户端超时无法有效防御这种滥用,因为它是一个不活动超时,这意味着如果攻击者不时发送一个字符,超时将不会触发。通过HTTP请求超时,无论客户端输入的速度如何,如果请求在规定时间内未完成,它将被中止。超时到期时,会向客户端发送HTTP 408响应,告知其问题,并关闭连接。日志将报告终止代码“cR”。一些最近的浏览器在此标准(有充分文档记录的行为)方面存在问题,因此可能需要使用“option http-ignore-probes”或“errorfile 408 /dev/null”来隐藏408代码。有关“cR”终止代码的更多详细信息,请参阅第8.5节。默认情况下,此超时仅适用于请求的头部部分,而不适用于任何数据。一旦收到空行,此超时将不再使用。当与“option http-buffer-request”结合使用时,此超时也适用于请求的正文。它在keep-alive连接上再次使用,以等待第二个请求,如果“timeout http-keep-alive”未设置。通常,将其设置为几秒钟就足够了,因为大多数客户端在连接后会立即发送完整请求。增加3秒或更多时间以覆盖TCP重传,但仅此而已。将其设置为非常低的值(例如50毫秒)通常可以在本地网络上正常工作,只要没有丢包。这将阻止人们使用telnet发送纯HTTP请求。如果未设置此参数,则客户端超时在传入请求的每个块之间仍然适用。它应在前端设置才能生效,除非前端处于TCP模式,在这种情况下将使用HTTP后端的超时。
timeout queue <timeout>
设置在队列中等待可用连接槽的最大时间

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当服务器的maxconn达到上限时,连接将保持挂起状态,这些连接可能特定于服务器或全局应用于后端。为了避免无限等待,会对排队中的请求应用超时。如果超时到期,则认为请求几乎不可能被服务,因此将被丢弃并向客户端返回503错误。“timeout queue”语句允许设置请求在队列中保持挂起的最大时间。如果未指定,则使用与后端连接超时(“timeout connect”)相同的值,以向后兼容没有“timeout queue”参数的旧版本。
timeout server <timeout>
设置服务器端的最大不活动时间。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时是指在服务器应确认或发送数据时适用的超时。在 HTTP 模式下,此超时在服务器响应的第一个阶段尤为重要,此时服务器必须发送标头,因为它直接代表服务器对请求的处理时间。要确定在此处设置何值,通常最好从被认为是不可接受的响应时间开始,然后检查日志以观察响应时间分布,并相应地调整值。默认情况下,该值以毫秒为单位指定,但如果数字后面附加了单位,则可以是任何其他单位,如本文档顶部所述。在 TCP 模式下(在 HTTP 模式下程度较轻),强烈建议客户端超时等于服务器超时,以避免出现难以调试的复杂情况。无论预期的服务器响应时间如何,最好通过设置略高于 3 秒倍数的超时(例如,至少 4 或 5 秒)来至少覆盖一次或几次 TCP 数据包丢失。如果存在长连接和短连接(例如 WebSocket 和 HTTP)混合的情况,则可以考虑“timeout tunnel”,它会覆盖“timeout client”和“timeout server”用于隧道。此参数特定于后端,但可以在“defaults”部分一次性指定。实际上,这是最简单的避免忘记它的方法之一。未指定的超时会导致无限超时,这是不推荐的。这种用法是接受的并且有效,但在启动时会报告警告,因为它可能会导致系统中的过期会话累积,如果系统的超时也没有配置的话。
为半关闭连接设置服务器侧的不活动超时。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时是指在服务器应确认或发送数据,但一个方向已关闭时适用的超时。此超时与“timeout server”不同,因为它仅适用于单向关闭的连接。这对于避免在远程服务器未正确断开连接时将连接保持在 FIN_WAIT 状态过长时间特别有用。此问题在 RDP 或 WebSocket 等长连接中尤为常见。请注意,当连接单向关闭时,此超时可以覆盖“timeout tunnel”。此设置是为了完整性而提供的,但在大多数情况下不需要。此参数特定于后端,但可以在“defaults”部分一次性指定。默认情况下,未设置,因此半关闭的连接将使用其他超时(timeout.server 或 timeout.tunnel)。
timeout tarpit <timeout>
设置被tarpit的连接将维持的时间

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

yes
参数
<timeout> 是 tarpit 的持续时间,默认以毫秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
当使用“http-request tarpit”对连接进行流量整形时,连接会在一段时间内保持打开状态而不进行活动,然后关闭。“timeout tarpit”定义了保持打开状态的时间。默认情况下,该值以毫秒为单位指定,但如果数字后面附加了单位,则可以是任何其他单位,如本文档顶部所述。如果未指定,则使用后端连接超时(“timeout connect”)的值,以实现与没有“timeout tarpit”参数的旧版本的向后兼容性。
timeout tunnel <timeout>
为隧道设置客户端和服务器侧的最大不活动时间。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
隧道超时是指在客户端和服务器之间建立双向连接,并且连接在两个方向上都保持不活动时适用的超时。一旦连接成为隧道,此超时将取代客户端和服务器超时。在 TCP 中,只要没有分析器附加到任一连接(例如,接受了 tcp 内容规则),就会使用此超时。在 HTTP 中,当连接升级时(例如,切换到 WebSocket 协议,或将 CONNECT 请求转发到代理时),或者在第一个响应后未指定 keepalive/close 选项时,将使用此超时。由于此超时通常与长连接结合使用,因此最好也设置“timeout client-fin”来处理客户端突然从网络消失并且不确认关闭,或发送关闭而不再确认挂起数据的情况。这种情况可能发生在存在防火墙的易丢包网络中,并且会通过检测大量处于 FIN_WAIT 状态的会话来发现。默认情况下,该值以毫秒为单位指定,但如果数字后面附加了单位,则可以是任何其他单位,如本文档顶部所述。无论预期的正常空闲时间如何,最好通过设置略高于 3 秒倍数的超时(例如,至少 4 或 5 秒)来至少覆盖一次或几次 TCP 数据包丢失。此参数特定于后端,但可以在“defaults”部分一次性指定。实际上,这是最简单的避免忘记它的方法之一。
示例
defaults http option http-server-close timeout connect 5s timeout client 30s timeout client-fin 30s timeout server 30s timeout tunnel 1h # 用于 WebSocket 和 CONNECT 的超时
transparent (已弃用)
启用客户端透明代理

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

no

yes

yes
参数:
引入此关键字是为了向第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力将远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。" transparent" 关键字已弃用,请改用 "option transparent"。请注意,与普遍看法相反,此选项在建立连接时并不会使 HAProxy 向服务器呈现客户端的 IP。
为每个请求生成一个唯一的 ID。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<string> 是一个日志格式字符串。
此关键字使用自定义日志格式为每个请求创建一个 ID。唯一的 ID 对于跟踪通过复杂基础设施中许多组件的请求非常有用。新创建的 ID 也可以使用日志格式字符串中的 %ID 标签进行记录。格式应由组合在一起时保证唯一的元素组成。例如,如果涉及多个 haproxy 实例,则可能需要包含节点名称。通常需要记录传入连接的源地址和目标地址及端口。请注意,由于可以在同一连接上执行多个请求,因此包含请求计数器可能有助于区分它们。同样,时间戳可以防止计数器翻转。记录进程 ID 将避免服务重启后发生冲突。建议对许多字段使用十六进制表示法,因为它使它们更紧凑并节省日志空间。
示例
unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid 将生成: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A
在 HTTP 请求中添加一个唯一的 ID 头部。

可在以下部分中使用:

defaultsfrontendlistenbackend

yes

yes

yes

no
参数
<name> 是头部的名称。
使用 unique-id-format 在发送到服务器的 HTTP 请求中添加一个 unique-id 头部。如果 unique-id-format 不存在,则无法工作。
示例
unique-id-format %{+X}o\ %ci:%cp_%fi:%fp_%Ts_%rt:%pid unique-id-header X-Unique-ID 将生成: X-Unique-ID: 7F000001:8296_7F00001E:1F90_4F7B0A69_0003:790A 另请参阅: "unique-id-format"
use_backend <backend> [{if | unless} <condition>]
如果/除非匹配基于 ACL 的条件,则切换到特定的后端。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

yes

yes

no
参数
<backend> 是一个有效的后端或 "listen" 部分的名称,或一个解析为后端名称的 "log-format" 字符串。<condition> 是由 ACL 组成的条件,如 第 7 节 所述。如果省略,则无条件应用该规则。
在进行内容切换时,连接到达前端,然后根据一系列条件分派到各种后端。“use_backend”关键字描述了条件与后端之间的关系。虽然通常与 HTTP 处理一起使用,但它也可以用于纯 TCP,无论是使用无状态 ACL(例如源地址验证)进行无内容切换,还是与“tcp-request”规则结合以等待某些有效载荷。可以有任意数量的“use_backend”规则。所有这些规则都按照其声明顺序进行评估,第一个匹配的规则将分配后端。在第一种形式中,如果满足条件,则使用后端。在第二种形式中,如果条件不满足,则使用后端。如果没有条件有效,则使用“default_backend”定义的后端。如果没有定义默认后端,则使用同一部分中的服务器(在“listen”部分的情况下),或者在前端的情况下,不使用服务器并返回 503 服务不可用响应。请注意,可以从 TCP 前端切换到 HTTP 后端。在这种情况下,要么前端已经检查过协议是 HTTP,然后立即进行后端处理,要么后端会等待完整的 HTTP 请求进入。当一个前端必须在唯一端口上解码多种协议,其中一种是 HTTP 时,此功能很有用。当  是一个简单名称时,它会在配置时解析,如果指定的后端不存在,则会报告错误。如果  是一个日志格式字符串,则在配置时可能不会进行任何检查,因此后端名称会在运行时动态解析。如果生成的后端名称与任何有效后端都不对应,则不会评估其他规则,并改为应用 default_backend 指令。请注意,在使用动态后端名称时,强烈建议使用其他后端不使用的前缀,以确保无法从请求中强制使用未经授权的后端。值得一提的是,具有显式名称的“use_backend”规则用于检测前端和后端之间的关联,以计算后端的“fullconn”设置。这对于动态名称来说是无法实现的。
定义用于后端的FastCGI应用程序。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<name> 是要使用的 FastCGI 应用程序的名称。
有关 FastCGI 应用程序设置的详细信息,请参见第 10.1 节
use-server <server> if <condition>
use-server <server> unless <condition>
仅在匹配/不匹配基于 ACL 的条件时才使用特定的服务器。

可在以下部分中使用:

defaultsfrontendlistenbackend

no

no

yes

yes
参数
<server>是同一后端部分中有效服务器的名称,或者是解析为服务器名称的"log-format"字符串。<condition>是由ACL组成的条件,如第7节所述。
默认情况下,到达后端的连接将根据配置的算法在可用服务器之间进行负载均衡,除非使用了 cookie 等持久化机制并在请求中找到。有时希望将特定请求转发到特定服务器,而无需为此服务器声明专用后端。这可以通过“use-server”规则来实现。这些规则在“redirect”规则之后、评估 cookie 之前进行评估,并且它们具有优先权。可以有任意数量的“use-server”规则。所有这些规则都按照其声明顺序进行评估,第一个匹配的规则将分配服务器。如果规则指定了一个处于关闭状态的服务器,并且未使用“option persist”且没有验证 force-persist 规则,则该规则将被忽略,并且评估将继续进行下一个规则,直到找到匹配的规则为止。在第一种形式中,如果满足条件,则使用该服务器。在第二种形式中,如果不满足条件,则使用该服务器。如果没有条件有效,则继续处理,并将根据其他持久化机制分配服务器。请注意,即使匹配了规则,仍然会执行 cookie 处理,但不会分配服务器。这允许前缀 cookie 被剥离其前缀。“use-server”语句在 HTTP 和 TCP 模式下均可用。这使其适用于基于内容的检查。例如,在使用隐式 TLS 的协议时(另请参阅“req.ssl_sni”),可以根据 TLS SNI 字段在服务器场中选择一个服务器。如果这些服务器的权重设置为零,它们将不用于其他流量。
示例
# 基于 SNI 字段拦截传入的 TLS 请求 use-server www if { req.ssl_sni -i www.example.com } server www 192.168.0.1:443 weight 0 use-server mail if { req.ssl_sni -i mail.example.com } server mail 192.168.0.1:465 weight 0 use-server imap if { req.ssl_sni -i imap.example.com } server imap 192.168.0.1:993 weight 0 # 所有其余请求都转发到此服务器 server default 192.168.0.2:443 check
当<server>是一个简单的名称时,它会与配置中现有的服务器进行检查,如果指定的服务器不存在,则报告错误。如果它是一个日志格式,则在解析配置时不会进行检查,如果我们在运行时无法解析出有效的服务器名称,但use-server规则的条件是一个返回true的ACL,则不会应用其他use-server规则,我们将回退到负载均衡。
bind”、“server”和“default-server”关键字支持一系列设置,具体取决于某些构建选项以及 HAProxy 构建所基于的系统。这些设置通常每个由一个单词组成,有时后面跟着一个值,写在与“bind”或“server”相同的行上。所有这些选项在此部分中都有描述。

5.1. Bind 选项

bind”关键字支持一定数量的设置,这些设置都作为参数在同一行上传递。这些参数的出现顺序无关紧要,只要它们出现在绑定地址之后即可。所有这些参数都是可选的。其中一些是单个单词(布尔值),而另一些则需要一个值。在这种情况下,必须在设置名称后立即提供该值。当前支持的设置如下。
accept-netscaler-cip <magic number>
强制在同一行上声明的任何 TCP 套接字接受的所有连接上使用 NetScaler 客户端 IP 插入协议。NetScaler 客户端 IP 插入协议规定了传入连接的第 3/4 层地址,这些地址将在任何使用地址的地方使用,唯一的例外是“tcp-request connection”规则,它只会看到真实的连接地址。日志将反映协议中指定的地址,除非协议被违反,在这种情况下仍将使用真实地址。此关键字与外部组件的支持相结合,可用作 X-Forwarded-For 机制的高效可靠的替代方案,后者并非总是可靠,甚至并非总是可用。另请参阅“tcp-request connection expect-netscaler-cip”,以更精细地设置允许使用该协议的客户端。
强制在由同一行上声明的任何套接字接受的任何连接上使用 PROXY 协议。PROXY 协议的版本 1 和 2 都受支持并能正确检测。PROXY 协议规定了传入连接的第 3/4 层地址,这些地址将在任何使用地址的地方使用,唯一的例外是 "tcp-request connection" 规则,它只会看到真实的连接地址。日志将反映协议中指示的地址,除非协议被违反,在这种情况下仍将使用真实地址。此关键字与外部组件的支持相结合,可以作为 X-Forwarded-For 机制的一种高效可靠的替代方案,该机制并非总是可靠,甚至并非总是可用。另请参阅 "tcp-request connection expect-proxy" 以更精细地设置允许哪些客户端使用该协议。
允许在使用TLSv1.3时接收早期数据。由于安全考虑,此功能默认禁用。因为它容易受到重放攻击,您只应在对可以安全重放的请求(即幂等请求)允许此功能。对于任何使用早期数据不安全的请求,您可以使用"wait-for-handshake"操作。
alpn <protocols>
此选项启用 TLS ALPN 扩展,并通告指定的协议列表作为 ALPN 支持的协议。协议列表是一个以逗号分隔的协议名称列表,例如:“http/1.1,http/1.0”(不含引号)。这要求 SSL 库在构建时启用了对 TLS 扩展的支持(请使用 haproxy -vv 进行检查)。ALPN 扩展取代了最初的 NPN 扩展。启用 HTTP/2 需要 ALPN。OpenSSL 1.0.2 之前的版本不支持 ALPN,只支持现已过时的 NPN 扩展。在撰写本文时,大多数浏览器仍然同时支持 ALPN 和 NPN 用于 HTTP/2,因此回退到 NPN 可能在一段时间内仍然有效。但应尽可能使用 ALPN。如果希望同时支持 HTTP/2 和 HTTP/1.1,可以按优先顺序通告这两个版本,如下所示: bind :443 ssl crt pub.pem alpn h2,http/1.1
backlog <backlog>
将套接字的 backlog 设置为此值。如果未指定或为 0,则使用前端的 backlog,通常默认为 maxconn 值。
ca-file <cafile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。
ca-ignore-err [all|<errorID>,...]
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 > 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
ca-sign-file <cafile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,其中包含用于创建和签署服务器证书的 CA 证书和 CA 私钥。当启用证书动态生成时,这是一个强制性设置。有关详细信息,请参见 'generate-certificates'。
ca-sign-pass <passphrase>
此设置仅在内置 OpenSSL 支持时可用。它是 CA 私钥的密码。此设置是可选的,仅在启用证书动态生成时使用。有关详细信息,请参见 'generate-certificates'。
此设置指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。它指定的 CA 证书不应包含在服务器 hello 消息中发送的 CA 名称中。通常,“ca-file”必须用中间证书定义,而“ca-verify-file”则用终止证书链的证书(如根 CA)定义。
ciphers <ciphers>
此设置仅在内置 OpenSSL 支持时可用。它设置描述在 SSL/TLS 握手期间(最高到 TLSv1.2)协商的密码算法列表(“密码套件”)的字符串。该字符串的格式在 OpenSSL 手册页的“man 1 ciphers”中定义。有关背景信息和建议,请参阅(https://wiki.mozilla.org/Security/Server_Side_TLS)和(https://mozilla.github.io/server-side-tls/ssl-config-generator/)。有关 TLSv1.3 密码配置,请检查“ciphersuites”关键字。
ciphersuites <ciphersuites>
此设置仅在内置 OpenSSL 支持且用于构建 HAProxy 的 OpenSSL 版本为 1.1.1 或更高版本时可用。它设置了在 TLSv1.3 握手中协商的密码算法(“密码套件”)列表的描述字符串。字符串的格式在 OpenSSL man 页的“man 1 ciphers”中的“ciphersuites”部分中定义。有关 TLSv1.2 及更早版本的密码配置,请查看“ciphers”关键字。此设置可能接受 TLSv1.2 密码套件,但这是未经文档化的行为,不推荐使用,因为它可能不一致或存在 bug。OpenSSL 的默认 TLSv1.3 密码套件是:“TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256”TLSv1.3 仅支持 5 个密码套件:- TLS_AES_128_GCM_SHA256 - TLS_AES_256_GCM_SHA384 - TLS_CHACHA20_POLY1305_SHA256 - TLS_AES_128_CCM_SHA256 - TLS_AES_128_CCM_8_SHA256
示例
ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
crl-file <crlfile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的证书吊销列表。
crt <cert>
此设置仅在内置 OpenSSL 支持时可用。它指定一个包含必需证书和任何关联私钥的 PEM 文件。此文件可以通过将多个 PEM 文件连接成一个文件来构建(例如,cat cert.pem key.pem > combined.pem)。如果您的 CA 需要中间证书,也可以将其连接到此文件中。中间证书也可以通过“issuers-chain-path”指令在目录中共享。如果文件不包含私钥,HAProxy 将尝试在同路径下查找以“.key”为后缀的文件。如果使用的 OpenSSL 支持 Diffie-Hellman,则会加载此文件中存在的参数。如果使用目录名而不是 PEM 文件,则会按字母顺序列出该目录中的所有文件,除非其名称以 '.key'、'.issuer'、'.ocsp' 或 '.sctl' 结尾(保留的扩展名)。可以多次指定此指令以从多个文件或目录加载证书。证书将呈现给提供有效 TLS 服务器名称指示(SNI)字段且该字段与其中一个 CN 或 alt subject 匹配的客户端。支持通配符,其中通配符字符 '*' 用于替换第一个主机名组件(例如,*.example.org 匹配 www.example.org 但不匹配 www.sub.example.org)。如果使用空目录,HAProxy 将不会启动,除非使用“strict-sni”关键字。如果客户端未提供 SNI,或者 SSL 库不支持 TLS 扩展,或者客户端提供的 SNI 主机名与任何证书都不匹配,则将呈现第一个加载的证书。这意味着在从目录加载证书时,强烈建议首先将默认证书作为文件加载,或者确保它始终是目录中的第一个。请注意,同一个证书可以多次加载而不会产生副作用。某些 CA(例如 GoDaddy)在获取证书时会提供一个服务器类型下拉列表,其中不包括 HAProxy。如果发生这种情况,请确保选择一个 CA 认为需要中间 CA 的 Web 服务器(对于 GoDaddy,选择 Apache Tomcat 将获得正确的捆绑包,但许多其他服务器,例如 nginx,会生成一个错误的捆绑包,该捆绑包对某些客户端无效)。对于每个 PEM 文件,haproxy 会检查同路径下以“.ocsp”为后缀的文件是否存在。如果找到这样的文件,将自动启用对 TLS 证书状态请求扩展(也称为“OCSP 订书钉”)的支持。此文件的内容是可选的。如果不为空,则必须包含一个有效的 DER 格式的 OCSP 响应。要有效,OCSP 响应必须遵守以下规则:它必须指示良好状态,它必须是 PEM 文件证书的单个响应,并且它必须在添加时有效。如果不遵守这些规则,OCSP 响应将被忽略并发出警告。为了识别 OCSP 响应适用于哪个证书,需要颁发者的证书。如果 PEM 文件中找不到颁发者的证书,它将从同路径下以“.issuer”为后缀的文件中加载(如果存在),否则将报告错误。对于每个 PEM 文件,haproxy 还会检查同路径下以“.sctl”为后缀的文件是否存在。如果找到这样的文件,将启用对证书透明度(RFC6962)TLS 扩展的支持。文件必须包含一个有效的签名证书时间戳列表,如 RFC 中所述。文件将被解析以检查基本语法,但不对签名进行验证。在某些情况下,希望支持多种密钥类型,例如在提供给客户端的密码套件中支持 RSA 和 ECDSA。这允许支持 EC 证书的客户端能够使用 EC 密码,同时支持旧的仅 RSA 客户端。为了提供此功能,需要多个 PEM 文件,每个文件具有不同的密钥类型。要将这些 PEM 文件捆绑为 haproxy 识别的“证书捆绑包”,必须以以下方式命名它们:所有要捆绑的 PEM 文件都必须具有相同的基本名称,并在后面加上表示密钥类型的后缀。目前支持三个后缀:rsa、dsa 和 ecdsa。例如,如果 www.example.com 有两个 PEM 文件,一个 RSA 文件和一个 ECDSA 文件,它们必须命名为:“example.pem.rsa”和“example.pem.ecdsa”。文件名中的第一部分是任意的;只有后缀才重要。要将此捆绑包加载到 haproxy 中,只需指定基本名称即可。
示例
bind :8443 ssl crt example.pem
请注意,不会将后缀提供给 haproxy;这会告诉 haproxy 查找证书包。HAProxy 将同时加载包中的所有 PEM 文件,以尝试支持多种密钥类型。PEM 文件基于通用名称(CN)和主题备用名称(SAN)进行组合,以支持 SNI 查找。这意味着即使您向 haproxy 提供了一个证书包,如果该包中的证书没有共享的 CN/SAN 条目,haproxy 也将无法提供多证书支持。假设上面的示例中的包包含以下内容:
文件名CNSAN
example.pem.rsawww.example.comrsa.example.com
example.pem.ecdsawww.example.comecdsa.example.com
使用 SNI“www.example.com”连接的用户将能够使用 RSA 和 ECDSA 密码套件。使用 SNI“rsa.example.com”连接的用户将只能使用 RSA 密码套件,而使用“ecdsa.example.com”连接的用户将只能使用 ECDSA 密码套件。使用 BoringSSL 和 Openssl >= 1.1.1 时,多证书是原生支持的,无需打包证书。如果客户端支持 ECDSA 证书,则会优先选择 ECDSA 证书。如果为 <cert> 参数提供了目录名,haproxy 将自动在该目录中搜索并加载打包的文件。OSCP 文件(.ocsp)和颁发者文件(.issuer)支持多证书打包。每个证书都可以有自己的 .ocsp 和 .issuer 文件。目前,sctl 不支持多证书打包。
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 == 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
crt-list <file>
此设置仅在内置 OpenSSL 支持时可用。它指定了一个 PEM 文件列表,其中包含可选的 ssl 配置和每个证书的 SNI 过滤器,每行格式如下: <crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...] sslbindconf 支持“allow-0rtt”、“alpn”、“ca-file”、“ca-verify-file”、“ciphers”、“ciphersuites”、“crl-file”、“curves”、“ecdhe”、“no-ca-names”、“npn”、“verify”配置。使用 BoringSSL 和 Openssl >= 1.1.1 时,“ssl-min-ver”和“ssl-max-ver”也支持。它会覆盖 bind 行中为证书设置的配置。通配符在 SNI 过滤器中受支持。负向过滤器也受支持,这在与通配符过滤器结合使用以排除特定 SNI 时很有用,或者在第一个证书之后用于排除其 CN 或 Subject Alt Name (SAN) 的模式。证书将呈现给提供有效 TLS 服务器名称指示字段且该字段与 SNI 过滤器之一匹配的客户端。如果未指定 SNI 过滤器,则使用 CN 和 SAN。可以多次指定此指令。有关更多信息,请参阅“crt”选项。默认证书仍需要满足 OpenSSL 的期望。如果未使用它,则可以使用“strict_sni”选项。多证书捆绑(请参阅“crt”)在 crt-list 中受支持,只要在 crt-list 中只给出基本名称即可。SNI 过滤器将对所有捆绑的证书执行相同的操作。使用 BoringSSL 和 Openssl >= 1.1.1 时,多证书是本地支持的,请避免多证书捆绑。RSA 和 ECDSA 证书可以按顺序声明,并设置不同的 ssl 和过滤器参数。空行和以哈希('#')开头的行将被忽略。bind 行中声明的第一个证书用作默认证书,无论是来自 crt 还是 crt-list 选项,HAProxy 在 TLS 握手中应使用该证书,如果没有其他证书匹配。如果提供的 SNI 匹配其 CN 或 SAN,即使在任何 crt-list 上找到匹配的 SNI 过滤器,也将使用此证书。SNI 过滤器 !* 可以在声明的第一个证书之后使用,以不将其 CN 和 SAN 包含在 SNI 树中,因此它永远不会匹配,除非没有其他证书匹配。这样,第一个声明的证书充当回退。crt-list 文件示例:cert1.pem !* # comment cert2.pem [alpn h2,http/1.1] certW.pem *.domain.tld !secure.domain.tld certS.pem [curves X25519:P-256 ciphers ECDHE-ECDSA-AES256-GCM-SHA384] secure.domain.tld
curves <curves>
此设置仅在内置 OpenSSL 支持时可用。它设置描述在与 ECDHE 的 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的字符串。该字符串的格式是以冒号分隔的曲线名称列表。
示例
"X25519:P-256" (不带引号)
当设置了“curves”时,将忽略“ecdhe”参数。
是一个可选关键字,仅在某些 Linux 内核上受支持。它规定只有在连接上有数据到达时,或者最坏情况下在第一次重传后,才会接受连接。这只应在客户端首先发言的协议(例如 HTTP)上使用。它可以通过确保在接受连接时大部分请求已经可用,从而略微提高性能。另一方面,它将无法检测到不发言的连接。重要的是要注意,此选项在所有 2.6.31 之前的内核中都是有问题的,因为在客户端发言之前连接永远不会被接受。这可能会导致前端防火墙出现问题,前端防火墙会看到一个已建立的连接,而代理只会看到它处于 SYN_RECV 状态。此选项仅在 TCPv4/TCPv6 套接字上受支持,其他套接字会忽略它。
ecdhe <named curve>
此设置仅在内置 OpenSSL 支持时可用。它设置用于生成 ECDH 临时密钥的命名曲线(RFC 4492)。默认情况下,使用的命名曲线是 prime256v1。
此选项仅可用于 stats 套接字。它使您的 stats 套接字能够将监听器 FD 传递给另一个 HAProxy 进程。在 master-worker 模式下进行重载时,进程会自动重新执行,并添加 -x 和带有此选项的 stats 套接字之一。另请参见管理指南中的“-x”。
此选项强制对此监听器发起的 SSL 连接仅使用 SSLv3。对于高连接速率,SSLv3 通常比 TLS 对应项成本更低。此选项也可在全局语句“ssl-default-bind-options”上使用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制对此监听器发起的 SSL 连接仅使用 TLSv1.0。此选项也可在全局语句“ssl-default-bind-options”上使用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制对此监听器发起的 SSL 连接仅使用 TLSv1.1。此选项也可在全局语句“ssl-default-bind-options”上使用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制对此监听器发起的 SSL 连接仅使用 TLSv1.2。此选项也可在全局语句“ssl-default-bind-options”上使用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制对此监听器发起的 SSL 连接仅使用 TLSv1.3。此选项也可在全局语句“ssl-default-bind-options”上使用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。它启用动态 SSL 证书生成。需要一个 CA 证书及其私钥(参见“ca-sign-file”)。当 HAProxy 配置为透明转发代理时,由于呈现给客户端的证书上的通用名称不匹配,SSL 请求会产生错误。启用此选项后,HAProxy 将尝试使用客户端指示的 SNI 主机名伪造一个证书。这仅在没有证书与 SNI 主机名匹配时才会发生(参见“crt-list”)。如果发生错误,则使用默认证书,否则设置“strict-sni”选项。当 HAProxy 配置为反向代理时,它也可以用于简化具有许多后端的架构的部署。创建 SSL 证书是一项昂贵的操作,因此使用 LRU 缓存来存储伪造的证书(参见“tune.ssl.ssl-ctx-cache-size”)。它增加了 HAProxy 的内存占用,以减少多次使用同一证书时的延迟。
gid <gid>
将 UNIX 套接字的组设置为指定的系统 GID。也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置等同于“group”设置,不同之处在于使用组 ID 而不是其名称。非 UNIX 套接字会忽略此设置。
group <group>
将 UNIX 套接字的组设置为指定的系统组。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "gid" 设置等效,不同之处在于它使用组名而不是组 ID。此设置对非 UNIX 套接字无效。
id <id>
固定套接字 ID。默认情况下,套接字 ID 是自动分配的,但有时为了方便监控而固定它们会更方便。此值必须是严格正数,并且在侦听器/前端内是唯一的。此选项只能在定义单个套接字时使用。
interface <interface>
将套接字限制到特定接口。指定后,只有从该特定接口接收的数据包才会由套接字处理。目前仅在 Linux 上受支持。该接口必须是主系统接口,而不是别名接口。如果多个前端绑定到不同的接口,也可以将它们绑定到同一地址。请注意,绑定到网络接口需要 root 权限。此参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使配置了通过不同接口的显式路由也是如此。当同一客户端 IP 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
level <level>
此设置仅用于统计套接字,以限制可以在套接字上发出的命令的性质。它会被其他套接字忽略。 可以是以下之一:- “user”是权限最低的级别;只能读取非敏感统计信息,不允许进行任何更改。在难以限制对套接字访问的系统上,这会很有用。-“operator”是默认级别,适合大多数常见用途。所有数据都可以读取,并且只允许进行非敏感更改(例如,清除最大计数器)。-“admin”应谨慎使用,因为一切都允许(例如,清除所有计数器)。
maxconn <maxconn>
将套接字限制为此数量的并发连接。多余的连接将保留在系统的 backlog 中,直到释放一个连接。如果未指定,限制将与前端的 maxconn 相同。请注意,在端口范围或多个地址的情况下,相同的值将应用于每个套接字。此设置允许对昂贵的套接字进行不同的限制,例如 SSL 条目,它们很容易耗尽所有内存。
mode <mode>
设置用于定义 UNIX 套接字访问权限的八进制模式。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置对非 UNIX 套接字无效。
mss <maxseg>
设置要在传入连接上通告的 TCP 最大段大小(MSS)值。这可用于为某些特定端口强制使用较低的 MSS,例如用于通过 VPN 的连接。请注意,这依赖于一个内核功能,理论上在 Linux 下受支持,但在 2.6.28 之前的所有版本中都有错误。它可能在其他操作系统上工作,也可能不工作。它也可能不改变通告的值,而是改变传出段的有效大小。在以太网网络上,TCPv4 的通常通告值为 1460 = 1500(MTU) - 40(IP+TCP)。如果此值为正,它将用作通告的 MSS。如果为负,它将指示传出段应比传入连接的通告 MSS 减少多少。此参数仅与 TCP v4/v6 套接字兼容。
name <name>
为这些套接字设置一个可选名称,该名称将在统计页面上报告。
namespace <name>
在 Linux 上,可以指定套接字将属于哪个网络命名空间。此指令使得可以显式地将侦听器绑定到不同于默认命名空间的命名空间。请参考您的操作系统文档以了解有关网络命名空间的更多详细信息。
nice <nice>
设置从套接字发起的连接的“友好度”(niceness)。值必须在 -1024 到 1024(含)之间,默认为零。正值意味着此类连接对其他连接更友好,并且容易在调度器中让出位置。相反,负值意味着连接希望以比其他连接更高的优先级运行。这种差异仅在高负载下,当系统接近饱和时才会发生。负值适用于低延迟或管理服务,而高值通常推荐用于 CPU 密集型任务,如 SSL 处理或对延迟不那么敏感的批量传输。例如,为 SMTP 套接字使用正值,为 RDP 套接字使用负值可能是有意义的。
此设置仅在内置 OpenSSL 支持时可用。它在使用 ca-file 时阻止在服务器 hello 消息中发送 CA 名称。请使用“ca-verify-file”代替带有“no-ca-names”的“ca-file”。
此设置仅在内置 OpenSSL 支持时可用。它在 SSL 支持的监听器实例化的任何套接字上禁用 SSLv3 支持。请注意,SSLv2 在代码中被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句“ssl-default-bind-options”上使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。
此设置仅在内置 OpenSSL 支持时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复在 CPU 使用方面成本更高。此选项在全局语句“ssl-default-bind-options”中也可用。TLS ticket 机制仅用于 TLS 1.2 及以下版本。除非定期轮换 ticket 密钥(通过 reload 或使用“tls-ticket-keys”),否则使用 TLS ticket 会损害前向保密性。
此设置仅在内置 OpenSSL 支持时可用。它在 SSL 支持的监听器实例化的任何套接字上禁用 TLSv1.0 支持。请注意,SSLv2 在代码中被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句“ssl-default-bind-options”上使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。
此设置仅在内置 OpenSSL 支持时可用。它在 SSL 支持的监听器实例化的任何套接字上禁用 TLSv1.1 支持。请注意,SSLv2 在代码中被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句“ssl-default-bind-options”上使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。
此设置仅在内置 OpenSSL 支持时可用。它在 SSL 支持的监听器实例化的任何套接字上禁用 TLSv1.2 支持。请注意,SSLv2 在代码中被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句“ssl-default-bind-options”上使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。
此设置仅在内置 OpenSSL 支持时可用。它在 SSL 支持的监听器实例化的任何套接字上禁用 TLSv1.3 支持。请注意,SSLv2 在代码中被强制禁用,无法通过任何配置选项启用。此选项也可在全局语句“ssl-default-bind-options”上使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。
npn <protocols>
这启用了 NPN TLS 扩展,并将指定的协议列表作为 NPN 之上的支持协议进行声明。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库在启用 TLS 扩展支持的情况下进行构建(通过 haproxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(参见“alpn”关键字),尽管后者仅从 OpenSSL 1.0.2 开始可用。如果希望在旧版 OpenSSL 中使用 HTTP/2,仍可使用 NPN,因为在撰写本文时,大多数客户端仍支持它。可以同时启用 NPN 和 ALPN,尽管这可能没有实际意义,仅用于测试。
在选择密码套件时使用客户端的偏好,默认情况下强制使用服务器的偏好。此选项也可在全局语句“ssl-default-bind-options”中使用。请注意,对于 OpenSSL >= 1.1.1,如果 ChaCha20-Poly1305 密码位于客户端密码列表的顶部,ChaCha20-Poly1305 无论如何都会被重新优先排序(无需设置此选项)。
process <进程集>[/<线程集>]
这限制了允许此监听器运行的进程或线程列表。它不会强制任何进程,但会排除不匹配的进程。如果前端使用了“bind-process”设置,则将应用两者的交集。如果最终监听器不允许在任何剩余进程上运行,则会发出警告,并且监听器将在指定了单个进程时在监听器的第一个进程上运行,或者在指定了多个进程时在其所有进程上运行。如果指定了线程集,则会限制允许处理此监听器传入连接的线程(针对进程集)。如果配置了多个进程和线程,则会发出警告,因为这可能是配置错误或对这些模型的误解所致。对于需要多个范围的罕见情况,可以重复此指令。 <process-set> 和 <thread-set> 必须使用 all | odd | even | number[-[number]] 格式。范围可以部分定义。上限可以省略。在这种情况下,它将被相应的最大值替换。此指令的主要目的是与统计套接字一起使用,并为每个进程提供一个不同的套接字。第二个目的是让多个绑定行共享同一个 IP:port,但不在同一个监听器进程中,以便系统可以将传入连接分发到多个队列中,从而实现更平滑的进程间负载均衡。目前已知 Linux 3.9 及以上版本支持此功能。另请参阅“bind-process”和“nbproc”。
proto <name>
强制用于传入连接的复用器协议。它必须与前端的模式(TCP 或 HTTP)兼容。它也必须可以在前端使用。可用协议列表在 haproxy -vv 中报告。此选项的目的是绕过为从此监听套接字实例化的所有连接选择最佳复用器协议。例如,可以通过在绑定行中指定“proto h2”来强制在明文 TCP 上使用 http/2。
此设置仅与 stats 套接字一起使用,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围可以在 0 到 7 之间,符合 syslog rfc5424。请求数据的有效且成功的套接字命令(例如“show map”、“get acl foo”等)绝不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是以下之一:- “none”(默认)不向反馈消息前附加严重性级别。- “number” 严重性级别作为数字附加。- “string” 严重性级别作为遵循 rfc5424 约定的字符串附加。
此设置仅在内置 OpenSSL 支持时可用。它在此监听器实例化的连接上启用 SSL 解密。需要一个证书(参见上面的“crt”)。缓冲区中的所有内容都将以明文形式出现,因此 ACL 和 HTTP 处理只能访问解密后的内容。默认情况下禁用 SSLv3,使用“ssl-min-ver SSLv3”来启用它。
ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
此选项强制对由此监听器实例化的 SSL 连接使用 <version> 或更低版本。未使用“ssl-min-ver”使用此设置可能存在歧义,因为默认的 ssl-min-ver 值可能在未来的 HAProxy 版本中发生变化。此选项也可在全局语句“ssl-default-bind-options”中使用。另请参阅“ssl-min-ver”。
ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
此选项强制在此监听器实例化的 SSL 连接上使用 <version> 或更高版本。默认值为“TLSv1.2”。此选项也适用于全局语句“ssl-default-bind-options”。另请参见“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。仅当客户端提供的 SNI 与证书匹配时,才允许 SSL/TLS 协商。不使用默认证书。此选项还允许在 bind 行上没有任何证书的情况下启动,因此可以使用一个空目录,然后从 stats 套接字填充。有关更多信息,请参见“crt”选项。参见管理指南中的“add ssl crt-list”命令。
tcp-ut <delay>
为此监听套接字发起的任何传入连接设置 TCP 用户超时。此选项在 Linux 2.6.37 及更高版本中可用。它允许 haproxy 配置套接字的超时,这些套接字包含在配置延迟内未收到确认的数据。这对于经历长时间空闲期的长连接特别有用,例如远程终端或数据库连接池,其中客户端和服务器超时必须保持高位以允许长时间空闲,但重要的是要检测到客户端已消失,以便释放与之连接(以及服务器会话)相关的所有资源。参数默认以毫秒为单位表示延迟。这仅适用于常规 TCP 连接,并且会被其他协议忽略。
是一个可选关键字,仅在 Linux 内核版本 >= 3.7 上受支持。它在监听套接字上启用 TCP 快速打开(TCP Fast Open),这意味着支持此功能的客户端将能够在第二次连接开始的三次握手期间发送请求并接收响应,从而在第一次连接后节省一次往返时间。这仅对连接率高且每次往返都很重要的协议有意义。这可能会导致许多防火墙出现问题,因为它们不接受 SYN 数据包上的数据,因此只应在经过充分测试后才启用此选项。此选项仅在 TCPv4/TCPv6 套接字上受支持,并被其他套接字忽略。如果您的 libc 未定义 TCP_FASTOPEN,您可能需要使用 USE_TFO=1 来构建 HAProxy。
tls-ticket-keys <keyfile>
设置从中加载密钥的 TLS 票证密钥文件。根据使用 aes128 还是 aes256,密钥需要是 48 或 80 字节长,并使用 base64 编码,每行一个密钥(例如 openssl rand 80 | openssl base64 -A | xargs echo)。第一个密钥决定了后续密钥使用的密钥长度:您不能混合使用 aes128 和 aes256 密钥。密钥数量由 TLS_TICKETS_NO 构建选项指定(默认为 3),文件中至少需要存在同样数量的密钥。最后的 TLS_TICKETS_NO 个密钥将用于解密,倒数第二个密钥用于加密。这通过简单地将新密钥追加到文件并重新加载进程来实现轻松的密钥轮换。密钥必须定期轮换(例如每 12 小时),否则完美前向保密性会受到损害。将密钥远离任何永久性存储设备(如硬盘)也是一个好主意(提示:使用 tmpfs 并且不要交换这些文件)。生命周期提示可以使用 tune.ssl.timeout 进行更改。
是一个可选关键字,仅在某些 Linux 内核上受支持。它表示即使地址不属于本地机器,也会绑定这些地址,并且目标为这些地址的数据包将被截获,就好像这些地址是本地配置的一样。这通常需要启用 IP 转发。注意!不要将此与默认地址 '*' 一起使用,因为它会重定向指定端口的所有流量。此关键字仅在 HAProxy 使用 USE_LINUX_TPROXY=1 构建时可用。此参数仅与 TCPv4 和 TCPv6 套接字兼容,具体取决于内核版本。一些发行版的内核包含该功能的向后移植版本,因此请向您的供应商查询支持情况。
uid <uid>
将 UNIX 套接字的所有者设置为指定的系统 UID。也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置等同于“user”设置,不同之处在于使用用户的数字 ID 而不是其名称。非 UNIX 套接字会忽略此设置。
user <user>
将 UNIX 套接字的所有者设置为指定的系统用户。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“uid”设置等效,不同之处在于使用的是用户名而不是其 uid。此设置被非 UNIX 套接字忽略。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字同时绑定到 IPv4 和 IPv6。在默认情况下仅绑定到 IPv6 的系统上,这样做有时是必要的。它对非 IPv6 套接字没有影响,并被“v6only”选项覆盖。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字仅绑定到 IPv6。这样做有时比系统范围的设置更受欢迎,因为它是针对每个监听器的。它对非 IPv6 套接字没有影响,并优先于“v4v6”选项。
verify [none|optional|required]
此设置仅在构建时包含 OpenSSL 支持时可用。如果设置为 'none',则不请求客户端证书。这是默认设置。在其他情况下,会请求客户端证书。如果客户端在请求后未提供证书,并且 'verify' 设置为 'required',则握手将中止,而如果设置为 'optional',则会成功。客户端提供的证书始终使用来自 'ca-file' 的 CA 和来自 'crl-file' 的可选 CRL 进行验证。验证失败时,握手将中止,无论 'verify' 选项如何设置,除非错误代码与 'ca-ignore-err' 或 'crt-ignore-err' 中列出的错误代码完全匹配。

5.2. 服务器和默认服务器选项

server”和“default-server”关键字支持一定数量的设置,这些设置都作为参数传递到 server 行。这些参数的出现顺序无关紧要,而且它们都是可选的。其中一些设置是单个单词(布尔值),而另一些则期望其后跟一个或多个值。在这种情况下,值必须紧跟在设置名称之后。除了 default-server 之外,所有这些设置都必须在服务器地址之后指定(如果使用):server <name> <address>[:port] [settings ...] default-server [settings ...] 请注意,所有这些设置都同时被“server”和“default-server”关键字支持,但“id”仅被“server”支持。当前支持的设置如下。
addr <ipv4|ipv6>
使用“addr”参数,可以为发送健康检查或探测 agent-check 使用不同的 IP 地址。在某些服务器上,可能需要将一个 IP 地址专用于能够执行复杂测试的特定组件,这些测试比应用程序本身更适合进行健康检查。如果未设置“check”参数,则此参数将被忽略。另请参见“port”参数。
启用辅助代理检查,该检查独立于常规健康检查进行。代理健康检查通过连接到“agent-port”参数设置的端口并读取以第一个 '\r' 或 '\n' 结束的 ASCII 字符串来执行。该字符串由空格、制表符或逗号分隔的单词组成,顺序任意,每个单词包含:- 一个正整数百分比的 ASCII 表示,例如“75%”。此格式的值将根据 haproxy 启动时配置的服务器的初始权重成比例地设置权重。请注意,零权重在统计页面上报告为“DRAIN”,因为它对服务器的效果相同(将其从 LB 池中移除)。- 字符串“maxconn:”后跟一个整数(之间无空格)。此格式的值将设置服务器的最大连接数。宣传的最大连接数需要乘以负载均衡器的数量以及使用此健康检查的不同后端,以获得服务器可能接收的总连接数。示例:maxconn:30- 单词“ready”。这将把服务器的管理状态设置为 READY 模式,从而取消任何 DRAIN 或 MAINT 状态- 单词“drain”。这将把服务器的管理状态设置为 DRAIN 模式,因此它不会接受除通过持久性接受的连接之外的任何新连接。- 单词“maint”。这将把服务器的管理状态设置为 MAINT 模式,因此它根本不会接受任何新连接,并且健康检查将停止。- 单词“down”、“fail”或“stopped”,可选地后跟一个描述字符串,后面带有井号('#')。所有这些都将服务器的操作状态标记为 DOWN,但由于单词本身会报告在统计页面上,因此该差异允许管理员知道情况是否符合预期:服务可能有意停止,可能显示为 UP 但未能通过某些有效性测试,或者可能被视为 DOWN(例如,缺少进程或端口无响应)。- 单词“up”将服务器的操作状态重新设置为 UP,前提是健康检查也报告服务可访问。代理未宣传的参数不会被更改。例如,代理可能设计为监控 CPU 使用率,并且仅报告相对权重,并且从不与操作状态交互。同样,代理可以设计成一个用户界面,带有 3 个单选按钮,允许管理员仅更改管理状态。但是,需要注意的是,只有代理可以撤销自己的操作,因此如果服务器使用代理设置为 DRAIN 模式或 DOWN 状态,代理必须实现其他等效操作才能使服务恢复正常运行。连接到代理的失败不被视为错误,因为连接由“check”参数启用的常规健康检查进行测试。但请注意,在代理报告“down”后停止代理不是一个好主意,因为只有报告“up”的代理才能再次将服务器设置为 UP。请注意,Unix 统计套接字的 CLI 也能够强制代理的结果,以解决可能出现的错误代理问题。需要设置“agent-port”参数。另请参阅“agent-inter”和“no-agent-check”参数。
agent-send <string>
如果指定了此选项,haproxy 将在连接时将给定的字符串(按原样)发送到代理服务器。例如,您可以将后端名称编码到此字符串中,这将使您的代理能够根据后端发送不同的响应。请确保包含 `\n`,如果您想以换行符终止您的请求。
agent-inter <delay>
agent-inter”参数将两次 agent 检查之间的间隔设置为 <delay> 毫秒。如果未指定,延迟默认为 2000 毫秒。与所有其他基于时间的参数一样,它可以输入任何其他明确的单位,如 { us, ms, s, m, h, d }。“agent-inter”参数在未设置“timeout check”时也用作 agent 检查的超时。为了减少当多个服务器托管在同一硬件上时的“共振”效应,所有服务器的 agent 和健康检查都以一个小的时差启动。也可以使用全局“spread-checks”关键字在 agent 和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这样做是有意义的。另请参见“agent-check”和“agent-port”参数。
agent-addr <addr>
`agent-addr` 参数设置代理检查的地址。您可以将代理检查卸载到另一个目标,这样您就可以在一个地方管理 haproxy 中定义的服务器的状态和权重,以防您无法创建自我意识和自我管理的 à  服务。您可以指定 IP 或主机名,它们都将被解析。
agent-port <port>
agent-port”参数设置用于 agent 检查的 TCP 端口。另请参见“agent-check”和“agent-inter”参数。
在使用 TLS 1.3 时,允许向服务器发送早期数据。请注意,只有当客户端使用了早期数据,或者后端使用了带有“0rtt-rejected”关键字的“retry-on”时,才会发送早期数据。
alpn <protocols>
此功能启用 TLS ALPN 扩展,并宣布指定的协议列表作为 ALPN 之上的支持协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库已启用 TLS 扩展支持(通过 `haproxy -vv` 检查)。ALPN 扩展取代了原始的 NPN 扩展。ALPN 是连接到 HTTP/2 服务器所必需的。OpenSSL 版本早于 1.0.2 不支持 ALPN,仅支持现已废弃的 NPN 扩展。如果预期同时支持 HTTP/2 和 HTTP/1.1,则可以按首选顺序声明这两个版本,如下所示:`server 127.0.0.1:443 ssl crt pub.pem alpn h2,http/1.1`
当 server 行上存在“backup”时,该服务器仅在所有其他非备份服务器都不可用时才用于负载均衡。但是,带有引用该服务器的持久性 cookie 的请求将始终被处理。默认情况下,只使用第一个可操作的备份服务器,除非在后端设置了“allbackups”选项。另请参见“no-backup”和“allbackups”选项。
ca-file <cafile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,从中加载用于验证服务器证书的 CA 证书。
此选项在服务器上启用健康检查:- 未设置时,不执行任何健康检查,服务器始终被视为可用。- 设置时且未配置其他检查方法时,当可以在最高配置的传输层建立连接时,服务器被视为可用。这意味着默认情况下是 TCP,或者当设置了“ssl”或“check-ssl”时是 SSL/TLS,两者都可能与连接前缀(例如,当设置了“send-proxy”或“check-send-proxy”时, PROXY 协议头)结合使用。- 设置时且定义了应用程序级别健康检查时,将在配置的传输层之上执行应用程序级别交换,并且如果所有交换都成功,则服务器被视为可用。默认情况下,健康检查在服务器上配置的相同地址和端口上执行,使用相同的封装参数(SSL/TLS、proxy-protocol 头等)。可以使用“addr”更改目标地址,使用“port”更改端口。完成后,假定服务器未在服务端口上检查,并且已配置的封装参数不会被重用。必须显式设置“check-send-proxy”以发送连接头,“check-ssl”以使用 SSL/TLS。当在 server 行设置了“sni”或“alpn”时,它们的值不会用于健康检查,并且必须使用“check-sni”或“check-alpn”。健康检查流量的默认源地址与后端中定义的相同。可以使用“source”关键字更改。检查间隔可以使用“inter”关键字设置,而“rise”和“fall”关键字可用于定义需要多少次成功或失败的健康检查才能将服务器标记为可用或不可用。可选的应用程序级别健康检查可以使用“option httpchk”、“option mysql-check”、“option smtpchk”、“option pgsql-check”、“option ldap-check”或“option redis-check”进行配置。
示例
# 简单的 tcp 检查 backend foo server s1 192.168.0.1:80 check # 这会执行 tcp 连接 + tls 握手 backend foo server s1 192.168.0.1:443 ssl check # 简单的 tcp 检查足以使检查成功 backend foo option tcp-check tcp-check connect server s1 192.168.0.1:443 ssl check
此选项强制在出站健康检查中发送 PROXY 协议行,无论服务器是否为正常流量使用 send-proxy。默认情况下,如果 PROXY 协议已为正常流量启用,并且不存在“port”或“addr”指令,则为健康检查启用 PROXY 协议。但是,如果存在此类指令,则需要使用“check-send-proxy”选项来强制使用该协议。有关更多信息,请参见“send-proxy”选项。
check-alpn <protocols>
定义要通过 ALPN 通告的协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不含引号)。如果未设置,将使用服务器的 ALPN。
强制用于服务器健康检查连接的复用器协议。它必须与健康检查类型(TCP 或 HTTP)兼容。它也必须可以在后端使用。可用协议列表在 haproxy -vv 中报告。此选项的目的是绕过为建立到此服务器的健康检查连接选择最佳复用器协议。如果未定义,则使用服务器的协议,如果已设置。
check-sni <sni>
此选项允许您指定在通过 SSL 进行健康检查时使用的 SNI。只能使用字符串来设置 <sni>。如果您想为代理的流量设置 SNI,请参见“sni”。
此选项强制对所有 SSL 健康检查进行加密,无论服务器是否为正常流量使用 SSL。这通常在指定了显式的“port”或“addr”指令且 SSL 健康检查未被继承时使用。理解此选项将 SSL 传输层插入到检查下方非常重要,因此简单的 TCP 连接检查会变成 SSL 连接,从而取代旧的 ssl-hello-chk。最常见的用法是通过结合“httpchk”和 SSL 检查来发送 HTTPS 检查。所有 SSL 设置都对健康检查和流量通用(例如,密码)。有关更多信息,请参阅“ssl”选项,并使用“no-check-ssl”禁用此选项。
此选项启用使用上游 socks4 代理的传出运行状况检查。默认情况下,即使已为主流量启用 Socks 隧道,运行状况检查也不会通过 Socks 隧道。
ciphers <ciphers>
此设置仅在内置 OpenSSL 支持时可用。此选项设置一个字符串,该字符串描述了在与服务器进行 SSL/TLS 握手期间协商的密码算法列表。字符串的格式定义在 OpenSSL man 页面的“man 1 ciphers”中。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/)。对于 TLSv1.3 密码配置,请检查“ciphersuites”关键字。
ciphersuites <ciphersuites>
此设置仅在构建时包含 OpenSSL 支持并使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。此选项设置在与服务器的 TLS 1.3 握手中协商的密码算法列表的描述字符串。字符串的格式在 OpenSSL man 页的“man 1 ciphers”下的“ciphersuites”部分中定义。有关 TLSv1.2 及更早版本的密码配置,请查看“ciphers”关键字。
cookie <value>
cookie”参数将分配给服务器的 cookie 值设置为 <value>。此值将在传入请求中进行检查,并且将选择具有相同值的第一个可用服务器。作为回报,在 cookie 插入或重写模式下,此值将分配给发送给客户端的 cookie。拥有多个服务器共享相同的 cookie 值并没有错,事实上,在常规服务器和备用服务器之间相当常见。另请参阅后端节中的“cookie”关键字。
crl-file <crlfile>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载用于验证服务器证书的证书吊销列表。
crt <cert>
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书和关联的私钥。通过将这两个 PEM 文件连接到一个文件中,可以创建此文件。如果服务器发送客户端证书请求,则会发送此证书。
disabled”关键字将服务器启动为“disabled”状态。这意味着它被标记为维护模式下的 DOWN,并且除了持久模式允许的连接之外,任何其他连接都不会到达它。这非常适合设置新服务器,因为正常流量永远不会到达它们,同时仍然可以通过使用 force-persist 机制来测试服务。另请参阅“enabled”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“disabled”设置作为默认值。它也可作为“default-server”设置,以重置任何以前的“default-server”“disabled”设置。
error-limit <count>
如果启用了运行状况监视,“error-limit”参数指定触发“on-error”选项所选事件的连续错误次数。默认设置为 10 次连续错误。另请参阅“check”、“error-limit”和“on-error”。
fall <count>
fall”参数表示服务器将在 <count> 次连续不成功的运行状况检查后被视为死亡。如果未指定,此值默认为 3。另请参阅“check”、“inter”和“rise”参数。
此选项强制仅使用 SSLv3,当 SSL 用于与服务器通信时。SSLv3 对于高连接速率通常比 TLS 对应项成本更低。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.0,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.1,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.2,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.3,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
id <value>
为服务器设置一个持久化 ID。此 ID 必须是正数且对代理是唯一的。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 目前仅在统计信息中返回。
init-addr {last | libc | none | <ip>},[...]*
指示在服务器使用 FQDN 时,启动时应按什么顺序解析服务器地址。尝试通过依次应用列表中用逗号分隔的每种方法来解析地址。第一种成功的方法将被使用。如果到达列表末尾仍未找到有效的方法,则会抛出错误。“last”方法建议选择状态文件中出现的地址(参见“server-state-file”)。“libc”方法使用 libc 的内部解析器(根据操作系统和构建选项使用 gethostbyname() 或 getaddrinfo())。“none”方法专门指示服务器应在没有任何有效 IP 地址的情况下启动,处于 DOWN 状态。这对于在启动时忽略一些 DNS 问题很有用,等待稍后情况得到修复。最后,可以提供 IP 地址(IPv4 或 IPv6)。它可以是服务器当前已知的地址(例如,由配置生成器填充),或用于捕获旧会话并向其显示有意义的错误消息的虚拟服务器的地址。当使用“first”负载均衡算法时,此 IP 地址可以指向一个伪服务器,用于触发动态创建新实例。此选项默认为“last,libc”,表示首先使用状态文件中找到的上一个地址(如果存在),否则使用 libc 的解析器。这确保了与历史行为的持续兼容性。
示例
defaults # 地址解析永不失败 default-server init-addr last,libc,none
inter <delay>
fastinter <delay>
downinter <delay>
inter”参数将两次连续健康检查之间的间隔设置为 <delay> 毫秒。如果未指定,则延迟默认为 2000 毫秒。也可以使用“fastinter”和“downinter”根据服务器状态优化检查之间的延迟。
服务器状态使用的间隔
UP 100% (非过渡状态)inter
过渡性 UP (正在变为 down "fall"),
过渡性 DOWN (正在变为 up "rise"),
或尚未检查。
如果设置了“fastinter”,则使用它,
否则使用“inter”。
DOWN 100% (非过渡状态)
如果设置了“downinter”,则使用它,
否则使用“inter”。
与所有其他基于时间的参数一样,它们可以以任何其他显式单位 {us, ms, s, m, h, d} 输入。“inter”参数在未设置“timeout check”时,也用作服务器运行状况检查的超时。为了减少托管在同一硬件上的多个服务器之间的“共振”效应,代理和所有服务器的运行状况检查都以它们之间一个小的时差开始。还可以使用全局“spread-checks”关键字在代理和运行状况检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。
log-proto <logproto>
log-proto”指定用于将事件消息转发到环形部分中配置的服务器的协议。可能的值为“legacy”和“octet-count”,分别对应于 rfc6587 中的“Non-transparent-framing”和“Octet counting”。“legacy”是默认值。
maxconn <maxconn>
maxconn”参数指定将发送到此服务器的最大并发连接数。如果传入并发连接数超过此值,它们将被排队,等待插槽释放。此参数非常重要,因为它可以保护脆弱的服务器免受极端负载的影响。如果指定了“minconn”参数,则限制将变为动态。默认值为“0”,表示无限制。另请参阅“minconn”和“maxqueue”参数,以及后端的“fullconn”关键字。在 HTTP 模式下,此参数限制的是并发请求数而不是连接数。多个请求可能会通过单个 TCP 连接复用到服务器。例如,如果您指定 maxconn 为 50,您可能会看到 1 到 50 个实际服务器连接,但并发请求不超过 50 个。
maxqueue <maxqueue>
maxqueue”参数指定将等待此服务器队列的最大连接数。如果达到此限制,下一个请求将重新分发到其他服务器,而不是无限期地等待被服务。这将破坏持久性,但可能允许人们在尝试连接的服务器即将崩溃时快速重新登录。默认值为“0”,表示队列无限制。另请参阅“maxconn”和“minconn”参数。
max-reuse <count>
max-reuse”参数指示 HTTP 连接处理器,它们不应将服务器连接重复使用超过此次数来发送新请求。允许的值为 -1(默认值),它禁用此限制,或任何正值。值为零将有效禁用 keep-alive。这仅用于解决某些服务器随时间推移而导致资源泄漏的 bug。由于可能存在技术限制使其无法强制执行,因此底层可能不会完全遵守此参数。至少 HTTP/2 连接到服务器会遵守它。
minconn <minconn>
当设置了“minconn”参数时,maxconn 限制将变为动态限制,遵循后端的负载。服务器将始终接受至少 <minconn> 个连接,最多不超过 <maxconn> 个连接,当后端并发连接数少于 <fullconn> 时,限制将在两者之间逐渐增加。这使得在正常负载下限制服务器的负载成为可能,但在重要负载下可以将其进一步推高,而不会在异常负载下使服务器过载。另请参阅“maxconn”和“maxqueue”参数,以及“fullconn”后端关键字。
namespace <name>
在 Linux 上,可以指定套接字属于哪个网络命名空间。此指令使得可以明确地将服务器绑定到不同于默认命名空间的命名空间。有关网络命名空间的更多详细信息,请参阅您的操作系统文档。
此选项可以作为“server”设置,以重置从“default-server”指令继承的任何“agent-check”设置作为默认值。它也可以作为“default-server”设置,以重置任何先前的“default-server”的“agent-check”设置。
此选项可以作为“server”设置,以重置从“default-server”指令继承的任何“backup”设置作为默认值。它也可以作为“default-server”设置,以重置任何先前的“default-server”的“backup”设置。
此选项可以作为“server”设置,以重置从“default-server”指令继承的任何“check”设置作为默认值。它也可以作为“default-server”设置,以重置任何先前的“default-server”的“check”设置。
此选项可以作为“server”设置,以重置从“default-server”指令继承的任何“check-ssl”设置作为默认值。它也可以作为“default-server”设置,以重置任何先前的“default-server”的“check-ssl”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“send-proxy”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“send-proxy”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“send-proxy-v2”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“send-proxy-v2”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“send-proxy-v2-ssl”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“send-proxy-v2-ssl”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“send-proxy-v2-ssl-cn”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“send-proxy-v2-ssl-cn”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“ssl”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“ssl”设置。
此选项在 SSL 用于与服务器通信时禁用 SSL 会话重用。它将强制服务器为每个新连接执行完整的握手。这可能只对基准测试、故障排除和多疑用户有用。
此选项禁用与服务器通信时使用 SSL 的 SSLv3 支持。请注意,SSLv2 在代码中已被禁用,无法通过任何配置选项启用。请使用“ssl-min-ver”和“ssl-max-ver”代替。在 default-server 中支持:否
此设置仅在构建时支持 OpenSSL 时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复在服务器的 CPU 使用率方面成本更高。此选项也可用在全局语句 "ssl-default-server-options" 中。TLS Ticket 机制仅用于 TLS 1.2 及以下版本。前向保密会因 TLS Ticket 而受到损害,除非 Ticket 密钥被定期轮换(通过重载或使用 "tls-ticket-keys")。另请参阅 "tls-tickets"。
此选项禁用在 SSL 用于与服务器通信时对 TLSv1.0 的支持。请注意,SSLv2 在代码中已被禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可在全局语句“ssl-default-server-options”中使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。在 default-server 中支持:否
此选项禁用在 SSL 用于与服务器通信时对 TLSv1.1 的支持。请注意,SSLv2 在代码中已被禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可在全局语句“ssl-default-server-options”中使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。在 default-server 中支持:否
此选项禁用在 SSL 用于与服务器通信时对 TLSv1.2 的支持。请注意,SSLv2 在代码中已被禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可在全局语句“ssl-default-server-options”中使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。在 default-server 中支持:否
此选项禁用在 SSL 用于与服务器通信时对 TLSv1.3 的支持。请注意,SSLv2 在代码中已被禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 开销更大,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可在全局语句“ssl-default-server-options”中使用。请使用“ssl-min-ver”和“ssl-max-ver”代替。在 default-server 中支持:否
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“verifyhost”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“verifyhost”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“tfo”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“tfo”设置。
永远不要将分配给此服务器的连接添加到 stick-table。这可以与 backup 结合使用,以确保为 backup 服务器禁用 stick-table 持久性。
npn <protocols>
这会启用 NPN TLS 扩展,并在 NPN 之上声明支持的协议列表。协议列表是一系列由逗号分隔的协议名称,例如:"http/1.1,http/1.0"(不带引号)。这要求 SSL 库在启用 TLS 扩展支持的情况下构建(通过 haproxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(请参阅 "alpn" 关键字),尽管后者仅在 OpenSSL 1.0.2 及以上版本可用。
observe <mode>
此选项启用基于观察与服务器通信的健康状况调整。默认情况下,此功能被禁用,启用它还需要启用健康检查。支持两种模式:"layer4" 和 "layer7"。在 layer4 模式下,只有成功的/不成功的 tcp 连接是重要的。在 layer7 模式下(仅允许用于 http 代理),会验证从服务器收到的响应,例如有效的/无效的 http 代码、无法解析的头信息、超时等。有效的状态码包括 100 到 499、501 和 505。另请参阅 "check"、"on-error" 和 "error-limit"。
on-error <mode>
选择在检测到足够多的连续错误时应执行的操作。目前提供四种模式:- fastinter:强制 fastinter - fail-check:模拟失败的检查,也强制 fastinter(默认) - sudden-death:模拟一个预致命的健康检查失败,再多一次失败的检查将导致服务器标记为宕机,强制 fastinter - mark-down:立即将服务器标记为宕机并强制 fastinter 另请参阅 "check"、"observe" 和 "error-limit"。
修改服务器被标记为宕机时发生的操作。目前提供一种操作:- shutdown-sessions:关闭会话。启用此设置后,当服务器宕机时,所有到该服务器的连接将立即终止。如果健康检查检测到的情况比简单的连接状态更复杂,并且长时间的超时会导致服务长时间无响应,则可能需要使用此选项。例如,健康检查可能检测到数据库卡死,并且没有机会重用现有连接。以此方式终止的连接将以 'D' 终止代码(表示 "Down")进行记录。默认情况下,操作是禁用的。
on-marked-up <action>
修改服务器被标记为正常时发生的操作。目前提供一种操作:- shutdown-backup-sessions:关闭所有备用服务器上的会话。这仅在服务器未处于备用状态且未被禁用(其有效权重必须 > 0)时执行。当处理长会话(例如 LDAP、SQL 等)时,这有时可用于强制活动服务器在恢复后重新承担所有流量。这样做可能会比试图解决的问题更多(例如,未完成的事务),因此请谨慎使用此功能。因服务器启动而终止的会话将以 'U' 终止代码(表示 "Up")进行记录。默认情况下,操作是禁用的。
pool-low-conn <最大值>
为服务器设置一个较低的空闲连接数阈值,低于该阈值时,一个线程将不会尝试从另一个线程窃取连接。这对于在涉及许多非常快的服务器的场景中提高 CPU 使用模式可能很有用,以确保所有线程始终保持少量空闲连接,而不是让它们累积在一个线程上并跨线程迁移。通常是线程数两倍的值已经可以显示出非常好的性能,响应时间在亚毫秒级别。默认值为零,表示任何空闲连接都可以随时使用。对于常规使用,这是推荐的设置。这仅适用于可以根据与“http-reuse”相同的原理共享的连接。如果通过“tune.idle-pool.shared”禁用了线程之间的连接共享,那么使用此设置以确保每个线程始终有几个连接就变得非常重要,否则连接重用率会随着线程数的增加而降低。
pool-max-conn <最大值>
设置服务器的空闲连接最大数量。-1 表示无限连接,0 表示无空闲连接。默认值为 -1。启用空闲连接后,不再属于任何客户端会话的孤立空闲连接将被移至专用池,以便未来的客户端可以使用它们。这仅适用于可以根据与 "http-reuse" 相同的原则共享的连接。
设置开始清除空闲连接的延迟。每隔 <delay> 时间间隔,一半的空闲连接将被关闭。0 表示不保留任何空闲连接。默认值为 5 秒。
port <port>
使用 "port" 参数,可以为健康检查使用不同的端口。在某些服务器上,可能希望将一个端口专门用于能够执行复杂测试的特定组件,这些测试比应用程序更适合健康检查。例如,通常在 inetd 中运行一个简单的脚本。如果未设置 "check" 参数,则此参数将被忽略。另请参阅 "addr" 参数。
proto <名称>
强制复用器协议用于到此服务器的出站连接。它必须与后端的模式(TCP 或 HTTP)兼容。它还必须能在后端使用。可用协议列表在 haproxy -vv 中报告。此选项的目的是绕过为所有到此服务器建立的连接选择最佳复用器协议。
redir <prefix>
redir”参数为所有指向此服务器的 GET 和 HEAD 请求启用重定向模式。这意味着 HAProxy 不会而是将请求转发到服务器,而是发送一个“HTTP 302”响应,其中“Location”头部由此前缀组成,紧接着是请求的 URI(从路径组件的第一个 '/' 开始)。这意味着 <prefix> 后面不应使用斜杠。所有无效请求都将被拒绝,所有非 GET 或 HEAD 请求都将由服务器正常提供。请注意,由于响应完全是伪造的,因此响应中无法进行头部篡改或 cookie 插入。但是,请求中的 cookie 仍会被分析,这使得该解决方案在本地发生灾难时,可用于将用户重定向到远程位置。主要用途是通过让客户端直接连接到静态服务器来增加带宽。注意:此处切勿使用相对位置,否则会导致客户端和 HAProxy 之间出现循环!
示例
server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
rise <count>
"rise" 参数指定服务器将在连续 <count> 次成功的健康检查后被视为可运行。如果未指定,此值默认为 2。另请参阅 "check"、"inter" 和 "fall" 参数。
resolve-opts <选项>,<选项>,...
以逗号分隔的选项列表,应用于与此服务器关联的DNS解析。可用选项: * allow-dup-ip 默认情况下,HAProxy在运行时DNS解析操作时会阻止后端中IP地址重复。也就是说,在某些情况下,两个服务器(在同一个后端,由同一个FQDN解析)具有相同的IP地址是有意义的。对于这种情况,只需启用此选项。这与prevent-dup-ip相反。 * ignore-weight 忽略SRV记录中设置的任何权重。当您希望使用其他方法(例如使用"agent-check"或通过运行时API)控制权重时,此功能非常有用。 * prevent-dup-ip 确保HAProxy的默认行为在服务器上强制执行:防止在同一后端中,共享相同FQDN的服务器之间重复使用已设置的IP地址。这与allow-dup-ip相反。
示例
backend b_myapp default-server init-addr none resolvers dns server s1 myapp.example.com:80 check resolve-opts allow-dup-ip server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
设置了 allow-dup-ip 选项后:* 如果域名服务器返回单个 IP 地址,则两个服务器都将使用它 * 如果域名服务器返回 2 个 IP 地址,则每个服务器将选择一个不同的地址 默认值:未设置
当为服务器启用 DNS 解析并且返回了来自不同族的多个 IP 地址时,HAProxy 将优先使用 "resolve-prefer" 参数中指定的族中的 IP 地址。可用族:"ipv4" 和 "ipv6" 默认值:ipv6
示例
server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6
resolve-net <网络>[,<网络[,...]]
此选项优先选择匹配网络的 IP 地址。这在云环境中很有用,可以优先选择本地 IP。在某些情况下,云高可用服务可以通过多个数据中心上的多个 IP 地址进行 anúnciate。数据中心之间的延迟不可忽略,因此此补丁允许优先选择本地数据中心。如果没有任何地址与配置的网络匹配,则会选择其他地址。
示例
server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8
指向一个现有的 "resolvers" 部分,以解析当前服务器的主机名。
示例
server s1 app1.domain.com:80 check resolvers mydns
另请参见 第 5.3 节
send-proxy”参数强制在与此服务器建立的任何连接上使用 PROXY 协议。PROXY 协议会告知对方有关传入连接的第 3/4 层地址的信息,以便它能够了解客户端地址或其访问的公共地址,而不管上层协议是什么。对于由“accept-proxy”或“accept-netscaler-cip”监听器接受的连接,将使用通告的地址。仅支持 TCPv4 和 TCPv6 地址族。其他族(如 Unix 套接字)将报告 UNKNOWN 族。使用此选项的服务器可以完全链接到另一个使用“accept-proxy”设置的 haproxy 实例。如果服务器不了解该协议,则不得使用此设置。当向服务器发送健康检查时,如果设置了此选项,将自动使用 PROXY 协议,除非有显式的“port”或“addr”指令指示检查应发送到不同位置,在这种情况下,还需要显式的“check-send-proxy”指令才能使用 PROXY 协议。另请参阅本节的“no-send-proxy”选项以及“bind”关键字的“accept-proxy”和“accept-netscaler-cip”选项。
send-proxy-v2”参数强制在与此服务器建立的任何连接上使用 PROXY 协议版本 2。PROXY 协议会告知对方有关传入连接的第 3/4 层地址的信息,以便它能够了解客户端地址或其访问的公共地址,而不管上层协议是什么。如果协商了 ALPN,它还会发送 ALPN 信息。如果服务器不了解此协议版本,则不得使用此设置。另请参阅本节的“no-send-proxy-v2”选项以及“bind”关键字的“send-proxy”选项。
proxy-v2-options <选项>[,<选项>]*
"proxy-v2-options"参数在使用"send-proxy-v2"时,向PROXY协议版本2添加要发送的选项。可用选项有: - ssl:另请参阅"send-proxy-v2-ssl"。 - cert-cn:另请参阅"send-proxy-v2-ssl-cn"。 - ssl-cipher:使用的密码名称。 - cert-sig:使用的证书的签名算法。 - cert-key:使用的证书的密钥算法。 - authority:客户端传递的主机名值(仅支持TLS连接中的SNI)。 - crc32c:PROXYv2头的校验和。 - unique-id:在PROXYv2头中发送使用前端"unique-id-format"生成的唯一ID。此unique-id主要用于“mode tcp”。在“mode http”中可能会导致意外结果,因为生成的unique ID也用于Keep-Alive连接中的第一个HTTP请求。
send-proxy-v2-ssl”参数强制在与此服务器建立的任何连接上使用 PROXY 协议版本 2。PROXY 协议会告知对方有关传入连接的第 3/4 层地址的信息,以便它能够了解客户端地址或其访问的公共地址,而不管上层协议是什么。此外,还会将 PROXY 协议的 SSL 信息扩展添加到 PROXY 协议头部。如果服务器不了解此协议版本,则不得使用此设置。另请参阅本节的“no-send-proxy-v2-ssl”选项以及“bind”关键字的“send-proxy-v2”选项。
send-proxy-v2-ssl”参数强制在与此服务器建立的任何连接上使用 PROXY 协议版本 2。PROXY 协议会告知对方有关传入连接的第 3/4 层地址的信息,以便它能够了解客户端地址或其访问的公共地址,而不管上层协议是什么。此外,会将 PROXY 协议的 SSL 信息扩展以及客户端证书主题(如果有)的通用名称添加到 PROXY 协议头部。如果服务器不了解此协议版本,则不得使用此设置。另请参阅本节的“no-send-proxy-v2-ssl-cn”选项以及“bind”关键字的“send-proxy-v2”选项。
slowstart <start_time_in_ms>
服务器的“slowstart”参数接受一个以毫秒为单位的值,表示刚恢复运行的服务器将在多久后全速运行。与所有其他基于时间参数一样,它可以以 { us, ms, s, m, h, d } 中的任何其他显式单位输入。速度在此期间线性增长,从 0% 到 100%。该限制适用于两个参数:- maxconn:服务器接受的连接数将从 1% 增长到正常动态限制(由 minconn、maxconn、fullconn 定义)的 100%。- weight:当后端使用动态加权算法时,权重将线性增长,从 1% 到 100%。在这种情况下,权重在每次健康检查时更新。因此,重要的是“inter”参数小于“slowstart”,以最大化步数。当 haproxy 启动时,slowstart 永远不会应用,否则会给正在运行的服务器带来麻烦。它仅在服务器之前被视为失败时才适用。
sni <expression>
sni”参数评估样本获取表达式,将其转换为字符串,并使用结果作为在 SNI TLS 扩展中发送到服务器的主机名。典型的用例是在桥接的 TCP/SSL 场景中发送从客户端接收到的 SNI,并使用“ssl_fc_sni”样本获取作为表达式。THIS MUST NOT BE USED FOR HTTPS,其中应使用 req.hdr(host) 代替,因为 HTTPS 中的 SNI 必须始终与 Host 字段匹配,并且客户端允许在同一连接上使用不同的主机名)。如果设置了“verify required”(这是推荐设置),则结果名称还将与服务器证书的名称进行匹配。有关更多详细信息,请参阅“verify”指令。如果要为健康检查设置 SNI,请参阅“check-sni”指令了解更多详情。
source <addr>[:<pl>[-<ph>]] [usesrc { <addr2>[:<port2>] | client | clientip } ]
source <addr>[:<port>] [usesrc { <addr2>[:<port2>] | hdr_ip(<hdr>[,<occ>]) } ]
source <addr>[:<pl>[-<ph>]] [interface <name>] ...
source”参数设置连接到服务器时将使用的源地址。它遵循与后端“source”关键字完全相同的参数和原则,只是它仅适用于引用它的服务器。请参考“source”关键字了解详情。此外,服务器行上的“source”语句允许通过指示以短划线('-')分隔的下限和上限来指定源端口范围。某些操作系统在指定源端口范围时可能需要有效的 IP 地址。允许多个服务器具有相同的 IP/范围。这样做可以绕过最多 64k 总并发连接的限制。然后限制将达到每个服务器 64k 连接。自 Linux 4.2/libc 2.23 起,IP_BIND_ADDRESS_NO_PORT 会为指定了源地址但未指定端口的连接设置。
此选项在到服务器的出站连接上启用 SSL 加密。使用 SSL 连接到服务器时,使用“verify”验证服务器证书至关重要,否则通信容易受到简单的中间人攻击,从而使 SSL 无效。使用此选项时,健康检查也会自动以 SSL 方式发送,除非有“port”或“addr”指令指示检查应发送到不同的位置。另请参阅“no-ssl”以禁用“ssl”选项,并参阅“check-ssl”选项以强制 SSL 健康检查。
ssl-max-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
使用 SSL 与服务器通信时,此选项强制使用 <version> 或更低版本。此选项也可用在全局语句 "ssl-default-server-options" 中。另请参阅 "ssl-min-ver"。
ssl-min-ver [ SSLv3 | TLSv1.0 | TLSv1.1 | TLSv1.2 | TLSv1.3 ]
使用 SSL 与服务器通信时,此选项强制使用 <version> 或更高版本。此选项也可用在全局语句 "ssl-default-server-options" 中。另请参阅 "ssl-max-ver"。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“no-ssl-reuse”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“no-ssl-reuse”设置。
此选项可用作“server”设置,以重置任何可能从“default-server”指令继承的作为默认值的“non-stick”设置。它还可以用作“default-server”设置,以重置任何先前“default-server”的“non-stick”设置。
socks4 <地址>:<端口>
此选项为到服务器的出站连接启用上游 socks4 隧道。使用此选项默认不会强制健康检查通过 socks4。您需要使用关键字 "check-via-socks4" 来启用它。
tcp-ut <delay>
设置到此服务器的所有出站连接的 TCP 用户超时。此选项自 Linux 2.6.37 版本起可用。它允许 haproxy 为包含在配置延迟内未收到确认的数据的套接字配置超时。这对于经历长时间空闲期的长连接特别有用,例如远程终端或数据库连接池,其中客户端和服务器超时必须保持较高以允许长时间空闲,但重要的是要检测到服务器已消失,以便释放与其连接(以及客户端会话)相关的所有资源。另一个典型用例是强制死服务器连接在健康检查太慢或在软重新加载期间(因为此时健康检查被禁用)终止。参数默认以毫秒为单位表示延迟。这仅适用于常规 TCP 连接,对于其他协议将被忽略。
此选项在支持它的系统(目前仅限 Linux 内核 >= 4.11)上启用连接到服务器时使用 TCP Fast Open。有关 TCP Fast Open 的更多信息,请参阅 "tfo" bind 选项。请注意,在使用 tfo 时,您还应该为 "retry-on" 使用 "conn-failure"、"empty-response" 和 "response-timeout" 关键字,否则 haproxy 将无法在失败时重试连接。另请参阅 "no-tfo"。
track [<后端>/]<服务器>
此选项通过跟踪另一个服务器来设置服务器的当前状态。可以跟踪一个本身跟踪另一个服务器的服务器,前提是链的末端有一个启用了健康检查的服务器。如果省略 <backend>,则使用当前服务器。如果使用了 disable-on-404,则必须在两个代理上都启用它。
此选项可用于“server”设置,以重置从“default-server”指令继承的任何“no-tls-tickets”设置作为默认值。TLS ticket 机制仅用于 TLS 1.2。如果票证密钥未定期轮换(通过 reload 或使用“tls-ticket-keys”),则前向保密性会受到损害。它也可用于“default-server”设置,以重置任何先前的“default-server” “no-tls-tickets”设置。
verify [none|required]
此设置仅在内置 OpenSSL 支持时可用。如果设置为“none”,则不验证服务器证书。在其他情况下,在检查证书中的名称是否与通过“sni”指令传递的名称匹配,或如果未提供,则与通过“verifyhost”指令传递的静态主机名匹配之后,将使用来自“ca-file”的 CA 和可选的“crl-file”的 CRL 来验证服务器提供的证书。找不到名称时,将忽略证书中的名称。因此,没有 SNI 时,使用“verifyhost”很重要。验证失败时,握手将被中止。使用 SSL 连接服务器时,验证服务器证书至关重要,否则通信容易受到轻微的中间人攻击,使 SSL 完全无效。除非“ssl_server_verify”出现在全局部分,否则默认情况下,“verify”设置为“required”。
verifyhost <hostname>
此设置仅在内置 OpenSSL 支持时可用,并且仅在同时指定“verify required”时生效。此指令设置了一个默认的静态主机名,用于在未使用 SNI 连接服务器时与服务器证书进行检查。如果未使用 SNI,这是启用主机名验证的唯一方法。此静态主机名(设置后)也将用于运行状况检查(这些运行状况检查无法提供 SNI 值)。如果证书中的任何主机名与指定的主机名不匹配,则握手将被中止。服务器提供的证书中的主机名可能包含通配符。另请参阅“verify”、“sni”和“no-verifyhost”选项。
weight <weight>
weight”参数用于调整服务器相对于其他服务器的权重。所有服务器将根据其权重相对于所有权重总和的比例接收负载,因此权重越高,负载越高。默认权重为 1,最大值为 256。值为 0 表示服务器不参与负载均衡,但仍接受持久连接。如果使用此参数根据服务器容量分配负载,建议从可以增长和收缩的值开始,例如 10 到 100 之间,以便为以后调整留出足够的空间。

5.3. 使用 DNS 进行服务器 IP 地址解析

HAProxy 允许在服务器行中使用主机名通过名称服务器检索其 IP 地址。默认情况下,HAProxy 在解析配置文件时解析名称,并在启动时缓存结果,并在进程生命周期内缓存该结果。这在某些情况下不够用,例如在 Amazon 中,服务器的 IP 地址在重启后可能会发生变化,或者 ELB 虚拟 IP 地址会根据当前工作负载而变化。本章介绍 HAProxy 如何配置为在运行时处理服务器名称解析。无论是否启用了运行时服务器名称解析,HAProxy 在解析配置时都会继续进行第一次解析。

5.3.1. 总体概述

正如我们在引言中所见,HAProxy 中的名称解析发生在进程生命周期的两个不同阶段:1. 启动时,HAProxy 解析服务器行定义并匹配主机名。它使用 libc 函数来解析主机名。此解析依赖于 /etc/resolv.conf 文件。2. 运行时,HAProxy 会定期执行名称解析,用于需要 DNS 解析的服务器。其他一些事件可能会触发运行时名称解析:- 当服务器的运行状况检查以连接超时结束时:这可能是因为服务器具有新的 IP 地址。因此,我们需要触发名称解析来了解这个新 IP。使用解析器时,服务器名称可以是主机名,也可以是 SRV 标签。HAProxy 将任何以下划线开头的视为 SRV 标签。如果指定了 SRV 标签,则将从 DNS 服务器检索相应的 SRV 记录,并使用提供的名称。SRV 标签将定期检查,如果添加或删除任何服务器,haproxy 将自动执行相同的操作。需要注意的一些事项:- 同时查询所有名称服务器。HAProxy 将处理第一个有效响应。- 当所有服务器都返回错误时,解析被视为无效(NX、超时、拒绝)。

5.3.2. resolvers 部分

本节专门介绍与 HAProxy 中的名称解析相关的宿主信息。可以根据需要配置任意数量的解析器部分。每个部分都可以包含多个名称服务器。当在解析器部分中配置了多个名称服务器时,HAProxy 会使用第一个有效响应。在无效响应的情况下,只有最后一个响应会被处理。目的是给慢服务器一个机会,在快速故障或过时的服务器之后提供有效答案。当每个服务器返回不同的错误类型时,HAProxy 只使用最后一个错误。将应用以下处理来处理此错误:1. HAProxy 使用新的查询类型重试相同的 DNS 查询。A 查询切换到 AAAA 或反之。SRV 查询不在此范围内。超时错误也被排除。2. 当查询类型回退完成(或不适用)后,HAProxy 使用首选查询类型重试原始 DNS 查询。3. HAProxy 重试上述步骤  次。如果之后仍未收到有效响应,它将停止 DNS 解析并报告错误。例如,在解析器部分配置了 2 个名称服务器时,可能出现以下场景:- 第一个响应有效并直接应用,第二个响应被忽略-第一个响应无效,第二个有效,然后应用第二个响应-第一个响应是 NX 域,第二个是截断响应,然后 HAProxy 使用新类型重试查询-第一个响应是 NX 域,第二个是超时,然后 HAProxy 使用新类型重试查询-两个名称服务器的查询都超时,然后 HAProxy 使用相同的查询类型重试查询由于 DNS 服务器可能无法在单个 DNS 请求中应答所有 IP,haproxy 会缓存之前的应答,在没有返回 IP 的  秒后,应答将被视为过时。
resolvers <resolvers id>
创建一个新的名为 <resolvers id> 的域名服务器列表。resolvers 部分接受以下参数:
定义 HAProxy 接受的最大负载大小,并通告给此 resolvers 部分中配置的所有名称服务器。<nb> 以字节为单位。如果未设置,HAProxy 会通告 512。 (RFC 6891 定义的最小值) 注意:允许的最大值为 8192。
nameserver <id> <ip>:<port>
DNS 服务器描述: <id> :服务器的标签,应唯一 <ip> :服务器的 IP 地址 <port> :DNS 服务实际运行的端口
将 /etc/resolv.conf 中找到的所有域名服务器添加到此 resolvers 域名服务器列表中。顺序如同 /etc/resolv.conf 中的每个域名服务器被单独放置在此指令的位置。
hold <status> <period>
在收到 DNS 响应  后,确定服务器的状态是否应从 UP 更改为 DOWN。为了做出此决定,它会检查在过去的  内是否收到了任何有效状态,以对抗刚刚收到的无效状态。:最后一个名称解析状态。nx 在收到 NXDOMAIN 状态后,检查在最后一个时期内是否有任何有效状态。refused 在收到 REFUSED 状态后,检查在最后一个时期内是否有任何有效状态。timeout 在“timeout retry”触发后,检查在最后一个时期内是否有任何有效状态。other 在收到任何其他无效状态后,检查在最后一个时期内是否有任何有效状态。valid 仅适用于“http-request do-resolve”和“tcp-request content do-resolve”操作。它定义了服务器在触发下一次解析之前将保持有效响应的时间段。它不影响服务器的动态解析。obsolete 定义在收到更新的应答记录后,等待多长时间才能删除过时的 DNS 记录。它适用于 SRV 记录。:在过去多少时间内必须收到有效响应。它遵循 HAProxy 时间格式,默认以毫秒为单位。对于依赖动态 DNS 解析来确定其 IP 地址的服务器,收到无效的 DNS 响应(如 NXDOMAIN)将导致服务器状态从 UP 更改为 DOWN。“hold”指令定义了回溯到多远以查找有效响应。如果在  内收到了有效响应,则将忽略刚刚收到的无效状态。除非在最后一个时期内收到了有效响应,否则服务器将被标记为 DOWN。例如,如果设置了“hold nx 30s”,并且最后一个收到的 DNS 响应是 NXDOMAIN,则服务器将被标记为 DOWN,除非在最后 30 秒内收到了有效响应。在收到 DNS 服务器的有效状态后,处于 DOWN 状态的服务器将立即标记为 UP。“hold valid”和“hold obsolete”有单独的行为。
定义在放弃之前为解析服务器名称而发送的查询次数 <nb>。默认值:3。当名称服务器超时或完整的 DNS 查询类型故障转移序列结束并且我们需要从默认的 ANY 查询类型重新开始时,会发生重试。
timeout <event> <time>
定义与名称解析相关的超时。<event>:<time> 超时周期适用的事件。可用事件有: - resolve:当没有其他时间适用时,触发名称解析的默认时间。默认值:1s - retry:两次 DNS 查询之间的时间,当没有收到有效响应时。默认值:1s <time>:与事件相关的时间。它遵循 HAProxy 时间格式。<time> 以毫秒表示。
示例
resolvers mydns nameserver dns1 10.0.0.1:53 nameserver dns2 10.0.0.2:53 parse-resolv-conf resolve_retries 3 timeout resolve 1s timeout retry 1s hold other 30s hold refused 30s hold nx 30s hold timeout 30s hold valid 10s hold obsolete 30s
HAProxy provides a cache, which was designed to perform cache on small objects (favicon, css...). This is a minimalist low-maintenance cache which runs in RAM. The cache is based on a memory which is shared between processes and threads, this memory is split in blocks of 1k. If an object is not used anymore, it can be deleted to store a new object independently of its expiration date. The oldest objects are deleted first when we try to allocate a new one. The cache uses a hash of the host header and the URI as the key. It's possible to view the status of a cache using the Unix socket command "show cache" consult section 9.3 "Unix Socket commands" of Management Guide for more details. When an object is delivered from the cache, the server name in the log is replaced by "<CACHE>".

6.1. 限制

在以下情况下,缓存不会存储和交付对象:- 如果响应不是 200- 如果响应包含 Vary 标头- 如果 Content-Length + 标头大小大于“max-object-size”- 如果响应不可缓存- 如果请求不是 GET- 如果请求的 HTTP 版本低于 1.1- 如果请求包含 Authorization 标头

6.2. 设置

To setup a cache, you must define a cache section and use it in a proxy with the corresponding http-request and response actions.

6.2.1. 缓存部分

cache <名称>
声明一个缓存部分,分配一个名为 <name> 的共享缓存内存,缓存大小是强制性的。
total-max-size <兆字节>
以兆字节为单位定义缓存的 RAM 大小。此大小被分成 1kB 的块,供缓存条目使用。其最大值为 4095。
定义要缓存的对象最大大小。不得大于 “total-max-size” 的一半。如果未设置,则等于缓存大小的 256 分之一。所有大小大于 “max-object-size” 的对象将不会被缓存。
max-age <秒>
Define the maximum expiration duration. The expiration is set has the lowest value between the s-maxage or max-age (in this order) directive in the Cache-Control response header and this value. The default value is 60 seconds, which means that you can't cache an object more than 60 seconds by default.

6.2.2. 代理部分

http-request cache-use <name> [ { if | unless } <condition> ]
Try to deliver a cached object from the cache <name>. This directive is also mandatory to store the cache as it calculates the cache hash. If you want to use a condition for both storage and delivering that's a good idea to put it after this one.
http-response cache-store <name> [ { if | unless } <condition> ]
Store an http-response within the cache. The storage of the response headers is done at this step, which means you can use others http-response actions to modify headers before or after the storage of the response. This action is responsible for the setup of the cache storage filter.
示例
backend bck1 mode http http-request cache-use foobar http-response cache-store foobar server srv1 127.0.0.1:80 cache foobar total-max-size 4 max-age 240
HAProxy 能够从请求或响应流、客户端或服务器信息、表、环境信息等中提取数据……提取此类数据的操作称为获取样本。一旦检索到,这些样本可用于各种目的,例如作为粘滞表的键,但最常见的用法是将其与称为模式的预定义常量数据进行匹配。

7.1. ACL 基础

访问控制列表(ACL)的使用提供了一种灵活的解决方案,用于执行内容切换,以及通常基于从请求、响应或任何环境状态中提取的内容来做出决策。原理很简单:- 从流、表或环境中提取数据样本- 可选地对提取的样本应用一些格式转换- 在样本匹配一个或多个模式匹配方法- 仅当模式与样本匹配时执行操作操作通常包括阻止请求、选择后端或添加标头。为了定义测试,使用“acl”关键字。语法是:acl <aclname> <criterion> [flags] [operator] [<value>] ... 这将创建一个新的 ACL <aclname> 或使用新的测试来完成现有的 ACL。这些测试适用于 <criterion> 中指定的请求/响应部分,并可通过可选标志 [flags] 进行调整。某些条件也支持一个操作符,该操作符可以在值集之前指定。可选地,可以将某些转换操作符应用于样本,它们将在第一个关键字之后指定为逗号分隔的关键字列表。值是条件支持的类型,并用空格分隔。ACL 名称必须由大写和小写字母、数字、-(连字符)、_(下划线)、.(点)和 :(冒号)组成。ACL 名称区分大小写,这意味着“my_acl”和“My_Acl”是两个不同的 ACL。ACL 的数量没有强制限制。未使用的 ACL 不会影响性能,它们只占用少量内存。条件通常是样本获取方法的名称,或其 ACL 特定变体之一。默认测试方法由该样本获取方法的输出类型隐含。ACL 变体可以描述同一样本获取方法的替代匹配方法。样本获取方法是唯一支持转换的方法。样本获取方法返回的数据类型可以是以下几种:- 布尔值- 整数(有符号或无符号)- IPv4 或 IPv6 地址- 字符串- 数据块转换器将这些数据中的任何一种转换为这些类型中的任何一种。例如,某些转换器可能会将字符串转换为小写字符串,而其他转换器会将字符串转换为 IPv4 地址,或将掩码应用于 IP 地址。结果样本的类型是应用于列表的最后一个转换器的类型,默认是样本获取方法的类型。每个样本或转换器都返回特定类型的数据,该数据在本文档中由其关键字指定。当使用标准样本获取方法声明 ACL 时,某些类型会自动涉及默认匹配方法,总结如下表:+---------------------+-----------------+ | 样本或转换器 | 默认 | | 输出类型 | 匹配方法 | +---------------------+-----------------+ | 布尔值 | bool | +---------------------+-----------------+ | 整数 | int | +---------------------+-----------------+ | IP | ip | +---------------------+-----------------+ | 字符串 | str | +---------------------+-----------------+ | 二进制 | none, use "-m" | +---------------------+-----------------+ 注意,为了匹配二进制样本,必须指定匹配方法,请参阅下文。ACL 引擎可以将这些类型与以下类型的模式进行匹配:- 布尔值- 整数或整数范围- IP 地址/网络- 字符串(精确、子字符串、后缀、前缀、子目录、域)- 正则表达式- 十六进制块以下 ACL 标志当前受支持:-i:在匹配所有后续模式时忽略大小写。-f:从文件中加载模式。-m:使用特定的模式匹配方法-n:禁止 DNS 解析-M:将 -f 指向的文件加载为映射文件。-u:强制 ACL 的唯一 ID--:强制标志结束。当字符串看起来像标志之一时很有用。“-f”标志后面是文件名,从中读取所有行作为单独的值。如果模式要从多个文件中加载,甚至可以传递多个“-f”参数。空行以及以 '#' 开头的行将被忽略。所有前导空格和制表符将被剥离。如果绝对有必要插入一个以 '#' 开头的有效模式,只需在其前面加上一个空格,以免被视为注释。根据数据类型和匹配方法,haproxy 可能会将行加载到二进制树中,从而实现非常快速的查找。这对于 IPv4 和精确字符串匹配是正确的。在这种情况下,重复项将自动删除。“-M”标志允许 ACL 使用映射文件。如果设置了此标志,则该文件将被解析为两列文件。第一列包含 ACL 使用的模式,第二列包含样本。样本稍后可由映射使用。在某些罕见情况下,ACL 仅用于在应用映射之前检查映射中是否存在模式,这可能很有用。“-u”标志强制 ACL 的唯一 ID。此唯一 ID 与套接字接口一起使用,用于识别 ACL 并动态更改其值。请注意,文件始终通过其名称标识,即使设置了 ID。此外,“-i”标志应用于后续条目,而不是应用于前面文件中加载的条目。例如: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 特定条件都隐含模式匹配方法,通常不需要此标志。然而,此标志对于通用样本获取方法很有用,用于描述它们将如何与模式匹配。对于返回没有明显匹配方法的 A 字符串类型(例如字符串或二进制)的样本获取方法,这是必需的。当指定“-m”并后跟模式匹配方法名称时,将使用此方法而不是准则的默认方法。这使得能够以最初未计划的方式,或使用返回字符串的样本获取方法进行匹配。匹配方法也会影响模式的解析。“-n”标志禁止 DNS 解析。它用于加载 IP 文件。默认情况下,如果解析器无法解析 IP 地址,它会认为解析的字符串可能是域名并尝试 DNS 解析。“-n”标志禁用此解析。它对于检测格式错误的 IP 列表很有用。请注意,如果 DNS 服务器无法访问,haproxy 的配置解析可能需要数分钟等待超时。在此期间不显示任何错误消息。“-n”标志禁用此行为。请注意,在运行时,此功能已对动态 ACL 修改禁用。但是,存在一些限制。并非所有方法都可以与所有样本获取方法一起使用。此外,如果“-m”与“-f”结合使用,则必须先放置它。模式匹配方法必须是以下之一:-“found”:仅检查是否在流中找到请求的样本,而不与任何模式进行比较。建议不要传递任何模式以避免混淆。此匹配方法对于检测某些内容(如标头、cookie 等)的存在特别有用,即使它们是空的,并且不与任何内容进行比较或计数。-“bool”:将值检查为布尔值。它只能应用于返回布尔值或整数值的获取,并且不接受模式。值为零或 false 不匹配,所有其他值都匹配。-“int”:将值作为整数匹配。它可以与整数和布尔样本一起使用。布尔 false 是整数 0,true 是整数 1。-“ip”:将值作为 IPv4 或 IPv6 地址进行匹配。它仅与 IP 地址样本兼容,因此它是隐含的,从不需要。-“bin”:将内容与表示二进制序列的十六进制字符串进行匹配。这可以与二进制或字符串样本一起使用。-“len”:将样本的长度作为整数进行匹配。这可以与二进制或字符串样本一起使用。-“str”:精确匹配:将内容与字符串进行匹配。这可以与二进制或字符串样本一起使用。-“sub”:子字符串匹配:检查内容是否至少包含提供的字符串模式之一。这可以与二进制或字符串样本一起使用。-“reg”:正则表达式匹配:将内容与正则表达式列表进行匹配。这可以与二进制或字符串样本一起使用。-“beg”:前缀匹配:检查内容是否以提供的字符串模式开头。这可以与二进制或字符串样本一起使用。-“end”:后缀匹配:检查内容是否以提供的字符串模式结尾。这可以与二进制或字符串样本一起使用。-“dir”:子目录匹配:检查由斜杠(“/”)分隔的内容的某个部分是否与提供的字符串模式之一精确匹配。这可以与二进制或字符串样本一起使用。-“dom”:域匹配:检查由点(“.”)、冒号(“:”)、斜杠(“/”)、问号(“?”)分隔的内容的某个部分是否与提供的字符串模式之一精确匹配。这可用于 URL。所提供模式中的前导和尾随分隔符将被忽略。ACL 匹配,如果其中任何一个匹配。例如,为了快速检测 HTTP 请求中是否存在 cookie“JSESSIONID”,可以这样做:acl jsess_present req.cook(JSESSIONID) -m found为了将正则表达式应用于缓冲区的前 500 个字节,可以使用以下 acl:acl script_tag req.payload(0,500) -m reg -i <script>在正则表达式库在使用“-i”时速度慢得多的系统上,可以将样本转换为小写,如下所示:acl script_tag req.payload(0,500),lower -m reg <script>所有 ACL 特定条件都隐含默认匹配方法。大多数情况下,这些条件是通过连接原始样本获取方法的名称和匹配方法来组成的。例如,“hdr_beg”将“beg”匹配应用于使用“hdr”获取方法检索的样本。此匹配方法只能在关键字单独使用时使用,没有转换器。如果在此类 ACL 关键字之后应用了任何此类转换器,则 ACL 关键字的默认匹配方法将被忽略,因为匹配的关键是最后一个转换器的输出类型。由于所有 ACL 特定条件都依赖于样本获取方法,因此始终可以选择使用原始样本获取方法和显式的“-m”匹配方法。例如,以下所有 ACL 都完全等效: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.下表总结了样本或转换器类型与要获取的模式类型之间的兼容性矩阵。它为每种兼容的组合指示了要使用的匹配方法名称,当方法是默认方法且不需要“-m”时,用角括号“>”和“<”括起来。+-------------------------------------------------+ | 输入样本类型 | +----------------------+---------+---------+---------+---------+---------+ | 模式类型 | 布尔值 | 整数 | IP | 字符串 | 二进制 | +----------------------+---------+---------+---------+---------+---------+ | 无(仅存在) | found | found | found | found | found | +----------------------+---------+---------+---------+---------+---------+ | 无(布尔值) |> bool <| bool | | bool | | +----------------------+---------+---------+---------+---------+---------+ | 整数(值) | int |> int <| int | int | | +----------------------+---------+---------+---------+---------+---------+ | 整数(长度) | len | len | len | len | len | +----------------------+---------+---------+---------+---------+---------+ | IP 地址 | | |> ip <| ip | ip | +----------------------+---------+---------+---------+---------+---------+ | 精确字符串 | str | str | str |> str <| str | +----------------------+---------+---------+---------+---------+---------+ | 前缀 | beg | beg | beg | beg | beg | +----------------------+---------+---------+---------+---------+---------+ | 后缀 | end | end | end | end | end | +----------------------+---------+---------+---------+---------+---------+ | 子字符串 | sub | sub | sub | sub | sub | +----------------------+---------+---------+---------+---------+---------+ | 子目录 | dir | dir | dir | dir | dir | +----------------------+---------+---------+---------+---------+---------+ | 域 | dom | dom | dom | dom | dom | +----------------------+---------+---------+---------+---------+---------+ | 正则表达式 | reg | reg | reg | reg | reg | +----------------------+---------+---------+---------+---------+---------+ | 十六进制块 | | | | bin | bin | +----------------------+---------+---------+---------+---------+---------+

7.1.1. 匹配布尔值

为了匹配布尔值,不需要任何值,所有值都会被忽略。布尔匹配默认用于所有类型为“boolean”的获取方法。当使用布尔匹配时,获取的值会按原样返回,这意味着布尔值“true”将始终匹配,而布尔值“false”将永远不匹配。布尔匹配也可以通过在返回整数值的获取方法上使用“-m bool”来强制执行。然后,整数值 0 会被转换为布尔值“false”,所有其他值都会被转换为“true”。

7.1.2. 匹配整数

整数匹配默认应用于整数获取方法。也可以使用“-m int”强制应用于布尔获取。在这种情况下,“false”转换为整数 0,“true”转换为整数 1。整数匹配还支持整数范围和运算符。请注意,整数匹配仅适用于正值。范围是用冒号分隔的下界和上界表示的值,两者都可以省略。例如,“1024:65535”是表示非特权端口范围的有效范围,并且“1024:”也有效。“0:1023”是特权端口的有效表示,并且“:1023”也有效。作为特殊情况,某些 ACL 函数支持实际上是两个由点分隔的整数的十进制数。这用于某些版本检查。所有整数属性都适用于这些十进制数,包括范围和运算符。为了更方便使用,还支持比较运算符。请注意,对范围使用运算符意义不大,强烈不建议这样做。同样,对值集执行顺序比较也没有太大意义。整数匹配可用的运算符是:eq:如果测试值等于至少一个值,则为 truege:如果测试值大于或等于至少一个值,则为 truegt:如果测试值大于至少一个值,则为 truete:如果测试值小于或等于至少一个值,则为 truelt:如果测试值小于至少一个值,则为 true例如,以下 ACL 匹配任何负 Content-Length 标头:acl negative-length req.hdr_val(content-length) lt 0此匹配 SSL 版本介于 3.0 和 3.1 之间(含):acl sslv3 req.ssl_ver 3:3.1

7.1.3. 匹配字符串

字符串匹配应用于字符串或二进制获取方法,存在 6 种不同形式:- 精确匹配(-m str):提取的字符串必须与模式精确匹配;- 子字符串匹配(-m sub):在提取的字符串中查找模式,并且如果其中任何一个被找到,ACL 就会匹配;- 前缀匹配(-m beg):将模式与提取的字符串的开头进行比较,并且如果其中任何一个匹配,ACL 就会匹配。- 后缀匹配(-m end):将模式与提取的字符串的结尾进行比较,并且如果其中任何一个匹配,ACL 就会匹配。- 子目录匹配(-m dir):在字符串的开头或结尾,由斜杠(“/”)分隔的字符串中的任何位置查找模式。如果其中任何一个匹配,ACL 就会匹配。因此,字符串“/images/png/logo/32x32.png”将匹配“/images”、“/images/png”、“images/png”、“/png/logo”、“logo/32x32.png”或“32x32.png”,但不能匹配“png”或“32x32”。- 域匹配(-m dom):在字符串的开头或结尾,由点(“.”)、冒号(“:”)、斜杠(“/”)、问号(“?”)分隔的字符串中的任何位置查找模式。这用于 URL。模式中的前导和尾随分隔符将被忽略。如果其中任何一个匹配,ACL 就会匹配。因此,在示例字符串“http://www1.dc-eu.example.com:80/blah”中,模式“http”、“www1”、“.www1”、“dc-eu”、“example”、“com”、“80”、“dc-eu.example”、“blah”、“:www1:” 、“dc-eu.example:80”将匹配,但“eu”或“dc”不会匹配。通常不建议使用它来匹配域后缀进行过滤或路由,因为通过在另一个域前面加上匹配的前缀,路由很容易被欺骗。字符串匹配应用于按原样传递的字面字符串,除了反斜杠(“\”)之外,它还可以转义某些字符,例如空格。如果“-i”标志在第一个字符串之前传递,则匹配将执行,忽略大小写。为了匹配字符串“-i”,请将其设置为第二个,或在第一个字符串之前传递“--”标志。匹配字符串“--”当然也适用。不要对可能包含空字节(0x00)的二进制获取使用字符串匹配,因为比较会在第一个空字节处停止。相反,请先使用 hex 转换器将二进制获取转换为十六进制字符串。
示例
# 如果字符串 <tag> 存在于二进制样本中,则匹配 acl tag_found req.payload(0,0),hex -m sub 3C7461673E

7.1.4. 匹配正则表达式 (regexes)

与字符串匹配一样,正则表达式匹配也适用于按字面传递的字符串,但反斜杠("\")除外,它使得可以转义某些字符,如空格。如果在第一个正则表达式之前传递了“-i”标志,则匹配将忽略大小写。为了匹配字符串“-i”,要么将其放在第二个位置,要么在第一个正则表达式之前传递“--”标志。当然,匹配字符串“--”也适用相同的原则。

7.1.5. 匹配任意数据块

可以将一些提取的样本与一个可能无法安全地表示为字符串的二进制块进行匹配。为此,当匹配方法设置为二进制时,模式必须以偶数个十六进制数字的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
示例
# 在输入流中匹配 "Hello\n" (\x48 \x65 \x6c \x6c \x6f \x0a) acl hello req.payload(0,6) -m bin 48656c6c6f0a

7.1.6. 匹配 IPv4 和 IPv6 地址

IPv4 地址值可以指定为普通地址,也可以附加网络掩码,在这种情况下,IPv4 地址将在网络内匹配。普通地址也可以被可解析的主机名替换,但这种做法通常不被推荐,因为它使得配置的读取和调试更加困难。如果使用主机名,您至少应该确保它们存在于 /etc/hosts 中,这样配置就不会依赖于在解析配置时发生的任何随机 DNS 匹配。IPv4 地址的点分表示法在常规形式和省略所有零字节的缩写形式中都支持: +------------------+------------------+------------------+ | 示例 1 | 示例 2 | 示例 3 | +------------------+------------------+------------------+ | 192.168.0.1 | 10.0.0.12 | 127.0.0.1 | | 192.168.1 | 10.12 | 127.1 | | 192.168.0.1/22 | 10.0.0.12/8 | 127.0.0.1/8 | | 192.168.1/22 | 10.12/8 | 127.1/8 | +------------------+------------------+------------------+ 注意,这与 RFC 4632 CIDR 地址表示法不同,在 RFC 4632 中,192.168.42/24 等同于 192.168.42.0/24。 IPv6 可以按其常规形式输入,可附加网络掩码,也可不附加。IPv6 网络掩码只接受位数计数。为避免与随机解析的 IP 地址发生任何风险,IPv6 模式中不允许使用主机名。HAProxy 还能在以下情况下匹配 IPv4 地址与 IPv6 地址: - 被测试地址是 IPv4,模式地址是 IPv4,匹配在 IPv4 中进行,使用提供的掩码(如果有)。 - 被测试地址是 IPv6,模式地址是 IPv6,匹配在 IPv6 中进行,使用提供的掩码(如果有)。 - 被测试地址是 IPv6,模式地址是 IPv4,如果 IPv6 地址与 2002:IPV4::、::IPV4 或 ::ffff:IPV4 匹配,则在 IPv4 中使用模式的掩码进行匹配,否则失败。 - 被测试地址是 IPv4,模式地址是 IPv6,IPv4 地址首先通过在前面添加 ::ffff: 转换为 IPv6,然后使用提供的 IPv6 掩码在 IPv6 中应用匹配。

7.2. 使用 ACL 形成条件

某些操作仅在条件有效时执行。条件是 ACL 和运算符的组合。支持 3 种运算符: - AND(隐式) - OR(显式使用 "or" 关键字或 "||" 运算符) - 使用感叹号 ("!") 进行否定。条件以析取范式形式构成: [!]acl1 [!]acl2 ... [!]acln { or [!]acl1 [!]acl2 ... [!]acln } ... 这些条件通常在 "if" 或 "unless" 语句之后使用,指示何时条件将触发操作。例如,要阻止对 "*" URL 的 HTTP 请求(除了 "OPTIONS" 方法),以及没有 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. # 现在为所有仅静态主机以及主机 "www" 的静态 URL 使用后端 "static"。 # 对于其余的,使用后端 "www"。 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 } 通常不建议使用此构造,因为这样编写时很容易在配置中留下错误。但是,对于仅匹配一个源 IP 地址的非常简单的规则,使用它们比声明具有随机名称的 ACL 更有意义。另一个好的使用示例是: 使用命名 ACL: acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor fail if site_dead 使用匿名 ACL: monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 } 有关 "http-request deny" 和 "use_backend" 关键字的详细帮助,请参阅 第 4.2 节

7.3. 获取样本

历史上,样本提取方法仅用于检索数据以与 ACL 的模式进行匹配。随着 stick-table 的出现,创建了一类新的样本提取方法,它们通常与它们的 ACL 对应项具有相同的语法。这些样本提取方法也称为 "fetches"。现在,ACL 和 fetches 已经融合。所有 ACL 提取方法都已作为 fetch 方法提供,ACL 也可以使用任何样本 fetch 方法。本节详细介绍了所有可用的样本 fetch 方法及其输出类型。某些样本 fetch 方法具有已弃用的别名,用于维护与现有配置的兼容性。然后将它们明确标记为已弃用,在新设置中不应使用它们。还会在可用时指示 ACL 派生项,以及它们各自的匹配方法。这些都具有明确定义的默认模式匹配方法,因此从不需要(尽管允许)使用 "-m" 选项来指示如何使用 ACL 匹配样本。如上面的样本类型与匹配兼容性矩阵所示,在 ACL 中使用通用样本 fetch 方法时,除非样本类型是布尔型、整数型、IPv4 或 IPv6,否则 "-m" 选项是强制的。当同一个关键字既是 ACL 关键字又是标准 fetch 方法时,ACL 引擎默认会自动选择仅用于 ACL 的那个。其中一些关键字支持一个或多个必需参数,以及一个或多个可选参数。这些参数是强类型的,并在解析配置时进行检查,因此没有运行带有错误参数(例如,未解析的后端名称)的风险。Fetch 函数参数在括号之间传递,并用逗号分隔。当参数是可选的时,将在下方用方括号 ('[ ]') 指示。当所有参数都是可选的时,可以省略括号。因此,标准样本 fetch 方法的语法是以下之一: - name - name(arg1) - name(arg1,arg2)

7.3.1. 转换器

样本 fetch 方法可以与应用于获取样本的转换(也称为“转换器”)相结合。这些组合形成了所谓的“样本表达式”,结果是一个“样本”。最初,这仅由 "stick on" 和 "stick store-request" 指令支持,但现在已扩展到所有可以使用样本的地方(ACL、log-format、unique-id-format、add-header 等)。这些转换枚举为样本 fetch 方法后面的特定关键字序列。这些关键字也可以直接附加在 fetch 关键字的参数后面,并用逗号分隔。这些关键字还可以支持一些参数(例如,网络掩码),这些参数必须放在括号中。一类转换器是位运算符和算术运算符,支持对整数执行基本操作。支持一些位运算(and、or、xor、cpl)和一些算术运算(add、sub、mul、div、mod、neg)。提供了一些比较器(odd、even、not、bool),可以报告匹配而无需编写 ACL。当前可用的转换关键字列表包括:
51d.single(<prop>[,<prop>*])
以字符串形式返回所请求属性的值,值之间由“51degrees-property-separator”指定的分隔符分隔。设备通过传递给转换器的 User-Agent 标头来识别。该函数最多可以传递五个属性名称,如果找不到属性名称,则返回“NoData”值。
示例
# 此处,标头 "X-51D-DeviceTypeMobileTablet" 被添加到请求中, # 它包含了通过传递给转换器的 User-Agent 所请求的三个属性的值。 frontend http-in bind *:8081 default_backend servers http-request set-header X-51D-DeviceTypeMobileTablet \ %[req.fhdr(User-Agent),51d.single(DeviceType,IsMobile,IsTablet)]
add(<value>)
将 <value> 添加到有符号整数类型的输入值中,并将结果作为有符号整数返回。<value> 可以是数值或变量名。变量名以作用域指示开头。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后面跟着一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>)
根据 <bits> 参数,使用 AES128-GCM、AES192-GCM 或 AES256-GCM 算法解密原始字节输入。所有其他参数都需要进行 base64 编码,返回的结果是原始字节格式。如果 <aead_tag> 验证失败,转换器不会返回任何数据。<nonce>、<key> 和 <aead_tag> 可以是字符串或变量。此转换器至少需要 OpenSSL 1.0.1。
示例
http-response set-header X-Decrypted-Text %[var(txn.enc),\ aes_gcm_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]
and(<value>)
对 <value> 与输入的有符号整数值执行按位“AND”操作,并将结果作为有符号整数返回。 <value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将base64编码的输入字符串转换为其二进制表示。它执行base64()的逆操作。
将二进制输入样本转换为base64字符串。它用于以可靠传输的方式(例如,SSL ID可以复制到标头中)记录或传输二进制内容。
如果类型为有符号整数的输入值非空,则返回布尔值 TRUE,否则返回 FALSE。与 and() 结合使用,可用于报告输入值的位测试的真/假(例如,验证标志的存在)。
bytes(<offset>[,<length>])
从输入二进制样本中提取一些字节。结果是一个二进制样本,从原始样本的偏移量(以字节为单位)开始,并可选地在给定长度处截断。
concat([<start>],[<var>],[<end>])
将当前样本后面的最多 3 个字段连接起来,然后将该样本转换为字符串。第一个字段 `` 是一个常量字符串,将立即附加到现有样本之后。如果未使用,则可以省略。第二个字段 `` 是一个变量名。将查找该变量,将其内容转换为字符串,并将其立即附加到 `` 部分之后。如果找不到变量,则不附加任何内容。它也可以省略。第三个字段 `` 是一个常量字符串,将附加在变量之后。它也可以省略。总之,这些元素允许将变量与分隔符连接到现有变量集。这可用于构建由其他变量组成的连续的新变量,例如用冒号分隔的值。如果需要逗号或闭括号作为分隔符,则必须用引号或反斜杠进行保护,自身也需要进行保护,以免被第一级解析器剥离。请参阅下面的示例。
示例
tcp-request session set-var(sess.src) src tcp-request session set-var(sess.dn) ssl_c_s_dn tcp-request session set-var(txn.sig) str(),concat(<ip=,sess.ip,>),concat(<dn=,sess.dn,>) tcp-request session set-var(txn.ipport) "str(),concat('addr=(',sess.ip),concat(',',sess.port,')')" http-request set-header x-hap-sig %[var(txn.sig)]
获取类型为有符号整数的输入值,应用取反(翻转所有位)并以有符号整数的形式返回结果。
crc32([<avalanche>])
使用 CRC32 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它旨在与其他需要对某些输入键计算 CRC32 的软件兼容,因此它遵循在以太网、Gzip、PNG 等中最常见的实现。它比其他算法慢,但可能提供更好或至少更不可预测的分布。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
crc32c([<avalanche>])
使用 CRC32C 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用 RFC4960 附录 B [8] 中描述的相同函数。它旨在与其他需要对某些输入键计算 CRC32C 的软件兼容。它比其他算法慢,并且不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32”和“hash-type”指令。
在找到的第一个回车符('\r')或换行符('\n')处截断输入样本的字符串表示。仅更新字符串长度。
da-csv-conv(<prop>[,<prop>*])
要求DeviceAtlas转换器识别输入的User Agent字符串,并发出一个由参数中枚举的属性串联而成的字符串,并由全局关键字“deviceatlas-property-separator”定义的分隔符(或默认管道字符('|'))分隔。haproxy配置语言施加了12个不同属性的限制。
示例
frontend www bind *:8881 default_backend servers http-request set-header X-DeviceAtlas-Data %[req.fhdr(User-Agent),da-csv(primaryHardwareType,osName,osVersion,browserName,browserVersion,browserRenderingEngine)]
debug([<prefix][,<destination>])
此转换器用作调试工具。它捕获输入样本并将其发送到事件接收器 <destination>,该接收器可以指定一个环形缓冲区,如“buf0”,以及“stdout”或“stderr”。可用的接收器可以在运行时通过在 CLI 上发出“show events”来检查。如果未指定,输出将是“buf0”,可以通过 CLI 的“show events”命令进行查询。可以传递一个可选的前缀 <prefix> 来帮助区分来自多个表达式的输出。然后它将出现在输出消息的冒号之前。输入样本按原样传递到输出,因此将调试转换器插入链中的任何位置都是安全的,即使对于不可打印的样本类型也是如此。
示例
tcp-request connection track-sc0 src,debug(track-sc)
digest(<algorithm>)
将二进制输入样本转换为消息摘要。结果是一个二进制样本。`` 必须是 OpenSSL 消息摘要名称(例如 sha256)。请注意,此转换器仅在 haproxy 已使用 USE_OPENSSL 编译时可用。
div(<value>)
将输入的有符号整数值除以 <value>,并将结果作为有符号整数返回。如果 <value> 为 null,则返回最大的无符号整数(通常为 2^63-1)。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
djb2([<avalanche>])
使用 DJB2 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘性表条目来收集粗略统计。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“crc32”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
如果类型为有符号整数的输入值为偶数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "not,and(1),bool"。
field(<index>,<delimiters>[,<count>])
从输入字符串中,根据给定的分隔符,从开头(正索引)或结尾(负索引)提取给定索引处的子字符串。索引从 1 或 -1 开始,分隔符是格式化为字符串的字符列表。您可以选择指定要提取的字段数量 <count>(默认为 1)。值为 0 表示提取所有剩余字段。
示例
str(f1_f2_f3__f5),field(4,_) # <空> str(f1_f2_f3__f5),field(5,_) # f5 str(f1_f2_f3__f5),field(2,_,0) # f2_f3__f5 str(f1_f2_f3__f5),field(2,_,2) # f2_f3 str(f1_f2_f3__f5),field(-2,_,3) # f2_f3_ str(f1_f2_f3__f5),field(-3,_,0) # f1_f2_f3
将二进制输入样本转换为十六进制字符串,其中每个输入字节对应两个十六进制数字。它用于以可靠的方式记录或传输某些二进制输入数据的十六进制转储(例如,可以将 SSL ID 复制到标头中)。
将每个输入字节包含两个十六进制数字的十六进制字符串转换为整数。如果输入值无法转换,则返回零。
将输入的整数值转换为其 32 位二进制表示形式(网络字节序)。由于样本提取方法拥有有符号 64 位整数,因此在使用此转换器时,输入的整数值将首先被强制转换为无符号 32 位整数。hmac(<algorithm>, <key>) 使用给定的密钥将二进制输入样本转换为消息认证码。结果是一个二进制样本。`` 必须是注册的 OpenSSL 消息摘要名称之一(例如 sha256)。`` 参数必须是 base64 编码的,可以是字符串或变量。请注意,此转换器仅在 haproxy 已使用 USE_OPENSSL 编译时可用。
http_date([<offset],[<unit>])
将一个假定包含自纪元以来日期的整数转换为适合在 HTTP 标头字段中使用的字符串表示形式。如果指定了偏移值,则在进行转换之前将其添加到日期中。这对于发出 Date 标头字段、响应中与正偏移量结合使用的 Expires 值,或者当偏移量为负时使用的 Last-Modified 值特别有用。如果指定了单位值,则将时间戳视为“s”(秒,默认行为)、“ms”(毫秒)或“us”(微秒)自纪元以来。偏移量假定与输入时间戳具有相同的单位。
in_table(<table>)
使用输入样本的字符串表示在指定表中进行查找。如果在表中找不到键,则返回布尔值false。否则返回布尔值true。这可以用于验证表中是否存在某个键,该键跟踪某些元素(例如,是否已看到源IP地址或授权标头)。ipmask(<mask4>[,<mask6>])将掩码应用于IP地址,并将结果用于查找和存储。这可以用于使某个掩码内的所有主机共享相同的表条目,从而使用相同的服务器。mask4可以以点分形式(例如,255.255.255.0)或CIDR形式(例如,24)给出。mask6可以以四分体形式(例如,ffff:ffff::)或CIDR形式(例如,64)给出。如果未给出mask6,IPv6地址将因向后兼容性原因而无法转换。
json([<input-code>])
转义输入字符串,并生成一个 ASCII 输出字符串,可用于 JSON 字符串。该转换器尝试根据 `` 参数解码输入字符串。它可以是 "ascii"、"utf8"、"utf8s"、"utf8p" 或 "utf8ps"。"ascii" 解码器从不失败。"utf8" 解码器检测 3 种错误: - 错误的 UTF-8 序列(单独的延续字节、错误的延续字节数,...) - 无效范围(解码值在 UTF-8 禁止的范围内) - 码点过长(使用比必需的字节数更多的字节进行编码)。UTF-8 JSON 编码可能产生 "too long value" 错误,当 UTF-8 字符大于 0xffff 时,因为 JSON 字符串转义规范只允许 4 个十六进制数字用于值编码。UTF-8 解码器有 4 个变体,由两个后缀字母的组合指定:"p" 表示 "permissive"(宽松),"s" 表示 "silently ignore"(静默忽略)。解码器的行为是: - "ascii":从不失败; - "utf8":在检测到任何错误时失败; - "utf8s":从不失败,但删除与错误对应的字符; - "utf8p":接受并修复过长错误,但对任何其他错误都会失败; - "utf8ps":从不失败,接受并修复过长错误,但删除与其他错误对应的字符。此转换器特别适用于为消耗 JSON 格式流量日志的服务器构建正确转义的 JSON。
示例
capture request header Host len 15 capture request header user-agent len 150 log-format '{"ip":"%[src]","user-agent":"%[capture.req.hdr(1),json(utf8s)]"}'
来自客户端 127.0.0.1 的输入请求: GET / HTTP/1.0 User-Agent: Very "Ugly" UA 1/2 输出日志: {"ip":"127.0.0.1","user-agent":"Very \"Ugly\" UA 1\/2"}
language(<value>[,<default>])
从 "accept-language" 标头中使用 "req.fhdr" 提取的列表中返回具有最高 q-factor 的值。没有 q-factor 的值其 q-factor 为 1。q-factor 为 0 的值被丢弃。只有属于分号分隔的 <values> 列表中的值才会被考虑。<value> 参数的语法是 "lang[;lang[;lang[;...]]]"。如果没有值与给定列表匹配,并且提供了默认值,则返回默认值。请注意,语言名称在破折号('-')后可能有变体。如果此变体存在于列表中,它将被匹配,但如果不存在,则只检查基础语言。匹配是区分大小写的,输出字符串始终是参数中提供的字符串之一。参数的顺序没有意义,只有请求中值的顺序有意义,因为在共享相同 q-factor 的多个值中,第一个值被使用。
示例
# 此配置根据请求切换到匹配 # 给定语言的后端: acl es req.fhdr(accept-language),language(es;fr;en) -m str es acl fr req.fhdr(accept-language),language(es;fr;en) -m str fr acl en req.fhdr(accept-language),language(es;fr;en) -m str en use_backend spanish if es use_backend french if fr use_backend english if en default_backend choose_your_language
获取字符串的长度。这只能放在字符串样本提取函数或返回字符串类型的转换关键字之后。结果是整数类型。
将字符串样本转换为小写。这只能放在字符串样本获取函数之后或返回字符串类型的转换关键字之后。结果类型为字符串。
ltime(<format>[,<offset>])
将一个应包含自纪元以来日期的整数转换为表示该日期的本地时间的字符串,使用 strftime(3) 定义的 <format> 字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(正或负,以秒为单位)。有关操作系统支持的格式,请参阅 strftime() 手册页。另请参阅 utime 转换器。
示例
# 输出两列,一列是本地时间,另一列是 ip:port # 例如 20140710162350 127.0.0.1:57325 log-format %[date,ltime(%Y%m%d%H%M%S)]\ %ci:%cp
ltrim(<chars>)
从输入样本的字符串表示的开头跳过任何属于 <chars> 的字符。
map(<map_file>[,<default_value>])
map_<match_type>(<map_file>[,<default_value>]) map_<match_type>_<output_type>(<map_file>[,<default_value>]) 使用 `` 匹配方法从 `` 中搜索输入值,并返回转换为 `` 类型的关联值。如果输入值在 `` 中找不到,转换器将返回 ``。如果未设置 ``,转换器将失败,并表现为未获取任何输入值。如果未设置 ``,则默认为 "str"。同样,如果未设置 ``,则默认为 "str"。为了方便起见,"map" 关键字是 "map_str" 的别名,并将字符串映射到另一个字符串。避免键重叠很重要:IP 地址和字符串存储在树中,因此将使用第一个最精细的匹配。其他键存储在列表中,因此将使用第一个匹配的出现。以下数组包含按输入类型、匹配类型和输出类型排序的所有可用 map 函数列表。
输入类型匹配方法输出类型 str输出类型 int输出类型 ip
strstrmap_strmap_str_intmap_str_ip
strbegmap_begmap_beg_intmap_end_ip
strsubmap_submap_sub_intmap_sub_ip
strdirmap_dirmap_dir_intmap_dir_ip
strdommap_dommap_dom_intmap_dom_ip
strendmap_endmap_end_intmap_end_ip
strregmap_regmap_reg_intmap_reg_ip
strregmap_regmmap_reg_intmap_reg_ip
intintmap_intmap_int_intmap_int_ip
ipipmap_ipmap_ip_intmap_ip_ip
名为“map_regm”的特殊映射在正则表达式中期望匹配区域,并修改输出,将反向引用(如“\1”)替换为相应的匹配文本。文件包含每行一个键+值。以“#”开头的行被忽略,空行也是如此。删除前导制表符和空格。然后,键是第一个“word”(一系列非空格/制表符字符),值是该系列空格/制表符之后直到行尾的内容,不包括尾随空格/制表符。
示例
# 这是一条注释,会被忽略 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- 尾部空格被忽略 | | | `---------- 值 | | `-------------------- 中间空格被忽略 | `---------------------------- 键 `------------------------------------ 前导空格被忽略
mod(<value>)
将输入的有符号整数值除以 <value>,并将余数作为有符号整数返回。如果 <value> 为 null,则返回零。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
mul(<value>)
将输入的有符号整数值乘以 <value>,并将乘积作为有符号整数返回。在溢出的情况下,将返回符号的最大可能值,以便操作不会环绕。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
接受一个字符串类型的输入值,将其解释为后端名称,并返回该后端中可用服务器的数量。可用于需要从动态名称(如 map 查找的结果)查找后端的地方。
获取类型为有符号整数的输入值,计算其相反值,并以有符号整数的形式返回余数。0 是单位元。此运算符用于反向减法:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。
如果输入的有符号整数值非零,则返回布尔值 FALSE,否则返回 TRUE。与 and() 结合使用,可用于报告输入值的位测试结果是真还是假(例如,验证某个标志是否存在)。
如果类型为有符号整数的输入值为奇数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "and(1),bool"。
or(<value>)
对 <value> 和输入的有符号整数值执行按位“OR”操作,并将结果作为有符号整数返回。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
protobuf(<field_number>,[<field_type>])
此操作从输入二进制样本表示的协议缓冲区消息中以原始模式提取协议缓冲区消息字段,其中 `` 是字段编号(点分表示法),如果 `` 不存在,或者如果是整数样本(参见下面的 "ungrpc")如果字段存在。授权类型的列表如下:"int32"、"int64"、"uint32"、"uint64"、"sint32"、"sint64"、"bool"、"enum"(用于 "varint" 线型 0),"fixed64"、"sfixed64"、"double"(用于 64 位线型 1),"fixed32"、"sfixed32"、"float"(用于线型 5)。请注意,"string" 被视为长度分隔类型,因此不需要 `` 参数即可提取。有关协议缓冲区消息字段类型的更多信息,请访问:https://developers.google.com/protocol-buffers/docs/encoding
regsub(<regex>,<subst>[,<flags>])
对输入字符串应用基于正则表达式的替换。它执行与众所周知的 "sed" 工具 "s/<regex>/<subst>/" 相同的操作。默认情况下,它将替换输入字符串中匹配正则表达式 `` 的最大部分的第一个出现,使用替换字符串 ``。通过在第三个参数 `` 中添加标志 "g",可以替换所有出现。还可以在 `` 中添加标志 "i" 使正则表达式不区分大小写。由于 `` 是一个字符串,它由所有期望的标志的串联组成。因此,如果同时需要 "i" 和 "g",使用 "gi" 或 "ig" 会产生相同效果。此转换器的第一个用途是使用其他字符或字符序列替换某些字符或字符序列。强烈建议使用受保护的引号来分隔正则表达式部分,以提高清晰度,并避免正则表达式的闭括号与函数括号混淆。就像在 Bourne shell 中一样,第一级引号在分隔行上的单词组时被处理,第二级可用于参数。建议在外部使用单引号,因为它们不会尝试解析反斜杠或美元符号。
示例
# 去除 "x-path" 标头中的重复 "/"。 # 输入: x-path: /////a///b/c/xzxyz/ # 输出: x-path: /a/b/c/xzxyz/ http-request set-header x-path "%[hdr(x-path),regsub('/+','/','g')]" # 将查询字符串复制到 x-query 并删除所有前导的 '?', ';' 和 '&' http-request set-header x-query "%[query,regsub([?;&]*,'')]" # 捕获组和反向引用 # 两行代码作用相同。 http-request redirect location %[url,'regsub("(foo|bar)([0-9]+)?","\2\1",i)'] http-request redirect location %[url,regsub(\"(foo|bar)([0-9]+)?\",\"\2\1\",i)]
捕获请求槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
捕获响应槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
rtrim(<chars>)
从输入样本的字符串表示的末尾跳过任何属于 <chars> 的字符。
sdbm([<avalanche>])
使用 SDBM 哈希函数将二进制输入样本哈希成一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,可以对输出应用一个完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘滞表条目来收集粗略的统计数据。它不应用于安全目的,因为 32 位哈希很容易被破解。另请参见“crc32”、“djb2”、“wt6”、“crc32c”和“hash-type”指令。
比较 `` 的内容与输入值。两个值都被视为二进制字符串。返回一个布尔值,指示两个二进制字符串是否匹配。如果两个二进制字符串的长度相同,则比较将以恒定时间进行。请注意,此转换器仅在 haproxy 已使用 USE_OPENSSL 编译时可用。
示例
http-request set-var(txn.token) hdr(token) # 检查客户端发送的令牌是否与密钥令牌 # 的值匹配,而不会通过时间攻击泄露内容。 acl token_given str(my_secret_token),secure_memcmp(txn.token)
set-var(<var name>) 使用输入内容设置一个变量,并按原样返回内容。变量保留值和关联的输入类型。变量名以其作用域的指示开头。允许的作用域有:"proc":变量与整个进程共享; "sess":变量与整个会话共享; "txn":变量与事务(请求和响应)共享; "req":变量仅在请求处理期间共享; "res":变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是 '.'。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将二进制输入样本转换为 SHA-1 摘要。结果是一个长度为 20 字节的二进制样本。
sha2([<bits>])
将二进制输入样本转换为 SHA-2 系列的摘要。结果是一个长度为 ``/8 字节的二进制样本。`` 的有效值为 224、256、384、512,每个都对应 SHA-<bits>。默认值为 256。请注意,此转换器仅在 haproxy 已使用 USE_OPENSSL 编译时可用。
接受一个字符串类型的输入值,可以是服务器名称或 <backend>/<server> 格式,并返回该服务器上排队会话的数量。 可用于需要从动态名称(如 cookie 值(例如 req.cook(SRVID),srv_queue))查找排队会话,然后决定中断持久性或将请求定向到其他地方的情况。
strcmp(<var>)
将 <var> 的内容与字符串类型的输入值进行比较。返回一个与 strcmp(3) 兼容的有符号整数结果:如果两个字符串相同,则为 0。如果左侧字符串在字典序上小于右侧字符串或左侧字符串更短,则返回小于 0 的值。否则返回大于 0 的值(右侧字符串大于左侧字符串或右侧字符串更短)。如果您需要以恒定时间比较两个二进制字符串,另请参见 secure_memcmp 转换器。
示例
http-request set-var(txn.host) hdr(host) # 检查客户端是否正在尝试域前置(domain fronting)。 acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0
sub(<value>)
从输入的有符号整数值中减去 <value>,并将结果作为有符号整数返回。注意:为了从常量中减去输入,只需执行“neg,add(value)”。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享,"req" : 变量仅在请求处理期间共享,"res" : 变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均客户端到服务器字节速率,以字节量/周期(在表中配置)衡量。另请参阅 sc_bytes_in_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均服务器到客户端字节速率,以字节量/周期(在表中配置)衡量。另请参阅 sc_bytes_out_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回与指定表中输入样本关联的传入连接的累积数量。另请参见 sc_conn_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的当前并发跟踪连接数。另请参阅 sc_conn_cur 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的平均传入连接速率。另请参阅 sc_conn_rate 样本获取关键字。
table_gpt0(<table>)
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回布尔值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的标签的当前值。另请参阅 sc_get_gpt0 样本获取关键字。
table_gpc0(<table>)
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的计数器的当前值。另请参阅 sc_get_gpc0 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在表中配置的周期内 gpc0 计数器递增的频率,与指定表中输入样本相关联。另请参阅 sc_get_gpc0_rate 样本获取关键字。
table_gpc1(<table>)
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的第二个通用目的计数器的当前值。另请参见 sc_get_gpc1 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 gpc1 计数器在表中配置的时间段内增量的频率。另请参见 sc_get_gpc1_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 错误累积数量。另请参见 sc_http_err_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。另请参阅 sc_http_err_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 请求累积数量。另请参见 sc_http_req_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。另请参阅 sc_http_req_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的客户端到服务器数据的累积数量,以千字节为单位。当前测试是在 32 位整数上进行的,这会将值限制在 4 TB。另请参见 sc_kbytes_in 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器到客户端数据的累积数量,以千字节为单位。当前测试是在 32 位整数上进行的,这会将值限制在 4 TB。另请参见 sc_kbytes_out 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器 ID。当连接到服务器成功时,服务器 ID 通过“stick”规则进行关联。服务器 ID 零表示没有与此键关联的服务器。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的传入会话的累积数量。请注意,此处会话是指由“tcp-request connection”规则集接受的传入连接。另请参见 sc_sess_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中的输入样本关联的平均传入会话速率。请注意,此处的会话指的是被“tcp-request connection”规则集接受的传入连接。另请参阅 sc_sess_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在指定表中跟踪与输入样本相同键的当前并发连接数。它与 table_conn_cur 的不同之处在于,它不依赖任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。另请参阅 sc_trackers 样本提取关键字。
将字符串样本转换为大写。这只能放在字符串样本提取函数之后或返回字符串类型的转换关键字之后。结果为字符串类型。
url_dec([<in_form>])
接受一个经过 URL 编码的字符串作为输入,并返回其解码后的版本作为输出。输入和输出的类型都是字符串。如果将 <in_form> 参数设置为非零整数值,则假定输入字符串是表单或查询字符串的一部分,并且“+”字符将被转换为空格(' ')。否则,只有在表示查询字符串的问号(“?”)之后才会发生这种情况。
url_enc([<enc_type>])
接受一个字符串作为输入,并返回其编码后的版本作为输出。输入和输出的类型都是字符串。默认情况下,编码类型用于`query`类型。目前不支持其他类型,但可选参数是为了将来的更改而保留的。
ungrpc(<field_number>,[<field_type>])
此操作从输入 gRPC 消息的二进制样本表示中以原始模式提取 gRPC 消息字段,其中 `` 是字段编号(点分表示法),如果 `` 不存在,或者如果是整数样本。授权类型的列表如下:"int32"、"int64"、"uint32"、"uint64"、"sint32"、"sint64"、"bool"、"enum"(用于 "varint" 线型 0),"fixed64"、"sfixed64"、"double"(用于 64 位线型 1),"fixed32"、"sfixed32"、"float"(用于线型 5)。请注意,"string" 被视为长度分隔类型,因此不需要 `` 参数即可提取。有关协议缓冲区消息字段类型的更多信息,请访问:https://developers.google.com/protocol-buffers/docs/encoding
示例
// 这是一个根据 // https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto 改编的 protocol buffer .proto 文件内容 message Point { int32 latitude = 1; int32 longitude = 2; } message PPoint { Point point = 59; } message Rectangle { // 矩形的一个角。 PPoint lo = 48; // 矩形的另一个角。 PPoint hi = 49; }
假设请求体由一个 "Rectangle" 对象值(两个 PPoint 协议缓冲区消息)组成,这四个协议缓冲区字段可以用这些 "ungrpc" 指令提取: req.body,ungrpc(48.59.1,int32) # 第一个 PPoint 的 "lo" 的 "latitude" req.body,ungrpc(48.59.2,int32) # 第一个 PPoint 的 "lo" 的 "longitude" req.body,ungrpc(49.59.1,int32) # 第二个 PPoint 的 "hi" 的 "latitude" req.body,ungrpc(49.59.2,int32) # 第二个 PPoint 的 "hi" 的 "longitude" 我们也可以像这样提取中间的 48.59 字段作为二进制样本: req.body,ungrpc(48.59) 由于 gRPC 消息总是由 gRPC 头后跟协议缓冲区消息组成,在上面的示例中,第一个 PPoint 的 "lo" 的 "latitude" 可以通过以下等效指令提取: req.body,ungrpc(48.59),protobuf(1,int32) req.body,ungrpc(48),protobuf(59.1,int32) req.body,ungrpc(48),protobuf(59),protobuf(1,int32) 注意,第一个转换必须是 "ungrpc",其余的必须是 "protobuf",并且只有最后一个可以有一个或没有第二个参数来解释前面的二进制样本。unset-var(<var name>) 如果输入内容已定义,则取消设置变量。变量名以其作用域的指示开头。允许的作用域有:"proc":变量与整个进程共享; "sess":变量与整个会话共享; "txn":变量与事务(请求和响应)共享; "req":变量仅在请求处理期间共享; "res":变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是 '.'。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
utime(<format>[,<offset>])
将一个假定包含自纪元以来日期的整数,使用 strftime(3) 定义的 <format> 字符串格式,转换为表示该日期的 UTC 时间字符串。目的是允许在日志中使用任何日期格式。可以对输入日期应用一个可选的 <offset>(以秒为单位,可正可负)。有关您的操作系统支持的格式,请参阅 strftime() 手册页。另请参阅 ltime 转换器。
示例
# 输出两个部分,一个包含 UTC 时间,另一个包含 ip:port # 例如 20140710162350 127.0.0.1:57325 log-format %[date,utime(%Y%m%d%H%M%S)]\ %ci:%cp
word(<index>,<delimiters>[,<count>])
根据给定的分隔符,从输入字符串中提取从头开始(正索引)或从尾开始(负索引)计数的第 n 个单词。索引从 1 或 -1 开始,分隔符是格式化为字符串的字符列表。空单词会被跳过。这意味着输入字符串开头或结尾的分隔符会被忽略,输入字符串内的连续分隔符被视为单个分隔符。您可以选择性地指定要提取的单词数 <count>(默认为 1)。值为 0 表示提取所有剩余的单词。
示例
str(f1_f2_f3__f5),word(4,_) # f5 str(f1_f2_f3__f5),word(5,_) # <未找到> str(f1_f2_f3__f5),word(2,_,0) # f2_f3__f5 str(f1_f2_f3__f5),word(3,_,2) # f3__f5 str(f1_f2_f3__f5),word(-2,_,3) # f1_f2_f3 str(f1_f2_f3__f5),word(-3,_,0) # f1_f2 str(/f1/f2/f3/f4),word(1,/) # f1 str(/f1////f2/f3/f4),word(1,/) # f2
wt6([<avalanche>])
使用 WT6 哈希函数将二进制输入样本哈希为一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用全雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘滞表条目以收集粗略的统计数据。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参阅“crc32”、“djb2”、“sdbm”、“crc32c”和“hash-type”指令。
xor(<value>)
对 <value> 和类型为有符号整数的输入值执行按位“XOR”(异或)操作,并将结果作为有符号整数返回。<value> 可以是数字值或变量名。变量名以指示其范围的指示符开头。允许的作用域是:“proc”:变量与整个进程共享;“sess”:变量与整个会话共享;“txn”:变量与事务(请求和响应)共享;“req”:变量仅在请求处理期间共享;“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
xxh32([<seed>])
使用 XXHash 哈希函数的 32 位变体将二进制输入样本哈希为一个无符号 32 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
xxh64([<seed>])
使用 XXHash 哈希函数的 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。

7.3.2. 从内部状态提取样本

第一组样本提取方法适用于甚至不涉及任何客户端信息的内部信息。这些方法有时与“monitor-fail”指令一起使用,向外部监视器报告内部状态。本节描述的样本提取方法可在任何地方使用。
always_false : 布尔值
始终返回布尔值“false”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
always_true : 布尔值
始终返回布尔值“true”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
avg_queue([<backend>]) : 整数
返回指定后端的排队连接总数除以活动服务器数量。如果未指定后端,则使用当前后端。这与 "queue" 非常相似,除了考虑了农场的规模,以便更准确地衡量新连接可能需要多长时间才能得到处理。主要用途是使用 ACL 将一个抱歉页面返回给新用户,当确定他们将获得降级服务时,或者将其传递给后端服务器的标头中,以便它们决定以降级模式工作或禁用某些功能以加快处理速度。请注意,如果没有活动服务器了,将考虑排队连接数的两倍作为测量值。这是一个公平的估计,因为我们预计会很快恢复一个服务器,但我们仍然宁愿将新流量发送到状况更好的另一个后端。另请参阅 "queue"、"be_conn" 和 "be_sess_rate" 样本提取。
be_conn([<backend>]) : 整数
适用于后端上当前已建立的连接数,可能包括正在评估的连接。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“fe_conn”、“queue”、“be_conn_free”和“be_sess_rate”标准。
be_conn_free([<backend>]) : integer
返回一个整数值,对应于后端中可用服务器上的可用连接数。不包括队列槽位。也不包括备份服务器,除非所有其他服务器都已关闭。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“be_conn”、“connslots”和“srv_conn_free”标准。其他注意事项和说明:如果任何服务器的 maxconn 或 maxqueue 为 0(表示无限制),则此提取显然没有意义,在这种情况下返回的值将为 -1。
be_sess_rate([<backend>]) : 整数
返回一个整数值,对应于后端上的会话创建速率,以每秒新会话数表示。这与 ACL 一起使用,以便在昂贵或脆弱的后端达到过高的会话速率时切换到备用后端,或限制服务滥用(例如防止在线词典被爬取)。使用 log-format 指令将此元素添加到日志中也很有用。
示例
# 如果字典请求过于频繁,则重定向到错误页面 backend dynamic mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
bin(<hex>) : bin
返回一个二进制链。输入是字符串的十六进制表示。
bool(<bool>) : 布尔值
返回一个布尔值。<bool> 可以是 'true'、'false'、'1' 或 '0'。'false' 和 '0' 相同。'true' 和 '1' 相同。
connslots([<backend>]) : 整数
返回一个整数值,表示后端中仍可用的连接槽数,方法是汇总所有服务器的最大连接数和最大队列大小。这可能仅用于 ACL。基本思想是能够测量仍然可用的连接“槽”数(连接 + 队列),以便将超出此数量的任何内容(预期用途;请参阅 "use_backend" 关键字)重定向到另一个后端。'connslots' = 可用的服务器连接槽数 + 可用的服务器队列槽数。请注意,虽然可以使用 "fe_conn",但当流量流向单个 IP,分成多个后端(可能使用 ACL 进行基于名称的负载均衡)时,"connslots" 会特别有用,并且您想要区分不同的后端及其可用的 "connslots"。此外,虽然 "nbsrv" 仅衡量实际上*已关闭*的服务器,此 fetch 更精细,还会查看可用连接槽的数量。另请参阅 "queue" 和 "avg_queue"。其他注意事项:目前,代码不处理动态连接。此外,如果任何服务器的最大连接数或最大队列数为 0,则此 fetch 显然没有意义,在这种情况下,返回值将是 -1。
cpu_calls : integer
返回自处理流或当前请求的任务分配以来对其的调用次数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值通常应较低且稳定(对于典型的简单请求约为 2 次调用),但如果执行了某些处理(压缩、缓存或分析),则可能会变高。这纯粹是为了性能监控。
cpu_ns_avg : integer
返回处理流或当前请求的每个任务调用的平均纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。注意:此值正好是 cpu_ns_tot 除以 cpu_calls。
cpu_ns_tot : integer
返回处理流或当前请求的每个任务调用的总纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),导致机器上的 CPU 成本,并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。由于 cpu_calls 计数较高(例如,在处理许多 HTTP 块时),该值可能会人为地偏高,因此通常首选记录 cpu_ns_avg。
date([<offset>],[<unit>]) : integer
以纪元(自 1970 年 1 月 1 日以来的秒数)形式返回当前日期。如果指定了偏移值,则在返回值之前将其添加到当前日期。这对于计算相对日期特别有用,因为允许正负偏移。与 http_date 转换器结合使用时很有用。<unit> 是可选的,可以设置为“s”表示秒(默认行为)、“ms”表示毫秒或“us”表示微秒。如果设置了 unit,则返回值是一个整数,反映自纪元以来的秒数、毫秒数或微秒数,再加上偏移量。当需要不到一秒的时间分辨率时,这很有用。
示例
# 在每个响应中设置一个到期头,时间为现在+1小时 http-response set-header Expires %[date(3600),http_date] # 在每个响应中设置一个到期头,时间为现在+1小时, # 具有毫秒级粒度 http-response set-header Expires %[date(3600000,ms),http_date(0,ms)]
date_us : integer
返回日期的微秒部分(“秒”部分由 date 样本返回)。此样本与 date 样本一致,因为它来自相同的 timeval 结构。
distcc_body<token>[,<occ>]):二进制
解析distcc消息并返回与标记<token>的出现次数#<occ>关联的正文。出现次数从1开始,如果未指定,则任何出现次数都可能匹配,尽管实际上目前只检查第一个。这可用于提取通过haproxy构建的文件中的文件名或参数。有关支持的令牌的完整列表,请参阅distcc的协议文档。
distcc_param<token>[,<occ>]):整数
解析distcc消息并返回与标记<token>的出现次数#<occ>关联的参数。出现次数从1开始,如果未指定,则任何出现次数都可能匹配,尽管实际上目前只检查第一个。这可用于提取某些信息,例如协议版本、文件大小或通过haproxy构建的文件中的参数。另一个用例是等待预处理文件内容开始,然后再连接到服务器,以避免保持空闲连接。有关支持的令牌的完整列表,请参阅distcc的协议文档。
示例
# 等待预处理文件上传最多 20 秒 tcp-request inspect-delay 20s tcp-request content accept if { distcc_param(DOTI) -m found } # 将大文件发送到大型服务器场 use_backend big_farm if { distcc_param(DOTI) gt 1000000 }
env(<name>) : 字符串
返回一个包含环境变量 <name> 值的字符串。提醒一下,环境变量是每个进程的,并在进程启动时采样。这对于将一些信息传递给下一跳服务器,或者与 ACL 结合使用以在进程以特定方式启动时采取特定操作很有用。
示例
# 将 Via 头传递给下一跳,其中包含本地主机名 http-request add-header Via 1.1\ %[env(HOSTNAME)] # 当设置了 STOP 环境变量时,拒绝无 cookie 的请求 http-request deny if !{ req.cook(SESSIONID) -m found } { env(STOP) -m found }
fe_conn([<frontend>]) : 整数
返回前端上当前已建立的连接数,可能包括正在评估的连接。如果未指定前端名称,则使用当前前端。但也可以检查另一个前端。它可用于在硬阻塞之前返回一个“抱歉”页面,或者在服务器场被认为已满时使用特定的后端来处理新请求。这主要与 ACL 一起使用,但也可以用于在 HTTP 头中将一些统计信息传递给服务器。另请参阅“dst_conn”、“be_conn”、“fe_sess_rate”提取。
fe_req_rate([<frontend>]) : 整数
返回一个整数值,对应于每秒发送到前端的 HTTP 请求数。在启用客户端保持连接(keep-alive)的情况下,此数字可能与“fe_sess_rate”不同。
fe_sess_rate([<frontend>]) : 整数
返回一个整数值,对应于前端上的会话创建速率,单位为每秒新会话数。这与 ACL 一起使用,将传入会话速率限制在可接受的范围内,以便尽早防止服务滥用,例如,当与其他第 4 层 ACL 结合使用时,以强制客户端等待一段时间,直到速率下降到限制以下。使用 log-format 指令将此元素添加到日志中也很有用。另请参阅前端中使用的“rate-limit sessions”指令。
示例
# 此前端将传入邮件限制为 10/s,最多 100 个 # 并发连接。我们接受低于 10/s 的任何连接,并 # 强制超出的客户端等待 100 毫秒。由于客户端限制为 # 最多 100 个,因此每秒传入的邮件不能超过 10 封。 frontend mail bind :25 mode tcp maxconn 100 acl too_fast fe_sess_rate ge 10 tcp-request inspect-delay 100ms tcp-request content accept if ! too_fast tcp-request content accept if WAIT_END
hostname : string
返回系统主机名。
int(<integer>) : 有符号整数
返回一个有符号整数。
ipv4(<ipv4>) : ipv4
返回一个 IPv4 地址。
ipv6(<ipv6>) : ipv6
返回一个 IPv6 地址。
lat_ns_avg : integer
返回任务处理流被唤醒的时刻到它被有效调用的时刻之间的纳秒数。在 HTTP 持久连接的情况下,此数字对于同一连接上的每个新请求都会重置。此值指示所有其他并行处理的请求对当前请求造成的总体延迟,是由于嘈杂邻居导致的感知性能的直接指标。为了保持该值较低,可以通过 "tune.runqueue-depth" 减少调度器的运行队列深度,通过 "tune.maxpollevents" 减少一次处理的并发事件数量,通过 "bind" 行或前端上的 "nice" 选项降低流的 nice 值,通过 "tune.sched.low-latency" 启用低延迟调度,或在日志中查找其他重度请求(那些显示 "cpu_ns_avg" 值的请求),这些请求需要调整或修复。压缩大缓冲区可能是一个原因,例如重型正则表达式或长列表的正则表达式。注意:此值等于 lat_ns_tot 除以 cpu_calls。
lat_ns_tot : integer
返回任务处理流被唤醒的时刻到它被有效调用的时刻之间花费的总纳秒数。在 HTTP 持久连接的情况下,此数字对于同一连接上的每个新请求都会重置。此值指示所有其他并行处理的请求对当前请求造成的总体延迟,是由于嘈杂邻居导致的感知性能的直接指标。为了保持该值较低,可以通过 "tune.runqueue-depth" 减少调度器的运行队列深度,通过 "tune.maxpollevents" 减少一次处理的并发事件数量,通过 "bind" 行或前端上的 "nice" 选项降低流的 nice 值,通过 "tune.sched.low-latency" 启用低延迟调度,或在日志中查找其他重度请求(那些显示 "cpu_ns_avg" 值的请求),这些请求需要调整或修复。压缩大缓冲区可能是一个原因,例如重型正则表达式或长列表的正则表达式。注意:虽然直观上总延迟会增加传输时间,但这几乎从未发生,因为当任务等待 CPU 时,网络缓冲区会继续填充,并且下一次调用将处理更多内容。由于 cpu_calls 计数很高,例如在处理许多 HTTP 块时,该值可能会人为地高,因此通常首选记录 lat_ns_avg,这是一个更相关的性能指标。
meth(<method>) : 方法
返回一个方法。
nbproc : 整数
返回一个整数值,对应于已启动的进程数(它等于全局“nbproc”设置)。这对于日志记录和调试目的很有用。
nbsrv([<backend>]) : 整数
返回一个整数值,对应于当前后端或指定后端的可用服务器数量。这主要与 ACL 一起使用,但在添加到日志中时也很有用。这通常用于在服务器数量过低而无法处理某些负载时切换到备用后端。当与“monitor fail”结合使用时,报告故障很有用。
prio_class : integer
返回http模式下当前会话或tcp模式下连接的优先级类别。该值将是最后一次调用“http-request set-priority-class”或“tcp-request content set-priority-class”时设置的值。
prio_offset : integer
返回http模式下当前会话或tcp模式下连接的优先级偏移量。该值将是最后一次调用“http-request set-priority-offset”或“tcp-request content set-priority-offset”时设置的值。
proc : 整数
返回一个整数值,对应于调用该函数的进程的位置,介于 1 和 global.nbproc 之间。这对于日志记录和调试目的很有用。
queue([<backend>]) : 整数
返回指定后端的排队连接总数,包括服务器队列中的所有连接。如果未指定后端名称,则使用当前后端,但也可以检查另一个后端。这对于 ACL 或将统计信息传递给后端服务器很有用。这可用于在排队超过已知水平时采取行动,这通常表示流量激增或服务器大规模减速。一个可能的操作是拒绝新用户但仍然接受老用户。另请参阅“avg_queue”、“be_conn”和“be_sess_rate”提取。
rand([<range>]) : 整数
返回一个在 <range> 个可能值范围内的随机整数值,从零开始。如果未指定范围,则默认为 2^32,即数字介于 0 和 4294967295 之间。例如,传递一些需要用于做出某些路由决策的值可能很有用,或者仅仅用于调试目的。此随机数不得用于安全目的。
srv_conn([<backend>/]<server>) : 整数
返回一个整数值,对应于指定服务器上当前已建立的连接数,可能包括正在评估的连接。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“fe_conn”、“be_conn”、“queue”和“srv_conn_free”提取方法。
srv_conn_free([<backend>/]<server>) : integer
返回一个整数值,对应于指定服务器上的可用连接数,可能包括正在评估的连接。该值不包括队列槽位。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“be_conn_free”和“srv_conn”提取方法。其他注意事项和说明:如果服务器的 maxconn 为 0,则此提取显然没有意义,在这种情况下返回的值将为 -1。
srv_is_up([<backend>/]<server>) : 布尔值
当指定服务器处于 UP 状态时返回 true,当其处于 DOWN 或维护模式时返回 false。如果省略 <backend>,则在当前后端中查找服务器。它主要用于根据通过健康检查报告的外部状态采取行动(例如,地理站点的可用性)。另一种可能的用途,更像是一种技巧,是使用虚拟服务器作为布尔变量,可以从 CLI 启用或禁用,以便可以实时调整依赖于这些 ACL 的规则。
srv_queue([<backend>/]<server>) : integer
返回一个整数值,对应于当前在指定服务器队列中等待的连接数。如果省略 <backend>,则在当前后端中查找服务器。有时可以与“use-server”指令一起使用,以在已知更快的服务器负载不大时强制使用它。另请参见“srv_conn”、“avg_queue”和“queue”样本提取方法。
srv_sess_rate([<backend>/]<server>) : 整数
返回一个对应于指定服务器上的会话创建速率的整数,以每秒新会话数表示。如果省略 <backend>,则在当前后端中查找服务器。这主要与 ACL 一起使用,但在日志中也可能有意义。这用于在昂贵或脆弱的服务器达到过高的会话速率时切换到备用后端,或限制服务滥用(例如防止潜在请求使服务器过载)。
示例
# 重定向到单独的后端 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
stopping : 布尔值
如果调用该函数的进程当前正在停止,则返回 TRUE。这对于日志记录,或在优雅关闭时放宽某些检查或帮助关闭某些连接很有用。
str(<string>) : 字符串
返回一个字符串。
table_avl([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中可用条目的总数。另请参阅 table_cnt。
table_cnt([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中当前使用的条目总数。有关其他条目计数方法,请参阅 src_conn_cnt 和 table_avl。
thread : integer
返回一个整数值,对应于调用该函数的线程的位置,介于 0 和 (global.nbthread-1) 之间。这对于日志记录和调试目的很有用。
uuid([<version>]) : string
返回遵循RFC4122标准的UUID。如果未指定版本,则返回UUID版本4(完全随机)。目前,仅支持版本4。
var(<var-name>) : 未定义
返回带有存储类型变量。如果变量未设置,则采样获取失败。变量名以其范围的指示开始。允许的范围是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。

7.3.3. 在第 4 层提取样本

第 4 层通常仅描述传输层,在 haproxy 中,它是最接近连接的层,此时还没有内容可用。此处描述的 fetch 方法可用于低至 "tcp-request connection" 规则集,除非它们需要未来信息。这些通常包括 TCP/IP 地址和端口,以及与传入连接相关的 stick-table 中的元素。要从粘性计数器检索值,计数器编号可以显式设置为 0、1 或 2,使用预定义的 "sc0_"、"sc1_" 或 "sc2_" 前缀。只有当 MAX_SESS_STKCTR 值不超过 3 时,才能使用这三个预定义前缀,否则在使用 "sc*" 前缀时,可以将计数器编号指定为第一个整数参数。从 "sc_0" 到 "sc_N",其中 N 是 (MAX_SESS_STKCTR-1)。可以使用 "sc*" 形式指定一个可选表,在这种情况下,将查找当前跟踪的键在此备用表中而不是在当前跟踪的表中。
bc_http_major : integer
返回后端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
be_id : 整数
返回包含当前后端 ID 的整数。它可以在前端响应中使用,以检查哪个后端处理了请求。它也可以在 tcp-check 或 http-check 规则集中使用。
be_name : string
返回包含当前后端名称的字符串。它可以在前端响应中使用,以检查哪个后端处理了请求。它也可以在 tcp-check 或 http-check 规则集中使用。
dst : ip
这是客户端的连接目标 IPv4 地址,即客户端连接到的地址。在透明模式下运行时可能很有用。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效地址。当传入连接经过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,如果设置了 nf_conntrack_tcp_loose sysctl,源地址和目标地址可能会很少出现颠倒,因为晚期响应可能会重新打开一个已超时连接并切换被认为是源地址和目标地址的地址。
dst_conn : 整数
返回一个整数值,对应于同一套接字上当前建立的连接数,包括正在评估的连接。它通常与 ACL 一起使用,但也可以用于在 HTTP 头中或日志中将信息传递给服务器。它可以用于在硬阻塞之前返回一个“抱歉”页面,或者在套接字被认为饱和时使用特定的后端来处理新请求。这提供了为不同的侦听端口或地址分配不同限制的能力。另请参阅“fe_conn”和“be_conn”提取。
dst_is_local : boolean
如果传入连接的目标地址是本地系统地址,则返回 true;如果地址不存在于系统中(意味着它在透明模式下被拦截),则返回 false。这对于默认情况下对转发流量应用某些规则,而对定向到机器实际地址的流量应用其他规则可能很有用。例如,统计页面可能仅在该地址上提供,或者 SSH 访问可能被本地重定向。请注意,该检查涉及一些系统调用,因此最好每个连接只执行一次。
dst_port : 整数
返回一个整数值,对应于客户端侧连接的目标 TCP 端口,即客户端连接到的端口。这可能在透明模式下运行、为某些客户端的整个应用程序会话分配动态端口、将所有用户粘滞到同一台服务器,或使用 HTTP 头将目标端口信息传递给服务器时使用。
fc_fackets : integer
返回内核为客户端连接测量的 fack 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_http_major : integer
报告前端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
fc_lost : integer
返回内核为客户端连接测量的丢失计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回客户端在 PROXY 协议头中发送的权威 TLV(如果有)。
返回客户端在 PROXY 协议头中发送的唯一 ID TLV(如果有)。
fc_rcvd_proxy : boolean
如果客户端使用 PROXY 协议头启动连接,则返回 true。
fc_reordering : integer
返回内核为客户端连接测量的重排序计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
fc_retrans : integer
返回内核为客户端连接测量的重传计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_rtt(<unit>) : integer
返回内核为客户端连接测量的往返时间(RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
fc_rttvar(<unit>) : integer
返回内核为客户端连接测量的往返时间(RTT)方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
fc_sacked : integer
返回内核为客户端连接测量的 sacked 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fc_unacked : integer
返回内核为客户端连接测量的未确认计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
fe_defbe : string
返回前端的默认后端名称的字符串。它可以在前端用于检查哪个后端将默认处理请求。
fe_id : 整数
返回一个包含当前前端 ID 的整数。它可以在后端使用,以检查它是从哪个前端调用的,或将通过同一前端进入的所有用户粘滞到同一台服务器。
fe_name : string
返回当前前端名称的字符串。它可以在后端用于检查它是由哪个前端调用的,或者将来自同一前端的所有用户粘性到同一服务器。
sc_bytes_in_rate(<ctr>[,<table>]) : 整数
sc0_bytes_in_rate([<table>]) : 整数
sc1_bytes_in_rate([<table>]) : 整数
sc2_bytes_in_rate([<table>]) : 整数
返回当前跟踪的计数器中客户端到服务器的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_in_rate。
sc_bytes_out_rate(<ctr>[,<table>]) : 整数
sc0_bytes_out_rate([<table>]) : 整数
sc1_bytes_out_rate([<table>]) : 整数
sc2_bytes_out_rate([<table>]) : 整数
返回当前跟踪的计数器中服务器到客户端的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_out_rate。
sc_clr_gpc0(<ctr>[,<table>]) : 整数
sc0_clr_gpc0([<table>]) : 整数
sc1_clr_gpc0([<table>]) : 整数
sc2_clr_gpc0([<table>]) : 整数
清除与当前跟踪的计数器关联的第一个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
示例
# 如果连续 5 个请求的速率持续高于每秒 10 个会话,则阻止, # 并在流量减慢时立即重置计数器。 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
清除与当前跟踪计数器关联的第二个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
sc_conn_cnt(<ctr>[,<table>]) : 整数
sc0_conn_cnt([<table>]) : 整数
sc1_conn_cnt([<table>]) : 整数
sc2_conn_cnt([<table>]) : 整数
返回当前跟踪的计数器所统计的传入连接的总数。另请参阅 src_conn_cnt。
sc_conn_cur(<ctr>[,<table>]) : 整数
sc0_conn_cur([<table>]) : 整数
sc1_conn_cur([<table>]) : 整数
sc2_conn_cur([<table>]) : 整数
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。另请参阅 src_conn_cur。
sc_conn_rate(<ctr>[,<table>]) : 整数
sc0_conn_rate([<table>]) : 整数
sc1_conn_rate([<table>]) : 整数
sc2_conn_rate([<table>]) : 整数
返回当前跟踪的计数器中的平均连接速率,以表中配置的时间段内的连接数量来衡量。另请参阅 src_conn_rate。
sc_get_gpc0(<ctr>[,<table>]) : 整数
sc0_get_gpc0([<table>]) : 整数
sc1_get_gpc0([<table>]) : 整数
sc2_get_gpc0([<table>]) : 整数
返回与当前跟踪的计数器关联的第一个通用计数器的值。另请参阅 src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。
sc_get_gpc1(<ctr>[,<table>]) : integer
sc0_get_gpc1([<table>]) : integer
sc1_get_gpc1([<table>]) : integer
sc2_get_gpc1([<table>]) : integer
返回与当前跟踪的计数器关联的第二个通用目的计数器的值。另请参阅 src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。
sc_get_gpt0(<ctr>[,<table>]) : 整数
sc0_get_gpt0([<table>]) : 整数
sc1_get_gpt0([<table>]) : 整数
sc2_get_gpt0([<table>]) : 整数
返回与当前跟踪的计数器关联的第一个通用标签(General Purpose Tag)的值。另请参阅 src_get_gpt0。
sc_gpc0_rate(<ctr>[,<table>]) : 整数
sc0_gpc0_rate([<table>]) : 整数
sc1_gpc0_rate([<table>]) : 整数
sc2_gpc0_rate([<table>]) : 整数
返回与当前跟踪的计数器关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 src_gpc0_rate、sc/sc0/sc1/sc2_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
sc_gpc1_rate(<ctr>[,<table>]) : integer
sc0_gpc1_rate([<table>]) : integer
sc1_gpc1_rate([<table>]) : integer
sc2_gpc1_rate([<table>]) : integer
返回与当前跟踪计数器关联的第二个通用计数器的平均增量速率。它报告了在配置的时间段内 gpc1 计数器被增量的频率。另请参阅 src_gpcA_rate、sc/sc0/sc1/sc2_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。请注意,“gpc1_rate”计数器必须存储在粘滞表中才能返回一个值,因为“gpc1”只保存事件计数。
sc_http_err_cnt(<ctr>[,<table>]) : 整数
sc0_http_err_cnt([<table>]) : 整数
sc1_http_err_cnt([<table>]) : 整数
sc2_http_err_cnt([<table>]) : 整数
返回当前跟踪计数器中的 HTTP 错误总数。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_cnt。
sc_http_err_rate(<ctr>[,<table>]) : 整数
sc0_http_err_rate([<table>]) : 整数
sc1_http_err_rate([<table>]) : 整数
sc2_http_err_rate([<table>]) : 整数
返回当前跟踪的计数器中 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_rate。
sc_http_req_cnt(<ctr>[,<table>]) : 整数
sc0_http_req_cnt([<table>]) : 整数
sc1_http_req_cnt([<table>]) : 整数
sc2_http_req_cnt([<table>]) : 整数
返回当前跟踪计数器的累计 HTTP 请求数。这包括所有开始的请求,无论有效与否。另请参阅 src_http_req_cnt。
sc_http_req_rate(<ctr>[,<table>]) : 整数
sc0_http_req_rate([<table>]) : 整数
sc1_http_req_rate([<table>]) : 整数
sc2_http_req_rate([<table>]) : 整数
返回当前跟踪的计数器中 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。另请参阅 src_http_req_rate。
sc_inc_gpc0(<ctr>[,<table>]) : 整数
sc0_inc_gpc0([<table>]) : 整数
sc1_inc_gpc0([<table>]) : 整数
sc2_inc_gpc0([<table>]) : 整数
递增与当前跟踪的计数器关联的第一个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用将其增加到 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
递增与当前跟踪计数器关联的第二个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 1 并返回 1。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
sc_kbytes_in(<ctr>[,<table>]) : 整数
sc0_kbytes_in([<table>]) : 整数
sc1_kbytes_in([<table>]) : 整数
sc2_kbytes_in([<table>]) : 整数
返回当前跟踪的计数器中客户端到服务器的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_in。
sc_kbytes_out(<ctr>[,<table>]) : 整数
sc0_kbytes_out([<table>]) : 整数
sc1_kbytes_out([<table>]) : 整数
sc2_kbytes_out([<table>]) : 整数
返回当前跟踪的计数器中服务器到客户端的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_out。
sc_sess_cnt(<ctr>[,<table>]) : 整数
sc0_sess_cnt([<table>]) : 整数
sc1_sess_cnt([<table>]) : 整数
sc2_sess_cnt([<table>]) : 整数
返回从当前跟踪计数器中转换为会话的传入连接总数,这意味着它们被“tcp-request connection”规则接受。后端可能会计算比连接更多的会话,因为每个连接都可能导致许多后端会话,如果通过与客户端的连接执行了某些 HTTP keep-alive。另请参阅 src_sess_cnt。
sc_sess_rate(<ctr>[,<table>]) : 整数
sc0_sess_rate([<table>]) : 整数
sc1_sess_rate([<table>]) : 整数
sc2_sess_rate([<table>]) : 整数
返回当前跟踪的计数器中的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request connection”规则的连接。一个后端可能会计算比连接更多的会话,因为如果通过与客户端的连接执行了 HTTP 保持连接(keep-alive),每个连接可能会导致多个后端会话。另请参阅 src_sess_rate。
sc_tracked(<ctr>[,<table>]) : 布尔值
sc0_tracked([<table>]) : 布尔值
sc1_tracked([<table>]) : 布尔值
sc2_tracked([<table>]) : 布尔值
如果指定的会话计数器当前正被当前会话跟踪,则返回 true。这在决定是否要在传递给服务器的头中设置某些值时很有用。
sc_trackers(<ctr>[,<table>]) : 整数
sc0_trackers([<table>]) : 整数
sc1_trackers([<table>]) : 整数
sc2_trackers([<table>]) : 整数
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。它与 sc0_conn_cur 的不同之处在于,它不依赖于任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。
so_id : 整数
返回一个包含当前监听套接字 ID 的整数。在涉及多个“bind”行但需要在前端中使用的监听套接字 ID 非常有用,或者将通过同一套接字传入的所有用户绑定到同一服务器。
so_name : string
返回一个包含当前监听套接字名称的字符串,该名称在“bind”行中通过 name 定义。它的用途与 so_id 相同,但使用字符串而不是整数。
src : ip
这是会话客户端的源 IPv4 地址。它属于 IP 类型,可在 IPv4 和 IPv6 表上工作。在 IPv6 表上,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效地址。请注意,使用的是 TCP 级别的源地址,而不是代理后面的客户端地址。但是,如果使用了 "accept-proxy" 或 "accept-netscaler-cip" bind 指令,则对于除 "tcp-request connection" 之外的所有规则集,它都可以是 PROXY 协议兼容组件后面的客户端地址,其中 "tcp-request connection" 看到的是真实地址。当传入连接通过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,如果设置了 nf_conntrack_tcp_loose sysctl,源和目标有时可能会出现颠倒,因为一个延迟响应可能会重新打开一个已超时的连接并切换被认为是源和目标的地址。
示例
# 在请求中添加一个带有源地址国家的 HTTP 头 http-request set-header X-Country %[src,map_ip(geoip.lst)]
src_bytes_in_rate([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均字节速率,以表中配置的时间段内的字节量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_bytes_in_rate。
src_bytes_out_rate([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,发往传入连接源地址的平均字节速率,以表中配置的时间段内的字节量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_bytes_out_rate。
src_clr_gpc0([<table>]) : 整数
清除与当前代理的 stick-table 或指定的 stick-table 中传入连接的源地址关联的第一个通用计数器,并返回其先前的值。如果未找到地址,将创建一个条目并返回 0。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
示例
# 如果连续 5 个请求的速率持续高于每秒 10 个会话,则阻止, # 并在流量减慢时立即重置计数器。 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>]) : 整数
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的已建立连接的总数。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_cnt。
src_conn_cur([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,从当前传入连接的源地址发起的当前并发连接数。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_cur。
src_conn_rate([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均连接速率,以表中配置的时间段内的连接数量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_rate。
src_get_gpc0([<table>]) : 整数
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc0 和 src_inc_gpc0。
src_get_gpc1([<table>]) : integer
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器的值。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc1 和 src_inc_gpc1。
src_get_gpt0([<table>]) : 整数
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用标签的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpt0。
src_gpc0_rate([<table>]) : 整数
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 sc/sc0/sc1/sc2_gpc0_rate、src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
src_gpc1_rate([<table>]) : integer
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器的平均增量率。它报告 gpc1 计数器在配置周期内的增量频率。另请参阅 sc/sc0/sc1/sc2_gpc1_rate、src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。请注意,“gpc1_rate”计数器必须存储在 stick-table 中才能返回值,因为“gpc1”只包含事件计数。
src_http_err_cnt([<table>]) : 整数
返回当前代理的 stick-table 或指定 stick-table 中传入连接的源地址的 HTTP 错误总数。这包括请求错误和 4xx 错误响应。另请参阅 sc/sc0/sc1/sc2_http_err_cnt。如果未找到该地址,则返回零。
src_http_err_rate([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_err_rate。
src_http_req_cnt([<table>]) : 整数
返回当前代理的 stick-table 或指定 stick-table 中传入连接的源地址的 HTTP 请求总数。这包括每个已启动的请求,无论是否有效。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_cnt。
src_http_req_rate([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_rate。
src_inc_gpc0([<table>]) : 整数
递增与当前代理的 stick-table 或指定的 stick-table 中传入连接的源地址关联的第一个通用计数器,并返回其新值。如果未找到地址,将创建一个条目并返回 1。另请参阅 sc0/sc2/sc2_inc_gpc0。这通常用作表达式中的第二个 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。另请参阅 sc0/sc2/sc2_inc_gpc1。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
src_is_local : boolean
如果入站连接的源地址是本地的,则返回 true,如果地址不存在于系统中(意味着它来自远程计算机),则返回 false。请注意,UNIX 地址被视为本地的。这有助于根据客户端的来源应用某些访问限制(例如,对远程计算机要求身份验证或 https)。请注意,此检查涉及一些系统调用,因此最好每个连接只执行一次。
src_kbytes_in([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,从传入连接源地址接收的总数据量,以千字节为单位。如果找不到地址,则返回零。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 sc/sc0/sc1/sc2_kbytes_in。
src_kbytes_out([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,发送到传入连接源地址的总数据量,以千字节为单位。如果找不到地址,则返回零。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 sc/sc0/sc1/sc2_kbytes_out。
src_port : 整数
返回一个整数值,对应于客户端侧连接的 TCP 源端口,即客户端连接的来源端口。此函数的用途非常有限,因为现代协议如今不太关心源端口。
src_sess_cnt([<table>]) : 整数
返回当前代理的 stick-table 或指定 stick-table 中传入连接的源 IPv4 地址建立的连接总数,这些连接已转换为会话,这意味着它们已被“tcp-request”规则接受。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_sess_cnt。
src_sess_rate([<table>]) : 整数
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request”规则的连接。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_sess_rate。
src_updt_conn_cnt([<table>]) : 整数
在当前代理的粘滞表或指定的粘滞表中,为传入连接的源地址创建或更新关联的条目。此表必须配置为存储 "conn_cnt" 数据类型,否则匹配将被忽略。当前计数会加一,并且到期计时器会刷新。更新后的计数将被返回,因此此匹配不会返回零。这曾被用来根据源地址拒绝滥用服务的用户。注意:建议改用 "tcp-request" 规则中功能更完整的 "track-sc*" 操作。
示例
# 此前端限制每个源地址的传入 SSH 连接为每 10 秒 3 次, # 并拒绝超出的连接,直到观察到 10 秒的静默期。最多跟踪 20 个地址。 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 规则集中使用。

7.3.4. 在第 5 层获取样本

第 5 层通常仅描述会话层,在 haproxy 中,这最接近于所有连接握手完成但尚无内容可用时的会话。这里描述的获取方法最低可在 "tcp-request content" 规则集使用,除非它们需要某些未来的信息。这些信息通常包括 SSL 协商的结果。
51d.all(<prop>[,<prop>*]) : string
以字符串形式返回请求的属性值,值之间用“51degrees-property-separator”指定的定界符分隔。设备通过请求中的所有重要 HTTP 头部来识别。该函数最多可以传递五个属性名称,如果找不到属性名称,则返回“NoData”。
示例
# 此处将头部 "X-51D-DeviceTypeMobileTablet" 添加到请求中 # 包含使用请求中的所有相关头部请求的三个属性。 frontend http-in bind *:8081 default_backend servers http-request set-header X-51D-DeviceTypeMobileTablet \ %[51d.all(DeviceType,IsMobile,IsTablet)]
ssl_bc : boolean
当后端连接是通过 SSL/TLS 传输层建立并已本地解密时,返回 true。这意味着出站连接是使用“ssl”选项与服务器建立的。它可以用于 tcp-check 或 http-check 规则集。
返回出站连接通过 SSL/TLS 传输层建立时支持的对称密码(cipher)密钥大小(以位为单位)。它可以用于 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_bc_cipher : string
返回通过 SSL/TLS 传输层建立的出站连接所使用的密码(cipher)的名称。它可以用于 tcp-check 或 http-check 规则集。
当入站连接通过 SSL/TLS 传输层建立时,返回后端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
当后端连接通过 SSL/TLS 传输层建立,并且新创建的 SSL 会话是通过缓存会话或 TLS 票据恢复的,则返回 true。它可以用于 tcp-check 或 http-check 规则集。
ssl_bc_npn : string
从通过 TLS 传输层建立的出站连接中提取下一个协议协商字段。结果是包含与服务器协商的协议名称的字符串。SSL 库必须已编译并支持 TLS 扩展(检查 haproxy -vv)。请注意,除非 "server" 行上的 "npn" 关键字指定了一个协议列表,否则 TLS NPN 扩展不会被宣告。另外,没有什么能迫使服务器从该列表中选择一个协议,任何其他协议都可以使用。请注意,TLS NPN 扩展已被 ALPN 取代。它可以在 tcp-check 或 http-check 规则集中使用。
返回通过 SSL/TLS 传输层建立的出站连接所使用的协议的名称。它可以用于 tcp-check 或 http-check 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回 RFC 5929 第 3 节定义的 TLS 唯一 ID。可以使用转换器将唯一 ID 编码为 base64:“ssl_bc_unique_id,base64”。它可以用于 tcp-check 或 http-check 规则集。
当入站连接通过 SSL/TLS 传输层建立时,返回后端连接的服务器随机数(server random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL ID。如果想要知道会话是否被重用,它对于日志记录很有用。它可以用于 tcp-check 或 http-check 规则集。
当出站连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL 会话主密钥。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。它可以用于 tcp-check 或 http-check 规则集。
返回出站连接通过 SSL/TLS 传输层建立时使用的对称密码(cipher)密钥大小(以位为单位)。它可以用于 tcp-check 或 http-check 规则集。
ssl_c_ca_err : integer
当传入连接通过 SSL/TLS 传输层建立时,如果在验证深度 > 0 的客户端证书期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证客户端证书期间检测到第一个错误,则返回该错误在 CA 链中的深度。如果未遇到错误,则返回 0。
返回客户端提供的 DER 格式链证书,当传入连接是通过 SSL/TLS 传输层建立时。当用于 ACL 时,要匹配的值可以以十六进制形式传递。可以使用接受 ASN.1 DER 数据的任何库来解析结果。它目前不支持恢复的会话。
ssl_c_der : binary
当传入连接通过 SSL/TLS 传输层建立时,返回由客户端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_c_err : integer
当传入连接通过 SSL/TLS 传输层建立时,如果在深度为 0 的验证期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
ssl_c_i_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回客户端提供的证书颁发者的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_c_i_dn(OU,2)”表示第二个组织单位,而“ssl_c_i_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_c_i_dn(,0,rfc2253)
ssl_c_key_alg : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成客户端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
ssl_c_s_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回客户端提供的证书主题的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_c_s_dn(OU,2)”表示第二个组织单位,而“ssl_c_s_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_c_s_dn(,0,rfc2253)
ssl_c_serial : binary
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_c_sha1 : binary
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的 SHA-1 指纹。这可用于将客户端粘滞到某个服务器,或将此信息传递给服务器。请注意,输出是二进制格式,因此如果要将该签名传递给服务器,您需要将其编码为十六进制或 base64,如下例所示:
示例
http-request set-header X-SSL-Client-SHA1 %[ssl_c_sha1,hex]
ssl_c_sig_alg : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署客户端证书的算法名称。
ssl_c_used : boolean
如果当前 SSL 会话使用了客户端证书,则返回 true,即使当前连接使用的是 SSL 会话恢复。另请参阅 "ssl_fc_has_crt"。
ssl_c_verify : integer
当传入连接通过 SSL/TLS 传输层建立时,返回验证结果的错误 ID;如果未遇到错误,则返回零。有关完整的错误代码列表,请参考您的 SSL 库文档。
ssl_c_version : integer
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的版本。
ssl_f_der : binary
当传入连接通过 SSL/TLS 传输层建立时,返回前端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_f_i_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回前端提供的证书颁发者的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_f_i_dn(OU,2)”表示第二个组织单位,而“ssl_f_i_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_f_i_dn(,0,rfc2253)
ssl_f_key_alg : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成前端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
ssl_f_s_dn([<entry>[,<occ>[,<format>]]]) : string
当入站连接通过 SSL/TLS 传输层建立时,在未指定 <entry> 时,返回前端提供的证书主题的完整区分名(Distinguished Name, DN),或者返回从 DN 开始的第一个给定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 的开头/结尾开始的第 n 个给定条目的值。例如,“ssl_f_s_dn(OU,2)”表示第二个组织单位,而“ssl_f_s_dn(CN)”则检索通用名称。<format> 参数允许您获取适合不同协议使用的 DN。目前支持 LDAP v3 的 rfc2253。如果您只想修改格式,可以指定一个空字符串和零作为前两个参数。例如:ssl_f_s_dn(,0,rfc2253)
ssl_f_serial : binary
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_f_sha1 : binary
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的 SHA-1 指纹。这可用于了解使用 SNI 选择了哪个证书。
ssl_f_sig_alg : string
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署前端证书的算法名称。
ssl_f_version : integer
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的版本。
ssl_fc : boolean
当前端连接是通过 SSL/TLS 传输层建立并且本地解密时,返回 true。这意味着它匹配了一个使用“bind”行声明的套接字,该套接字具有“ssl”选项。
示例
# 当客户端通过 SSL 连接时,向服务器传递 "X-Proto: https" listen http-https bind :80 bind :443 ssl crt /etc/haproxy.pem http-request add-header X-Proto https if { ssl_fc }
当传入连接通过 SSL/TLS 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
ssl_fc_alpn : string
此操作从通过 TLS 传输层建立并由 haproxy 本地解密的出站连接中提取应用程序层协议协商字段。结果是一个包含客户端广告的协议名称的字符串。SSL 库必须已编译并支持 TLS 扩展(检查 haproxy -vv)。请注意,除非 "bind" 行上的 "alpn" 关键字指定了一个协议列表,否则 TLS ALPN 扩展不会被宣告。另外,没有什么能迫使客户端从该列表中选择一个协议,任何其他协议都可以被请求。TLS ALPN 扩展是为了取代 TLS NPN 扩展。另请参阅 "ssl_fc_npn"。
ssl_fc_cipher : string
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
返回客户端 hello 密码列表的二进制形式。返回值的最大长度与“tune.ssl.capture-cipherlist-size”的值一致。
返回编码为十六进制的客户端 hello 密码列表的二进制形式。返回值的最大长度与“tune.ssl.capture-cipherlist-size”的值一致。
返回已解码的客户端 hello 密码列表的文本形式。返回的密码最大数量与“tune.ssl.capture-cipherlist-size”的值一致。请注意,此采样获取仅在 OpenSSL >= 1.0.2 时可用。如果未启用该函数,则此采样获取将返回类似“ssl_fc_cipherlist_xxh”的哈希值。
返回密码列表的 xxh64 哈希值。只有当“tune.ssl.capture-cipherlist-size”的值设置为大于 0 时才能返回此哈希值,但是哈希值会考虑密码列表的所有数据。
当入站连接通过 SSL/TLS 传输层建立时,返回前端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_EARLY_TRAFFIC_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_HANDSHAKE_TRAFFIC_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 CLIENT_TRAFFIC_SECRET_0 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 EXPORTER_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
当通过 TLS 1.3 传输层建立入站连接时,返回 EARLY_EXPORTER_SECRET 作为十六进制字符串,用于前端连接。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调用于生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志记录必须通过全局部分的“tune.ssl.keylog on”进行激活。另请参阅“tune.ssl.keylog”。
ssl_fc_has_crt : boolean
如果传入的 SSL/TLS 传输层连接中存在客户端证书,则返回 true。在 'verify' 语句设置为 'optional' 时很有用。注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中不存在客户端证书,但可以从缓存或票据中检索。因此,如果您想检查当前 SSL 会话是否使用了客户端证书,请优先使用 "ssl_c_used"。
如果发送了早期数据,并且握手尚未发生,则返回 true。由于它具有安全隐患,因此能够拒绝这些数据或等到握手发生后再处理它们非常有用。
ssl_fc_has_sni : boolean
这会检查入站连接是否通过 SSL/TLS 传输层建立,以及是否包含服务器名称指示(Server Name Indication, SNI)TLS 扩展。当入站连接提供 TLS SNI 字段时,返回 true。这需要 SSL 库已构建为支持 TLS 扩展(请检查 haproxy -vv)。
如果通过 SSL/TLS 传输层传入的连接上,SSL/TLS 会话已通过使用 SSL 会话缓存或 TLS 票据得到恢复,则返回 true。
ssl_fc_npn : string
此项从通过TLS传输层建立并由haproxy本地解密后的传入连接中提取“Next Protocol Negotiation”(NPN)字段。结果是一个包含客户端声明的协议名称的字符串。SSL库必须已构建为支持TLS扩展(检查haproxy -vv)。请注意,除非在“bind”行上指定了“npn”关键字(协议列表),否则不会声明TLS NPN扩展。此外,没有任何强制客户端从列表中选择协议,客户端可能会请求任何其他协议。请注意,TLS NPN扩展已被ALPN取代。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。可以使用转换器 "ssl_fc_unique_id,base64" 将唯一 ID 编码为 base64。
当传入连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回前端连接的 SERVER_HANDSHAKE_TRAFFIC_SECRET。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调函数转储以生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志必须在全局部分使用 "tune.ssl.keylog on" 激活。另请参阅 "tune.ssl.keylog"
当传入连接通过 TLS 1.3 传输层建立时,以十六进制字符串形式返回前端连接的 SERVER_TRAFFIC_SECRET_0。需要 OpenSSL >= 1.1.1。这是 OpenSSL keylog 回调函数转储以生成 SSLKEYLOGFILE 的密钥之一。SSL 密钥日志必须在全局部分使用 "tune.ssl.keylog on" 激活。另请参阅 "tune.ssl.keylog"
在连接通过 SSL/TLS 传输层建立时,返回前端连接的服务器随机数。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传入连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL ID。这对于将给定客户端粘滞到某个服务器很有用。需要注意的是,某些浏览器每隔几分钟就会刷新其会话 ID。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
ssl_fc_sni : string
此项从通过SSL/TLS传输层建立并由haproxy本地解密后的传入连接中提取“Server Name Indication”(SNI)TLS扩展字段。结果(如果存在)通常是一个匹配HTTPS主机名的字符串(最多253个字符)。SSL库必须已构建为支持TLS扩展(检查haproxy -vv)。此获取与上面的“req.ssl_sni”不同,因为它应用于haproxy正在解密的连接,而不是盲目转发的SSL内容。另请参阅下面的“ssl_fc_sni_end”和“ssl_fc_sni_reg”。这要求SSL库已构建为支持TLS扩展(检查haproxy -vv)。注意!在非常特定的条件下,通常不应将此字段用作HTTP“Host”头字段的替代。例如,当将HTTPS连接转发到服务器时,SNI字段必须使用“req.hdr(host)”从HTTP Host头字段设置,而不是从前端SNI值设置。原因是SNI仅用于选择服务器端将呈现的证书,然后客户端可以发送具有不同Host值的请求,只要它们与证书中的名称匹配即可。因此,除非后端在TCP模式下工作,“ssl_fc_sni”通常不应作为“sni”服务器关键字的参数。ACL派生:ssl_fc_sni_end:后缀匹配ssl_fc_sni_reg:正则表达式匹配
当传入连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
ssl_s_der : binary
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的 DER 格式的证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当通过SSL/TLS传输层建立出站连接时,返回服务器提供的DER格式链证书。当用于ACL时,匹配值可以以十六进制形式传递。可以使用任何接受ASN.1 DER数据的库来解析结果。目前不支持会话恢复。
ssl_s_key_alg : string
当出站连接通过 SSL/TLS 传输层建立时,返回用于生成服务器呈现的证书密钥的算法名称。
当出站连接通过 SSL/TLS 传输层建立时,以 YYMMDDhhmmss[Z] 格式的字符串返回服务器呈现的到期日期。
当出站连接通过 SSL/TLS 传输层建立时,以 YYMMDDhhmmss[Z] 格式的字符串返回服务器呈现的开始日期。
ssl_s_i_dn([<entry>[,<occ>[,<format>]]]) : string
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书颁发者的完整专有名称,如果没有指定 <entry>,或者返回从 DN 开始找到的第一个指定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 开始/结束的第 n 个指定条目的值。例如,“ssl_s_i_dn(OU,2)”返回第二个组织单元,“ssl_s_i_dn(CN)”返回通用名称。<format> 参数允许您获取适合不同协议使用的 DN 格式。目前支持 rfc2253 用于 LDAP v3。如果您只想修改格式,您可以指定一个空字符串和零作为前两个参数。示例:ssl_s_i_dn(,0,rfc2253)
ssl_s_s_dn([<entry>[,<occ>[,<format>]]]) : string
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书主体的完整专有名称,如果没有指定 <entry>,或者返回从 DN 开始找到的第一个指定条目的值。如果指定了正数/负数的出现次数作为可选的第二个参数,则返回从 DN 开始/结束的第 n 个指定条目的值。例如,“ssl_s_s_dn(OU,2)”返回第二个组织单元,“ssl_s_s_dn(CN)”返回通用名称。<format> 参数允许您获取适合不同协议使用的 DN 格式。目前支持 rfc2253 用于 LDAP v3。如果您只想修改格式,您可以指定一个空字符串和零作为前两个参数。示例:ssl_s_s_dn(,0,rfc2253)
ssl_s_serial : binary
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
ssl_s_sha1 : binary
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书的 SHA-1 指纹。这可以用来知道使用 SNI 选择的证书。
ssl_s_sig_alg : string
当出站连接通过 SSL/TLS 传输层建立时,返回用于签名服务器呈现的证书的算法名称。
ssl_s_version : integer
当出站连接通过 SSL/TLS 传输层建立时,返回服务器呈现的证书的版本。

7.3.5. 从缓冲区内容(第 6 层)获取样本

从缓冲区内容获取样本与上述的样本获取方法有些不同,因为采样的数据是短暂的。这些数据只有在可用时才能使用,并且在转发后会丢失。因此,例如,在请求期间从缓冲区内容获取的样本不能在响应中使用。即使在获取数据时,它们也可能发生变化。有时需要设置一些延迟或组合多种样本获取方法,以确保预期的数据是完整和可用的,例如通过 TCP 请求内容检查。有关该主题的更多详细信息,请参阅 "tcp-request content" 关键字。
payload(<offset>,<length>) : binary (已弃用)
这是 "req.payload" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload" 的别名。
payload_lv(<offset1>,<length>[,<offset2>]) : binary (已弃用)
这是 "req.payload_lv" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload_lv" 的别名。
req.len : integer
req_len : integer (已弃用)
返回一个整数值,对应于请求缓冲区中存在的字节数。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着在会话开始时,等于零的检查几乎总是会立即匹配,而检查更多数据的测试将等待数据进入,并且仅当 haproxy 确定不会有更多数据进入时才会返回 false。此测试旨在与 TCP 请求内容检查一起使用。
req.payload(<offset>,<length>) : binary
这会从请求缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。ACL 派生:req.payload(<offset>,<length>):十六进制二进制匹配
req.payload_lv(<offset1>,<length>[,<offset2>]) : binary
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在请求缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。ACL 派生:req.payload_lv(<offset1>,<length>[,<offset2>]):十六进制二进制匹配
示例
请参考 "stick store-response" 关键字中的示例。
req.proto_http : boolean
req_proto_http : boolean (已弃用)
当请求缓冲区中的数据看起来像 HTTP 并且能被正确解析时,返回 true。它与通用的 HTTP 请求解析器相同,因此应该不会有意外。在请求完成、失败或超时之前,此测试不会匹配。此测试可用于在 TCP 日志中报告协议,但最大的用途是阻止 TCP 请求分析,直到缓冲区中出现完整的 HTTP 请求,例如为了跟踪某个头部。
示例
# 按 "base"(Host+URL 的拼接)跟踪请求计数 tcp-request inspect-delay 10s tcp-request content reject if !HTTP tcp-request content track-sc0 base table req-rate
req.rdp_cookie([<name>]) : string
rdp_cookie([<name>]) : string (已弃用)
当请求缓冲区看起来像 RDP 协议时,提取 RDP cookie <name>,或者在未指定时提取任何 cookie。解析器仅检查第一个 cookie,如 RDP 协议规范所示。cookie 名称不区分大小写。通常使用 "MSTS" cookie 名称,因为它可能包含连接到服务器的客户端用户名(如果客户端配置正确)。"MSTSHASH" cookie 也经常用于会话粘性到服务器。这与 "balance rdp-cookie" 不同,因为可以使用任何平衡算法,因此客户端到后端服务器的分布与 RDP cookie 的哈希值无关。设想使用 "balance roundrobin" 或 "balance leastconn" 等平衡算法将导致客户端到后端服务器的分布比 "balance rdp-cookie" 的哈希值更均匀。ACL 派生:req.rdp_cookie([<name>]):精确字符串匹配
示例
listen tse-farm bind 0.0.0.0:3389 # 在请求中等待 RDP cookie 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # 应用 RDP cookie 持久性 persist rdp-cookie # 基于 mstshash cookie 进行持久化 # 仅在不使用 balance rdp-cookie 时 # 才有意义 stick-table type string size 204800 stick on req.rdp_cookie(mstshash) server srv1 1.1.1.1:3389 server srv1 1.1.1.2:3389
req.rdp_cookie_cnt([name]) : integer
rdp_cookie_cnt([name]) : integer (已弃用)
尝试将请求缓冲区解析为 RDP 协议,然后返回一个整数,表示找到的 RDP cookie 的数量。如果提供了可选的 cookie 名称,则只考虑匹配该名称的 cookie。这主要用于 ACL。ACL 派生:req.rdp_cookie_cnt([<name>]):整数匹配
req.ssl_alpn : string
返回一个字符串,其中包含客户端在SSL ClientHello消息中发送的应用层协议协商(ALPN)TLS扩展(RFC7301)的值。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“bind”行一起工作。这在ACL中很有用,可以根据TLS客户端的ALPN首选项进行路由决策,如下例所示。另请参阅“ssl_fc_alpn”。
示例
# 等待客户端 hello 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } use_backend bk_acme if { req.ssl_alpn acme-tls/1 } default_backend bk_default
req.ssl_ec_ext : boolean
返回一个布尔值,指示客户端是否在SSL ClientHello消息中发送了RFC4492中定义的“Supported Elliptic Curves Extension”(支持的椭圆曲线扩展)第5.1节。这可用于向ECC兼容客户端提供EC证书,并为其他客户端在同一IP地址上使用RSA。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“bind”行一起工作。
req_ssl_hello_type : integer (已弃用)
如果请求缓冲区中的数据可以解析为完整的SSL(v3或更高版本)客户端Hello消息,则返回包含SSL Hello消息类型的整数值。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“bind”行一起工作。这主要用于ACL中,以检测应包含可用于粘性的SSL会话ID的SSL Hello消息的存在。
req.ssl_sni : string
req_ssl_sni : string (已弃用)
如果请求缓冲区中的流包含可以解析为完整的SSL(v3或更高版本)客户端Hello消息的数据,则返回一个包含客户端在TLS流中发送的Server Name TLS扩展值的字符串。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“bind”行一起工作。这仅适用于实际的隐式TLS协议,如HTTPS(443)、IMAPS(993)、SMTPS(465),但它不适用于显式TLS协议,如SMTP(25/587)或IMAP(143)。SNI通常包含客户端尝试连接的主机名(对于较新浏览器)。SNI有助于允许或拒绝客户端使用SSL/TLS访问某些主机。此测试旨在与TCP请求内容检查一起使用。如果需要内容切换,建议先等待完整的客户端Hello(类型1),如下例所示。另请参阅“ssl_fc_sni”。ACL派生:req.ssl_sni:精确字符串匹配
示例
# 等待客户端 hello 最多 5 秒 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_st_ext : integer
如果客户端未发送SessionTicket TLS扩展(RFC5077),则返回0。如果客户端发送了SessionTicket TLS扩展,则返回1。如果客户端还发送了非零长度的TLS SessionTicket,则返回2。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“bind”行一起工作。例如,这可用于检测客户端是否发送了SessionTicket并相应地进行粘性设置,如果没有SessionTicket,则在SessionID上进行粘性设置,或者不进行粘性设置,因为在使用SessionTickets时没有服务器端状态。
req.ssl_ver : integer
req_ssl_ver : integer (已弃用)
返回一个整数值,其中包含请求缓冲区中存在的SSL/TLS协议流的版本。支持SSLv2 Hello消息和SSLv3消息。TLSv1声明为SSL版本3.1。该值由主版本乘以65536加上次版本组成。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“bind”行一起工作。ACL版本测试匹配形式为MAJOR.MINOR(例如3.1)的十进制表示。此获取主要用于ACL。ACL派生:req.ssl_ver:十进制匹配
res.len : integer
返回一个整数值,该值对应于响应缓冲区中存在的字节数。这主要用于ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回false。这意味着等于零的检查几乎总是在会话开始时立即匹配,而对更多数据的测试将等待数据传入,并且仅在haproxy确定没有更多数据传入时才返回false。此测试旨在与TCP响应内容检查一起使用。但它也可以在基于tcp-check的expect规则中使用。
res.payload(<offset>,<length>) : binary
这会从响应缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。它也可用于基于 tcp-check 的 expect 规则。
res.payload_lv(<offset1>,<length>[,<offset2>]) : binary
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在响应缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。它也可用于基于 tcp-check 的 expect 规则。
示例
请参考 "stick store-response" 关键字中的示例。
rep_ssl_hello_type : integer (已弃用)
如果响应缓冲区中的数据可以解析为完整的SSL(v3或更高版本)Hello消息,则返回包含SSL Hello消息类型的整数值。请注意,这仅适用于响应缓冲区中找到的原始内容,而不适用于通过SSL数据层解密的内容,因此这不会与具有“ssl”选项的“server”行一起工作。这主要用于ACL中,以检测应包含可用于粘性的SSL会话ID的SSL Hello消息的存在。
wait_end : boolean
此获取在检查周期结束时返回 true,否则不获取任何内容。它仅用于 ACL 中,与内容分析结合使用,以避免过早返回错误的判断。它也可用于延迟某些操作,例如对某些特殊地址进行延迟拒绝。由于它要么停止规则评估,要么立即返回 true,因此建议将此 acl 用作规则中的最后一个。请注意,默认的 ACL "WAIT_END" 始终可用,无需事先声明。此测试旨在与 TCP 请求内容检查一起使用。
示例
# 将每个传入请求延迟 2 秒 tcp-request inspect-delay 2s tcp-request content accept if WAIT_END # 不要立即告诉坏家伙他们被拒绝了 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

7.3.6. 获取 HTTP 样本 (第 7 层)

可以从 HTTP 内容、请求和响应中获取样本。这个应用层也称为第 7 层。只有当完整的 HTTP 请求或响应已从其各自的请求或响应缓冲区中解析出来时,才可能获取本节中的数据。对于所有 HTTP 特定规则和以 "mode http" 运行的部分,情况总是如此。使用 TCP 内容检查时,可能需要支持检查延迟,以便让请求或响应首先进入。这些获取可能需要比第 4 层获取更多的 CPU 资源,但由于请求和响应已被索引,所以不会多太多。
base : string
此函数返回第一个 Host 头部和请求路径部分的拼接,路径部分从第一个斜杠开始,到问号之前结束。在虚拟托管环境中,这对于检测 URL 滥用以及提高共享缓存效率很有用。将其与有限大小的粘滞表一起使用,还可以收集有关按主机/路径最常请求对象的数据。通过 ACL,它可以实现涉及主机和路径的简单内容切换规则,例如 "www.example.com/favicon.ico"。另请参阅 "path" 和 "uri"。ACL 派生词:base:精确字符串匹配 base_beg:前缀匹配 base_dir:子目录匹配 base_dom:域名匹配 base_end:后缀匹配 base_len:长度匹配 base_reg:正则表达式匹配 base_sub:子串匹配
base32 : integer
此函数返回上面 "base" 获取方法返回值的 32 位哈希值。这对于在高流量网站上跟踪每个 URL 的活动很有用,而无需存储所有 URL。相反,存储一个更短的哈希值,可以节省大量内存。输出类型是无符号整数。使用的哈希函数是 SDBM,输出具有完全雪崩效应。技术上,base32 完全等同于 "base,sdbm(1)"。
base32+src : binary
此函数返回上面 base32 获取结果和下面 src 获取结果的拼接。结果类型为 binary,大小为 8 或 20 字节,具体取决于源地址族。这可用于跟踪每个 IP、每个 URL 的计数器。
capture.req.hdr(<idx>) : string
此函数提取由 "capture request header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。
此函数提取 HTTP 请求的 METHOD。它可以在请求和响应中使用。与 "method" 不同,因为它被分配了内存,所以可以在请求和响应中使用。
capture.req.uri : string
此函数提取请求的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "req.ver" 不同,因为它依赖于一个持久性标志,所以可以在请求、响应和日志中使用。
capture.res.hdr(<idx>) : string
此函数提取由 "capture response header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。第一个条目的索引为 0。
此函数提取响应的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "res.ver" 不同,因为它依赖于一个持久性标志,所以可以在日志中使用。
req.body : binary
这会返回 HTTP 请求的可用正文作为数据块。建议使用 "option http-buffer-request" 来确保尽可能等待请求的正文。
req.body_param([<name>) : string
此获取假设 POST 请求的正文是 url-encoded 的。用户可以检查 "content-type" 是否包含值 "application/x-www-form-urlencoded"。此函数提取正文中参数 <name> 的第一次出现,该参数在 '&' 之前结束。参数名称区分大小写。如果未给出名称,则任何参数都会匹配,并返回第一个。结果是一个字符串,对应于请求正文中呈现的参数 <name> 的值(不执行 URL 解码)。请注意,此获取的 ACL 版本会遍历多个参数,如果未给出名称,则会迭代报告所有参数值。
req.body_len : integer
这会返回 HTTP 请求可用正文的长度(以字节为单位)。如果正文大于缓冲区,则其长度可能小于广告长度。建议使用 "option http-buffer-request" 来确保尽可能等待请求的正文。
req.body_size : integer
这会返回 HTTP 请求正文的广告长度(以字节为单位)。它将代表广告的 Content-Length 标头,或在分块编码情况下可用数据的大小。
req.cook([<name>]) : string
cook([<name>]) : string (已弃用)
这会从请求的“Cookie”头行中提取Cookie名称<name>的最后一个出现项,并将其值作为字符串返回。如果未指定名称,则返回第一个cookie值。当与ACL一起使用时,会评估所有匹配的cookie。根据Cookie头规范(RFC6265)的要求,忽略名称和值周围的空格。Cookie名称区分大小写。空Cookie是有效的,因此如果存在,空Cookie可能会返回空值。使用“found”匹配来检测存在。使用res.cook()变体来处理服务器发送的响应Cookie。ACL派生:req.cook([<name>]):精确字符串匹配req.cook_beg([<name>]):前缀匹配req.cook_dir([<name>]):子目录匹配req.cook_dom([<name>]):域匹配req.cook_end([<name>]):后缀匹配req.cook_len([<name>]):长度匹配req.cook_reg([<name>]):正则表达式匹配req.cook_sub([<name>]):子字符串匹配
req.cook_cnt([<name>]) : integer
cook_cnt([<name>]) : integer (已弃用)
返回一个整数值,表示名为 <name> 的 cookie 在请求中出现的次数;如果未指定 <name>,则表示所有 cookie 的数量。
req.cook_val([<name>]) : integer
cook_val([<name>]) : integer (已弃用)
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 的值。在 ACL 中使用时,将遍历所有匹配的名称,直到找到一个匹配的值。
cookie([<name>]) : string (已弃用)
从请求的“Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,或从响应的“Set-Cookie”标头中提取,并返回其值作为字符串。典型的用途是让共享相同配置文件的多个客户端使用相同的服务器。这可以与“appsession”通过“request-learn”语句所做的类似,但支持多对同步和跨重启的状态保持。如果未指定名称,则返回第一个 cookie 值。此获取不应再使用,应替换为 req.cook() 或 res.cook(),因为它根据使用它的上下文含糊地使用方向。
hdr([<name>[,<occ>]]) : string
在请求上使用时,此函数等同于 req.hdr();在响应上使用时,等同于 res.hdr()。有关更多详细信息,请参考这些各自的获取。如果不确定获取方向,请使用明确的函数。请注意,与 hdr() 样本获取方法相反,hdr_* ACL 关键字明确地应用于请求头部。
req.fhdr(<name>[,<occ>]) : string
返回 HTTP 请求中标头 <name> 的最后一次出现的完整值。它与 req.hdr() 的区别在于,它会返回值中存在的任何逗号,而不会将它们用作分隔符。这有时对 User-Agent 等标头很有用。从 ACL 使用时,会迭代所有出现直到找到匹配。可选地,可以通过位置编号指定特定的出现次数。正数表示从第一次出现开始的位置,1 是第一个。负数表示相对于最后一个的位置,-1 是最后一个。一个典型的用途是与 X-Forwarded-For 标头(在转换为 IP 后)相关联。
req.fhdr_cnt([<name>]) : integer
返回请求标头字段名称 <name> 的出现次数的整数值,如果未指定 <name>,则返回总标头字段数。与 req.fhdr() 不同,它不会在逗号处分割标头。ACL 中,它可以用于检测特定标头的存在、不存在或滥用,以及通过拒绝包含多个特定标头的请求来阻止请求伪装攻击。有关标头匹配的更多信息,请参阅 req.hdr()。
req.hdr([<name>[,<occ>]]) : string
此项返回HTTP请求中头部<name>的最后一个逗号分隔的值。此项会考虑任何逗号作为分隔符来区分不同的值。如果您需要处理定义为值列表的头部,例如Accept或X-Forwarded-For,这将非常有用。如果您需要完整的头部行,请使用req.fhdr()。请仔细检查RFC 7231,以了解某些头部应如何解析。此外,其中一些头部是不区分大小写的(例如,Connection)。从ACL使用时,会迭代所有出现的内容,直到找到匹配项。可选地,可以通过位置号指定特定的出现次数。正值表示从第一次出现开始的位置,1为第一次。负值表示相对于最后一个出现的位置,-1为最后一个。一个典型用法是与X-Forwarded-For头部(转换为IP后)相关联的IP粘性表。ACL派生:hdr([<name>[,<occ>]]):精确字符串匹配hdr_beg([<name>[,<occ>]]):前缀匹配hdr_dir([<name>[,<occ>]]):子目录匹配hdr_dom([<name>[,<occ>]]):域匹配hdr_end([<name>[,<occ>]]):后缀匹配hdr_len([<name>[,<occ>]]):长度匹配hdr_reg([<name>[,<occ>]]):正则表达式匹配hdr_sub([<name>[,<occ>]]):子字符串匹配
req.hdr_cnt([<name>]) : integer
hdr_cnt([<header>]) : integer (已弃用)
返回请求标头字段名称 <name> 的出现次数的整数值,如果未指定 <name>,则返回所有标头字段值。与 req.hdr() 一样,它计算标头值中每个逗号分隔的部分。如果需要计算完整的行标头,则应改用 req.fhdr_cnt()。使用 ACL,它可以用于检测特定标头的存在、不存在或滥用,以及通过拒绝包含多个特定标头的请求来阻止请求伪装攻击。有关更多信息,请参阅 req.hdr()。
req.hdr_ip([<name>[,<occ>]]) : ip
hdr_ip([<name>[,<occ>]]) : ip (已弃用)
提取 HTTP 请求中最后一个标头 <name> 的值,将其转换为 IPv4 或 IPv6 地址,并返回该地址。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则检查每个标头的所有值。解析器严格遵循 RFC7239 中描述的格式,并扩展支持 IPv4 地址后面可选地跟着一个冒号 (':') 和一个有效的十进制端口号(0 到 65535),该端口号将被静默删除。所有其他格式将不匹配并导致地址被忽略。<occ> 参数的处理方式与 req.hdr() 相同。典型的用法是 X-Forwarded-For 和 X-Client-IP 标头。
req.hdr_val([<name>[,<occ>]]) : integer
hdr_val([<name>[,<occ>]]) : integer (已弃用)
提取 HTTP 请求中最后一个标头 <name> 的值,并将其转换为整数值。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则检查每个标头的所有值。<occ> 参数的处理方式与 req.hdr() 相同。典型的用法是 X-Forwarded-For 标头。
req.hdrs : string
以字符串形式返回当前请求标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。
req.hdrs_bin : binary
以预解析的二进制形式返回当前请求标头。这对于使用 SPOE 进行部分处理非常有用。每个字符串由长度后面跟着长度指示的字节数描述。长度使用 SPOE 文档中详细的可变整数编码表示。列表的末尾由一对空标头名称和值(长度均为 0)标记。*(<str:header-name><str:header-value>)<empty string><empty string> int:参考 SPOE 文档的编码 str:<int:length><bytes>
http_auth(<userlist>) : boolean
返回一个布尔值,指示从客户端收到的身份验证数据是否与指定用户列表中存储的用户名和密码匹配。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。
http_auth_group(<userlist>) : string
如果从客户端收到的身份验证数据中的用户名和密码根据指定用户列表均有效,则返回一个对应于该用户名的字符串。其主要目的是在 ACL 中使用,然后检查该用户是否属于列表中的任何组。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。ACL 派生词:http_auth_group(<userlist>) : group ... 当从请求中提取的用户(其密码根据指定用户列表有效)属于至少一个组时返回 true。
返回用户在从客户端接收到的身份验证数据中找到的密码,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
返回用户在从客户端接收到的身份验证数据中找到的身份验证方法,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
返回用户在从客户端接收到的身份验证数据中找到的用户名,该数据在 Authorization 标头中提供。此样本获取不执行任何检查。仅支持 Basic 身份验证。
http_first_req : boolean
当正在处理的请求是连接的第一个请求时返回 true。这可用于添加或删除在请求不是第一个时某些请求中可能缺少的头部,或帮助在日志中对请求进行分组。
method : integer + string
返回一个对应于 HTTP 请求中方法的整数值。例如,"GET" 等于 1(检查源代码以确定匹配关系)。值 9 表示“其他方法”,并可能转换为从流中提取的字符串。这不应直接用作样本,它仅用于 ACL,ACL 会透明地将方法从模式转换为这些整数 + 字符串值。一些预定义的 ACL 已经检查了最常见的方法。ACL 派生词:method:不区分大小写的方法匹配
示例
# 只接受 GET 和 HEAD 请求 acl valid_method method GET HEAD http-request deny if ! valid_method
path : string
此项提取请求的URL路径,该路径从第一个斜杠开始,在问号之前结束(不包含主机部分)。典型用法是与预取缓存和需要从数据库聚合多个信息并将其保留在缓存中的门户网站一起使用。请注意,对于出站缓存,使用“url”会更好。对于ACL,通常用于匹配确切的文件名(例如“/login.php”)或使用派生形式的目录部分。另请参阅“url”和“base”获取方法。请注意,URI中的任何片段引用(路径后的“#”)均严格禁止HTTP标准,并将被拒绝。但是,如果接收请求的前端具有“option accept-invalid-http-request”,则将接受此片段部分,并且该片段也将出现在路径中。ACL派生:path:精确字符串匹配path_beg:前缀匹配path_dir:子目录匹配path_dom:域匹配path_end:后缀匹配path_len:长度匹配path_reg:正则表达式匹配path_sub:子字符串匹配
pathq : string
这会提取带有查询字符串的请求 URL 路径,从第一个斜杠开始。这个示例提取非常方便,总是能获取相对 URI,排除 scheme 和 authority 部分(如果存在)。事实上,虽然这是 HTTP/1.1 请求目标的常见表示,但在 HTTP/2 中,通常使用绝对 URI。这个示例提取在两种情况下都会返回相同的结果。请注意,URI 中的任何片段引用(路径后的“#”)严格禁止由 HTTP 标准,并将被拒绝。但是,如果接收请求的前端具有“option accept-invalid-http-request”选项,则该片段部分将被接受,并也会出现在路径中。
query : string
此函数提取请求的查询字符串,它从第一个问号之后开始。如果没有问号,此获取不返回任何内容。如果存在问号但后面没有任何内容,则返回一个空字符串。这意味着可以使用 "found" 匹配方法轻松地知道是否存在查询字符串。此获取是 "path" 的补充,后者在问号之前停止。
req.hdr_names([<delim>]) : string
此函数构建一个字符串,该字符串由规则评估时请求中出现的所有头部名称拼接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。
req.ver : string
req_ver : string (已弃用)
返回 HTTP 请求的版本字符串,例如“1.1”。这对于日志很有用,但主要用于 ACL。一些预定义的 ACL 已经检查版本 1.0 和 1.1。ACL 派生:req.ver:精确字符串匹配
res.body : binary
这会返回 HTTP 响应的可用正文作为数据块。与请求端不同,没有指令可以等待响应的正文。此样本获取在健康检查上下文中非常有用(且可用)。它可用于基于 tcp-check 的 expect 规则。
res.body_len : integer
这会返回 HTTP 响应可用正文的长度(以字节为单位)。与请求端不同,没有指令可以等待响应的正文。此样本获取在健康检查上下文中非常有用(且可用)。它可用于基于 tcp-check 的 expect 规则。
res.body_size : integer
这会返回 HTTP 响应正文的广告长度(以字节为单位)。它将代表广告的 Content-Length 标头,或在分块编码情况下可用数据的大小。与请求端不同,没有指令可以等待响应正文。此样本获取在健康检查上下文中非常有用(且可用)。它可用于基于 tcp-check 的 expect 规则。
res.comp : boolean
如果响应已被 HAProxy 压缩,则返回布尔值 "true",否则返回布尔值 "false"。这可用于在日志中添加信息。
res.comp_algo : string
如果响应被 HAProxy 压缩,则返回一个包含所用算法名称的字符串,例如:“deflate”。这可用于在日志中添加一些信息。
res.cook([<name>]) : string
scook([<name>]) : string (已弃用)
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并返回其值。如果未指定名称,则返回第一个 cookie 值。它可用于基于 tcp-check 的 expect 规则。ACL 派生:res.scook([<name>]:精确字符串匹配
res.cook_cnt([<name>]) : integer
scook_cnt([<name>]) : integer (已弃用)
返回响应中 cookie <name> 的出现次数的整数值,如果未指定 <name>,则返回所有 cookie。这在与 ACL 结合以检测可疑响应时非常有用。它可用于基于 tcp-check 的 expect 规则。
res.cook_val([<name>]) : integer
scook_val([<name>]) : integer (已弃用)
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 值。它可用于基于 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
shdr([<name>[,<occ>]]) : string (已弃用)
此项获取方式与req.hdr()获取方式相同,但它作用于HTTP响应内的头部。与req.hdr()一样,res.hdr()获取方式将逗号视为分隔符。如果不需要,应使用res.fhdr()。它可以用于基于tcp-check的expect规则。ACL派生:res.hdr([<name>[,<occ>]]):精确字符串匹配res.hdr_beg([<name>[,<occ>]]):前缀匹配res.hdr_dir([<name>[,<occ>]]):子目录匹配res.hdr_dom([<name>[,<occ>]]):域匹配res.hdr_end([<name>[,<occ>]]):后缀匹配res.hdr_len([<name>[,<occ>]]):长度匹配res.hdr_reg([<name>[,<occ>]]):正则表达式匹配res.hdr_sub([<name>[,<occ>]]):子字符串匹配
res.hdr_cnt([<name>]) : integer
shdr_cnt([<name>]) : integer (已弃用)
此项获取方式与req.hdr_cnt()获取方式相同,但它作用于HTTP响应内的头部。与req.hdr_cnt()一样,res.hdr_cnt()获取方式将逗号视为分隔符。如果不需要,应使用res.fhdr_cnt()。它可以用于基于tcp-check的expect规则。
res.hdr_ip([<name>[,<occ>]]) : ip
shdr_ip([<name>[,<occ>]]) : ip (已弃用)
此获取器的工作方式类似于 req.hdr_ip() 获取器,区别在于它作用于 HTTP 响应中的标头。这有助于将某些数据学习到粘滞表中。它可用于基于 tcp-check 的 expect 规则。
res.hdr_names([<delim>]) : string
在规则求值时,此函数会创建一个字符串,该字符串由响应中出现的名称相同的标头连接而成。默认分隔符是逗号 (','),但可以作为可选参数 <delim> 覆盖。在这种情况下,只考虑 <delim> 的第一个字符。它可用于基于 tcp-check 的 expect 规则。
res.hdr_val([<name>[,<occ>]]) : integer
shdr_val([<name>[,<occ>]]) : integer (已弃用)
此获取器的工作方式类似于 req.hdr_val() 获取器,区别在于它作用于 HTTP 响应中的标头。这有助于将某些数据学习到粘滞表中。它可用于基于 tcp-check 的 expect 规则。
res.hdrs : string
以字符串形式返回当前响应标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。它也可用于基于 tcp-check 的 expect 规则。
res.hdrs_bin : binary
以预解析的二进制形式返回当前响应标头。这对于使用 SPOE 进行部分处理非常有用。它可用于基于 tcp-check 的 expect 规则。每个字符串由长度后面跟着长度指示的字节数描述。长度使用 SPOE 文档中详细的可变整数编码表示。列表的末尾由一对空标头名称和值(长度均为 0)标记。*(<str:header-name><str:header-value>)<empty string><empty string> int:参考 SPOE 文档的编码 str:<int:length><bytes>
res.ver : string
resp_ver : string (已弃用)
返回 HTTP 响应中的版本字符串,例如“1.1”。这在日志中很有用,但主要用于 ACL。它可用于基于 tcp-check 的 expect 规则。ACL 派生:resp.ver:精确字符串匹配
set-cookie([<name>]) : string (已弃用)
从响应的“Set-Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,并使用相应的值进行匹配。这可以与“appsession”的默认选项所做的相媲美,但支持多对同步和跨重启的状态保持。此获取函数已弃用,已被“res.cook”获取器取代。此关键字很快就会消失。
status : integer
返回 HTTP 响应中的 HTTP 状态码的整数值,例如 302。它主要用于 ACL 和整数范围,例如,如果响应不是 3xx,则删除任何 Location 标头。它可以在基于 tcp-check 的 expect 规则中使用。
unique-id : string
返回附加到请求的唯一 ID。必须设置“unique-id-format”指令。如果未设置,则 unique-id 样本获取将失败。请注意,unique-id 通常与 HTTP 请求一起使用,但是此样本获取也可以与其他协议一起使用。显然,如果它与 HTTP 以外的协议一起使用,unique-id-format 指令不应包含 HTTP 部分。另请参阅:unique-id-format 和 unique-id-header
url : string
此项提取请求中显示的URL。典型用法是与预取缓存和需要从数据库聚合多个信息并将其保留在缓存中的门户网站一起使用。对于ACL,使用“path”优于使用“url”,因为客户端可能会发送完整的URL,就像通常对代理所做的那样。唯一真正的用途是匹配“*”,它在“path”中不匹配,并且已经有一个预定义的ACL。另请参阅“path”和“base”。请注意,URI中的任何片段引用(路径后的“#”)均严格禁止HTTP标准,并将被拒绝。但是,如果接收请求的前端具有“option accept-invalid-http-request”,则将接受此片段部分,并且该片段也将出现在URL中。ACL派生:url:精确字符串匹配url_beg:前缀匹配url_dir:子目录匹配url_dom:域匹配url_end:后缀匹配url_len:长度匹配url_reg:正则表达式匹配url_sub:子字符串匹配
url_ip : ip
当主机部分以 IP 地址形式呈现时,此函数从请求的 URL 中提取 IP 地址。其用途非常有限。例如,监控系统可能会使用此字段作为源 IP 的替代方案,以测试给定源地址将遵循的路径,或为给定源地址在表中强制创建一个条目。对于 ACL,它可以用于限制通过代理访问某些系统,例如与选项 "http_proxy" 结合使用时。
url_port : integer
此函数从请求的 URL 中提取端口部分。请注意,如果请求中未指定端口,则假定为端口 80。对于 ACL,它可以用于限制通过代理访问某些系统,例如与选项 "http_proxy" 结合使用时。
urlp([<name>[,<delim>]]) : string
url_param([<name>[,<delim>]]) : string
此项提取查询字符串中参数<name>的第一个出现,它开始于“?”或<delim>之后,并以“&”、“;”或<delim>之前结束。参数名区分大小写。如果未给出名称,则任何参数都会匹配,并返回第一个参数。结果是请求中出现的参数<name>的值字符串(不执行URL解码)。这可用于基于客户端ID的会话粘性,提取作为URL参数传递的应用程序cookie,或在ACL中应用某些检查。请注意,此项的ACL版本会迭代多个参数,并且在未给出名称时会迭代所有参数值。ACL派生:urlp(<name>[,<delim>]):精确字符串匹配urlp_beg(<name>[,<delim>]):前缀匹配urlp_dir(<name>[,<delim>]):子目录匹配urlp_dom(<name>[,<delim>]):域匹配urlp_end(<name>[,<delim>]):后缀匹配urlp_len(<name>[,<delim>]):长度匹配urlp_reg(<name>[,<delim>]):正则表达式匹配urlp_sub(<name>[,<delim>]):子字符串匹配
示例
# 匹配 http://example.com/foo?PHPSESSIONID=some_id stick on urlp(PHPSESSIONID) # 匹配 http://example.com/foo;JSESSIONID=some_id stick on urlp(JSESSIONID,;)
urlp_val([<name>[,<delim>]]) : integer
参见上面的 "urlp"。此函数提取请求中的 URL 参数 <name> 并将其转换为整数值。例如,这可用于基于用户 ID 的会话粘性,或与 ACL 一起匹配页码或价格。
url32 : integer
此函数返回一个 32 位哈希值,该值由连接第一个 Host 标头和整个 URL(包括参数,而不仅仅是请求的路径部分,如上面的 "base32" 提取)得到。这对于跟踪每个 URL 的活动很有用。存储一个较短的哈希值可以节省大量内存。输出类型是无符号整数。
url32+src : binary
此函数返回 "url32" 提取和 "src" 提取的连接结果。结果类型为 binary,大小为 8 或 20 字节,具体取决于源地址族。这可用于跟踪每个 IP、每个 URL 的计数器。

7.3.7. 为开发人员提取样本

这组样本获取方法是为开发人员保留的,除了开发人员要求出于调试目的外,绝不能在生产环境中使用。此外,不会特别注意向后兼容性。不保证以下样本获取永远不会改变、重命名或简单地删除。因此,如果您使用其中一个,请务必小心。为避免任何歧义,这些样本获取被放置在专用的 "internal" 作用域中,例如 "internal.strm.is_htx"。
返回与通道关联的HTX消息中数据使用的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中的可用空间(大小-已用)的字节数。通道的选择取决于样本方向。
返回与通道关联的HTX消息中数据使用的可用空间的字节数。通道的选择取决于样本方向。
如果与通道关联的HTX消息包含消息结束块(EOM),则返回true。否则,返回false。通道的选择取决于样本方向。
返回与通道关联的HTX消息中存在的块的数量。通道的选择取决于样本方向。
返回与通道关联的HTX消息的总字节大小。通道的选择取决于样本方向。
返回与通道关联的HTX消息中使用的总大小(数据+元数据)的字节数。通道的选择取决于样本方向。
internal.htx_blk.size(<idx>) : integer
返回与通道关联的HTX消息中位置<idx>处的块的大小,如果不存在则返回0。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.type(<idx>) : string
返回与通道关联的HTX消息中位置<idx>处的块的类型,如果不存在则返回“HTX_BLK_UNUSED”。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.data(<idx>) : binary
返回与通道关联的HTX消息中位置<idx>处的DATA块的值,如果不存在或不是DATA块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.hdrname(<idx>) : string
返回与通道关联的HTX消息中位置<idx>处的HEADER块的头部名称,如果不存在或不是HEADER块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
internal.htx_blk.hdrval(<idx>) : string
返回与通道关联的HTX消息中位置<idx>处的HEADER块的头部值,如果不存在或不是HEADER块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
返回与通道关联的HTX消息中位置<idx>处的REQ_SL或RES_SL块的值,如果不存在或不是SL块,则返回空字符串。通道的选择取决于样本方向。<idx>可以是任何正整数或以下特殊值之一:* head:最先插入的块* tail:最新插入的块* first:进行(重新)分析的第一个块
如果当前流是HTX流,则返回true。这意味着通道缓冲区中的数据使用内部HTX表示法存储。否则,返回false。

7.4. 预定义的 ACL

一些预定义的 ACL 是硬编码的,因此不必在每个需要它们的前端中声明。它们的名称都使用大写字母,以避免混淆。下面提供了它们的等效项。
ACL 名称等同于Usage
FALSEalways_false从不匹配
HTTPreq.proto_http匹配如果协议是有效的HTTP
HTTP_1.0req.ver 1.0匹配如果HTTP请求版本是1.0
HTTP_1.1req.ver 1.1匹配如果HTTP请求版本是1.1
HTTP_CONTENTreq.hdr_val(content-length) gt 0匹配HTTP请求中存在的content-length
HTTP_URL_ABSurl_reg ^[^/:]*://匹配带协议方案的绝对 URL
HTTP_URL_SLASHurl_beg /匹配以 "/" 开头的 URL
HTTP_URL_STARurl *匹配等于 "*" 的 URL
LOCALHOSTsrc 127.0.0.1/8匹配来自本地主机的连接
METH_CONNECTmethod CONNECT匹配 HTTP CONNECT 方法
METH_DELETEmethod DELETE匹配HTTP DELETE方法
METH_GETmethod GET HEAD匹配 HTTP GET 或 HEAD 方法
METH_HEADmethod HEAD匹配 HTTP HEAD 方法
METH_OPTIONSmethod OPTIONS匹配 HTTP OPTIONS 方法
METH_POSTmethod POST匹配 HTTP POST 方法
METH_PUTmethod PUT匹配HTTP PUT方法
METH_TRACEmethod TRACE匹配 HTTP TRACE 方法
RDP_COOKIEreq.rdp_cookie_cnt gt 0匹配请求缓冲区中是否存在RDP cookie
REQ_CONTENTreq.len gt 0匹配请求缓冲区中的数据
TRUEalways_true总是匹配
WAIT_ENDwait_end等待内容分析结束
HAProxy的强大之处之一无疑是其精确的日志记录。它可能提供了此类产品中可用的最高级别的信息,这对于对复杂环境进行故障排除非常重要。日志中提供的标准信息包括客户端端口、TCP/HTTP状态计时器、精确的会话终止状态和精确的终止原因、有关将流量定向到服务器的决策信息,当然还有捕获任意头部的能力。为了提高管理员的响应能力,它提供了对遇到的内部和外部问题的极大透明度,并且可以同时将日志发送到具有不同级别过滤器但源不同的位置:-全局进程级别日志(系统错误、启动/停止等)-每个实例的系统和内部错误(资源不足、错误等)-每个实例的外部问题(服务器正常/下线、最大连接数)-每个实例的活动(客户端连接),在建立或终止时。-每个请求的日志级别控制,例如,http-request set-log-level silent if sensitive_request将不同级别的日志分发到不同的日志服务器允许多个生产团队互动并尽快修复他们的问题。例如,系统团队可能会监控系统范围内的错误,而应用程序团队可能会实时监控其服务器的正常/下线状态,安全团队可能会延迟一小时分析活动日志。

8.1. 日志级别

TCP和HTTP连接可以记录诸如日期、时间、源IP地址、目标地址、连接持续时间、响应时间、HTTP请求、HTTP返回码、传输的字节数、会话结束的条件,甚至交换的cookie值等信息。例如,跟踪特定用户的问题。所有消息最多可以发送到两个syslog服务器。有关日志设施的更多信息,请参见第4.2节中的“log”关键字。

8.2. 日志格式

HAProxy支持5种日志格式。这些格式之间有几个字段是通用的,将在以下部分进行详细说明。由于某些选项的特定指示符,其中一些字段可能会根据配置略有不同。支持的格式如下:-默认格式,非常基础且很少使用。它仅在接受传入连接时提供非常基本的信息:源IP:端口、目标IP:端口和前端名称。此模式最终将消失,因此不会详细描述。-TCP格式,更高级。当在前端设置“option tcplog”时,此格式将被启用。HAProxy通常会等待连接终止后再进行日志记录。此格式提供更丰富的信息,如计时器、连接计数、队列大小等。此格式推荐用于纯TCP代理。-HTTP格式,是HTTP代理最先进的格式。当在前端设置“option httplog”时,此格式将被启用。它提供与TCP格式相同的信息,但包含一些HTTP特定字段,如请求、状态码以及头部和cookie的捕获。此格式推荐用于HTTP代理。-CLF HTTP格式,等同于HTTP格式,但字段的顺序与CLF格式相同。在此模式下,所有计时器、捕获、标志等都出现在公共字段末尾的每个字段中,顺序与标准HTTP格式相同。-自定义日志格式,允许您创建自己的日志行。下一节将更详细地介绍每种格式。格式规范将在“字段”的基础上进行。除非另有说明,字段是文本片段,由任意数量的空格分隔。由于syslog服务器可能会在行开头插入字段,因此始终假定第一个字段包含进程名和标识符。注意:由于日志行可能相当长,下面各节中的日志示例可能会分成多行。示例日志行将以3个右尖括号(“>>>”)作为前缀,每次日志被分成多行时,每个非最后一行将以反斜杠(“\”)结尾,下一行将从两个字符的缩进开始。

8.2.1. 默认日志格式

当没有设置特定选项时,使用此格式。日志在连接被接受后立即发出。需要注意的是,这目前是唯一记录请求目标 IP 和端口的格式。
示例
listen www mode http log global server srv1 127.0.0.1:8000 >>> Feb 6 12:12:09 localhost \ haproxy[14385]: Connect from 10.0.1.2:33312 to 10.0.3.31:8012 \ (www/HTTP)
字段格式从上面的示例中提取1 process_name '[' pid ']:' haproxy[14385]: 2 'Connect from' Connect from 3 source_ip ':' source_port 10.0.1.2:33312 4 'to' to 5 destination_ip ':' destination_port 10.0.3.31:8012 6 '(' frontend_name '/' mode ')' (www/HTTP) 详细字段描述:-“source_ip”是发起连接的客户端的IP地址。-“source_port”是发起连接的客户端的TCP端口。-“destination_ip”是客户端连接到的IP地址。-“destination_port”是客户端连接到的TCP端口。-“frontend_name”是接收和处理该连接的前端(或监听器)的名称。-“mode”是前端运行的模式(TCP或HTTP)。对于UNIX套接字,源和目标地址标记为“unix:”,端口反映接受连接的套接字的内部ID(与统计信息中报告的ID相同)。建议不要在新安装中使用此已弃用的格式,因为它最终将消失。

8.2.2. TCP 日志格式

当在前端指定“option tcplog”时,将使用TCP格式,并且是纯TCP代理推荐的格式。它提供了大量宝贵的信息用于故障排除。由于此格式包含计时器和字节计数,因此日志通常在会话结束时发出。如果指定了“option logasap”,则可以更早地发出日志,这在大多数具有长会话的环境(如远程终端)中有意义。匹配“monitor”规则的会话永远不会被记录。通过在前端指定“option dontlognull”来不记录客户端和服务器之间未交换任何数据的会话也是可能的。如果前端指定了“option dontlog-normal”,则不会记录成功连接。根据某些配置选项,一些字段可能会略有不同,这些字段在下面的字段名称后用星号(“*”)标记。
示例
frontend fnt mode tcp option tcplog log global default_backend bck backend bck server srv1 127.0.0.1:8000 >>> Feb 6 12:12:56 localhost \ haproxy[14387]: 10.0.1.2:33313 [06/Feb/2009:12:12:51.443] fnt \ bck/srv1 0/0/5007 212 -- 0/0/0/0/3 0/0
字段格式 示例中的提取 1 process_name '[' pid ']:' haproxy[14387]: 2 client_ip ':' client_port 10.0.1.2:33313 3 '[' accept_date ']' [06/Feb/2009:12:12:51.443] 4 frontend_name fnt 5 backend_name '/' server_name bck/srv1 6 Tw '/' Tc '/' Tt* 0/0/5007 7 bytes_read* 212 8 termination_state -- 9 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 0/0/0/0/3 10 srv_queue '/' backend_queue 0/0 详细字段描述: - "client_ip" 是发起 TCP 连接到 haproxy 的客户端的 IP 地址。如果连接是在 UNIX 套接字上接受的,则 IP 地址将被“unix”一词替换。请注意,当连接在配置了 "accept-proxy" 并正确使用了 PROXY 协议的套接字上接受,或者配置了 "accept-netscaler-cip" 并正确使用了 NetScaler 客户端 IP 插入协议的套接字上接受时,日志将反映转发连接的信息。 - "client_port" 是发起连接的客户端的 TCP 端口。如果连接是在 UNIX 套接字上接受的,则端口将被接受套接字 ID 替换,该 ID 也在统计界面中报告。 - "accept_date" 是 haproxy 收到连接的确切日期(如果在系统积压中存在某些排队,这可能与网络上观察到的日期略有不同)。这通常是任何上游防火墙日志中可能出现的相同日期。在 HTTP 模式下使用时,accept_date 字段将被重置为连接可以接收新请求的第一个时刻(HTTP/1 中前一个响应的结束,HTTP/2 中前一个请求之后立即)。 - "frontend_name" 是接收并处理连接的前端(或监听器)的名称。 - "backend_name" 是被选定用于管理与服务器连接的后端(或监听器)的名称。如果未应用任何切换规则,这将与前端相同,这在 TCP 应用程序中很常见。 - "server_name" 是发送连接的最后一个服务器的名称,如果发生连接错误并进行了重定向,则该名称可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果连接在到达服务器之前被中止,则会指示 "< <NOSRV> >" 而不是服务器名称。 - "Tw" 是在各种队列中等待的总毫秒数。如果连接在到达队列之前被中止,则可能为 "-1"。有关更多详细信息,请参见下面的“计时器”。 - "Tc" 是等待与最终服务器建立连接的总毫秒数,包括重试。如果连接在建立连接之前被中止,则可能为 "-1”。有关更多详细信息,请参见下面的“计时器”。 - "Tt" 是从接受到最后关闭之间经过的总毫秒数。它涵盖了所有可能的处理。有一个例外,如果指定了 "option logasap",则时间计数将在日志发出时停止。在这种情况下,值前面会加上一个 '+' 符号,表示最终值会更大。有关更多详细信息,请参见下面的“计时器”。 - "bytes_read" 是在发出日志时从服务器传输到客户端的总字节数。如果指定了 "option logasap",则此值将以 '+' 符号为前缀,表示最终值可能更大。请注意,此值是 64 位计数器,因此日志分析工具必须能够处理它而不会溢出。 - "termination_state" 是会话结束时会话所处的状态。这表明了会话状态、导致会话结束的一方以及原因(超时、错误等)。正常的标志应该是 "--",表示会话由任一方关闭,缓冲区中没有剩余数据。有关更多详细信息,请参见下面的“断开连接时的会话状态”。 - "actconn" 是记录会话时进程中的并发连接总数。这有助于检测是否已达到某些每个进程的系统限制。例如,如果 actconn 在发生多个连接错误时接近 512,则很高几率是系统将进程限制为最多使用 1024 个文件描述符,并且所有这些描述符都已用完。有关如何调整系统的更多信息,请参见 第 3 节“全局参数”。 - "feconn" 是记录会话时前端中的并发连接总数。这有助于估算维持高负载所需的资源量,并检测前端的 "maxconn" 是否已达到。大多数时候,当此值急剧增加时,是因为后端服务器上的拥塞,但有时也可能由拒绝服务攻击引起。 - "beconn" 是记录会话时后端处理的并发连接总数。它包括服务器上活动的并发连接总数以及队列中等待的连接数。这有助于估算支持给定应用程序的高负载所需的额外服务器数量。大多数时候,当此值急剧增加时,是因为后端服务器上的拥塞,但有时也可能由拒绝服务攻击引起。 - "srv_conn" 是记录会话时服务器上仍活动的并发连接总数。它永远不会超过服务器配置的 "maxconn" 参数。如果此值经常接近或等于服务器的 "maxconn",则表示流量调节涉及很多,意味着服务器的 maxconn 值太低,或者没有足够的服务器以最佳响应时间处理负载。当只有服务器的 "srv_conn" 中的一个很高时,通常意味着该服务器存在一些问题,导致连接比其他服务器花费更长的时间来处理。 - "retries" 是此会话在尝试连接到服务器时遇到的连接重试次数。通常应为零,除非服务器在尝试连接的同一时刻被停止。频繁重试通常表明 haproxy 与服务器之间存在网络问题,或者服务器上的系统积压配置错误,阻止了新连接入队。此字段可以选择性地以 '+' 符号为前缀,表示会话在达到初始服务器的最大重试次数后已经历重定向。在这种情况下,日志中出现的服务器名称是连接被重定向到的服务器,而不是第一个服务器,尽管两者在哈希等情况下可能有时相同。因此,经验法则是,当重试计数前面有一个 '+' 时,此计数不应归因于记录的服务器。 - "srv_queue" 是服务器队列中此请求之前的已处理请求总数。当请求未通过服务器队列时为零。通过将花在队列上的时间除以队列中的请求数,可以估算近似服务器响应时间。值得注意的是,如果一个会话经历重定向并在两个服务器队列之间传递,它们的顺序将是累积的。除非发生重定向,否则请求不应同时通过服务器队列和后端队列。 - "backend_queue" 是后端全局队列中此请求之前的已处理请求总数。当请求未通过全局队列时为零。通过将平均队列长度除以服务器的 "maxconn" 参数,可以估算平均队列长度,这很容易转化为缺少的服务器数量。值得注意的是,如果一个会话经历重定向,它可能通过后端队列两次,然后两个顺序都将是累积的。除非发生重定向,否则请求不应同时通过服务器队列和后端队列。

8.2.3. HTTP 日志格式

HTTP 格式是最完整的,也是最适合 HTTP 代理的。它通过在前端指定 "option httplog" 来启用。它提供了与 TCP 格式相同的信息级别,并增加了特定于 HTTP 协议的功能。与 TCP 格式一样,日志通常在会话结束时发出,除非指定了 "option logasap",这通常只对下载站点有意义。匹配 "monitor" 规则的会话永远不会被记录。通过在前端指定 "option dontlognull" 也可以不记录客户端未发送任何数据的会话。如果前端指定了 "option dontlog-normal",则不会记录成功的连接。大多数字段与 TCP 日志共享,有些字段不同。少数字段可能因某些配置选项而略有不同。这些字段在下面的字段名称后标有星号 ('*')。
示例
frontend http-in mode http option httplog log global default_backend bck backend static server srv1 127.0.0.1:8000 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \ {} "GET /index.html HTTP/1.1"
字段格式 示例中的提取 1 process_name '[' pid ']:' haproxy[14389]: 2 client_ip ':' client_port 10.0.1.2:33317 3 '[' request_date ']' [06/Feb/2009:12:14:14.655] 4 frontend_name http-in 5 backend_name '/' server_name static/srv1 6 TR '/' Tw '/' Tc '/' Tr '/' Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state ---- 12 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 1/1/1/1/0 13 srv_queue '/' backend_queue 0/0 14 '{' captured_request_headers* '}' {haproxy.1wt.eu} 15 '{' captured_response_headers* '}' {} 16 '"' http_request '"' "GET /index.html HTTP/1.1" 详细字段描述: - "client_ip" 是发起 TCP 连接到 haproxy 的客户端的 IP 地址。如果连接是在 UNIX 套接字上接受的,则 IP 地址将被“unix”一词替换。请注意,当连接在配置了 "accept-proxy" 并正确使用了 PROXY 协议的套接字上接受,或者配置了 "accept-netscaler-cip" 并正确使用了 NetScaler 客户端 IP 插入协议的套接字上接受时,日志将反映转发连接的信息。 - "client_port" 是发起连接的客户端的 TCP 端口。如果连接是在 UNIX 套接字上接受的,则端口将被接受套接字 ID 替换,该 ID 也在统计界面中报告。 - "request_date" 是 haproxy 收到 HTTP 请求的第一个字节的确切日期(日志字段 %tr)。 - "frontend_name" 是接收并处理连接的前端(或监听器)的名称。 - "backend_name" 是被选定用于管理与服务器连接的后端(或监听器)的名称。如果未应用任何切换规则,这将与前端相同。 - "server_name" 是发送连接的最后一个服务器的名称,如果发生连接错误并进行了重定向,则该名称可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果请求在到达服务器之前被中止,则会指示 "< <NOSRV> >" 而不是服务器名称。如果请求被统计子系统拦截,则会指示 "< <STATS> >"。 - "TR" 是在收到第一个字节后,等待从客户端接收完整 HTTP 请求(不包括正文)的总毫秒数。如果请求在收到完整请求之前被中止或收到错误请求,则可能为 "-1"。它通常应该非常小,因为请求通常包含在一个数据包中。这里的长耗时通常表明客户端与 haproxy 之间的网络问题或手动输入请求。有关更多详细信息,请参见 第 8.4 节“计时事件”。 - "Tw" 是在各种队列中等待的总毫秒数。如果连接在到达队列之前被中止,则可能为 "-1”。有关更多详细信息,请参见 第 8.4 节“计时事件”。 - "Tc" 是等待与最终服务器建立连接的总毫秒数,包括重试。如果请求在建立连接之前被中止,则可能为 "-1”。有关更多详细信息,请参见第 8.4 节“计时事件”。 - "Tr" 是等待服务器发送完整 HTTP 响应(不包括数据)的总毫秒数。如果请求在收到完整响应之前被中止,则可能为 "-1”。它通常与服务器处理请求的时间匹配,但可能会因客户端发送到服务器的数据量而改变。对于 "GET" 请求,这里的长耗时通常表明服务器过载。有关更多详细信息,请参见 第 8.4 节“计时事件”。 - "Ta" 是请求在 haproxy 中保持活动的总毫秒数,即从收到请求的第一个字节到发送响应的最后一个字节所经过的总时间。它涵盖了除握手(参见 Th)和空闲时间(参见 Ti)之外的所有可能处理。有一个例外,如果指定了 "option logasap",则时间计数将在日志发出时停止。在这种情况下,值前面会加上一个 '+' 符号,表示最终值会更大。有关更多详细信息,请参见 第 8.4 节“计时事件”。 - "status_code" 是返回给客户端的 HTTP 状态码。此状态通常由服务器设置,但当服务器无法访问或其响应被 haproxy 阻止时,也可能由 haproxy 设置。 - "bytes_read" 是在发出日志时传输到客户端的总字节数。这包括 HTTP 标头。如果指定了 "option logasap",则此值将以 '+' 符号为前缀,表示最终值可能更大。请注意,此值是 64 位计数器,因此日志分析工具必须能够处理它而不会溢出。 - "captured_request_cookie" 是一个可选的 "name=value" 条目,表示客户端在请求中包含此 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。当未设置该选项时,该字段为单个破折号 ('-')。最多只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "captured_response_cookie" 是一个可选的 "name=value" 条目,表示服务器在响应中返回了一个 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。当未设置该选项时,该字段为单个破折号 ('-')。最多只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "termination_state" 是会话结束时会话所处的状态。这表明了会话状态、导致会话结束的一方以及原因(超时、错误等),就像在 TCP 日志中一样,并且最后两个字符包含有关 cookie 上持久化操作的信息。正常标志应以 "--" 开头,表示会话由任一方关闭,缓冲区中没有剩余数据。有关更多详细信息,请参见下面的“断开连接时的会话状态”。 - "actconn" 是记录会话时进程中的并发连接总数。这有助于检测是否已达到某些每个进程的系统限制。例如,如果 actconn 在发生多个连接错误时接近 512 或 1024,则很高几率是系统将进程限制为最多使用 1024 个文件描述符,并且所有这些描述符都已用完。有关如何调整系统的更多信息,请参见 第 3 节“全局参数”。 - "feconn" 是记录会话时前端中的并发连接总数。这有助于估算维持高负载所需的资源量,并检测前端的 "maxconn" 是否已达到。大多数时候,当此值急剧增加时,是因为后端服务器上的拥塞,但有时也可能由拒绝服务攻击引起。 - "beconn" 是记录会话时后端处理的并发连接总数。它包括服务器上活动的并发连接总数以及队列中等待的连接数。这有助于估算支持给定应用程序的高负载所需的额外服务器数量。大多数时候,当此值急剧增加时,是因为后端服务器上的拥塞,但有时也可能由拒绝服务攻击引起。 - "srv_conn" 是记录会话时服务器上仍活动的并发连接总数。它永远不会超过服务器配置的 "maxconn" 参数。如果此值经常接近或等于服务器的 "maxconn",则表示流量调节涉及很多,意味着服务器的 maxconn 值太低,或者没有足够的服务器以最佳响应时间处理负载。当只有服务器的 "srv_conn" 中的一个很高时,通常意味着该服务器存在一些问题,导致请求比其他服务器花费更长的时间来处理。 - "retries" 是此会话在尝试连接到服务器时遇到的连接重试次数。通常应为零,除非服务器在尝试连接的同一时刻被停止。频繁重试通常表明 haproxy 与服务器之间存在网络问题,或者服务器上的系统积压配置错误,阻止了新连接入队。此字段可以选择性地以 '+' 符号为前缀,表示会话在达到初始服务器的最大重试次数后已经历重定向。在这种情况下,日志中出现的服务器名称是连接被重定向到的服务器,而不是第一个服务器,尽管两者在哈希等情况下可能有时相同。因此,经验法则是,当重试计数前面有一个 '+' 时,此计数不应归因于记录的服务器。 - "srv_queue" 是服务器队列中此请求之前的已处理请求总数。当请求未通过服务器队列时为零。通过将花在队列上的时间除以队列中的请求数,可以估算近似服务器响应时间。值得注意的是,如果一个会话经历重定向并在两个服务器队列之间传递,它们的顺序将是累积的。除非发生重定向,否则请求不应同时通过服务器队列和后端队列。 - "backend_queue" 是后端全局队列中此请求之前的已处理请求总数。当请求未通过全局队列时为零。通过将平均队列长度除以服务器的 "maxconn" 参数,可以估算平均队列长度,这很容易转化为缺少的服务器数量。值得注意的是,如果一个会话经历重定向,它可能通过后端队列两次,然后两个顺序都将是累积的。除非发生重定向,否则请求不应同时通过服务器队列和后端队列。 - "captured_request_headers" 是由于前端存在 "capture request header" 语句而捕获的请求头列表。可以捕获多个标头,它们将用竖线 ('|') 分隔。当未启用捕获时,大括号不会出现,导致其余字段发生偏移。需要注意的是,此字段可能包含空格,并且使用它需要比不使用它时更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "captured_response_headers" 是由于前端存在 "capture response header" 语句而捕获的响应头列表。可以捕获多个标头,它们将用竖线 ('|') 分隔。当未启用捕获时,大括号不会出现,导致其余字段发生偏移。需要注意的是,此字段可能包含空格,并且使用它需要比不使用它时更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "http_request" 是完整的 HTTP 请求行,包括方法、请求和 HTTP 版本字符串。不可打印字符会进行编码(参见下面的“不可打印字符”部分)。这始终是最后一个字段,并且始终由引号分隔,是唯一可以包含引号的字段。如果向日志格式添加了新字段,它们将在此字段之前添加。如果请求非常大且不适合标准 syslog 缓冲区(1024 个字符),则此字段可能会被截断。这就是为什么此字段必须始终保持最后一个的原因。

8.2.4. 自定义日志格式

log-format 指令允许您在 http 模式和 tcp 模式下自定义日志。它接受一个字符串作为参数。HAProxy 理解一些日志格式变量。% 符号后面是日志格式变量。变量可以使用大括号 ('{}') 来接受参数,多个参数在括号内用逗号分隔。可以通过在标志前面加上 '+' 或 '-' 符号来添加或删除标志。特殊变量 "%o" 可用于将其标志传播给同一格式字符串上的所有其他变量。这对于带引号("Q")和转义("E")的字符串格式特别有用。如果一个变量名在方括号 ('[' .. ']') 中,则它被用作采样表达式规则(参见 第 7.3 节)。这有助于添加一些不太常见的信息,例如客户端 SSL 证书的 DN,或者记录用于将条目存储到 stick table 中的密钥。注意:空格必须进行转义。在配置指令 "log-format"、"log-format-sd" 和 "unique-id-format" 中,空格被视为分隔符并合并。为了输出字面意义上的 '%',它必须前面加上另一个 '%',从而产生 '%%'。注意:使用 RFC5424 syslog 消息格式时,PARAM-VALUE 中的字符 '"'、'\' 和 ']' 应以 '\' 作为前缀进行转义(有关更多详细信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3.3)。在这种情况下,应考虑使用 "E" 标志。标志是:* Q: 引号字符串 * X: 十六进制表示 (IP、端口、%Ts、%rt、%pid) * E: 使用 '\' 作为前缀转义字符串中的字符 '"'、'\' 和 ']'(目的是为了 RFC5424 结构化数据日志格式)
示例
log-format %T\ %t\ Some\ Text log-format %{+Q}o\ %t\ %s\ %{-Q}r log-format-sd %{+Q,+E}o\ [exampleSDID@1234\ header=%[capture.req.hdr(0)]]
目前,默认的 HTTP 格式定义如下:log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC \ %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r" 默认的 CLF 格式定义如下:log-format "%{+Q}o %{-Q}ci - - [%trg] %r %ST %B \"\" \"\" %cp \ %ms %ft %b %s %TR %Tw %Tc %Tr %Ta %tsc %ac %fc \ %bc %sc %rc %sq %bq %CC %CS %hrl %hsl" 默认的 TCP 格式定义如下:log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts \ %ac/%fc/%bc/%sc/%rc %sq/%bq" 请参考下表了解当前定义的变量:+---+------+-----------------------------------------------+-------------+ | R | var | 字段名称 (8.2.2 和 8.2.3 描述) | type | +---+------+-----------------------------------------------+-------------+ | | %o | 特殊变量,将标志应用于所有后续变量 | | +---+------+-----------------------------------------------+-------------+ | | %B | bytes_read (从服务器到客户端) | numeric | | H | %CC | captured_request_cookie | string | | H | %CS | captured_response_cookie | string | | | %H | hostname | string | | H | %HM | HTTP method (例如:POST) | string | | H | %HP | HTTP 请求 URI(不含查询字符串) | string | | H | %HQ | HTTP 请求 URI 查询字符串 (例如:?bar=baz) | string | | H | %HU | HTTP 请求 URI (例如:/foo?bar=baz) | string | | H | %HV | HTTP 版本 (例如:HTTP/1.0) | string | | | %ID | unique-id | string | | | %ST | status_code | numeric | | | %T | gmt_date_time | date | | H | %Ta | 请求的活动时间(从 TR 到结束) | numeric | | | %Tc | Tc | numeric | | | %Td | Td = Tt - (Tq + Tw + Tc + Tr) | numeric | | | %Tl | local_date_time | date | | | %Th | 连接握手时间(SSL、PROXY proto) | numeric | | H | %Ti | HTTP 请求前的空闲时间 | numeric | | H | %Tq | Th + Ti + TR | numeric | | H | %TR | 从第一个字节接收完整请求的时间 | numeric | | H | %Tr | Tr (响应时间) | numeric | | | %Ts | timestamp | numeric | | | %Tt | Tt | numeric | | | %Tu | Tu | numeric | | | %Tw | Tw | numeric | | | %U | bytes_uploaded (从客户端到服务器) | numeric | | | %ac | actconn | numeric | | | %b | backend_name | string | | | %bc | beconn (后端并发连接数) | numeric | | | %bi | backend_source_ip (连接地址) | IP | | | %bp | backend_source_port (连接地址) | numeric | | | %bq | backend_queue | numeric | | | %ci | client_ip (接受的地址) | IP | | | %cp | client_port (接受的地址) | numeric | | | %f | frontend_name | string | | | %fc | feconn (前端并发连接数) | numeric | | | %fi | frontend_ip (接受的地址) | IP | | | %fp | frontend_port (接受的地址) | numeric | | | %ft | frontend_name_transport ('~' 后缀表示 SSL) | string | | | %lc | frontend_log_counter | numeric | | | %hr | captured_request_headers default style | string | | | %hrl | captured_request_headers CLF style | string list | | | %hs | captured_response_headers default style | string | | | %hsl | captured_response_headers CLF style | string list | | | %ms | accept date milliseconds (左侧用 0 填充) | numeric | | | %pid | PID | numeric | | H | %r | http_request | string | | | %rc | retries | numeric | | | %rt | request_counter (HTTP 请求或 TCP 会话) | numeric | | | %s | server_name | string | | | %sc | srv_conn (服务器并发连接数) | numeric | | | %si | server_IP (目标地址) | IP | | | %sp | server_port (目标地址) | numeric | | | %sq | srv_queue | numeric | | S | %sslc| ssl_ciphers (例如:AES-SHA) | string | | S | %sslv| ssl_version (例如:TLSv1) | string | | | %t | date_time (带有毫秒分辨率) | date | | H | %tr | HTTP 请求的 date_time | date | | H | %trg | HTTP 请求开始的 gmt_date_time | date | | H | %trl | HTTP 请求开始的 local_date_time | date | | | %ts | termination_state | string | | H | %tsc | 带有 cookie 状态的 termination_state | string | +---+------+-----------------------------------------------+-------------+ R = Restrictions : H = 仅限 http 模式 ; S = 仅限 SSL

8.2.5. 错误日志格式

当传入连接因 SSL 握手或无效的 PROXY 协议头而失败时,haproxy 将使用更短的固定行格式记录事件。默认情况下,日志以 LOG_INFO 级别发出,除非在后端设置了 "option log-separate-errors" 选项,在这种情况下将使用 LOG_ERR 级别。如果设置了 "dontlognull" 选项,则不会记录没有数据交换的连接(例如,探测)。格式如下:>>> Dec 3 18:27:14 localhost \ haproxy[6103]: 127.0.0.1:56059 [03/Dec/2012:17:35:10.380] frt/f1: \ Connection error during SSL handshake 字段格式 示例中的提取 1 process_name '[' pid ']:' haproxy[6103]: 2 client_ip ':' client_port 127.0.0.1:56059 3 '[' accept_date ']' [03/Dec/2012:17:35:10.380] 4 frontend_name "/" bind_name ":" frt/f1: 5 message Connection error during SSL handshake 这些字段仅提供最少的信息来帮助调试连接失败。

8.3. 高级日志记录选项

一些高级日志记录选项经常被寻找,但仅通过查看各种选项不容易找到。这里是几个可以实现更好日志记录的选项的入口点。有关其用法的更多信息,请参考关键字参考。

8.3.1. 禁用外部测试的日志记录

通常会有一些监控工具对haproxy进行健康检查。有时它会是一个LVS之类的3层负载均衡器,或者任何商用负载均衡器,有时它仅仅是一个更完整的监控系统,例如Nagios。当测试非常频繁时,用户经常会问如何禁用这些检查的日志记录。有三种可能性:-如果连接来自四面八方,并且只是TCP探测,通常希望通过在前端设置“option dontlognull”来禁用没有数据交换的连接日志记录。这也会禁用端口扫描日志记录,这可能是也可能不是您想要的。-如果连接来自已知的源网络,请使用“monitor-net”将该网络声明为仅用于监控。该网络中的任何主机届时将只能执行健康检查,并且它们的请求不会被记录。这通常适用于指定其他负载均衡器等设备列表。-如果测试是在已知的URI上执行的,请使用“monitor-uri”将该URI声明为专门用于监控。发送此请求的任何主机将只能获得健康检查的结果,并且请求不会被记录。

8.3.2. 在等待会话终止前记录日志

在连接结束时进行日志记录的问题在于,您无法了解长时间会话(例如远程终端会话或大文件下载)期间正在发生的事情。可以通过在前段指定 "option logasap" 来解决此问题。HAProxy 将尽快记录,就在数据传输开始之前。这意味着在 TCP 的情况下,它仍会记录到服务器的连接状态,在 HTTP 的情况下,它将在处理服务器标头后立即记录。在这种情况下,报告的字节数是发送到客户端的标头字节数。为了避免与正常日志混淆,总时间字段和字节数前面会加上“+”号,表示实际数字肯定更大。

8.3.3. 发生错误时提高日志级别

有时,将正常流量与错误日志分开会更方便,例如,为了简化从日志文件中监控错误。当使用 "log-separate-errors" 选项时,遇到错误、超时、重试、重新分派或 HTTP 状态码为 5xx 的连接,其 syslog 级别将从 "info" 提高到 "err"。这将帮助 syslog 守护进程将日志存储在一个单独的文件中。将错误也保留在正常流量文件中非常重要,这样日志顺序就不会改变。如果您已经配置了 syslog 守护进程将所有高于 "notice" 的日志存储在 "admin" 文件中,您也应该小心,因为 "err" 级别高于 "notice"。

8.3.4. 禁用成功连接的日志记录

虽然这乍听起来可能很奇怪,但一些大型站点必须处理每秒数千条日志,并且在长时间保持其完整性或在其中检测错误方面遇到困难。如果在前端设置了 "dontlog-normal" 选项,所有正常的连接都不会被记录。在这方面,正常连接定义为没有任何错误、超时、重试或重新分派的连接。在 HTTP 中,状态码也会被检查,状态为 5xx 的响应不被认为是正常的,也会被记录。当然,这样做是强烈不鼓励的,因为它会从日志中删除大部分有用的信息。只有在没有其他选择的情况下才这样做。

8.4. 计时事件

计时器在排查网络问题方面提供了极大的帮助。所有值均以毫秒(ms)报告。这些计时器应与会话终止标志结合使用。在TCP模式下,如果前端设置了“option tcplog”,则会报告3个控制点,形式为“Tw/Tc/Tt”,在HTTP模式下,会报告5个控制点,形式为“TR/Tw/Tc/Tr/Ta”。此外,还提供了其他三项度量:“Th”、“Ti”和“Tq”。HTTP模式下的计时事件:第一个请求 第二个请求 |<-------------------------------->|<-------------- ... t tr t tr ... ---|----|----|----|----|----|----|----|----|-- : Th Ti TR Tw Tc Tr Td : Ti ... :<---- Tq ---->: :<-------------- Tt -------------->: :<-- -----Tu--------------->: :<--------- Ta --------->: TCP模式下的计时事件:TCP会话 |<----------------->| t t ---|----|----|----|----|--- | Th Tw Tc Td | |<------ Tt ------->| - Th:接受TCP连接并为低级协议执行握手所花费的总时间。目前,这些协议是proxy-protocol和SSL。这可能在整个连接的生命周期中只发生一次。此处的时间长可能表明客户端只预先建立了连接但未进行通信,或者它正在经历网络问题,阻止其在合理时间内完成握手(例如MTU问题),或者SSL握手计算成本很高。请注意,此时间仅在第一个请求之前报告,因此将其平均到所有请求以计算摊销值是安全的。第二个及后续请求将在此处始终报告零。 - Ti:HTTP请求之前的空闲时间(仅限HTTP模式)。此计时器计算从握手结束到HTTP请求的第一个字节之间的时间。在keep-alive模式下处理第二个请求时,它从上一个响应传输结束开始计时。使用HTTP/2等多路复用协议时,它在上一请求之后立即开始计时。某些浏览器会预先建立与服务器的连接,以减少未来请求的延迟,并将其保持挂起状态,直到它们需要。此延迟将报告为空闲时间。值为-1表示连接上未收到任何内容。 - TR:获取客户端请求的总时间(仅限HTTP模式)。它是从接收到的第一个字节到代理收到标记HTTP头部结束的空行之间的时间。值为“-1”表示从未看到头部结束。这发生在客户端过早关闭连接或超时时。此时间通常非常短,因为大多数请求都包含在单个数据包中。时间长可能表示在测试期间手动输入的请求。 - Tq:从接受日期或自上一个响应的最后一个字节发出以来获取客户端请求的总时间(仅限HTTP模式)。它严格等于Th + Ti + TR,除非其中任何一个为-1,在这种情况下,它也返回-1。此计时器在HTTP keep-alive和浏览器预连接功能出现之前非常有用。目前建议放弃它,转而使用TR,因为空闲时间会给报告增加很多噪音。 - Tw:在队列中等待连接槽的总时间。它包括后端队列和服务器队列,取决于队列大小以及服务器完成先前请求所需的时间。值为“-1”表示请求在到达队列之前就被终止了,这通常发生在无效或被拒绝的请求时。 - Tc:与服务器建立TCP连接的总时间。它是从代理发送连接请求到服务器确认的时刻,或者从TCP SYN数据包到匹配的SYN/ACK数据包之间的经过时间。值为“-1”表示连接从未建立。 - Tr:服务器响应时间(仅限HTTP模式)。它是从与服务器建立TCP连接的时刻到服务器发送其完整响应头部的时刻之间的时间。它纯粹显示其请求处理时间,不包括数据传输的网络开销。值得注意的是,当客户端有数据要发送到服务器时,例如在POST请求期间,时间已经开始计算,这可能会扭曲响应时间的表观值。因此,在处理来自不受信任的网络后面的客户端发起的POST请求时,通常明智的做法是不要过多地依赖此字段。值为“-1”表示从未看到最后一个响应头部(空行),最可能是因为服务器在服务器处理请求之前超时了,或者服务器返回了无效的响应。 - Td:响应载荷传输到发送给客户端的最后一个字节的总传输时间。在HTTP中,它在最后一个响应头部(Tr之后)开始。发送的数据不保证会被客户端收到,它们可能卡在内核或网络中。 - Ta:HTTP请求的总活动时间,介于代理接收到请求头部第一个字节的时刻和响应正文最后一个字节发出的时刻之间。例外情况是指定了“option logasap”选项时。在这种情况下,它仅等于(TR+Tw+Tc+Tr),并带有“+”号前缀。从这个字段,我们可以通过减去其他计时器(如果有效)来推导出“Td”,即数据传输时间:Td = Ta - (TR + Tw + Tc + Tr) 值为“-1”的计时器必须从该方程中排除。请注意,“Ta”永远不会为负数。 - Tt:总会话持续时间,从代理接受它到两端都关闭的时刻。例外情况是指定了“logasap”选项时。在这种情况下,它仅等于(Th+Ti+TR+Tw+Tc+Tr),并带有“+”号前缀。从这个字段,我们可以通过减去其他计时器(如果有效)来推导出“Td”,即数据传输时间:Td = Tt - (Th + Ti + TR + Tw + Tc + Tr) 值为“-1”的计时器必须从该方程中排除。在TCP模式下,还必须排除“Ti”、“Tq”和“Tr”。请注意,“Tt”永远不会为负数,并且对于HTTP,Tt仅等于(Th+Ti+Ta)。 - Tu:从客户端的角度来看,从代理接受它到两端都关闭的时刻之间估算的总时间,不包括空闲时间。这有助于大致衡量用户所看到的端到端时间,而不受请求之间keep-alive时间的空闲时间干扰。此计时器仅是用户所见时间的估算,因为它假定网络延迟在两个方向上都是相同的。例外情况是指定了“logasap”选项时。在这种情况下,它仅等于(Th+TR+Tw+Tc+Tr),并带有“+”号前缀。这些计时器提供了关于故障原因的宝贵指示。由于TCP协议定义了3秒、6秒、12秒……的重传延迟,我们可以确定地知道接近3秒倍数的计时器几乎总是与因网络问题(线路、协商、拥塞)丢失的包有关。此外,如果“Ta”或“Tt”接近配置中指定的超时值,通常意味着会话因超时而被中止。最常见的情况: - 如果“Th”或“Ti”接近3000,则可能在客户端和代理之间丢失了一个数据包。这在本地网络上非常罕见,但在客户端位于遥远的网络并发送大型请求时可能会发生。有时会出现比正常值大的情况,而没有任何网络原因。例如,在遭受攻击期间或资源耗尽刚刚结束时,haproxy可能会在几毫秒内接受数千个连接。接受这些连接所花费的时间将不可避免地略微延迟其他连接的处理,并且在一次性接受了数千个新连接后,可能会出现几十毫秒数量级的请求时间。使用keep-alive模式之一可能会显示更长的空闲时间,因为“Ti”测量的是等待额外请求的时间。 - 如果“Tc”接近3000,则可能在服务器和代理之间建立服务器连接阶段丢失了一个数据包。此值应始终非常低,例如在本地网络上为1毫秒,在远程网络上则小于几十毫秒。 - 如果“Tr”始终低于3000,除了某些罕见的、似乎被3000平均值放大的值之外,很可能在代理和服务器之间丢失了一些数据包。 - 如果“Ta”即使对于小字节数也很大,通常是因为客户端和服务器都不决定关闭连接,而haproxy正在隧道模式下运行,并且它们都同意了keep-alive连接模式。为了解决这个问题,需要指定HTTP选项之一来操纵前端或后端的keep-alive或关闭选项。当使用服务器上的“maxconn”选项进行连接调节时,具有最小的“Ta”或“Tt”很重要,因为在另一个连接释放之前,不会向服务器发送新的连接。其他值得注意的HTTP日志案例(“xx”表示任何要忽略的值):TR/Tw/Tc/Tr/+Ta 在前端存在“option logasap”,并且日志在数据阶段之前发出。所有计时器都有效,除了“Ta”,它比实际值短。 -1/xx/xx/xx/Ta 客户端无法及时发送完整请求,或者过早中止。检查会话终止标志,然后检查“timeout http-request”和“timeout client”设置。 TR/-1/xx/xx/Ta 无法处理请求,可能是因为服务器顺序错误,请求无效或被ACL规则禁止。检查会话终止标志。 TR/Tw/-1/xx/Ta 无法在服务器上建立连接。它要么主动拒绝,要么在Ta-(TR+Tw)毫秒后超时。检查会话终止标志,然后检查“timeout connect”设置。请注意,tarpit操作可能会返回外观相似的模式,其中“Tw”等于维护客户端连接打开的时间。 TR/Tw/Tc/-1/Ta 服务器已接受连接,但未在规定时间内返回完整响应,或者在Ta-(TR+Tw+Tc)毫秒后意外关闭了连接。检查会话终止标志,然后检查“timeout server”设置。

8.5. 断开连接时的会话状态

TCP和HTTP日志在连接数之前,在“termination_state”字段中提供了一个会话终止指示器。在TCP模式下,它有2个字符长,在HTTP模式下扩展到4个字符,每个字符都有特殊的含义:- 第一个字符,一个代码,报告导致会话终止的第一个事件:C:TCP会话被客户端意外中止。S:TCP会话被服务器意外中止,或者服务器明确拒绝了它。P:会话被代理过早中止,因为强制执行了连接限制,因为匹配了DENY过滤器,或者因为安全检查检测并阻止了服务器响应中可能导致信息泄露的危险错误(例如,可缓存的cookie)。L:会话由haproxy在本地处理,未传递给服务器。统计信息和重定向就是这样进行的。R:代理上的资源(内存、套接字、源端口等)已耗尽。通常,这会在连接阶段出现,系统日志应包含精确错误副本。如果发生这种情况,必须尽快以任何方式修复,这被认为是非常严重的异常。I:代理在自我检查期间识别出内部错误。这永远不应该发生,并且鼓励您报告包含此内容的日志,因为这几乎肯定是一个bug。在这种情况下,为了防止由于内存损坏可能导致的问题,最好也立即重启进程。D:会话被haproxy杀死,因为服务器被检测为宕机,并且在宕机时配置为杀死所有连接。U:会话被haproxy在此备份服务器上杀死,因为检测到一个活动服务器处于启动状态,并且在启动时配置为杀死所有备份连接。K:会话被操作haproxy的管理员主动杀死。c:等待客户端发送或接收数据时,客户端超时。s:等待服务器发送或接收数据时,服务器超时。-:正常会话完成,客户端和服务器都已关闭,缓冲区中没有剩余数据。- 第二个字符,TCP或HTTP会话关闭时的状态:R:代理正在等待来自客户端的完整、有效的请求(仅限HTTP模式)。没有发送任何内容给服务器。Q:代理在队列中等待连接槽。只有当服务器设置了“maxconn”参数时才会发生这种情况。在与一个宕机服务器连接失败后进行重定向的全局队列中也可能发生。如果没有报告重定向,则没有尝试连接任何服务器。C:代理正在等待连接到服务器。服务器最多可能注意到连接尝试。H:代理正在等待来自服务器的完整、有效的响应头(仅限HTTP)。D:会话处于数据传输阶段。L:代理仍在向客户端传输最后的数据,而服务器已完成。这种情况非常罕见,因为它只能发生在客户端在接收最后一个数据包时死亡。T:请求被减速(tarpitted)。它在整个“timeout tarpit”持续时间内或直到客户端关闭时一直保持与客户端的连接,两者都会在“Tw”计时器中报告。-:数据传输结束后正常会话完成。- 第三个字符,指示持久性cookie是否由客户端提供(仅限HTTP模式):N:客户端未提供cookie。这通常是新访问者的情况,因此在日志中统计此标志的出现次数通常表明了网站访问量的有效趋势。I:客户端提供的无效cookie与任何已知服务器都不匹配。这可能是由于最近的配置更改、HTTP/HTTPS站点之间的混合cookie、持久性被有条件地忽略,或一次攻击造成的。D:客户端提供的cookie指向一个宕机的服务器,因此使用了“option persist”并将客户端发送到该服务器,或者未设置该选项,并将客户端重新定向到另一台服务器。V:客户端提供的有效cookie,并被发送到关联的服务器。E:客户端提供的cookie有效,但“maxidle”cookie参数允许的最后访问日期已过,因此cookie被视为已过期并被忽略。请求将像没有cookie一样被重新定向。O:客户端提供的cookie有效,但“maxlife”cookie参数允许的首次访问日期已过,因此cookie被视为过时并被忽略。请求将像没有cookie一样被重新定向。U:存在cookie,但由于使用了其他服务器选择机制(通常是“use-server”规则),因此未使用该cookie选择服务器。-:不适用(配置中未设置cookie)。- 最后一个字符,报告对服务器返回的持久性cookie执行了哪些操作(仅限HTTP模式):N:服务器未提供任何cookie,也没有插入任何cookie。I:服务器未提供cookie,代理插入了一个。请注意,在“cookie insert”模式下,如果服务器提供cookie,它仍将被覆盖并在此处报告为“I”。U:代理更新了客户端提供的cookie中的最后访问日期。这只能发生在带有“maxidle”的插入模式下。每次在与cookie中指示的日期不同的日期发生活动时都会发生这种情况。如果发生任何其他更改,例如重定向,则cookie将被标记为已插入。P:服务器提供了cookie,并按原样传输。R:服务器提供的cookie被代理重写,这发生在“cookie rewrite”或“cookie prefix”模式下。D:服务器提供的cookie被代理删除。-:不适用(配置中未设置cookie)。前两个标志的组合提供了关于会话终止时发生了什么以及为什么会终止的大量信息。它有助于检测服务器饱和、网络故障、本地系统资源匮乏、攻击等...最常见的终止标志组合如下所示。它们按字母顺序排序,小写字母紧随大写字母之后,以便于查找和理解。标志 原因 -- 正常终止。CC 在与服务器建立连接之前,客户端被中止。当haproxy尝试连接到一个最近宕机(或未检查)的服务器时,可能会发生这种情况,而haproxy在等待服务器响应或“timeout connect”过期时,客户端中止。CD 数据传输过程中,客户端意外中止。这可能是由于浏览器崩溃、客户端与haproxy之间的中间设备主动断开连接、客户端与haproxy之间的网络路由问题,或者客户端与服务器之间的keep-alive会话首先由客户端终止。cD 客户端在“timeout client”延迟时间内未发送或确认任何数据。这通常是由客户端的网络故障引起的,或者客户端未干净地离开网络。CH 客户端在等待服务器开始响应时被中止。可能是服务器响应过慢,或者客户端点击“停止”按钮太快。cH 在POST请求中等待客户端数据时,“timeout client”已到期。这有时是由PPPoE网络中过大的TCP MSS值引起的,这些网络无法传输全尺寸数据包。当客户端超时小于服务器超时,并且服务器响应过慢时,也可能发生这种情况。CQ 客户端在会话排队等待服务器有足够空闲槽位接受时被中止。可能是所有服务器都已饱和,或者分配的服务器响应过慢。CR 客户端在发送完整的HTTP请求之前被中止。最可能是手动通过telnet客户端输入的请求,并且过早中止。HTTP状态码很可能是400。有时这也可能是由IDS杀死haproxy和客户端之间的连接引起的。“option http-ignore-probes”可用于忽略没有数据传输的连接。cR 在客户端发送完整的HTTP请求之前,“timeout http-request”已到期。这有时是由PPPoE网络中客户端过大的TCP MSS值引起的,这些值无法传输全尺寸数据包,或者由手动发送请求但输入速度不够快或忘记在请求末尾输入空行的客户端引起的。HTTP状态码很可能是408。注意:最近,一些浏览器开始实现“预连接”功能,即推测性地连接到一些最近访问过的网站,以防用户想要访问它们。这会导致许多连接建立到网站,如果超时首先发生,则会收到408 Request Timeout,或者如果浏览器首先决定关闭它们,则收到400 Bad Request。这些请求会污染日志并填充错误计数器。一些浏览器版本甚至被报告显示了错误代码。通过在前端添加“option http-ignore-probes”可以解决此行为的不良影响,从而完全忽略零数据传输的连接。但这肯定会隐藏那些遇到连接问题的用户的错误。CT 客户端在会话被减速(tarpitted)时被中止。检查这是否发生在有效请求上很重要,以确保没有编写错误的减速规则。如果发生很多这种情况,可能需要将“timeout tarpit”值降低到接近平均报告的“Tw”计时器值,以避免仅仅为了几个攻击者而消耗资源。LR 请求被haproxy拦截并本地处理。通常这意味着它是一个重定向或统计请求。SC 服务器或其与haproxy之间的中间设备明确拒绝了TCP连接(代理收到TCP RST或ICMP消息作为响应)。在某些情况下,也可能是网络堆栈告诉代理服务器不可达(例如,本地网络上没有路由或没有ARP响应)。在HTTP模式下发生这种情况时,状态码很可能是502或503。sC 在连接到服务器完成之前,“timeout connect”已到期。在HTTP模式下发生这种情况时,状态码很可能是503或504。SD 服务器连接在数据传输过程中因错误而中断。这通常意味着haproxy在与服务器交换数据时收到了服务器的RST或中间设备的ICMP消息。这可能是由服务器崩溃或中间设备上的网络问题引起的。sD 在数据阶段,“timeout server”设置期间,服务器未发送或确认任何数据。这通常是由于服务器之前的L4设备(防火墙、负载均衡器等)上的超时设置过短,以及客户端和服务器之间维护的keep-alive会话在haproxy上首先过期引起的。SH 服务器在发送完整的HTTP响应头之前被中止,或者在处理请求时崩溃了。由于服务器此时中止非常罕见,因此最好检查其日志以确认它是否崩溃以及原因。记录的请求可能表明有一小组有问题的请求,展示了应用程序中的错误。有时这也可能是由IDS杀死haproxy和服务器之间的连接引起的。sH 在服务器能够返回响应头之前,“timeout server”已到期。这是最常见的异常,表明事务时间过长,可能由服务器或数据库饱和引起。即时解决方法是增加“timeout server”设置,但请记住,用户体验会因这些长时间的响应而受到影响。唯一的长期解决方案是修复应用程序。sQ 会话在队列中花费了过多的时间并已过期。如果这种情况经常发生,请参阅“timeout queue”和“timeout connect”设置以了解如何修复。如果它经常在短时间内大量发生,这可能表明受影响的服务器由于I/O或数据库拥塞而存在普遍问题,或者是由外部攻击引起的饱和。PC 代理拒绝与服务器建立连接,因为在尝试连接时达到了进程的套接字限制。可以在配置中增加全局“maxconn”参数,以免再次发生这种情况。此状态非常罕见,并且可能发生在全局“ulimit-n”参数被手动强制设置时。PD 代理阻止了请求或响应中格式错误的块状编码消息,这发生在服务器发出其标头之后。在大多数情况下,这将指示来自服务器的无效消息。HAProxy支持高达2GB-1(2147483647字节)的块大小。任何更大的尺寸都将被视为错误。PH 代理阻止了服务器的响应,因为它是无效的、不完整的、危险的(缓存控制),或者匹配了安全过滤器。在任何情况下,都会向客户端发送HTTP 502错误。此错误的一个可能原因是HTTP头名称中包含未经授权的字符。如果代理在服务器响应之前阻止了来自客户端的块状编码请求,由于语法无效,这也可能发生,但这种情况非常罕见。在这种情况下,会向客户端发送HTTP 400错误并在日志中报告。最后,这可能是由于响应中的HTTP头重写失败。在这种情况下,会发送HTTP 500错误(有关更多信息,请参阅“tune.maxrewrite”和“http-response strict-mode”)。PR 代理阻止了客户端的HTTP请求,原因可能是HTTP语法无效(在这种情况下,它向客户端返回HTTP 400错误),或者是因为匹配了deny过滤器(在这种情况下,它向客户端返回HTTP 403错误)。这也可能是由于请求中的HTTP头重写失败。在这种情况下,会发送HTTP 500错误(有关更多信息,请参阅“tune.maxrewrite”和“http-request strict-mode”)。PT 代理阻止了客户端的请求,并在返回500服务器错误之前减速了其连接。没有向服务器发送任何内容。连接保持打开状态,时间长度由“Tw”计时器字段报告。RC 已耗尽本地资源(内存、套接字、源端口),导致无法建立到服务器的连接。错误日志将详细说明缺少什么。这种情况非常罕见,只能通过适当的系统调优来解决。最后两个标志的组合提供了关于客户端、服务器和haproxy如何处理持久性的信息。这对于排除用户抱怨需要重新认证的断开连接问题非常重要。常见的标志是:-- 未启用持久性cookie。NN 客户端未提供cookie,响应中也未插入任何cookie。例如,这可能是“insert”模式下对GET请求设置了“postonly”。II 客户端提供的cookie指向一个无效的服务器,响应中插入了一个有效的cookie。当“server”条目从配置中删除时,通常会发生这种情况,因为客户端可能会提供其cookie值,而没有其他服务器知道它。NI 客户端未提供cookie,响应中插入了一个cookie。这通常发生在“insert”模式下每个用户的首次请求,这是一种统计真实用户的好方法。VN 客户端提供了cookie,响应中没有插入任何cookie。对于客户端已经获取到cookie的大多数响应,都会发生这种情况。VU 客户端提供的cookie,最后访问日期不是最新的,因此在响应中提供了更新的cookie。这也可以发生在没有日期,或者有日期但未设置“maxidle”参数时,因此cookie可以切换为无限期。EI 客户端提供的cookie,最后访问日期对于“maxidle”参数来说太旧了,因此cookie被忽略,并在响应中插入了一个新cookie。OI 客户端提供的cookie,首次访问日期对于“maxlife”参数来说太旧了,因此cookie被忽略,并在响应中插入了一个新cookie。DI cookie指定的服务器宕机了,选择了一个新服务器,并在响应中发出新cookie。VI cookie指定的服务器未被标记为宕机,但无法访问。发生了重定向,并选择了另一个服务器,然后将其广告在响应中。

8.6. 不可打印字符

为了在查阅日志时避免给日志分析工具或终端带来麻烦,不可打印的字符不会按原样发送到日志文件中,而是会转换为其 ASCII 码的两位十六进制表示,并以字符“#”为前缀。唯一可以不经转义直接记录的字符范围是 32 到 126(含)。显然,转义字符“#”本身也会被编码以避免任何歧义(“#23”)。字符“"”也是如此,它会变成“#22”,以及在记录头时,“{”、“|”和“}”也是如此。请注意,空格字符(' ')在头中不被编码,这可能会给依赖空格计数来定位字段的工具带来问题。一个包含空格的典型头是“User-Agent”。最后,据观察,一些 syslog 守护进程(如 syslog-ng)会用反斜杠('\')来转义引号('\"')。可以安全地执行反向操作,因为日志中其他任何地方都不会出现引号。

8.7. 捕获 HTTP cookie

Cookie 捕获简化了对完整用户会话的跟踪。这可以通过在前端使用“capture cookie”语句来实现。更多详情请参考第 4.2 节。只能捕获一个 cookie,并且同一个 cookie 将同时在请求(“Cookie:”头)和响应(“Set-Cookie:”头)中进行检查。相应的值将报告在 HTTP 日志的“captured_request_cookie”和“captured_response_cookie”位置(请参阅关于 HTTP 日志格式的第 8.2.3 节)。当任一 cookie 未被看到时,一个破折号('-')将取代该值。这样,就很容易检测到用户何时切换到新会话,例如,因为服务器将为其重新分配一个新的 cookie。也可以检测服务器是否意外地向客户端设置了错误的 cookie,从而导致会话交叉。
示例
# 捕获第一个名称以“ASPSESSION”开头的 cookie capture cookie ASPSESSION len 32 # 捕获第一个名称正好是“vgnvisitor”的 cookie capture cookie vgnvisitor= len 32

8.8. 捕获 HTTP 头

Header captures are useful to track unique request identifiers set by an upper proxy, virtual host names, user-agents, POST content-length, referrers, etc. In the response, one can search for information about the response length, how the server asked the cache to behave, or an object location during a redirection. Header captures are performed using the "capture request header" and "capture response header" statements in the frontend. Please consult their definition in section 4.2 for more details. It is possible to include both request headers and response headers at the same time. Non-existent headers are logged as empty strings, and if one header appears more than once, only its last occurrence will be logged. Request headers are grouped within braces '{' and '}' in the same order as they were declared, and delimited with a vertical bar '|' without any space. Response headers follow the same representation, but are displayed after a space following the request headers block. These blocks are displayed just before the HTTP request in the logs. As a special case, it is possible to specify an HTTP header capture in a TCP frontend. The purpose is to enable logging of headers which will be parsed in an HTTP backend if the request is then switched to this HTTP backend.
示例
    # This instance chains to the outgoing proxy listen proxy-out mode http option httplog option logasap log global server cache1 192.168.1.1:3128 # log the name of the virtual server capture request header Host len 20 # log the amount of data uploaded during a POST capture request header Content-Length len 10 # log the beginning of the referrer capture request header Referer len 20 # server name (useful for outgoing proxies only) capture response header Server len 20 # logging the content-length is useful with "option logasap" capture response header Content-Length len 10 # log the expected cache behavior on the response capture response header Cache-Control len 8 # the Via header will report the next proxy's name capture response header Via len 20 # log the URL location during a redirection capture response header Location len 20 >>> Aug 9 20:26:09 localhost \ haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09] proxy-out \ proxy-out/cache1 0/0/0/162/+162 200 +350 - - ---- 0/0/0/0/0 0/0 \ {fr.adserver.yahoo.co||http://fr.f416.mail.} {|864|private||} \ "GET http://fr.adserver.yahoo.com/" >>> Aug 9 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/0/182/+182 200 +279 - - ---- 0/0/0/0/0 0/0 \ {w.ods.org||} {Formilux/0.1.8|3495|||} \ "GET http://trafic.1wt.eu/ HTTP/1.1" >>> Aug 9 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/2/126/+128 301 +223 - - ---- 0/0/0/0/0 0/0 \ {www.sytadin.equipement.gouv.fr||http://trafic.1wt.eu/} \ {Apache|230|||http://www.sytadin.} \ "GET http://www.sytadin.equipement.gouv.fr/ HTTP/1.1"

8.9. 日志示例

These are real-world examples of logs accompanied with an explanation. Some of them have been made up by hand. The syslog part has been removed for better reading. Their sole purpose is to explain how to decipher them. >>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http \ px-http/srv1 6559/0/7/147/6723 200 243 - - ---- 5/3/3/1/0 0/0 \ "HEAD / HTTP/1.0" => long request (6.5s) entered by hand through 'telnet'. The server replied in 147 ms, and the session ended normally ('----') >>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http \ px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 \ 0/9 "HEAD / HTTP/1.0" => Idem, but the request was queued in the global queue behind 9 other requests, and waited there for 1230 ms. >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.654] px-http \ px-http/srv1 9/0/7/14/+30 200 +243 - - ---- 3/3/3/1/0 0/0 \ "GET /image.iso HTTP/1.0" => request for a long data transfer. The "logasap" option was specified, so the log was produced just before transferring data. The server replied in 14 ms, 243 bytes of headers were sent to the client, and total time from accept to first data byte is 30 ms. >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http \ px-http/srv1 9/0/7/14/30 502 243 - - PH-- 3/2/2/0/0 0/0 \ "GET /cgi-bin/bug.cgi? HTTP/1.0" => the proxy blocked a server response either because of an "http-response deny" rule, or because the response was improperly formatted and not HTTP-compliant, or because it blocked sensitive information which risked being cached. In this case, the response is replaced with a "502 bad gateway". The flags ("PH--") tell us that it was haproxy who decided to return the 502 and not the server. >>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http \ px-http/<NOSRV> -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 "" => the client never completed its request and aborted itself ("C---") after 8.5s, while the proxy was waiting for the request headers ("-R--"). Nothing was sent to any server. >>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http \ px-http/<NOSRV> -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 "" => The client never completed its request, which was aborted by the time-out ("c---") after 50s, while the proxy was waiting for the request headers ("-R--"). Nothing was sent to any server, but the proxy could send a 408 return code to the client. >>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp \ px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0 => This log was produced with "option tcplog". The client timed out after 5 seconds ("c----"). >>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http \ px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 \ 0/0 "HEAD / HTTP/1.0" => The request took 3s to complete (probably a network problem), and the connection to the server failed ('SC--') after 4 attempts of 2 seconds (config says 'retries 3'), and no redispatch (otherwise we would have seen "/+3"). Status code 503 was returned to the client. There were 115 connections on this server, 202 connections on this proxy, and 205 on the global process. It is possible that the server refused the connection because of too many already established.
此处列出了官方支持的过滤器及其接受的参数。根据编译选项,其中一些过滤器可能不可用。可用过滤器的列表将在 haproxy -vv 中报告。

9.1. 跟踪

filter trace [name <name>] [random-parsing] [random-forwarding] [hexdump]
参数
<name> is an arbitrary name that will be reported in messages. If no name is provided, "TRACE" is used. <random-parsing> enables the random parsing of data exchanged between the client and the server. By default, this filter parses all available data. With this parameter, it only parses a random amount of the available data. <random-forwarding> enables the random forwarding of parsed data. By default, this filter forwards all previously parsed data. With this parameter, it only forwards a random amount of the parsed data. <hexdump> dumps all forwarded data to the server and the client.
此过滤器可用作开发新过滤器的基础。它定义了所有回调,并在标准错误流(stderr)上打印一条包含所有回调有用信息的消息。调试其他过滤器活动或 HAProxy 本身活动时可能很有用。使用 <;random-parsing> 和/或 <;random-forwarding> 参数是通过在处理中增加延迟来测试解析客户端和服务器之间交换数据的过滤器行为的好方法。

9.2. HTTP 压缩

HTTP compression has been moved to a filter in HAProxy 1.7. "compression" keyword must still be used to enable and configure HTTP compression. And when no other filter is used, it is enough. When used with the cache or the fcgi-app enabled, it is also enough. In this case, the compression is always done after the response is stored in the cache. But it is mandatory to explicitly use a filter line to enable HTTP compression when at least one filter other than the cache or the fcgi-app is used for the same listener/frontend/backend. This is important to know the filters evaluation order.

9.3. Stream Processing Offload Engine (SPOE)

filter spoe [engine <name>] config <file>
参数
<name> is the engine name that will be used to find the right scope in the configuration file. If not provided, all the file will be parsed. <file> is the path of the engine configuration file. This file can contain configuration of several engines. In this case, each part must be placed in its own scope.
The Stream Processing Offload Engine (SPOE) is a filter communicating with external components. It allows the offload of some specifics processing on the streams in tiered applications. These external components and information exchanged with them are configured in dedicated files, for the main part. It also requires dedicated backends, defined in HAProxy configuration. SPOE communicates with external components using an in-house binary protocol, the Stream Processing Offload Protocol (SPOP). For all information about the SPOE configuration and the SPOP specification, see "doc/SPOE.txt".

9.4. Cache

参数
<name> is name of the cache section this filter will use.
缓存使用过滤器来存储可缓存的响应。必须使用 HTTP 规则“cache-store”和“cache-use”来定义如何以及何时使用缓存。默认情况下,相应的过滤器是隐式定义的。并且当没有使用除 fcgi-app 或压缩之外的其他过滤器时,这就足够了。在这种情况下,压缩过滤器始终在缓存过滤器之后评估。但是,当同一监听器/前端/后端使用了除压缩或 fcgi-app 之外的至少一个过滤器时,必须明确使用过滤器行来使用缓存。了解过滤器的评估顺序很重要。

9.5. Fcgi-app

参数
<name> is name of the fcgi-app section this filter will use.
The FastCGI application uses a filter to evaluate all custom parameters on the request path, and to process the headers on the response path. the <name> must reference an existing fcgi-app section. The directive "use-fcgi-app" should be used to define the application to use. By default the corresponding filter is implicitly defined. And when no other filters than cache or compression are used, it is enough. But it is mandatory to explicitly use a filter line to a fcgi-app when at least one filter other than the compression or the cache is used for the same backend. This is important to know the filters evaluation order.
HAProxy 能够向 Responder FastCGI 应用程序发送 HTTP 请求。此功能已在 HAProxy 2.1 中添加。要做到这一点,服务器必须配置为使用 FastCGI 协议(在服务器行中使用关键字 "proto fcgi"),并且必须配置一个 FastCGI 应用程序并由管理这些服务器的后端使用(在代理部分中使用关键字 "use-fcgi-app")。可以定义多个 FastCGI 应用程序,但每个后端一次只能使用一个。HAProxy 实现 Responder 应用程序的 FastCGI 规范的所有功能。特别是,它能够在一个连接上多路复用多个请求。

10.1. 设置

10.1.1. Fcgi-app 部分

fcgi-app <name>
声明一个名为 <name> 的 FastCGI 应用程序。要使其有效,至少必须定义 document root。
acl <aclname> <criterion> [flags] [operator] <value> ...
声明或完成访问列表。有关 ACL 使用的详细信息,请参阅第 4.2 节第 7 节中的“acl”关键字。为 FastCGI 应用程序定义的 ACL 是私有的。它们不能被任何其他应用程序或任何代理使用。同样,在任何其他部分定义的 ACL 也不能被 FastCGI 应用程序使用。但是,可以使用预定义的 ACL。
docroot <path> 定义远程主机上的文档根目录。<path> 将用于构建 FastCGI 参数 SCRIPT_FILENAME 和 PATH_TRANSLATED 的默认值。这是一个强制性设置。
index <script-name>
定义将在以斜杠 ("/") 结尾的 URI 之后附加的脚本名称,用于设置 FastCGI 参数 SCRIPT_NAME 的默认值。这是一个可选设置。
示例
index index.php
log-stderr <address> [len <length>] [format <format>] [sample <ranges>:<sample_size>] <facility> [<level> [<minlevel>]]
启用 FastCGI 应用程序报告的 STDERR 消息的日志记录。有关详细信息,请参阅第 4.2 节中的 "log" 关键字。这是一个可选设置。默认情况下,STDERR 消息将被忽略。
pass-header <name> [ { if | unless } <condition> ]
指定将传递到 FastCGI 应用程序的请求头名称。它可能可选地跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时才会对其进行评估。大多数请求头已经可供 FastCGI 应用程序使用,并带有“HTTP_”前缀。因此,此指令仅用于传递故意省略的头。当前,“Authorization”、“Proxy-Authorization”以及 hop-by-hop 头都会被省略。请注意,“Content-type”和“Content-length”头永远不会传递给 FastCGI 应用程序,因为它们已经被转换为参数。
path-info <regex>
定义一个正则表达式,用于从 URL 解码的路径中提取脚本名称和 path-info。因此,<regex> 可能有两个捕获:第一个捕获脚本名称,第二个捕获 path-info。第一个是强制性的,第二个是可选的。这样,就可以从路径中提取脚本名称而忽略 path-info。这是一个可选设置。如果未定义,则不会对路径进行匹配。并且 FastCGI 参数 PATH_INFO 和 PATH_TRANSLATED 不会被填充。出于安全原因,当定义此正则表达式时,URL 解码后的路径中禁止使用换行符和空字符。限制的原因是,由于 HAProxy 中正则表达式的执行方式存在限制,否则匹配将始终失败。因此,如果 URL 解码的路径中找到这两个字符中的任何一个,将向客户端返回错误。此处应用了最小惊讶原则。
示例
path-info ^(/.+\.php)(/.*)?$ # both script-name and path-info may be set path-info ^(/.+\.php) # the path-info is ignored
启用或禁用有关连接管理的变量检索。HAProxy 能够在连接建立时发送 FCGI_GET_VALUES 记录,以检索以下变量的值:* FCGI_MAX_REQS 此应用程序将接受的并发请求的最大数量。* FCGI_MPXS_CONNS 如果此应用程序不进行连接多路复用,则为 "0",否则为 "1"。某些 FastCGI 应用程序不支持此功能。另一些应用程序在发送响应后立即关闭连接。因此,默认情况下,此选项是禁用的。请注意,FastCGI 应用程序接受的最大并发请求数是一个连接变量。它仅限制每个连接的流数。如果必须限制应用程序的全局负载,则必须设置服务器参数 "maxconn" 和 "pool-max-conn"。此外,如果应用程序不支持连接多路复用,则最大并发请求数将自动设置为 1。
指示 FastCGI 应用程序在发送响应后是否保持连接打开。如果禁用,FastCGI 应用程序将在响应此请求后关闭连接。默认情况下,此选项处于启用状态。
定义此应用程序将接受的最大并发请求数。如果连接建立期间检索到 FCGI_MAX_REQS 变量,此选项可能会被覆盖。此外,如果应用程序不支持连接多路复用,则将忽略此选项。默认设置为 1。
启用或禁用连接多路复用的支持。如果连接建立期间检索到 FCGI_MPXS_CONNS 变量,此选项可能会被覆盖。默认情况下禁用。
set-param <name> <fmt> [ { if | unless } <condition> ]
Set a FastCGI parameter that should be passed to this application. Its value, defined by <fmt> must follows the log-format rules (see section 8.2.4 "Custom Log format"). It may optionally be followed by an ACL-based condition, in which case it will only be evaluated if the condition is true. With this directive, it is possible to overwrite the value of default FastCGI parameters. If the value is evaluated to an empty string, the rule is ignored. These directives are evaluated in their declaration order.
示例
# PHP only, required if PHP was built with --enable-force-cgi-redirect set-param REDIRECT_STATUS 200 set-param PHP_AUTH_DIGEST %[req.hdr(Authorization)]

10.1.2. 代理部分

定义要用于后端的 FastCGI 应用程序。
参数
<name> 是要使用的 FastCGI 应用程序的名称。
此关键字仅适用于具有后端功能且至少有一个 FastCGI 服务器的 HTTP 代理。但是,FastCGI 服务器可以与 HTTP 服务器混合。但除非有充分理由,否则不建议这样做(有关详细信息,请参见第 10.3 节的限制)。每个后端一次只能定义一个应用程序。请注意,一旦为后端引用了 FastCGI 应用程序,根据配置,即使请求未发送到 FastCGI 服务器,也可能会执行某些处理。将参数设置或将头传递到应用程序的规则会被评估。

10.1.3. 示例

frontend front-http mode http bind *:80 bind *: use_backend back-dynamic if { path_reg ^/.+\.php(/.*)?$ } default_backend back-static backend back-static mode http server www A.B.C.D:80 backend back-dynamic mode http use-fcgi-app php-fpm server php-fpm A.B.C.D:9000 proto fcgi fcgi-app php-fpm log-stderr global option keep-conn docroot /var/www/my-app index index.php path-info ^(/.+\.php)(/.*)?$

10.2. 默认参数

Responder FastCGI 应用程序的作用与 CGI/1.1 程序相同。在 CGI/1.1 规范(RFC3875)中,必须将多个变量传递给脚本。因此,HAProxy 设置了它们以及 FastCGI 应用程序常用的其他变量。所有这些变量都可以被覆盖,但请谨慎操作。+-------------------+-----------------------------------------------------+ | AUTH_TYPE | 标识 HAProxy 用于验证用户的机制(如果有)。 | | | 实际上,仅支持 BASIC 身份验证机制。 | | | | +-------------------+-----------------------------------------------------+ | CONTENT_LENGTH | 包含附加到请求的消息正文的大小。 | | | 这意味着只有大小已知的请求才被视为有效并发送 | | | 到应用程序。 | | | | +-------------------+-----------------------------------------------------+ | CONTENT_TYPE | 包含附加到请求的消息正文的类型。 | | | 可能未设置。 | | | | +-------------------+-----------------------------------------------------+ | DOCUMENT_ROOT | 包含脚本应在其下执行的远程主机上的文档根目录, | | | 如应用程序配置中所定义。 | | | | +-------------------+-----------------------------------------------------+ | GATEWAY_INTERFACE | 包含 HAProxy 与 FastCGI 应用程序通信所使用的 | | | CGI 方言。 | | | 实际上,它被设置为 "CGI/1.1"。 | | | | +-------------------+-----------------------------------------------------+ | PATH_INFO | 包含 URI 路径层级中标识脚本本身的 | | | 部分之后的剩余部分。要设置此项,必须定义 | | | "path-info" 指令。 | | | | +-------------------+-----------------------------------------------------+ | PATH_TRANSLATED | 如果设置了 PATH_INFO,则它是其翻译版本。 | | | 它是 DOCUMENT_ROOT 和 PATH_INFO 的连接。 | | | 如果未设置 PATH_INFO,则此参数也不设置。 | | | | +-------------------+-----------------------------------------------------+ | QUERY_STRING | 包含请求的查询字符串。 | | | 可能未设置。 | | | | +-------------------+-----------------------------------------------------+ | REMOTE_ADDR | 包含发送请求的客户端的网络地址。 | | | | +-------------------+-----------------------------------------------------+ | REMOTE_USER | 包含客户端作为用户身份验证一部分提供的 | | | 用户标识字符串。 | | | | +-------------------+-----------------------------------------------------+ | REQUEST_METHOD | 包含脚本应使用的处理请求的方法。 | | | | +-------------------+-----------------------------------------------------+ | REQUEST_URI | 包含请求的 URI。 | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_FILENAME | 包含脚本的绝对路径名。它是 DOCUMENT_ROOT 和 | | | SCRIPT_NAME 的连接。 | | | | +-------------------+-----------------------------------------------------+ | SCRIPT_NAME | 包含脚本的名称。如果定义了 "path-info" | | | 指令,则它是 URI 路径层级的第一个部分, | | | 以脚本名称结尾。否则,它是整个 URI 路径。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_NAME | 包含客户端请求所指向的服务器主机的名称。 | | | 如果定义了 "Host" 头,则为 "Host" 头的值。 | | | 否则,为客户端连接的目标地址。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_PORT | 包含客户端连接的目标 TCP 端口,即客户端 | | | 连接的端口。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_PROTOCOL | 包含请求的协议。 | | | | +-------------------+-----------------------------------------------------+ | SERVER_SOFTWARE | 包含字符串 "HAProxy" 加上当前的 HAProxy 版本。 | | | | +-------------------+-----------------------------------------------------+ | HTTPS | 如果脚本是通过 HTTPS 协议查询的,则设置为非空值 | | | ("on")。 | | | | +-------------------+-----------------------------------------------------+

10.3. 限制

当前的实现存在一些限制。第一个限制是某些请求头隐藏给 FastCGI 应用程序的方式。这发生在后端进行头部分析时,在连接建立之前。在此阶段,HAProxy 知道后端正在使用 FastCGI 应用程序,但它不知道请求是否最终会路由到 FastCGI 服务器。但为了隐藏请求头,它会简单地将其从 HTX 消息中删除。因此,如果请求最终路由到 HTTP 服务器,它将永远看不到这些头部。因此,不建议在同一个后端混合使用 FastCGI 服务器和 HTTP 服务器。同样," set-param " 和 " pass-header " 规则在请求头部分析期间进行评估。因此,即使请求最终转发到 HTTP 服务器,评估也总是执行的。关于 " set-param " 规则,当应用规则时,会将一个伪头部添加到 HTX 消息中。因此,与 HTTP 头部重写一样,如果缓冲区已满,它可能会失败。 " set-param " 规则将与 "http-request" 规则竞争。最后,所有 FastCGI 参数和 HTTP 头部都发送到一个唯一的 FCGI_PARAM 记录中。该记录的编码必须一次完成,否则会返回处理错误。这意味着一旦编码的 FCGI_PARAM 记录不能超过缓冲区的大小。但是,这里没有预留需要遵守。


HAProxy 2.2.34 – 配置手册
, 2025/04/23