本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。下面的摘要旨在帮助您按名称搜索章节并浏览文档。文档贡献者须知:本文档每行格式为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. | ||
4. |
代理 | |
| 4.1. | ||
| 4.2. | ||
5. |
Bind 和 Server 选项 | |
| 5.1. | ||
| 5.2. | ||
| 5.3. | ||
| 5.3.1. | ||
| 5.3.2. | ||
6. |
HTTP 标头操作 | |
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.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. |
当haproxy以HTTP模式运行时,请求和响应都会被完全分析和索引,因此可以对内容中几乎所有找到的内容构建匹配条件。但是,理解HTTP请求和响应是如何形成的,以及HAProxy是如何分解它们的,这一点很重要。这样,编写正确的规则和调试现有配置就会更容易。
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中没有办法将响应与相应的请求关联起来。因此,服务器必须按照接收请求的顺序完全相同的顺序进行回复。默认情况下,HAProxy在持久连接方面以keep-alive模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间将连接保持空闲状态。HAProxy支持5种连接模式:- keep alive(保持连接):处理所有请求和响应(默认)。- tunnel(隧道):只处理第一个请求和响应,其他所有内容都会被转发而无需分析。- passive close(被动关闭):隧道模式,并在两个方向上添加“Connection: close”头部。- server close(服务器关闭):服务器端连接在响应后关闭。- forced close(强制关闭):连接在响应结束后被主动关闭。
首先,让我们考虑这个 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行是“请求行”。它总是由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请求一起使用,并且非常特定于所使用的语言、框架或应用程序。
头部从第二行开始。它们由行开头的名称组成,后面紧跟着一个冒号(':')。传统上,冒号后面会添加一个LWS,但这不是必需的。然后是值。多个相同的头部可以折叠成一个单行,用逗号分隔值,前提是保持它们的顺序。这在“Cookie:”字段中很常见。如果后续行以LWS开头,一个头部可以跨越多行。在1.2的示例中,第4行和第5行定义了“Accept:”头部总共3个值。与普遍的误解相反,头部名称不区分大小写,如果它们指向其他头部名称(如“Connection:”头部),它们的值也不区分大小写。头部的结束由第一个空行指示。人们常说这是双换行符,这并不准确,尽管双换行符是空行的一种有效形式。幸运的是,HAProxy在索引头部、检查值和计数时会处理所有这些复杂的组合,因此没有理由担心它们的写法,但不要因为应用程序执行不寻常但有效的事情而指责它存在bug。重要提示:如RFC7231所建议,HAProxy通过将头部中间的换行符替换为LWS来规范化头部,以合并多行头部。这对于正确的分析至关重要,并有助于能力较弱的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个字段组成:- 版本标签: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 访问统计页面,以及回复监控请求时 301 执行重定向时,取决于配置的代码 302 执行重定向时,取决于配置的代码 303 执行重定向时,取决于配置的代码 307 执行重定向时,取决于配置的代码 308 执行重定向时,取决于配置的代码 400 对于无效或过大的请求 401 执行操作时需要身份验证时(访问统计页面时) 403 请求被“block”ACL或“reqdeny”过滤器阻止时 408 请求超时在请求完成前触发 500 当haproxy遇到无法恢复的内部错误时,例如内存分配失败,这不应发生 502 服务器返回空、无效或不完整的响应,或当“rspdeny”过滤器阻止响应时。 503 没有可用服务器处理请求时,或响应匹配“monitor fail”条件的监控请求时 504 响应超时在服务器响应前触发上面的4xx和5xx错误代码可以自定义(参见第4.2节中的“errorloc”)。
响应头的处理方式与请求头完全相同,因此 HAProxy 对两者使用相同的解析函数。更多详情请参考 1.2.2 段。
HAProxy 的配置过程涉及 3 个主要的参数来源: - 命令行参数,它们总是优先 - “global”部分,设置进程范围的参数 - 代理部分,可以采用“defaults”、“listen”、“frontend”和“backend”的形式。配置文件语法由以本手册中引用的关键字开头的行组成,后面可以选择性地跟一个或多个由空格分隔的参数。
HAProxy的配置引入了一个类似于许多编程语言的引用和转义系统。配置文件支持3种类型:反斜杠转义、双引号弱引用和单引号强引用。如果字符串中必须包含空格,则必须用反斜杠('\')进行转义,或用引号括起来。反斜杠也必须通过加倍或强引用来转义。转义是通过在特殊字符前加上反斜杠('\')来实现的:\ 用来标记空格并将其与分隔符区分开\# 用来标记哈希并将其与注释区分开\\ 用来使用反斜杠\' 用来使用单引号并将其与强引用区分开\" 用来使用双引号并将其与弱引用区分开弱引用通过使用双引号("”)实现。弱引用可防止解释:空格作为参数分隔符' 单引号作为强引用分隔符# 哈希作为注释起始符弱引用允许解释变量,如果您想在双引号字符串中使用未解释的美元符号,您应该用反斜杠("\$")转义它,这在弱引用之外不起作用。转义和特殊字符的解释不受弱引用的阻止。强引用通过使用单引号(')实现。在单引号内,什么都不会被解释,这是引用正则表达式的有效方法。被引用和转义的字符串在内存中被替换为其解释后的等价物,这允许您执行连接。
# 以下是等价的: 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 # 以下是等价的: reqrep "^([^\ :]*)\ /static/(.*)" \1\ /\2 reqrep "^([^ :]*)\ /static/(.*)" '\1 /\2' reqrep "^([^ :]*)\ /static/(.*)" "\1 /\2" reqrep "^([^ :]*)\ /static/(.*)" "\1\ /\2"
HAProxy 的配置支持环境变量。这些变量仅在双引号内被解释。变量在配置解析期间展开。变量名前必须加上美元符号("$"),并可选地用大括号("{}")括起来,类似于 Bourne shell 中的做法。变量名可以包含字母数字字符或下划线("_"),但不应以数字开头。bind "fd@${FD_APP1}" log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器 user "$HAPROXY_USER"
一些参数涉及表示时间的值,例如超时。这些值通常以毫秒表示(除非另有明确说明),但也可以通过在数值后附加单位来以任何其他单位表示。考虑这一点很重要,因为每个关键字都不会重复说明。支持的单位有:- 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
# 一个简单的 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”部分支持以下关键字:* 进程管理和安全 - ca-base - chroot - crt-base - cpu-map - daemon - description - deviceatlas-json-file - deviceatlas-log-level - deviceatlas-separator - deviceatlas-properties-cookie - external-check - gid - group - hard-stop-after - log - log-tag - log-send-hostname - lua-load - nbproc - node - pidfile - presetenv - resetenv - uid - ulimit-n - user - setenv - stats - ssl-default-bind-ciphers - ssl-default-bind-options - ssl-default-server-ciphers - ssl-default-server-options - ssl-dh-param-file - ssl-server-verify - unix-bind - unsetenv - 51degrees-data-file - 51degrees-property-name-list - 51degrees-property-separator - 51degrees-cache-size - wurfl-data-file - wurfl-information-list - wurfl-information-list-separator - wurfl-engine-mode - wurfl-cache-size - wurfl-useragent-priority * 性能调优 - max-spread-checks - maxconn - maxconnrate - maxcomprate - maxcompcpuusage - maxpipes - maxsessrate - maxsslconn - maxsslrate - maxzlibmem - noepoll - nokqueue - nopoll - nosplice - nogetaddrinfo - noreuseport - spread-checks - server-state-base - server-state-file - tune.buffers.limit - tune.buffers.reserve - tune.bufsize - tune.chksize - tune.comp.maxlevel - tune.http.cookielen - tune.http.maxhdr - tune.idletimer - tune.lua.forced-yield - tune.lua.maxmem - tune.lua.session-timeout - tune.lua.task-timeout - tune.lua.service-timeout - tune.maxaccept - tune.maxpollevents - tune.maxrewrite - tune.pattern.cache-size - tune.pipesize - tune.rcvbuf.client - tune.rcvbuf.server - tune.recv_enough - tune.sndbuf.client - tune.sndbuf.server - tune.ssl.cachesize - tune.ssl.lifetime - tune.ssl.force-private-cache - tune.ssl.maxrecord - tune.ssl.default-dh-param - 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
当与“ca-file”或“crl-file”指令使用相对路径时,分配一个默认目录来从此目录获取 SSL CA 证书和 CRL。在“ca-file”和“crl-file”指令中指定的绝对位置将优先于并忽略“ca-base”。
更改当前目录到,然后在此处执行 chroot(),之后降低权限。这提高了安全性,以防万一出现未知的漏洞被利用,因为它会让攻击者非常难以利用系统。仅当进程以超级用户权限启动时,此功能才有效。务必确保 是空的且任何人都可以写入。
在 Linux 2.6 及更高版本中,可以将进程绑定到特定的 CPU 集合。这意味着该进程将永远不会在其他 CPU 上运行。“cpu-map”指令为进程集指定 CPU 集合。第一个参数是要绑定的进程号。此进程的编号必须介于 1 到 32(或 64,取决于机器的字长)之间,任何大于 nbproc 的进程 ID 都将被忽略。可以使用“all”一次性指定所有进程,“odd”指定奇数编号,“even”指定偶数编号,这与“bind-process”指令类似。第二个及后续参数是 CPU 集合。每个 CPU 集合可以是 0 到 31(或 63)之间的唯一编号,也可以是用连字符('-')分隔的两个此类编号的范围。可以指定多个 CPU 编号或范围,并且进程将被允许绑定到所有这些 CPU。显然,可以指定多个“cpu-map”指令。每个“cpu-map”指令在重叠时将替换之前的指令。
当使用 "crtfile" 指令的相对路径时,分配一个用于获取 SSL 证书的默认目录。"crtfile" 后面指定的绝对位置优先,并忽略 "crt-base"。
使进程分叉到后台运行。这是推荐的操作模式。它等效于命令行“-D”参数。可以使用命令行“-db”参数禁用它。
设置 API 加载的 DeviceAtlas JSON 数据文件的路径。路径必须是有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置 API 属性结果的字符分隔符。此指令是可选的,如果未设置,则默认为 |。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
允许使用外部代理执行健康检查。作为安全预防措施,此功能默认禁用。请参阅 "option external-check"。
将进程的组 ID 更改为 <number>。建议将组 ID 分配给 HAProxy 或一小组类似守护进程。HAProxy 必须以属于该组的用户或超级用户权限启动。请注意,如果 HAProxy 是由具有补充组的用户启动的,它只能在以超级用户权限启动时删除这些组。另请参阅“group”和“uid”。
定义执行干净的软停止所允许的最长时间。
<time> 是实例在通过 SIGUSR1 信号接收到软停止时将保持活动的最长时间(默认为毫秒)。
这可用于确保即使在软停止期间连接保持打开(例如,在 tcp 模式下为代理设置了长超时),实例也会退出。它适用于 TCP 和 HTTP 模式。
global hard-stop-after 30s
类似于“gid”,但使用 /etc/group 中的组名 <group name> 的 GID。另请参阅“gid”和“user”。
添加一个全局 syslog 服务器。可以定义多个全局服务器。它们将接收启动和退出的日志,以及通过“log global”配置的所有代理的日志。可以是以下之一:- IPv4 地址,后跟可选的冒号和 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- IPv6 地址,后跟冒号和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- 到 UNIX 域套接字的本地文件系统路径,同时请注意 chroot 的注意事项(确保路径在 chroot 内可访问)以及 uid/gid(确保路径具有适当的写入权限)。您可能希望在地址参数中引用某些环境变量,有关环境变量的信息,请参阅 第 2.3 节。是可选的最大行长度。大于此值的日志行将在发送前被截断。原因是 syslog 服务器在日志行长度上的行为不同。所有服务器都支持 1024 的默认值,但一些服务器会简单地丢弃较长的行,而另一些则会记录它们。如果服务器支持长行,则在此处设置此值可能很有意义,以避免截断长行。同样,如果服务器丢弃长行,最好在发送之前截断它们。接受的值为 80 到 65535(含)。1024 的默认值通常适用于所有标准用法。某些特定情况下的长捕获或 JSON 格式日志可能需要更大的值。 是生成 syslog 消息时使用的日志格式。它可以是以下之一:rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164)rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424)<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 可以指定一个可选级别来过滤传出的消息。默认情况下,所有消息都会发送。如果指定了最大级别,则只会发送严重性至少为此级别或更高的消息。可以指定一个可选的最小级别。如果设置了此级别,则会将其限制到此级别,以避免在某些默认 syslog 配置上将“emerg”消息发送到所有终端。已知有八个级别:emerg alert crit err warning notice info debug
设置 syslog 报头中的 hostname 字段。如果设置了可选的 "string" 参数,则报头将设置为该字符串内容,否则使用系统的主机名。通常在不通过中间 syslog 服务器中继日志或仅为自定义日志中打印的主机名时使用。
将 syslog 报头中的 tag 字段设置为此字符串。它默认为从命令行启动的程序名,通常是 "haproxy"。有时,区分同一主机上运行的多个进程会很有用。另请参阅每个代理的 "log-tag" 指令。此全局指令加载并执行一个 Lua 文件。此指令可以多次使用。
进入 daemon 模式时创建 <number> 个进程。这需要“daemon”模式。默认情况下,只创建一个进程,这是推荐的操作模式。对于每个进程文件描述符数量有限的系统,可能需要分叉多个守护进程。使用多个进程更难调试,并且非常不推荐。另请参阅“daemon”。
将所有守护进程的 pid 写入文件 <pidfile>。此选项等效于“-p”命令行参数。文件必须是启动进程的用户可访问的。另请参阅“daemon”。
将环境变量 <name> 设置为值 <value>。如果该变量已存在,则不会被覆盖。更改会立即生效,以便配置文件中的下一行可以看到新值。另请参阅 "setenv"、"resetenv" 和 "unsetenv"。
删除除参数中指定的环境变量之外的所有环境变量。它允许在使用 setenv 或 unsetenv 设置新值之前,使用一个干净受控的环境。请注意,一些内部函数可能会使用某些环境变量,例如时间操作函数,以及 OpenSSL 甚至外部检查。此命令必须极其小心使用,并且只能在完全验证后使用。更改会立即生效,因此配置文件中的下一行将看到新的环境。另请参阅 “setenv”、“presetenv” 和 “unsetenv”。
将统计套接字限制在特定的进程号集。默认情况下,统计套接字绑定到所有进程,当 nbproc 大于 1 时会发出警告,因为在连接时无法选择目标进程。但是,通过使用此设置,可以使统计套接字固定到特定的进程集,通常是第一个进程。使用此设置后,无论使用多少进程,警告都会自动禁用。最大进程 ID 取决于机器的字长(32 或 64)。一个更好的选项是使用“stats socket”行中的“process”设置来强制每行上的进程。
指定目录前缀,该前缀将附加在所有不以“/”开头的服务器状态文件名前面。另请参阅 "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"。
将环境变量 <name> 设置为值 <value>。如果该变量存在,则会被覆盖。更改会立即生效,因此配置文件中的下一行将看到新的值。另请参阅 “presetenv”、“resetenv” 和 “unsetenv”。
此设置仅在内置 OpenSSL 支持时可用。它设置了在 SSL/TLS 握手期间协商的密码算法(“密码套件”)的默认字符串,适用于所有未显式定义自己的“bind”行。字符串的格式在 OpenSSL man 页的“man 1 ciphers”中定义,例如可以是“AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH”(不带引号)这样的字符串。请参阅“bind”关键字以获取更多信息。
此设置仅在编译时支持 OpenSSL 时可用。它为所有 "bind" 行设置强制使用的默认 ssl-options。请查看 "bind" 关键字以了解可用选项。
global ssl-default-bind-options no-sslv3 no-tls-tickets
此设置仅在内置 OpenSSL 支持时可用。它设置了在与服务器的 SSL/TLS 握手中协商的密码算法的默认字符串,适用于所有未显式定义自己的“server”行。字符串的格式在“man 1 ciphers”中定义。请参阅“server”关键字以获取更多信息。
此设置仅在编译时支持 OpenSSL 时可用。它为所有 "server" 行设置强制使用的默认 ssl-options。请查看 "server" 关键字以了解可用选项。
此设置仅在内置 OpenSSL 支持时可用。它设置了在使用临时 Diffie-Hellman (DHE) 密钥交换期间用于 SSL/TLS 握算的默认 DH 参数,适用于所有未显式定义自己的“bind”行。如果绑定证书文件中存在自定义 DH 参数,则将被覆盖。如果未使用 ssl-dh-param-file 或直接在证书文件中设置自定义 DH 参数,则将使用 tune.ssl.default-dh-param 指定大小的预生成 DH 参数。自定义参数被认为更安全,因此建议使用它们。可以使用 OpenSSL 命令“openssl dhparam <size>”生成自定义 DH 参数,其中 size 至少应为 2048,因为 1024 位 DH 参数不应再被认为安全。
服务器端 SSL 验证的默认行为。如果指定为 'none',则不验证服务器证书。默认值为 'required',除非使用命令行选项 '-dV' 强制指定。
将UNIX套接字绑定到<path>,或将TCPv4/v6地址绑定到<address:port>。连接到此套接字将返回各种统计信息输出,甚至允许发出一些命令来更改某些运行时设置。请参阅管理指南的第9.3节“Unix Socket命令”以获取更多详细信息。支持"bind"行的所有参数,例如限制对某些用户或其访问权限的访问。有关更多信息,请参阅第5.1节。
统计套接字的默认超时时间设置为 10 秒。可以使用 "stats timeout" 更改此值。该值必须以毫秒为单位传递,或者带有时间单位后缀,如 { us, ms, s, m, h, d }。
默认情况下,统计套接字限制为 10 个并发连接。可以使用 "stats maxconn" 更改此值。
将进程的用户 ID 更改为 <number>。建议用户 ID 专供 HAProxy 或一小组类似的守护进程使用。HAProxy 必须以超级用户权限启动才能切换到其他用户。另请参阅“gid”和“user”。
将每个进程的最大文件描述符数设置为 <number>。默认情况下,它是自动计算的,因此建议不要使用此选项。
为在 "bind" 语句中声明的 UNIX 侦听套接字设置通用配置。这主要用于简化这些 UNIX 套接字的声明并减少错误风险,因为这些设置通常是必需的,但也是特定于进程的。<prefix> 设置可用于强制所有套接字路径相对于该目录。这可能需要访问另一个组件的 chroot。请注意,这些路径在 haproxy chroot 自身之前解析,因此它们是绝对路径。<mode>、<user>、<uid>、<group> 和 <gid> 的含义与 "bind" 语句使用的同名参数相同。如果两者都指定,则 "bind" 语句具有更高的优先级,这意味着 "unix-bind" 设置可被视为进程范围的默认设置。
删除参数中指定的环境变量。这对于隐藏某些操作期间偶尔从用户环境中继承的一些敏感信息很有用。不存在的变量会被静默忽略,因此操作后可以确定这些变量都不再存在。更改会立即生效,因此配置文件中的下一行将看不到这些变量。另请参阅 “setenv”、“presetenv” 和 “resetenv”。
类似于“uid”,但使用 /etc/passwd 中用户名为 <user name> 的用户的 UID。另请参阅“uid”和“group”。
只允许字母、数字、连字符和下划线,与 DNS 名称类似。此语句在 HA 配置中很有用,其中两个或多个进程或服务器共享相同的 IP 地址。通过在所有节点上设置不同的节点名称,可以轻松地立即发现哪个服务器正在处理流量。
添加描述实例的文本。请注意,需要转义某些字符(例如 #),并且此文本将插入 HTML 页面中,因此您应避免使用“<”和“>”字符。
提供设备检测服务的 51Degrees 数据文件的路径。该文件应解压缩,并且 HAProxy 具有相应的权限才能访问。请注意,此选项仅在 HAProxy 已使用 USE_51DEGREES 编译时可用。
要从数据集中加载的 51Degrees 属性名称列表。完整的名称列表可在 51Degrees 网站上找到:https://51degrees.com/resources/property-dictionary 请注意,此选项仅在 haproxy 编译时启用了 USE_51DEGREES 时可用。
一个字符,将附加到包含 51Degrees 结果的响应头中的每个属性值之后。如果未设置,则默认为“,”。请注意,此选项仅在 haproxy 编译时启用了 USE_51DEGREES 时可用。
将 51Degrees 转换器缓存的大小设置为 <number> 个条目。这是一个 LRU 缓存,用于记住以前的设备检测及其结果。默认情况下,此缓存是禁用的。请注意,此选项仅在 haproxy 编译时启用了 USE_51DEGREES 时可用。
提供设备检测服务的 WURFL 数据文件路径。该文件应由 HAProxy 访问,并具有相关权限。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
WURFL 功能、虚拟功能、我们计划在注入的标头中使用的属性名称的空格分隔列表。功能和虚拟功能的完整名称列表可在 Scientiamobile 网站上找到:https://www.scientiamobile.com/wurflCapability 有效的 WURFL 属性包括: - wurfl_id 包含匹配设备的设备 ID。 - wurfl_root_id 包含匹配设备的设备根 ID。 - wurfl_isdevroot 指示匹配的设备是否为根设备。可能的值为“TRUE”或“FALSE”。 - wurfl_useragent 此特定 Web 请求附带的原始用户代理。 - wurfl_api_version 包含表示当前使用的 Libwurfl API 版本的字符串。 - wurfl_engine_target 包含表示当前设置的 WURFL 引擎目标的字符串。可能的值为“HIGH_ACCURACY”、“HIGH_PERFORMANCE”、“INVALID”。 - wurfl_info 包含有关解析的 wurfl.xml 及其完整路径的信息的字符串。 - wurfl_last_load_time 包含 WURFL 最后成功加载的 UNIX 时间戳。 - wurfl_normalized_useragent 规范化的用户代理。 - wurfl_useragent_priority WURFL 使用的用户代理优先级。请注意,此选项仅在 HAProxy 已使用 USE_WURFL=1 编译时可用。
用于分隔包含 WURFL 结果的响应标头中值的字符。如果未设置,则默认使用逗号 (',')。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。WURFL 补丁文件路径列表。请注意,补丁是在启动时加载的,因此在 chroot 之前加载。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
设置WURFL引擎目标。您可以选择“accuracy”或“performance”目标。在performance模式下,桌面Web浏览器检测是按编程方式完成的,无需引用WURFL数据。因此,大多数桌面Web浏览器将以generic_web_browser WURFL ID返回以获得性能。如果performance或accuracy未定义,则默认启用performance模式。请注意,此选项仅在haproxy使用USE_WURFL=1编译时可用。
设置WURFL缓存策略。其中<U>是Useragent缓存大小,<D>是内部设备缓存大小。这里有三种可能性:-“0”:不使用缓存。-<U>:使用单个LRU缓存,大小以元素表示。-<U>,<D>:使用双重LRU缓存,两个大小都以元素表示。这是性能最高的选项。请注意,此选项仅在haproxy使用USE_WURFL=1编译时可用。
告知WURFL是否应优先使用纯用户代理('plain')而不是默认的sideloaded浏览器用户代理('sideloaded_browser')。请注意,此选项仅在haproxy使用USE_WURFL=1编译时可用。
默认情况下,haproxy 会尝试将健康检查的开始时间分散到服务器场中所有服务器的最小健康检查间隔内。其原理是避免对同一服务器上运行的服务进行密集检查。但是当使用较大的检查间隔(10 秒或更长)时,服务器场中的最后几个服务器需要一些时间才能开始被测试,这可能是一个问题。此参数用于强制设置第一个和最后一个检查之间的延迟上限,即使服务器的检查间隔较大。当服务器以较短的间隔运行时,它们的间隔仍将得到尊重。
将每个进程的最大并发连接数设置为 <number>。它等同于命令行参数 "-n"。当达到此限制时,代理将停止接受连接。"ulimit-n" 参数会根据此值自动调整。另请参阅 "ulimit-n"。注意:在某些平台上,"select" 轮询器不能可靠地使用超过 1024 个文件描述符。如果您的平台只支持 select 并在启动时报告 "select FAILED",您需要减少 maxconn 直到它正常工作(通常略低于 500)。如果未设置此值,它将默认为构建时在 DEFAULT_MAXCONN 中设置的值(在 haproxy -vv 中报告),如果没有强制执行内存限制,或者将根据内存限制、缓冲区大小、分配给压缩的内存、SSL 缓存大小以及是否使用 SSL 和相关的 maxsslconn(也可以是自动的)来计算。
将每个进程每秒的最大连接数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
将每个进程的最大输入压缩速率设置为 <number> 千字节/秒。对于每个会话,如果达到最大值,会话期间的压缩级别将降低。如果在会话开始时达到最大值,该会话将完全不压缩。如果未达到最大值,压缩级别将增加到 tune.comp.maxlevel。值为零表示没有限制,这是默认值。
设置 HAProxy 在停止对新请求进行压缩或降低当前请求的压缩级别之前可以达到的最大 CPU 使用率。它的工作方式类似于 'maxcomprate',但衡量的是 CPU 使用率而不是传入数据带宽。该值以 haproxy 使用的 CPU 百分比表示。在多进程(nbproc > 1)的情况下,每个进程管理其各自的使用率。值为 100 将禁用此限制。默认值为 100。设置较低的值将防止压缩工作减慢整个进程的速度并引入高延迟。
将每个进程的最大管道数设置为 <number>。目前,管道仅由基于内核的 tcp 拼接使用。由于一个管道包含两个文件描述符,"ulimit-n" 值将相应增加。默认值为 maxconn/4,这对于大多数重度使用情况来说似乎已经足够了。拼接代码动态分配和释放管道,并且可以回退到标准复制,因此将此值设置得太低可能只会影响性能。
将每个进程每秒的最大会话数设置为 <number>。当达到此限制时,代理将停止接受连接。它可以用来限制全局容量,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。此外,降低 tune.maxaccept 可以提高公平性。
将每个进程的并发 SSL 连接数设置为 <number>。默认情况下,没有特定于 SSL 的限制,这意味着全局 maxconn 设置将适用于所有连接。设置此限制可避免 openssl 使用过多内存而崩溃(因为它不幸地不能可靠地检查这种情况,因此 malloc 会返回 NULL)。请注意,该限制同时适用于传入和传出连接,因此一个经过解密然后加密的连接算作 2 个 SSL 连接。如果未设置此值,但强制执行了内存限制,则将根据内存限制、maxconn、缓冲区大小、分配给压缩的内存、SSL 缓存大小以及在前端、后端或两者中是否使用 SSL 来自动计算此值。如果在强制执行内存限制但未指定 maxconn 或 maxsslconn 的情况下,HAProxy 将自动调整这些值,以便 100% 的连接可以安全地通过 SSL 进行,并考虑已启用 SSL 的各个方面(前端、后端或两者)。
将每个进程每秒的最大 SSL 会话数设置为 <number>。当达到此限制时,SSL 侦听器将停止接受连接。它可以用来限制全局 SSL CPU 使用率,而不考虑每个前端的容量。需要注意的是,这只能用作服务保护措施,因为当达到限制时,前端之间不一定会公平分配,所以最好也为每个前端限制一个接近其预期份额的值。同样重要的是要注意,会话是在进入 SSL 堆栈之前而不是之后计算的,这也保护了堆栈免受不良握手的影响。此外,降低 tune.maxaccept 可以提高公平性。
设置 zlib 每个进程可用的最大 RAM 量(以兆字节为单位)。当达到最大量时,只要 RAM 不可用,将来的会话将不会压缩。当设置为 0 时,没有限制。默认值为 0。该值在 UNIX 套接字上以字节为单位可用,通过 "show info" 命令的 "MaxZlibMemUsage" 行显示,zlib 使用的内存为 "ZlibMemUsage"(以字节为单位)。
禁用在 Linux 上使用 "epoll" 事件轮询系统。它等同于命令行参数 "-de"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
禁用在 BSD 上使用 "kqueue" 事件轮询系统。它等同于命令行参数 "-dk"。下一个使用的轮询系统通常是 "poll"。另请参阅 "nopoll"。
禁用 "poll" 事件轮询系统的使用。它等同于命令行参数 "-dp"。下一个使用的轮询系统将是 "select"。通常不需要禁用 "poll",因为它在 HAProxy 支持的所有平台上都可用。另请参阅 "nokqueue" 和 "noepoll"。
禁用在 Linux 上使用内核在套接字之间进行 tcp 拼接。它等同于命令行参数 "-dS"。数据将使用传统的、更具可移植性的 recv/send 调用进行复制。内核 tcp 拼接仅限于一些非常近期的内核 2.6 实例。大多数 2.6.25 到 2.6.28 之间的版本都有错误,会转发损坏的数据,因此不得使用。此选项使得在有疑问时可以轻松地全局禁用内核拼接。另请参阅 "option splice-auto"、"option splice-request" 和 "option splice-response"。
禁用使用 getaddrinfo(3) 进行名称解析。它等同于命令行参数 "-dG"。将使用已弃用的 gethostbyname(3)。
禁用 SO_REUSEPORT 的使用 - 请参阅 socket(7)。它等同于命令行参数 "-dR"。
有时,希望避免以精确的间隔向服务器发送代理和健康检查,例如当许多逻辑服务器位于同一物理服务器上时。借助此参数,可以在检查间隔中添加 0 到 +/- 50% 之间的随机性。2 到 5 之间的值似乎效果很好。默认值仍为 0。
为每个进程可能分配的缓冲区数量设置硬限制。默认值为零,表示无限制。最小的非零值将始终大于“tune.buffers.reserve”,并且理想情况下应始终是其大小的两倍。强制设置此值可以特别有效地限制进程可能占用的内存量,同时保持正常行为。当达到此限制时,需要缓冲区的会话将等待另一个缓冲区被另一个会话释放。由于缓冲区是动态分配和释放的,因此等待时间非常短,并且只要限制保持合理,就不会被感知。事实上,有时降低限制可以通过提高 CPU 缓存的效率来提高性能。测试表明,对于平均 HTTP 流量,将限制设置为预期全局 maxconn 设置的 1/10 可获得良好结果,这还显著降低了内存使用量。内存节省来自于一个事实,即某些连接不会分配 2*tune.bufsize。除非 HAProxy 核心开发人员建议,否则最好不要更改此值。
设置预分配并保留的缓冲区数量,仅在内存分配失败导致的内存短缺情况下使用。最小值为 2,也是默认值。用户没有理由更改此值,它主要针对 haproxy 核心开发人员。
将缓冲区大小设置为此大小(以字节为单位)。较低的值允许更多的会话在相同数量的 RAM 中共存,而较高的值允许某些具有非常大 cookie 的应用程序正常工作。默认值为 16384,可以在构建时更改。强烈建议不要更改此值,因为非常低的值会破坏某些服务(如统计信息),而大于默认大小的值会增加内存使用量,可能导致系统内存不足。至少,全局 maxconn 参数应减小与此参数增加相同的比例。如果 HTTP 请求大于 (tune.bufsize - tune.maxrewrite),HAProxy 将返回 HTTP 400 (Bad Request) 错误。同样,如果 HTTP 响应大于此大小,HAProxy 将返回 HTTP 502 (Bad Gateway)。
将检查缓冲区大小设置为此大小(以字节为单位)。较高的值可能有助于在非常大的页面中查找字符串或正则表达式模式,但这可能意味着更多的内存和 CPU 使用。默认值为 16384,可以在构建时更改。不建议更改此值,而应尽可能使用更好的检查方法。
设置最大压缩级别。压缩级别影响压缩期间的 CPU 使用率。此值影响压缩期间的 CPU 使用率。每个使用压缩的会话都使用此值初始化压缩算法。默认值为 1。
设置捕获的 cookie 的最大长度。"capture cookie xxx len yyy" 允许的最大值将是此值,任何更高的值都将自动截断为此值。重要的是不要设置太高的值,因为所有 cookie 捕获无论其配置值如何都会分配此大小(它们共享一个池)。此值是每个请求每个响应的,因此每个连接分配的内存是此值的两倍。如果未指定,限制设置为 63 个字符。建议不要更改此值。
设置请求中的最大报头数。当请求的报头数(包括第一行)大于此值时,它将被拒绝,并返回 "400 Bad Request" 状态码。同样,过大的响应将被阻止,并返回 "502 Bad Gateway"。默认值为 101,对于所有用途来说已经足够,考虑到广泛部署的 Apache 服务器也使用相同的限制。有时可以进一步提高此限制,以便在修复错误的应用程序之前临时允许其工作。可接受的范围是 1..32767。请记住,每个新报头都会为每个会话消耗 32 位的内存,因此不要将此限制设置得太高。
设置 HAProxy 在多长时间后认为空缓冲区可能与空闲流相关联。这用于在交替转发大数据和小数据时优化某些数据包的大小。使用 splice() 或在 SSL 中发送大缓冲区进行的决策由此参数决定。该值以毫秒为单位,范围在 0 到 65535 之间。值为零表示 HAProxy 不会尝试检测空闲流。默认值为 1000,这似乎能正确检测最终用户的暂停(例如,在单击之前阅读页面)。更改此值应该没有理由。请检查下面的 tune.ssl.maxrecord。
此指令强制 Lua 引擎每执行 <number> 条指令执行一次 yield。这允许中断长时间运行的脚本,并允许 HAProxy 调度程序处理其他任务,例如接受连接或转发流量。默认值为 10000 条指令。如果 HAProxy 经常执行一些 Lua 代码但需要更高的响应性,则可以降低此值。如果 Lua 代码相当长,并且其结果对于处理数据绝对是必需的,则可以增加 <number>。
设置 Lua 每个进程可用的最大 RAM 量(以兆字节为单位)。默认情况下为零,表示无限制。设置限制很重要,以确保脚本中的错误不会导致系统内存耗尽。
这是 Lua 会话的执行超时。这对于防止无限循环或在 Lua 中花费过多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行 sleep,则 sleep 不会计入。默认超时为 4 秒。
目的与 "tune.lua.session-timeout" 相同,但此超时专用于任务。默认情况下,此超时未设置,因为任务可能在 HAProxy 的整个生命周期内保持活动状态。例如,用于检查服务器的任务。
这是 Lua 服务的执行超时。这对于防止无限循环或在 Lua 中花费过多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行 sleep,则 sleep 不会计入。默认超时为 4 秒。
设置一个进程在切换到其他工作之前可以连续接受的最大连接数。在单进程模式下,较高的数字在高连接率下性能更好。然而,在多进程模式下,在进程之间保持一点公平性通常能更好地提高性能。此值单独应用于每个侦听器,以便考虑到侦听器绑定的进程数。此值默认为 64。在多进程模式下,它除以侦听器绑定的进程数的两倍。将此值设置为 -1 将完全禁用此限制。通常不需要调整此值。
设置一次调用轮询系统可以处理的最大事件量。默认值根据操作系统进行调整。已经注意到,将其降低到 200 以下会略微降低延迟,但会牺牲网络带宽,而将其增加到 200 以上则会以延迟换取略微增加的带宽。
将保留的缓冲区空间设置为此大小(以字节为单位)。保留空间用于报头重写或追加。套接字上的第一次读取永远不会超过 bufsize-maxrewrite。历史上,它默认为 bufsize 的一半,但这没有太大意义,因为很少有大量的报头需要添加。设置得太高会妨碍处理大的请求或响应。设置得太低会妨碍向已有的较大请求或 POST 请求添加新报头。通常明智的做法是将其设置为大约 1024。如果大于 bufsize 的一半,它会自动调整为 bufsize 的一半。这意味着您在更改 bufsize 时不必担心它。
将模式查找缓存的大小设置为 <number> 条目。这是一个 LRU 缓存,可以记住之前的查找及其结果。ACL 和映射在缓慢的模式查找中使用它,特别是使用“sub”、“reg”、“dir”、“dom”、“end”、“bin”匹配方法以及不区分大小写的字符串。它适用于模式表达式,这意味着它能够记住配置行(包括从文件中加载的所有配置行)上指定的所有模式的查找结果。它会自动使通过 HTTP 操作或 CLI 更新的条目失效。默认缓存大小设置为 10000 个条目,这限制了其内存占用,在 32 位系统上约为 5 MB,在 64 位系统上约为 8 MB。此缓存中发生冲突的风险非常低,其风险大致等于缓存大小除以 2^64。通常,在每秒 10000 次请求和默认缓存大小 10000 个条目的情况下,暴力攻击导致单个冲突的概率在 60 年后为 1%,在 6 年后为 0.1%。这被认为远低于因老化组件引起的内存损坏风险。如果这不可接受,可以通过将此参数设置为 0 来禁用缓存。
将内核管道缓冲区大小设置为此大小(以字节为单位)。默认情况下,管道是系统的默认大小。但有时在使用 TCP 拼接时,增加管道大小可以提高性能,特别是在怀疑管道未被填满且执行了许多 splice() 调用时。这对内核的内存占用有影响,因此如果影响不明确,则不应更改此值。
将客户端或服务器端的内核套接字接收缓冲区大小强制设置为指定的字节数。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小 (0) 允许内核根据可用内存量自动调整此值。然而,有时将其设置为非常小的值(例如 4096)可以节省内核内存,防止它缓冲过多的接收数据。然而,较低的值会显著增加 CPU 使用率。
HAProxy 使用一些提示来检测短读是否表示套接字缓冲区的结束。其中一个提示是读取返回的字节数超过 <recv_enough>,默认为 10136(7 个段,每个段 1448 字节)。此默认值可以通过此设置更改,以更好地处理涉及大量短消息的工作负载,例如 telnet 或 SSH 会话。
将客户端或服务器端的内核套接字发送缓冲区大小强制设置为指定的字节数。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小 (0) 允许内核根据可用内存量自动调整此值。然而,有时将其设置为非常小的值(例如 4096)可以节省内核内存,防止它缓冲过多的接收数据。然而,较低的值会显著增加 CPU 使用率。另一个用例是防止由于内核等待大部分缓冲区被读取然后才再次通知 HAProxy 而导致的极慢客户端的写入超时。
以块数为单位设置全局 SSL 会话缓存的最大大小。一个块足够大,可以包含不带对端证书的编码会话。带有对端证书的编码会话根据对端证书的大小存储在多个块中。一个块约占用 200 字节内存。默认值可能在构建时强制设置,否则默认为 20000。当缓存已满时,最不活跃的条目将被清除并重新分配。较高的值会减少这种清除的发生频率,从而减少 CPU 密集型 SSL 握手的次数,确保所有用户尽可能长时间地保留其会话。所有条目在启动时预先分配,并且如果“nbproc”大于 1 时,会在所有进程之间共享。将此值设置为 0 将禁用 SSL 会话缓存。此选项禁用所有进程之间的 SSL 会话缓存共享。通常不应使用它,因为它会由于客户端命中随机进程而强制进行许多重新协商。但在某些操作系统上可能需要它,因为这些操作系统上可能无法使用任何 SSL 缓存同步方法。在这种情况下,在 SSL 层之前添加第一层基于哈希的负载均衡可能会限制缺少会话共享的影响。
设置缓存的 SSL 会话可以保持有效的时长。此时间以秒为单位表示,默认为 300(5 分钟)。重要的是要理解,这并不保证会话会持续那么长时间,因为如果缓存已满,最长时间空闲的会话将被清除,尽管它们配置了生命周期。此设置的真正用处是防止会话被使用太长时间。
设置一次传递给 SSL_write() 的最大字节数。默认值 0 表示没有限制。在 SSL/TLS 上,客户端只能在收到完整记录后才能解密数据。对于大型记录,这意味着客户端可能需要下载多达 16kB 的数据才能开始处理它们。限制此值可以提高位于高延迟或低带宽网络上的浏览器的页面加载时间。建议找到适合 1 或 2 个 TCP 段的最佳值(通常在以太网上传输时间戳时为 1448 字节,禁用时间戳时为 1460 字节),同时记住 SSL/TLS 会增加一些开销。测试期间,典型的 1419 和 2859 值取得了良好效果。使用“strace -e trace=write”查找最佳值。HAProxy 在检测到空闲流后(请参阅上面的 tune.idletimer)会自动切换到此设置。
在 DHE 密钥交换的情况下,设置用于生成临时/瞬时 Diffie-Hellman 密钥的 Diffie-Hellman 参数的最大大小。最终大小将尝试匹配服务器的 RSA(或 DSA)密钥的大小(例如,对于 2048 位 RSA 密钥使用 2048 位临时 DH 密钥),但不会超过此最大值。默认值为 1024。只允许 1024 或更高的值。较高的值会增加 CPU 负载,而大于 1024 位的值不受 Java 7 及更早版本的客户端支持。如果直接在证书文件中或使用 ssl-dh-param-file 参数提供了静态 Diffie-Hellman 参数,则不使用此值。
将用于存储生成证书的缓存大小设置为 <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。
启用调试模式,将所有交换信息转储到标准输出,并禁止 fork 到后台。它等同于命令行参数 "-d"。它绝不应在生产配置中使用,因为它可能会阻止系统完全启动。
启动期间不显示任何消息。它等同于命令行参数 "-q"。
可以通过仅允许经过身份验证和授权的用户来控制对前端/后端/侦听部分或 http 统计信息的访问。为此,需要创建至少一个用户列表并定义用户。
创建名为 <listname> 的新用户列表。可以使用许多独立的用户列表来存储独立客户的身份验证和授权数据。
将组 <groupname> 添加到当前用户列表。也可以通过使用逗号分隔的名称列表(前面有 "users" 关键字)将用户附加到此组。
将用户 <username> 添加到当前用户列表。可以使用安全(加密)和不安全(未加密)的密码。加密密码使用 crypt(3) 函数进行评估,因此根据系统的功能,支持不同的算法。例如,现代基于 Glibc 的 Linux 系统支持 MD5、SHA-256、SHA-512,当然还有经典的基于 DES 的密码加密方法。
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
请注意,这两个列表在功能上是相同的。
可以在多个 haproxy 实例之间通过 TCP 连接以多主方式传播粘性表中的任何数据类型的条目。每个实例将其本地更新和插入推送到远程对等节点。推送的值会覆盖远程值,而不进行聚合。中断的交换会自动检测并从最后一个已知点恢复。此外,在软重启期间,旧进程使用这样的 TCP 连接连接到新进程,以在新进程尝试连接其他对等节点之前推送其所有条目。这确保了在重新加载期间的快速复制,即使对于大型表,通常也只需要几分之一秒。请注意,服务器 ID 用于远程识别服务器,因此重要的是配置看起来相似,或者至少在所有参与者上对每个服务器强制使用相同的 ID。
创建名为 <peersect> 的新对等节点列表。它是一个独立的部分,由一个或多个粘性表引用。
禁用一个对等节点部分。它会禁用与此部分相关的侦听和任何同步。这用于禁用粘性表的同步,而无需注释掉所有 "peers" 引用。
这会重新启用先前被禁用的对等节点部分。
在对等节点部分内定义一个对等节点。如果 <peername> 设置为本地对等节点名称(默认为主机名,或使用 "-L" 命令行选项强制指定),haproxy 将在 <ip>:<port> 上侦听传入的远程对等节点连接。否则,<ip>:<port> 定义了连接到远程对等节点的位置,<peername> 在协议级别用于在服务器端识别和验证远程对等节点。在软重启期间,旧实例使用本地对等节点 <ip>:<port> 连接到新实例并启动完整的复制(教学过程)。强烈建议在所有对等节点上具有完全相同的 peers 声明,并且仅依赖 "-L" 命令行参数来更改本地对等节点名称。这使得在所有对等节点之间维护一致的配置文件变得更容易。您可能希望在地址参数中引用一些环境变量,请参阅关于环境变量的第 2.3 节。
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
当服务器状态发生变化时,可以发送电子邮件警报。如果配置了电子邮件警报,则会发送到邮件发送器部分中配置的每个邮件发送器。电子邮件使用 SMTP 发送给邮件发送器。
创建名为 <mailersect> 的新邮件发送器列表。它是一个独立的部分,由一个或多个代引用。
在邮件发送器部分内定义一个邮件发送器。
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
定义可用于建立邮件/连接并发送到邮件服务器的时间。如果未定义,默认值为 10 秒。为了允许在初始 TCP 握手期间至少发送两个 SYN-ACK 数据包,建议将此值保持在 4 秒以上。
mailers mymailers timeout mail 20s mailer smtp1 192.168.0.1:587
代理配置可以在以下部分中找到:- defaults [<name>] - frontend <name> - backend <name> - listen <name> "defaults" 部分设置了其声明后所有其他部分的默认参数。这些默认参数会在下一个 "defaults" 部分重置。有关可以在 "defaults" 部分设置的参数列表,请参阅下文。名称是可选的,但为了提高可读性,建议使用。 "frontend" 部分描述了一组接受客户端连接的监听套接字。 "backend" 部分描述了一组服务器,代理将连接到这些服务器来转发传入的连接。 "listen" 部分在一个部分中定义了一个完整的代理,包含其前端和后端部分。这对于纯 TCP 流量通常很有用。所有代理名称必须由大写和小写字母、数字、'-'(连字符)、'_'(下划线)、'.'(点)和':'(冒号)组成。 ACL 名称区分大小写,这意味着 "www" 和 "WWW" 是两个不同的代理。历史上,所有代理名称都可以重叠,这只会给日志带来麻烦。自从引入内容切换以来,具有重叠功能(frontend/backend)的两个代理必须具有不同的名称。但是,前端和后端仍然可以共享相同的名称,因为这种配置似乎很常见。目前支持两种主要的代理模式:"tcp",也称为第 4 层,和 "http",也称为第 7 层。在第 4 层模式下,HAProxy 仅在双方之间转发双向流量。在第 7 层模式下,HAProxy 会分析协议,并可以根据任意标准允许、阻止、切换、添加、修改或删除请求或响应中的任意内容来与之交互。在 HTTP 模式下,应用于通过连接流动的请求和响应的处理取决于前端的 HTTP 选项和后端的组合。HAProxy 支持 5 种连接模式:- KAL:keep alive ("option http-keep-alive"),这是默认模式:所有请求和响应都经过处理,连接在响应和新请求之间保持打开但空闲状态。- TUN:tunnel ("option http-tunnel"):这是版本 1.0 到 1.5-dev21 的默认模式:仅处理第一个请求和响应,其余所有内容都未经分析直接转发。此模式不应使用,因为它会导致日志记录和 HTTP 处理出现许多问题。- PCL:passive close ("option httpclose"):与 tunnel 模式完全相同,但在两个方向上都附加了 "Connection: close",以尝试使双方在第一次请求/响应交换后关闭。- SCL:server close ("option http-server-close"):在收到响应结束后,面向服务器的连接将被关闭,但面向客户端的连接将保持打开状态。- FCL:forced close ("option forceclose"):在响应结束后,连接将被主动关闭。通过前端和后端传递的连接将适用的有效模式可以通过以下矩阵中的两种代理模式确定,但简而言之,模式是对称的,keep-alive 是最弱的选项,force close 是最强的。 Backend mode | KAL | TUN | PCL | SCL | FCL ----+-----+-----+-----+-----+---- KAL | KAL | TUN | PCL | SCL | FCL ----+-----+-----+-----+-----+---- TUN | TUN | TUN | PCL | SCL | FCL Frontend ----+-----+-----+-----+-----+---- mode PCL | PCL | PCL | PCL | FCL | FCL ----+-----+-----+-----+-----+---- SCL | SCL | SCL | FCL | SCL | FCL ----+-----+-----+-----+-----+---- FCL | FCL | FCL | FCL | FCL | FCL支持以下关键字列表。其中大多数只能在有限的节类型中使用。其中一些被标记为“已弃用”,因为它们继承自旧的语法,可能令人困惑或功能有限,并且有新的推荐关键字来替换它们。标记为“(*)”的关键字可以使用“no”前缀选择性地反转,例如“no option contstats”。当选项默认启用并且必须为特定实例禁用时,这样做是有意义的。这些选项也可以以“default”为前缀,以恢复默认设置,无论在之前的“defaults”节中指定了什么。
本节提供了每个关键字及其用法的描述。
声明或完成一个访问控制列表。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
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 节。
基于一个现有的应用程序 cookie 定义会话粘性。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<cookie> 这是应用程序使用的 cookie 的名称,HAProxy 需要为每个新会话学习它。<length> 这是在每个 cookie 值中要记忆和检查的最大字符数。<holdtime> 这是 cookie 如果未使用,将在多久后从内存中删除。如果未指定单位,则此时间以毫秒为单位。request-learn 如果指定此选项,则当服务器未在响应中指定 cookie 时,haproxy 将能够学习请求中找到的 cookie。这通常是 PHPSESSID cookie 的情况,或者当 haproxy 的会话在应用程序的会话之前过期并且选择了正确的服务器时。建议指定此选项以提高可靠性。prefix 如果指定此选项,haproxy 将匹配 cookie 前缀(或 URL 参数前缀)。appsession 值是此前缀后的数据。例如:appsession ASPSESSIONID len 64 timeout 3h prefix 这将匹配 cookie ASPSESSIONIDXXXX=XXXXX,appsession 值将是 XXXX=XXXXX。mode 此选项允许更改 URL 解析器模式。目前支持 2 种模式:- path-parameters:解析器在路径参数部分(每个参数用分号分隔)查找 appsession,例如 JSESSIONID 很方便。如果未设置此选项,则这是默认模式。- query-string:在此模式下,解析器将在查询字符串中查找 appsession。
从 1.6 版本开始,appsession 已被移除。使用 stick-tables 更灵活、更方便,并且 stick-tables 支持多主复制和跨重载的数据保留,而 appsession 不支持。
向系统提供关于期望的监听队列(backlog)大致大小的提示。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<conns> 是待处理连接的数量。根据操作系统的不同,它可能表示已确认的连接数、未确认的连接数或两者之和。
为了防范 SYN 洪水攻击,一种解决方案是增加系统的 SYN 队列大小。根据系统的不同,有时它只能通过系统参数进行调整,有时根本无法调整,有时系统依赖于应用程序在调用 listen() 系统调用时给出的提示。默认情况下,HAProxy 将前端的 maxconn 值传递给 listen() 系统调用。在可以利用此值的系统上,有时能够指定一个不同的值会很有用,因此有了这个 backlog 参数。在 Linux 2.4 上,该参数被系统忽略。在 Linux 2.6 上,它被用作一个提示,系统最多接受不小于该值的最小的 2 的幂次方,并且永远不会超过某些限制(通常是 32768)。
定义在后端中使用的负载均衡算法。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<algorithm> 是在进行负载均衡时用于选择服务器的算法。这仅适用于没有持久性信息可用时,或当连接被重新分发到另一台服务器时。<algorithm> 可能是以下之一:roundrobin 每个服务器按其权重轮流使用。当服务器的处理时间保持相等分布时,这是最平滑、最公平的算法。此算法是动态的,这意味着服务器权重可以动态调整,例如用于慢启动。它被设计限制为每个后端最多 4095 个活动服务器。请注意,在一些大型集群中,当一台服务器在非常短的时间内从宕机状态恢复后,可能需要几百个请求才能将其重新集成到集群中并开始接收流量。这是正常的,尽管非常罕见。在此处提及是为了以防万一您有机会观察到它,以免担心。static-rr 每个服务器按其权重轮流使用。此算法与 roundrobin 非常相似,不同之处在于它是静态的,这意味着动态更改服务器权重将无效。另一方面,它对服务器数量没有设计限制,并且当服务器启动时,在重新计算完整映射后,它将始终立即重新引入集群。它还使用略少的 CPU 来运行(约 -1%)。leastconn 连接数最少的服务器接收连接。通过相同负载的服务器组进行轮询,以确保所有服务器都得到使用。建议在预期会话非常长的情况下使用此算法,例如 LDAP、SQL、TSE 等……但不适用于使用短会话的协议,如 HTTP。此算法是动态的,这意味着服务器权重可以动态调整,例如用于慢启动。first 具有可用连接槽的第一台服务器接收连接。服务器按最低数字标识符到最高数字标识符(请参阅服务器参数“id”)选择,默认为服务器在集群中的位置。一旦服务器达到其 maxconn 值,就会使用下一台服务器。不设置 maxconn 而使用此算法没有意义。此算法的目的是始终使用最少数量的服务器,以便在非高峰时段关闭额外的服务器。此算法会忽略服务器权重,并且对 RDP 或 IMAP 等长会话比 HTTP 更有益,尽管在 HTTP 中也有用。为了有效地使用此算法,建议云控制器定期检查服务器使用情况,在未使用的服务器关闭,并在队列膨胀时定期检查后端队列以开启新服务器。或者,使用“http-check send-state”可以告知服务器负载情况。source 源 IP 地址被哈希并除以运行服务器的总权重,以指定哪个服务器将接收请求。这确保了只要没有服务器宕机或上线,相同的客户端 IP 地址将始终访问同一台服务器。如果由于运行服务器数量的变化导致哈希结果发生变化,许多客户端将被定向到不同的服务器。此算法通常用于 TCP 模式,其中可能不会插入 cookie。它也可以在 Internet 上使用,以向拒绝会话 cookie 的客户端提供最佳的粘性。此算法默认是静态的,这意味着动态更改服务器权重将无效,但可以使用“hash-type”进行更改。uri 该算法哈希 URI 的左侧部分(问号之前)或整个 URI(如果存在“whole”参数),并将其哈希值除以运行服务器的总权重。结果指定将哪个服务器接收请求。这确保只要没有服务器上线或宕机,相同的 URI 将始终定向到同一台服务器。这用于代理缓存和防病毒代理,以最大化缓存命中率。请注意,此算法只能在 HTTP 后端使用。此算法默认是静态的,这意味着动态更改服务器权重将无效,但可以使用“hash-type”进行更改。此算法支持两个可选参数“len”和“depth”,后面都跟一个正整数。当需要仅基于 URI 的开头来平衡服务器时,这些选项可能很有用。“len”参数表示算法应仅考虑 URI 开头的字符数来计算哈希。请注意,“len”设置为 1 很少有意义,因为大多数 URI 都以斜杠“/”开头。“depth”参数表示用于计算哈希的最大目录深度。每次请求中的斜杠都算作一个级别。如果指定了这两个参数,则在达到其中一个时评估停止。url_param 参数中指定的 URL 参数将在每个 HTTP GET 请求的查询字符串中查找。如果使用“check_post”修饰符,则会在 HTTP POST 请求实体中搜索参数参数,当它在 URL 中问号 ('?') 之后的查询字符串中找不到时。消息体将在收到广告的数据量或请求缓冲区已满后才开始被分析。在极少数情况下,如果使用分块编码,则仅扫描第一个块。以块边界分隔的参数值可能会被随机平衡,如果根本不平衡的话。此关键字曾支持一个可选的 <max_wait> 参数,但现在已被忽略。如果找到该参数,后面跟着一个等号 ('=') 和一个值,则该值被哈希并除以运行服务器的总权重。结果指定将哪个服务器接收请求。这用于跟踪请求中的用户标识符,并确保只要没有服务器上线或宕机,同一个用户 ID 就会始终发送到同一台服务器。如果找不到值或找不到参数,则应用轮询算法。请注意,此算法只能在 HTTP 后端使用。此算法默认是静态的,这意味着动态更改服务器权重将无效,但可以使用“hash-type”进行更改。hdr(<name>) HTTP 标头 <name> 将在每个 HTTP 请求中查找。就像等效的 ACL 'hdr()' 函数一样,括号中的标头名称不区分大小写。如果标头不存在或不包含任何值,则改为应用 roundrobin 算法。一个可选的“use_domain_only”参数可用,用于将哈希算法缩减到具有特定标头(如“Host”)的主域部分。例如,在主机值“haproxy.1wt.eu”中,只考虑“1wt”。此算法默认是静态的,这意味着动态更改服务器权重将无效,但可以使用“hash-type”进行更改。rdp-cookie rdp-cookie(<name>) RDP cookie <name>(如果省略则为“mstshash”)将在每个传入的 TCP 请求中被查找和哈希。就像等效的 ACL 'req_rdp_cookie()' 函数一样,名称不区分大小写。这种机制很有用,作为一种降级的持久性模式,因为它使得可以将同一个用户(或同一个会话 ID)始终发送到同一台服务器。如果找不到 cookie,则使用正常的 roundrobin 算法。请注意,要使其正常工作,前端必须确保 RDP cookie 已存在于请求缓冲区中。为此,您必须使用“tcp-request content accept”规则并结合“req_rdp_cookie_cnt”ACL。此算法默认是静态的,这意味着动态更改服务器权重将无效,但可以使用“hash-type”进行更改。另请参阅 rdp_cookie 模式提取函数。<arguments> 是某些算法可能需要的可选参数列表。目前,只有“url_param”和“uri”支持可选参数。
当没有设置其他算法、模式或选项时,后端的负载均衡算法被设置为 roundrobin。每个后端只能设置一次算法。
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 reqideny 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 类型消息体无关。
在前端(frontend)中定义一个或多个监听地址和/或端口。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<address> 是可选的,可以是主机名、IPv4 地址、IPv6 地址或 '*'。它指定前端将监听的地址。如果未设置,则监听系统的所有 IPv4 地址。对于 '*' 或系统特殊地址 "0.0.0.0" 也适用。IPv6 等效是 '::'。可以选择使用地址族前缀,然后在地址之前强制指定地址族,这对于指定没有斜杠 ('/') 的 unix 套接字的路径很有用。当前支持的前缀有:- 'ipv4@' -> 地址始终是 IPv4- 'ipv6@' -> 地址始终是 IPv6- 'unix@' -> 地址是本地 unix 套接字的路径- 'abns@' -> 地址在抽象命名空间(仅限 Linux)。注意:由于抽象套接字不是“可重绑定的”,它们与软重启期间的多进程模式不兼容,因此最好避免在 nbproc 大于 1 的情况下使用它们。效果是,如果新进程启动失败,旧进程中只有一个能够重新绑定到套接字。- 'fd@<n>' -> 使用从父进程继承的文件描述符 <n>。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 兼容。
将一个实例的可见性限制在特定的进程号集合中。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
all 所有进程都会看到此实例。这是默认设置。它可用于覆盖默认值。odd 此实例将在进程 1,3,5,...63 上启用。此选项可以与其他数字组合使用。even 此实例将在进程 2,4,6,...64 上启用。此选项可以与其他数字组合使用。不要将其与少于 2 个进程一起使用,否则某些实例可能会从所有进程中丢失。number 该实例将在此进程号或范围内启用,其值必须全部在 1 到 32 或 64 之间,具体取决于机器的字大小。如果代理绑定到大于配置的 global.nbproc 的进程号,它将被强制绑定到进程 #1(如果指定了单个进程)或绑定到所有进程(否则)。
此关键字限制将某些实例绑定到某些进程。这有助于避免过多的进程监听同一端口。例如,在双核机器上,可以在 global 部分设置 'nbproc 2',然后将监听器分配到 'odd' 和 'even' 实例。目前,无法使用此关键字引用超过 32 或 64 个进程,但这对于大多数设置来说应该足够了。请注意,'all' 实际上意味着所有进程,而不管机器的字大小,并且不限于前 32 或 64 个。每个“bind”行还可以进一步限制为代理进程的子集,请参阅 第 5.1 节中的“process”绑定关键字。当前端没有显式的“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
如果/除非条件匹配,则阻止一个第 7 层请求。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
如果在层 7 处理的早期匹配/不匹配 <condition>,HTTP 请求将被阻止。如果请求被阻止,将返回 403 错误。该条件必须引用 ACL(参见 第 7 节)。这通常用于在满足或不满足某些条件时拒绝访问某些敏感资源。每个“block”语句没有固定数量的限制。要在第 4 层阻止连接(不发送 403 错误),请参阅“tcp-request connection reject”和“tcp-request content reject”规则。此形式已弃用,请勿在新配置中使用,而是使用新的“http-request deny”。
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 # block 已弃用。请改用 http-request deny: #block if invalid_src || local_dst http-request deny if invalid_src || local_dst
在请求和响应中捕获并记录一个 cookie。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<name> 是要捕获的 Cookie 名称的开头。为了精确匹配名称,只需在名称后加上等号 ('=')。完整名称将出现在日志中,这对于调整 Cookie 名称和值(例如:ASPSESSIONXXXXX)的应用程序服务器很有用。<length> 是在日志中报告的最大字符数,包括 Cookie 名称、等号和值,所有这些都以标准的“name=value”形式。如果字符串超过 <length>,则会在右侧截断。
只捕获第一个 Cookie。同时监控“cookie”请求头和“set-cookie”响应头。这对于检查导致用户之间会话交叉或盗窃的应用程序错误特别有用,因为用户 Cookie 通常只能在登录页面上更改。当客户端未提供 Cookie 时,关联的日志列将报告“-”。当请求不导致服务器分配 Cookie 时,将在响应列中报告“-”。捕获仅在前段进行,因为日志格式对于给定的前端不应因后端而改变。这将来可能会改变。请注意,一个前端只能有一个“capture cookie”语句。最大捕获长度由全局“tune.http.cookielen”设置确定,默认为 63 个字符。不能在“defaults”部分指定捕获。
capture cookie ASPSESSION len 32
捕获并记录指定请求头的最后一次出现。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<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
捕获并记录指定响应头的最后一次出现。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<name> 是要捕获的头的名称。头名称不区分大小写,但通常的做法是按照它们在响应中出现的样子来写,每个单词的首字母大写。头名称不会出现在日志中,只报告其值,但其在日志中的位置会得到尊重。<length> 是从值中提取并报告在日志中的最大字符数。如果字符串超过 <length>,它将被从右侧截断。
捕获该头最后一次出现的完整值。结果将在捕获的请求头之后,添加在日志中的大括号 ('{}') 之间。如果捕获了多个头,它们将由竖线 ('|') 分隔,并按照它们在配置中声明的相同顺序出现。不存在的头将被记录为空字符串。响应头捕获的常见用途包括 "Content-length" 头,它指示预计将返回多少字节,以及 "Location" 头,用于跟踪重定向。捕获的响应头数量及其长度没有限制,但明智的做法是保持它们较低以限制每个会话的内存使用。为了保持同一前端的日志格式一致,头捕获只能在前端声明。不能在 "defaults" 配置段中指定捕获。capture response header Content-length len 9 capture response header Location len 15
设置客户端侧的最大不活动时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 超时值默认以毫秒为单位指定,但也可以是任何其他单位,如果数字后跟有单位后缀,如本文档开头所述。
不活动超时适用于客户端应确认或发送数据时。在 HTTP 模式下,此超时在第一阶段(客户端发送请求时)和响应期间(客户端读取服务器发送的数据时)尤其重要。默认情况下,该值以毫秒为单位指定,但如果数字后缀有单位,则可以为任何其他单位,如本文档顶部所述。在 TCP 模式下(以及在 HTTP 模式下,程度较小),强烈建议客户端超时与服务器超时保持相等,以避免复杂的调试情况。良好的做法是通过指定略高于 3 秒倍数的超时(例如 4 或 5 秒)来覆盖一个或多个 TCP 数据包丢失。此参数特定于前端,但可以一次性在“defaults”部分指定。这实际上是最简单的解决方案之一,以免忘记它。未指定的超时将导致无限超时,这是不推荐的。这种用法是可以接受的并且可以工作,但在启动期间会报告警告,因为它可能导致系统中累积过期的会话(如果系统超时未配置)。此参数是为了兼容性而提供的,但目前已弃用。请改用“timeout client”。
启用 HTTP 压缩。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
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* 响应头“Transfer-Encoding”包含“chunked”(临时解决方法)* 响应不包含“Content-Length”头,也不包含最后一个值为“chunked”的“Transfer-Encoding”* 响应包含“Content-Type”头,其第一个值以“multipart”开头* 响应在“Cache-control”头中包含“no-transform”值* User-Agent 匹配“Mozilla/4”,除非它是带有 XP SP2 的 MSIE 6,或 MSIE 7 及更高版本* 响应包含“Content-Encoding”头,表示响应已压缩(请参阅压缩卸载)注意:压缩不会重写 Etag 头,也不会发出 Warning 头。
compression algo gzip compression type text/html text/plain
设置等待服务器连接尝试成功的最大时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 超时值默认以毫秒为单位指定,但也可以是任何其他单位,如果数字后跟有单位后缀,如本文档开头所述。
如果服务器位于与 haproxy 相同的局域网中,连接应该会立即建立(几毫秒以内)。无论如何,通过指定略高于 3 秒倍数的超时(例如 4 或 5 秒)来覆盖一个或多个 TCP 数据包丢失是一个好习惯。默认情况下,如果队列超时未指定,连接超时也会将队列超时设置为相同的值。从历史上看,contimeout 也用于在 listen 部分设置 tarpit 超时,这在纯前端中是不可能的。此参数特定于后端,但可以一次性在“defaults”部分指定。这实际上是最简单的解决方案之一,以免忘记它。未指定的超时将导致无限超时,这是不推荐的。这种用法是可以接受的并且可以工作,但在启动期间会报告警告,因为它可能导致系统中累积失败的会话(如果系统超时未配置)。此参数是为了向后兼容性而提供的,但目前已弃用。请改用“timeout connect”、“timeout queue”或“timeout tarpit”。
在后端启用基于 cookie 的持久性。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<name> 是将要被监控、修改或插入以实现持久性的 cookie 的名称。此 cookie 通过响应中的 "Set-Cookie" 标头发送到客户端,并在所有请求中通过客户端的 "Cookie" 标头带回。应特别注意选择一个不会与任何可能的应用程序 cookie 冲突的名称。此外,如果相同的后端服务器可能被相同的客户端使用(例如,HTTP/HTTPS),则应注意在所有后端服务器之间使用不同的 cookie 名称,除非期望它们之间存在持久性。rewrite 此关键字表示 cookie 将由服务器提供,haproxy 将不得不修改其值以在其内部设置服务器标识符。当复杂的 "Set-cookie" 和 "Cache-control" 标头组合的管理留给应用程序处理时,此模式非常方便。然后,应用程序可以决定是否发出持久性 cookie 是合适的。由于应监控所有响应,因此此模式在 HTTP 隧道模式下不起作用。除非应用程序的行为非常复杂和/或有缺陷,否则建议在新部署中不要从此模式开始。此关键字与 "insert" 和 "prefix" 不兼容。insert 此关键字表示如果客户端还没有允许其访问此服务器的 cookie,则 haproxy 将需要将其插入到服务器响应中。当不使用 "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 请求(通常是登录请求)之前不需要任何形式的持久性,因此这是一种在不冒缓存风险的情况下优化缓存的非常有效的方法。另请参阅 "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 模式 cookie。当 cookie 发送给客户端时,也会发送 cookie 发出的日期。在进一步呈现此 cookie 时,如果日期早于参数(以秒为单位)指示的延迟,则将其忽略。否则,在将响应发送给客户端时,如果需要,它将被刷新。这对于防止从不关闭浏览器的用户在同一服务器上停留时间过长(例如,在农场规模改变后)特别有用。设置此选项且 cookie 没有日期时,始终接受 cookie,但在响应中会刷新。这保留了管理员访问其站点的能力。日期超出 24 小时(未来)的 cookie 将被忽略。这样做可以使管理员修复时区问题,而不会冒着将用户踢出站点的风险。maxlife 此选项允许在一段时间后忽略插入的 cookie,无论其是否在使用中。它仅适用于 insert 模式 cookie。当 cookie 首次发送到客户端时,也会发送 cookie 发出的日期。在进一步呈现此 cookie 时,如果日期早于参数(以秒为单位)指示的延迟,则将其忽略。如果请求中的 cookie 没有日期,则接受它并设置日期。日期超出 24 小时(未来)的 cookie 将被忽略。这样做可以使管理员修复时区问题,而不会冒着将用户踢出站点的风险。与 maxidle 不同,此值不会刷新,仅第一个访问日期有效。maxidle 和 maxlife 都可以同时使用。这对于防止从不关闭浏览器的用户在同一服务器上停留时间过长(例如,在农场规模改变后)特别有用。它比 maxidle 方法更强大,因为它强制在某个绝对延迟后重新分发。attr 此选项告诉 haproxy 在插入 cookie 时添加一个额外的属性。属性值可以包含除控制字符或 ";" 以外的任何字符。此选项可以重复。
每个 HTTP 后端只能有一个持久性 cookie,并且可以在 defaults 配置段中声明。cookie 的值将是 "server" 语句中 "cookie" 关键字后指定的值。如果未为给定服务器声明 cookie,则不会设置 cookie。
cookie JSESSIONID prefix cookie SRV insert indirect nocache cookie SRV insert postonly indirect cookie SRV insert indirect nocache maxidle 30m maxlife 8h
声明一个捕获槽。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<length> 是允许捕获的长度。
此声明仅在 frontend 或 listen 配置段中可用,但保留的槽可以在 backend 中使用。“request”关键字分配一个用于请求中的捕获槽,“response”分配一个用于响应中的捕获槽。
更改后端中服务器的默认选项。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<param*> 是此服务器的参数列表。“default-server”关键字接受许多重要选项,并有专门的完整章节进行介绍。请参阅第 5 节以获取更多详细信息。
default-server inter 1000 weight 13
指定在没有匹配到“use_backend”规则时使用的后端。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<backend> 是要使用的后端的名称。
在使用“use_backend”关键字在前端和后端之间进行内容切换时,指明在没有规则匹配时将使用哪个后端通常很有用。这通常是动态后端,它将捕获所有未确定的请求。
use_backend dynamic if url_dyn use_backend static if url_css url_img extension_img default_backend dynamic
描述一个 listen、frontend 或 backend。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
允许添加一句话来在 HAProxy HTML 统计页面中描述相关对象。该描述将打印在其所描述对象名称的右侧。<string> 参数中的空格无需使用反斜杠转义。
禁用一个 proxy、frontend 或 backend。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
关键字 "disabled" 用于禁用实例,主要目的是释放监听端口或临时禁用服务。实例仍将被创建,其配置也将被检查,但它将处于 "stopped" 状态,并在统计信息中显示为此状态。它不会接收任何流量,也不会发送任何健康检查或日志。通过在 "defaults" 部分添加关键字 "disabled" 可以同时禁用多个实例。
设置一个默认服务器地址
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
“dispatch”关键字指定一个默认服务器,用于在没有其他服务器可以接受连接时使用。过去它曾被用于将非持久连接转发到辅助负载均衡器。由于其语法简单,它也被用于简单的 TCP 中继。为了更清晰,建议不要使用它,而是使用“server”指令。
启用一个 proxy、frontend 或 backend。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
关键字 "enabled" 用于显式启用实例,当默认设置为 "disabled" 时。这种情况非常少见。
返回文件内容以替代 HAProxy 生成的错误
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、403、405、408、429、500、502、503 和 504 码。<file> 指定一个包含完整 HTTP 响应的文件。建议遵循将 ".http" 追加到文件名中的常见做法,以免人们将其与 HTML 错误页面混淆,并使用绝对路径,因为文件在执行任何 chroot 之前就会被读取。
理解此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误,这一点很重要。这就是为什么支持的错误列表仅限于一小部分。响应匹配 "monitor-uri" 规则的请求会发出 200 码。文件将按原样返回到 TCP 套接字。这允许任何技巧,例如重定向到另一个 URL 或站点,以及清理 cookie、强制启用或禁用缓存等技巧... 该软件包提供了默认错误文件,其内容与默认错误相同。文件不应超过配置的缓冲区大小 (BUFSIZE),通常为 8 或 16 kB,否则将被截断。明智的做法是不包含任何对本地内容的引用(例如,图像),以避免在所有服务器都关闭时客户端和 HAProxy 之间发生循环,导致返回错误而不是图像。为了更好地符合 HTTP 标准,建议所有标头行都以 CR-LF 结尾,而不是单独的 LF。文件在配置的同时被读取并保存在内存中。因此,即使进程被 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
返回一个到某个 URL 的 HTTP 重定向,以替代 HAProxy 生成的错误
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、403、405、408、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。
返回一个到某个 URL 的 HTTP 重定向,以替代 HAProxy 生成的错误
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、403、405、408、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 之前设计的非常旧的浏览器可能不支持它,但到目前为止还没有报告过此类问题。
声明用于电子邮件警报的信封和头部的发件人电子邮件地址。这是发送电子邮件警报的来源地址。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<emailaddr> 是发送电子邮件警报时使用的发件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明将发送电子邮件警报的消息的最大日志级别。这充当发送电子邮件警报的过滤器。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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 或更低,并且发生了健康检查状态更新
声明发送电子邮件警报时要使用的邮件程序
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<mailersect> 是用于发送电子邮件警报的邮件程序部分的名称。
还需要设置“email-alert from”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明与邮件程序通信时要使用的主机名地址。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<hostname> 是与邮件程序通信时使用的主机名
默认使用系统的主机名。还需要设置“email-alert from”、“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
在电子邮件警报的信封和收件人地址中都声明收件人地址。这是发送电子邮件警报的地址。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<emailaddr> 是发送电子邮件警报时使用的收件人电子邮件地址
还需要设置“email-alert mailers”和“email-alert to”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明一个条件以强制在宕机服务器上保持持久性
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
默认情况下,请求不会分派到已关闭的服务器。可以使用 "option persist" 来强制执行此操作,但它是无条件的,并且如果设置了 "option redispatch" 则会重新分派到有效服务器。这样就几乎没有可能强制某些请求到达为维护操作而人为标记为关闭的服务器。"force-persist" 语句允许声明各种基于 ACL 的条件,当这些条件满足时,将导致请求忽略服务器的关闭状态,并仍然尝试连接到它。这使得可以启动一个服务器,仍然对健康检查返回错误,并运行一个专门配置的浏览器来测试服务。在方便的方法中,可以使用特定的源 IP 地址或特定的 cookie。cookie 的优点还在于可以从测试页面轻松地在浏览器中添加/删除。一旦服务得到验证,就可以通过对健康检查返回有效响应来向全世界开放该服务。当满足 "if" 条件或不满足 "unless" 条件时,将启用强制持久性。使用此选项时,始终禁用最终的重新分发。
将过滤器 <name> 添加到附加到代理的过滤器列表中。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<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
指定后端负载达到何种程度时服务器将达到其 maxconn
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<conns> 是后端上的连接数,该连接数将使服务器使用最大连接数。
当服务器指定了 "maxconn" 参数时,这意味着其并发连接数永远不会超过该值。此外,如果它还有一个 "minconn" 参数,则表示一个动态限制,该限制会根据后端负载进行调整。服务器将始终接受至少 <minconn> 个连接,永远不会超过 <maxconn> 个,并且当后端并发连接数少于 <conns> 时,限制将在这两个值之间变化。这使得可以在正常负载下限制服务器的负载,但在重要负载下可以进一步提高负载,而不会在异常负载下使服务器过载。由于很难正确设置此值,haproxy 会自动将其设置为可能连接到此后端的*所有前端*的 maxconn 总和的 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
在软停止后,维持代理在一段时间内可操作
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<time> 是当通过 SIGUSR1 信号接收到软停止时,实例将保持可操作且前端套接字仍在监听的时间(默认为毫秒)。
这可以用来确保服务按特定顺序消失。它被设计成这样,专用于外部设备监控的前端会立即失败,而其他前端则会保持运行,直到设备检测到故障所需的时间。请注意,目前使用此参数的好处非常小,实际上它可能会使软重新配置过程复杂化,而不是简化它。
指定有界负载一致性哈希的平衡因子
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 否![]() | 是![]() |
<factor> 是控制发送到服务器的最大并发请求数的参数,表示为所有活动服务器上平均并发请求数的百分比。
为具有 "hash-type consistent" 的服务器指定 "hash-balance-factor" 会启用一种算法,即使某些哈希桶接收的请求比其他请求多得多,也能防止任何单个服务器一次接收过多请求。将 <factor> 设置为 0(默认值)会禁用此功能。否则,<factor> 是一个大于 100 的百分比。例如,如果 <factor> 为 150,则任何服务器的负载都将不允许超过平均负载的 1.5 倍。如果使用了服务器权重,则会尊重这些权重。如果第一个选择的服务器不合格,算法将根据请求哈希选择另一个服务器,直到找到一个具有额外容量的服务器。较高的 <factor> 允许服务器之间的不平衡度更大,而较低的 <factor> 意味着平均会检查更多的服务器,从而影响性能。合理的值在 125 到 200 之间。
指定一种将哈希值映射到服务器的方法
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<method> 是用于从 <function> 计算出的哈希中选择服务器的方法:map-based 哈希表是一个包含所有存活服务器的静态数组。哈希值将非常平滑,会考虑权重,但会是静态的,意味着当服务器运行时更改权重将被忽略。这意味着不会有慢启动。此外,由于服务器是通过其在数组中的位置选择的,因此当服务器计数发生变化时,大多数映射都会被更改。这意味着当服务器上线或下线,或当服务器添加到集群时,大多数连接将被重新分配到不同的服务器。这对缓存来说可能不方便。consistent 哈希表是一个包含每个服务器许多副本的树。哈希键在树中查找,并选择最接近的服务器。此哈希是动态的,它支持在服务器运行时更改权重,因此与慢启动功能兼容。它的优点是,当服务器上线或下线时,只有它的关联会发生移动。当服务器添加到集群时,只有一部分映射会被重新分配,这使其成为缓存的理想方法。然而,由于其原理,分布永远不会非常平滑,有时可能需要调整服务器的权重或其 ID 来获得更均衡的分布。为了在多个负载均衡器上获得相同的分布,所有服务器具有完全相同的 ID 非常重要。注意:如果未指定哈希函数,consistent hash 使用 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 此指令表示不应直接使用上述哈希函数的结果,而是应首先应用一个 4 字节的全雪崩哈希。此步骤的目的是混合前一个哈希的结果位,以避免在输入包含某些有限值或服务器数量是哈希组件(SDBM 为 64,DJB2 为 33)的倍数时出现任何不良影响。启用 avalanche 倾向于使结果更不可预测,但它也不如使用原始函数时平滑。可能需要对某些工作负载进行一些测试。此哈希是 Bob Jenkins 提出的众多哈希之一。
默认的哈希类型是“map-based”,建议在大多数情况下使用。默认的函数是“sdbm”,函数的选择应基于被哈希值的范围。
在对健康检查响应 HTTP/404 时启用维护模式
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当设置此选项时,返回 HTTP 404 状态码的服务器将从进一步的负载均衡中排除,但仍会接收持久连接。这为 Web 管理员提供了一种非常方便的方法来优雅地关闭他们的服务器。同样重要的是要注意,在此模式下被检测为失败的服务器不会生成警报,只会生成一个通知。如果服务器再次响应 2xx 或 3xx,它将立即被重新插入到服务器组中。在统计页面上,处于此模式的服务器状态报告为“NOLB”。重要的是要注意,此选项仅与“httpchk”选项一起使用。如果此选项与“http-check expect”一起使用,则它优先于后者,因此 404 响应仍将被视为软停止。
使 HTTP 健康检查考虑响应内容或特定状态码
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<match> 是一个关键字,指示如何在响应中查找特定模式。该关键字可以是“status”、“rstatus”、“string”或“rstring”之一。关键字前面可以加上感叹号(“!”)以否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参见下文。<pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,必须使用通常的反斜杠('\')进行转义。
默认情况下,"option httpchk" 认为响应状态码 2xx 和 3xx 是有效的,其他都是无效的。当使用 "http-check expect" 时,它定义了什么是有效或无效的。每个后端只支持一个 "http-check" 语句。如果服务器未能响应或超时,检查显然会失败。可用的匹配有:status <string>:测试 HTTP 状态码的确切字符串匹配。如果响应的状态码与此字符串完全匹配,则健康检查响应将被视为有效。如果 "status" 关键字前面加上 "!",则如果状态码匹配,响应将被视为无效。rstatus <regex>:测试 HTTP 状态码的正则表达式。如果响应的状态码与表达式匹配,则健康检查响应将被视为有效。如果 "rstatus" 关键字前面加上 "!",则如果状态码匹配,响应将被视为无效。这主要用于检查多个代码。string <string>:测试 HTTP 响应正文中的确切字符串匹配。如果响应正文包含此确切字符串,则健康检查响应将被视为有效。如果 "string" 关键字前面加上 "!",则如果正文包含此字符串,响应将被视为无效。这可用于查找动态页面末尾的必需单词,或检测检查页面上出现特定错误(例如,堆栈跟踪)时的失败。rstring <regex>:在 HTTP 响应正文上测试正则表达式。如果响应正文与表达式匹配,则健康检查响应将被视为有效。如果 "rstring" 关键字前面加上 "!",则如果正文匹配表达式,响应将被视为无效。这可用于查找动态页面末尾的必需单词,或检测检查页面上出现特定错误(例如,堆栈跟踪)时的失败。需要注意的是,响应将被限制在全局 "tune.chksize" 选项定义的特定大小内,该选项默认为 16384 字节。因此,在使用 "string" 或 "rstring" 时,过大的响应可能不包含必需的模式。如果绝对需要大响应,可以通过设置全局变量来更改默认的最大大小。但是,需要记住的是,解析非常大的响应会浪费一些 CPU 周期,尤其是在使用正则表达式时,并且最好始终将检查重点放在较小的资源上。此外,"http-check expect" 不支持 HTTP keep-alive。请记住,它会自动添加 "Connection: close" 头,这意味着此头不应存在于 "option httpchk" 提供的请求中。最后,如果 "http-check expect" 与 "http-check disable-on-404" 结合使用,则当服务器响应 404 时,后者具有优先权。
# 只接受状态 200 为有效 http-check expect status 200 # 将 SQL 错误视为错误 http-check expect ! string SQL\ Error # 仅将状态 5xx 视为错误 http-check expect ! rstatus ^5 # 检查在 /html 之前是否有一个正确的十六进制标签 http-check expect rstring <!--tag:[0-9a-f]*--></html>
启用在 HTTP 健康检查中发送状态头
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
设置此选项后,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
第 7 层请求的访问控制
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
http-request 语句定义了一组适用于第 7 层处理的规则。当规则在 frontend、listen 或 backend 部分遇到时,将按照声明的顺序进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时,它才会被评估。第一个关键字是规则的操作。目前支持的操作包括:- "allow":这将停止规则的评估,允许请求通过检查。不再评估任何进一步的 "http-request" 规则。- "deny":这将停止规则的评估,并立即拒绝请求并发出 HTTP 403 错误,或者可以选择由 "deny_status" 的参数指定的响应码。允许的响应码列表限于可以被 "errorfile" 指令覆盖的那些。不再评估任何进一步的 "http-request" 规则。- "tarpit":这将停止规则的评估,并立即在指定的延迟时间内阻止请求而不响应,该延迟由 "timeout tarpit" 指定,如果前者未设置,则由 "timeout connect" 指定。在此延迟后,如果客户端仍然连接,将返回 HTTP 错误 500,以便客户端不会怀疑它已被 tarpit。日志将报告标志 "PT"。tarpit 规则的目标是在攻击期间减慢机器人的速度,当它们受到并发请求数量的限制时。它对于非常愚蠢的机器人非常有效,并且与 "deny" 规则相比,可以显著减少防火墙的负载。但是,在面对“正确”开发的机器人时,通过强制 haproxy 和前端防火墙支持数量惊人的并发连接,可能会使情况变得更糟。另请参阅下面的 "silent-drop" 操作。- "auth":这将停止规则的评估,并立即响应 HTTP 401 或 407 错误代码,以邀请用户提供有效的用户名和密码。不再评估任何进一步的 "http-request" 规则。支持可选的 "realm" 参数,它设置响应中返回的认证域(通常是应用程序的名称)。- "redirect":这将根据重定向规则执行 HTTP 重定向。这与 "redirect" 语句完全相同,只是它插入了一个可以在其他 "http-request" 规则中间处理的重定向规则,并且这些规则使用 "log-format" 字符串。有关规则的语法,请参阅 "redirect" 关键字。- "add-header":追加一个 HTTP 标头字段,其名称在 <name> 中指定,其值由 <fmt> 定义,<fmt> 遵循 log-format 规则(请参阅 第 8.2.4 节中的自定义日志格式)。这对于将连接特定的信息传递给服务器(例如,客户端的 SSL 证书)或将多个标头合并为一个非常有用。此规则不是最终的,因此可以添加其他类似规则。请注意,标头添加是立即执行的,因此一个规则可以重用前一个规则产生的标头。- "set-header":与 "add-header" 相同,只是如果标头名称已存在,则首先将其删除。这对于将安全信息传递给服务器很有用,因为标头不得被外部用户操纵。请注意,新值是在删除之前计算的,因此可以将值连接到现有标头。- "del-header":删除名称在 <name> 中指定的所有 HTTP 标头字段。- "replace-header":根据 <match-regex> 匹配标头字段 <name> 的所有出现中的正则表达式,并用 <replace-fmt> 参数替换它们。格式字符允许在 replace-fmt 中使用,并且其工作方式与 "add-header" 中的 <fmt> 参数相同。匹配仅区分大小写。理解此操作仅考虑整个标头行很重要,而不管它们可能包含多少个值。此用法适用于值中自然包含逗号的标头,例如 If-Modified-Since 等。
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 - “replace-value”的工作方式与“replace-header”类似,但它将正则表达式与头字段 <name> 的每个逗号分隔的值进行匹配,而不是整个头。这适用于允许携带多个值的所有头。一个例子可以是 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 - “set-method”用格式字符串 <fmt> 的评估结果重写请求方法。很少有正当理由需要这样做,因为这更有可能破坏某些东西而不是修复它。 - “set-path”用格式字符串 <fmt> 的评估结果重写请求路径。查询字符串(如果有)保持不变。如果在路径之前找到方案和授权机构,它们也保持不变。如果请求没有路径(“*”),则用格式替换它。这可以用于在路径前添加一个目录组件。另请参阅“set-query”和“set-uri”。
# 在路径前添加主机名 http-request set-path /%[hdr(host)]%[path]
- “set-query”用格式字符串 <fmt> 的评估结果重写请求的查询字符串,该字符串出现在第一个问号(“?”)之后。问号之前的部分保持不变。如果请求不包含问号并且新值不为空,则在 URI 的末尾添加一个问号,后跟新值。如果问号存在,即使值为空,它也永远不会被移除。这可以用于从查询字符串中添加或删除参数。另请参阅“set-query”和“set-uri”。
# 在查询字符串中将“%3D”替换为“=” http-request set-query %[query,regsub(%3D,=,g)]
- "set-uri":使用格式字符串 <fmt> 的评估结果重写请求 URI。方案、权限、路径和查询字符串一次性替换。这可用于在代理前面重写主机,或对 URI 进行复杂的修改,例如在路径和查询字符串之间移动部分。另请参阅 "set-path" 和 "set-query"。- "set-nice":设置当前正在处理的请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级就越低。较低的值将使请求比其他请求更重要。这对于提高某些请求的速度或降低非重要请求的优先级非常有用。未使用此设置进行事先实验可能会导致严重减慢。- "set-log-level":用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 个 syslog 级别(请参阅 "log" 关键字)加上特殊级别 "silent",它会禁用此请求的日志记录。此规则不是最终的,因此最后一个匹配的规则获胜。此规则对于禁用来自其他设备的运行状况检查非常有用。- "set-tos":用于在支持该功能的平台上将发送到客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中提供的值。该值代表 IP TOS 字段的整个 8 位,并且可以表示为十进制或十六进制格式(前缀为 "0x")。请注意,DSCP 或 TOS 中仅使用最高的 6 位,最低的 2 位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的某些路由行为。有关更多信息,请参阅 RFC 2474、2597、3260 和 4594。- "set-mark":用于在支持该功能的平台上将发送到客户端的所有数据包的 Netfilter MARK 设置为 <mark> 中提供的值。该值是一个无符号 32 位值,可以由 netfilter 和路由表匹配。它可以表示为十进制或十六进制格式(前缀为 "0x")。这对于强制某些数据包采取不同的路由(例如,更便宜的网络路径用于批量下载)非常有用。这在 Linux 内核 2.6.32 及更高版本上运行,并且需要管理员权限。- "add-acl":用于向 ACL 添加新条目。ACL 必须从文件中加载(即使是虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,它遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能很昂贵!它相当于 stats socket 中的 "add acl" 命令,但可以通过 HTTP 请求触发。- "del-acl":用于从 ACL 中删除条目。ACL 必须从文件中加载(即使是虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,它遵循 log-format 规则,用于收集要删除的条目的内容。它相当于 stats socket 中的 "del acl" 命令,但可以通过 HTTP 请求触发。- "del-map":用于从 MAP 中删除条目。MAP 必须从文件中加载(即使是虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,它遵循 log-format 规则,用于收集要删除的条目的内容。它接受一个参数:"文件名" 它相当于 stats socket 中的 "del map" 命令,但可以通过 HTTP 请求触发。- "set-map":用于向 MAP 添加新条目。MAP 必须从文件中加载(即使是虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它接受 2 个参数:<key fmt>,它遵循 log-format 规则,用于收集 MAP 键,以及 <value fmt>,它遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能很昂贵!它相当于 stats socket 中的 "set map" 命令,但可以通过 HTTP 请求触发。- capture <sample> [ len <length> | id <id> ]:从请求缓冲区捕获样本表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。生成的字符串存储在下一个请求的 "capture" 插槽中,因此它可能会出现在捕获的 HTTP 标头旁边。然后它将自动出现在日志中,并且可以使用样本提取规则提取它以馈入标头或其他内容。长度应受限制,因为此大小将在会话的整个生命周期中为每个捕获分配。请参阅 第 7.3 节(提取样本)和 "capture request header" 以获取更多信息。如果使用 "id" 关键字而不是 "len",操作会尝试将捕获的字符串存储在先前声明的捕获插槽中。这对于在后端运行捕获很有用。插槽 ID 可以通过先前的 "http-request capture" 指令或使用 "declare capture" 关键字声明。在后端使用此操作时,请仔细检查相关的 frontend 是否具有所需的捕获插槽,否则,此规则将在运行时被忽略。由于 HAProxy 能够实时动态解析后端名称,因此在配置解析时无法检测到此问题。- { 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" 规则将指定的表的计数器作为第三组进行跟踪。建议使用第一组计数器用于 per-frontend 计数器,第二组用于 per-backend 计数器。但这只是一个指导方针,所有计数器都可以用于任何地方。这些操作接受一个或两个参数:<key> 是必需的,并且是一个如 第 7.3 节中所述的样本表达式规则。它描述了传入请求或连接的哪些元素将被分析、提取、组合并用于选择哪个表条目来更新计数器。<table> 是一个可选的表,用于代替当前代理中声明的粘性表(stick-table)。然后,对于该键的所有匹配和更新的计数器都将在该表中执行,直到会话结束。一旦执行了 "track-sc*" 规则,就会在表中查找该键,如果找不到,则为其分配一个条目。然后,在会话的整个生命周期中会保留指向该条目的指针,并且该条目的计数器会尽可能频繁地更新,每次会话计数器更新时,并且系统地在会话结束时更新。计数器仅为跟踪开始后发生的事件更新。例外情况是,连接计数器和请求计数器会系统地更新,以便它们反映有用的信息。如果条目跟踪并发连接计数器,则只要跟踪该条目,就会计算一个连接,并且该条目在此期间不会过期。跟踪计数器还比仅检查键提供了性能优势,因为所有使用它的 ACL 检查只执行一次表查找。- sc-set-gpt0(<sc-id>) <int>:此操作根据由 <sc-id> 指定的粘性计数器和 <int> 的值设置 GPT0 标记。预期的结果是布尔值。如果发生错误,此操作将静默失败,并且操作评估将继续。- sc-inc-gpc0(<sc-id>):此操作根据由 <sc-id> 指定的粘性计数器递增 GPC0 计数器。如果发生错误,此操作将静默失败,并且操作评估将继续。- set-var(<var-name>) <expr>:用于设置变量的内容。变量是内联声明的。<var-name> 变量的名称以指示其范围的指示符开头。允许的作用域是:"proc":变量与整个进程共享"sess":变量与整个会话共享"txn":变量与事务(请求和响应)共享"req":变量仅在请求处理期间共享"res":变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是"."。名称只能包含字符 'a-z'、'A-Z'、'0-9' 和 '_'。<expr> 是一个标准的 HAProxy 表达式,由样本提取后跟一些转换器组成。
http-request set-var(req.my_var) req.fhdr(user-agent),lower
- unset-var(<var-name>):用于取消设置变量。有关 <var-name> 的详细信息,请参阅上文。
http-request unset-var(req.my_var)
- set-src <expr>:用于将源 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。- set-src-port <expr> :用于将源端口地址设置为指定表达式的值。<expr> 是一个标准的 HAProxy 表达式,由一个 sample-fetch 后跟一些转换器组成。
http-request set-src-port hdr(x-port) http-request set-src-port int(4000)
在可能的情况下,set-src-port 会保留原始源地址,只要地址族支持端口,否则它会在重写端口之前将源地址强制设置为 IPv4 "0.0.0.0"。- set-dst <expr> :用于将目标 IP 地址设置为指定表达式的值。当 HAProxy 前面的代理重写了目标 IP,但在 HTTP 头部中提供了正确的 IP 时,或者您想为了隐私而隐藏 IP 时,此选项很有用。如果您想连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。<expr> 是一个标准的 HAProxy 表达式,由一个 sample-fetch 后跟一些转换器组成。
http-request set-dst hdr(x-dst) http-request set-dst dst,ipmask(24)
在可能的情况下,set-dst 会保留原始目标端口,只要地址系列允许,否则目标端口设置为 0。- set-dst-port <expr>:用于将目标端口地址设置为指定表达式的值。如果您想连接到新的地址/端口,请在后端使用“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"。- "silent-drop" :这会停止规则的评估,并以一种系统依赖的方式突然终止客户端连接,试图防止客户端收到通知。其效果是客户端仍然看到一个已建立的连接,但 HAProxy 上实际上没有连接。目的是达到与 "tarpit" 类似的效果,但它不使用运行 HAProxy 的机器上的任何本地资源。它可以承受比 "tarpit" 更高的负载,并能减缓更强的攻击者。理解使用此机制的影响非常重要。放置在客户端和 HAProxy 之间的所有状态感知设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此受到影响。在具有足够权限运行的现代 Linux 系统上,使用 TCP_REPAIR 套接字选项来阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 被减小到 1,以便 TCP 重置不会经过第一个路由器,尽管它仍然会被传递到本地网络。除非您完全理解其工作原理,否则请勿使用它。每个实例的 http-request 语句的数量没有限制。重要的是要知道 http-request 规则在 HTTP 处理的早期阶段进行处理,紧随 "block" 规则之后,在 "reqdel" 或 "reqrep" 或 "reqadd" 规则之前。这样,由 "add-header"/"set-header" 添加的头部几乎对所有后续的 ACL 规则都可见。在新版本(>= 1.5)中,不鼓励使用 "reqadd"/"reqdel"/"reqrep" 来操作请求头部。但如果您需要使用正则表达式删除头部,仍然可以使用 "reqdel"。另外,请使用 "http-request deny/allow/tarpit" 而不是 "reqdeny"/"reqpass"/"reqtarpit"。
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 auth_ok http_auth_group(L1) G1 http-request auth unless auth_ok
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]
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
第 7 层响应的访问控制
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
http-response 语句定义了一组适用于层 7 处理的规则。当在 frontend、listen 或 backend 部分遇到这些规则时,它们会按照声明的顺序进行评估。任何规则都可以选择性地跟随一个基于 ACL 的条件,在这种情况下,它只会在条件为真时进行评估。由于这些规则适用于响应,因此后端规则首先应用,然后是前端规则。第一个关键字是规则的动作。目前支持的动作包括:- "allow" :这会停止规则的评估,并允许响应通过检查。当前部分不会再评估其他 "http-response" 规则。- "deny" :这会停止规则的评估,并立即拒绝响应并发出 HTTP 502 错误。当前部分不会再评估其他 "http-response" 规则。- "add-header" 追加一个 HTTP 头部字段,其名称在 <name> 中指定,其值由 <fmt> 定义,该值遵循 log-format 规则(参见 第 8.2.4 节中的自定义日志格式)。这可以用于例如向客户端发送 cookie,或传递一些内部信息。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则的结果头部。- "set-header" 的作用与 "add-header" 相同,但会首先删除已存在的同名头部。这在向服务器传递安全信息时非常有用,因为头部不能被外部用户篡改。- "del-header" 删除名称在 <name> 中指定的 **所有** HTTP 头部字段。- "replace-header" 根据 <match-regex> 在头部字段 <name> 的 **所有** 匹配项中查找正则表达式,并用 <replace-fmt> 参数替换它们。格式字符允许在 replace-fmt 中使用,其工作方式与 "add-header" 中的 <fmt> 参数类似。匹配仅区分大小写。重要的是要理解,此操作仅考虑 **完整的头部行**,而忽略它们可能包含的值的数量。此用法适用于其值中自然包含逗号的头部,例如 Set-Cookie、Expires 等。
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。 - "replace-value" 的工作方式与 "replace-header" 类似,不同之处在于它针对头部字段 <name> 的每个逗号分隔的值匹配正则表达式,而不是整个头部。这适用于所有允许携带多个值的头部。一个例子可以是 Accept 头部。
http-response replace-value Cache-control ^public$ private
应用于:Cache-Control: max-age=3600, public 输出:Cache-Control: max-age=3600, private - "set-status" 将响应状态码替换为 <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".
- "set-nice" 设置当前正在处理的请求的 "nice" 因子。它仅对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上被 "nice" 设置修改。可接受的范围是 -1024..1024。值越高,请求的 nice 度越高。较低的值会使请求比其他请求更重要。这对于提高某些请求的速度或降低非重要请求的优先级非常有用。在没有事先实验的情况下使用此设置可能会导致一些严重的减速。- "set-log-level" 用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 个 syslog 级别(参见 "log" 关键字)以及特殊的 "silent" 级别,它会禁用此请求的日志记录。此规则不是最终的,因此最后匹配的规则生效。此规则对于禁用来自其他设备的健康检查可能很有用。- "set-tos" 用于将发送到客户端的数据包的 TOS 或 DSCP 字段值设置为平台支持的 <tos> 中的值。此值表示 IP TOS 字段的整个 8 位,可以以十进制或十六进制格式(前缀为 "0x")表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的 2 位始终为 0。这可以用于根据请求中的某些信息来调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474、2597、3260 和 4594。- "set-mark" 用于将发送到客户端的所有数据包的 Netfilter MARK 设置为平台支持的 <mark> 中的值。此值是一个无符号 32 位值,可以被 netfilter 和路由表匹配。它可以以十进制或十六进制格式(前缀为 "0x")表示。这有助于强制某些数据包采取不同的路由(例如,为批量下载提供更便宜的网络路径)。这在 Linux 内核 2.6.32 及以上版本上有效,并且需要管理员权限。- "add-acl" 用于将新条目添加到 ACL。ACL 必须从文件(即使是空的虚拟文件)加载。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找是通过线性搜索完成的,对于大型列表可能非常昂贵!它等同于统计套接字中的 "add acl" 命令,但可以由 HTTP 响应触发。- "del-acl" 用于从 ACL 中删除条目。ACL 必须从文件(即使是空的虚拟文件)加载。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它等同于统计套接字中的 "del acl" 命令,但可以由 HTTP 响应触发。- "del-map" 用于从 MAP 中删除条目。MAP 必须从文件(即使是空的虚拟文件)加载。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它接受一个参数:"文件名" 它等同于统计套接字中的 "del map" 命令,但可以由 HTTP 响应触发。- "set-map" 用于将新条目添加到 MAP。MAP 必须从文件(即使是空的虚拟文件)加载。要更新的 MAP 的文件名在括号中传递。它接受 2 个参数:<key fmt>,遵循 log-format 规则,用于收集 MAP 键,以及 <value fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找是通过线性搜索完成的,对于大型列表可能非常昂贵!它等同于统计套接字中的 "set map" 命令,但可以由 HTTP 响应触发。- capture <sample> id <id> :从响应缓冲区捕获 <sample> 表达式,并将其转换为字符串。结果字符串存储在下一个请求的 "capture" 插槽中,因此它可能会出现在某些捕获的 HTTP 头部旁边。它将自动出现在日志中,并且可以使用 sample fetch 规则提取它以馈入头部或其他内容。请查阅 第 7.3 节(Fetching samples)和 "capture response header" 以获取更多信息。关键字 "id" 是用于存储字符串的捕获插槽的 ID。插槽 ID 必须在关联的 frontend 中定义。这对于在 backend 中运行捕获很有用。插槽 ID 可以通过先前的 "http-response capture" 指令或通过 "declare capture" 关键字来声明。当在 backend 中使用此操作时,请仔细检查相关的 frontend 是否具有所需的捕获插槽,否则,此规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析 backend 名称,因此这在配置解析时无法检测到。- "redirect" :这会根据重定向规则执行 HTTP 重定向。它支持类似于 "http-request redirect" 规则的格式字符串,但有一个例外,即在响应上只能使用 "location" 类型的重定向。有关规则的语法,请参阅 "redirect" 关键字。当在响应期间应用重定向规则时,与服务器的连接将被关闭,这样就无法将任何数据从服务器转发给客户端。- set-var(<var-name>) expr: 用于设置变量的内容。变量是内联声明的。<var-name> 变量的名称以其作用域的指示开头。允许的作用域是:"proc" :变量与整个进程共享 "sess" :变量与整个会话共享 "txn" :变量与事务(请求和响应)共享 "req" :变量仅在请求处理期间共享 "res" :变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是 '.'。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。<expr> 是一个标准的 HAProxy 表达式,由一个 sample-fetch 后跟一些转换器组成。
http-response set-var(sess.last_redir) res.hdr(location)
- unset-var(<var-name>):用于取消设置变量。有关 <var-name> 的详细信息,请参阅上文。
http-response unset-var(sess.last_redir)
- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>] : 启用跟踪粘性计数器。请参阅“http-request track-sc”以获取完整描述。与“http-request track-sc”的唯一区别是<key>样本表达式只能使用响应中的样本(例如,res.*、status 等)和 6 层以下的样本(例如,ssl 相关样本,请参阅第 7.3.4 节)。如果不支持样本,haproxy 将在解析配置时失败并发出警告。- sc-set-gpt0(<sc-id>) <int> : 此操作根据<sc-id>指定的粘性计数器和<int>的值设置 GPT0 标签。预期结果是布尔值。如果发生错误,此操作将静默失败,并继续评估操作。- sc-inc-gpc0(<sc-id>): 此操作根据<sc-id>指定的粘性计数器递增 GPC0 计数器。如果发生错误,此操作将静默失败,并继续评估操作。- "silent-drop" : 这将停止规则的评估,并以系统相关的方式突然关闭面向客户端的连接,试图阻止客户端被通知。其效果是客户端仍然看到一个已建立的连接,而 HAProxy 上不存在。其目的是达到与“tarpit”类似的效果,但它不使用运行 HAProxy 的机器上的任何本地资源。它可以承受比“tarpit”高得多的负载,并减缓更强的攻击者。理解使用此机制的影响非常重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持连接,并可能受到此操作的影响。在具有足够权限运行的现代 Linux 系统上,TCP_REPAIR 套接字选项用于阻止 TCP 重置的发出。在其他系统上,套接字的 TTL 会减至 1,这样 TCP 重置就不会通过第一个路由器,尽管它仍然会传递到本地网络。除非您完全了解其工作原理,否则请勿使用它。每个实例的 http-response 语句的数量没有限制。重要的是要知道 http-response 规则在 HTTP 处理的早期进行处理,在“rspdel”或“rsprep”或“rspadd”规则之前。这样,由“add-header”/“set-header”添加的头几乎对所有后续 ACL 规则都可见。在新版本(>= 1.5)中,不建议使用“rspadd”/“rspdel”/“rsprep”来操作请求头。但如果你需要使用正则表达式删除头,你仍然可以使用“rspdel”。另外,请使用“http-response deny”而不是“rspdeny”。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 连接如何在请求之间共享
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,haproxy 和后端服务器之间建立的连接属于启动它的会话。缺点是在响应和下一个请求之间,连接保持空闲状态并且未使用。在许多情况下,出于性能原因,最好能够重用这些空闲连接来为来自不同会话的其他请求服务。此指令允许调整此行为。参数指示所需的连接重用策略:-“never”:空闲连接永远不会在会话之间共享。这是默认选择。为了取消从 defaults 部分继承的不同策略或进行故障排除,可能需要强制执行此选项。例如,如果一个旧的错误应用程序认为同一个连接上的多个请求来自同一个客户端,并且无法修复该应用程序,那么在一个后端中禁用连接共享可能是有益的。一个这样的应用程序示例可能是一个旧的 haproxy,它在隧道模式下使用 cookie 插入并且不检查第一个请求之后的任何请求。-“safe”:这是推荐的策略。会话的第一个请求始终通过其自己的连接发送,只有后续请求才可能通过其他现有连接分派。这确保了在服务器关闭连接时发送请求,浏览器可以决定静默重试。由于它与常规的 keep-alive 完全等效,因此应该没有副作用。-“aggressive”:此模式可能在 webservices 环境中有用,在这种环境中,并非所有服务器都一定已知,并且将大多数第一个请求通过现有连接传递将是很可取的。在这种情况下,第一个请求仅通过已经至少重用过一次的现有连接传递,这证明服务器正确支持连接重用。只有当确信客户端可以偶尔重试失败的请求,并且积极的连接重用带来的好处远远大于罕见的连接失败的缺点时,才应使用它。-“always”:此模式仅在到服务器的路径已知在释放现有连接后永远不会快速中断时才推荐使用。它允许将会话的第一个请求发送到现有连接。当后端是缓存场时,这可以提供比“safe”策略显着的性能提升,因为此类组件倾向于表现出一致的行为,并将从连接共享中受益。建议在此模式下保持“http-keep-alive”超时时间较短,以便没有死连接保持可用。在大多数情况下,这将带来与“aggressive”相同的性能提升,但风险更大。只有当它比“aggressive”更能改善情况时才应使用。启用 HTTP 连接共享时,会非常小心地遵守连接属性和兼容性。具体而言:- 使用“usesrc”后跟客户端相关值(“client”、“clientip”、“hdr_ip”)建立的连接被标记为私有,永远不会共享;- 发送到带有 TLS SNI 扩展的服务器的连接被标记为私有,永远不会共享;- 接收到状态码 401 或 407 的连接期望获得相应的身份验证。由于某些错误身份验证方案(如 NTLM)依赖于连接,因此这些连接被标记为私有,并且永远不会共享;不涉及任何连接池,一旦会话死亡,它所连接的最后一个空闲连接将同时被删除。这确保了连接在所有会话关闭后不会持续存在。注意:连接重用提高了“server maxconn”设置的准确性,因为在空闲连接可用时,几乎不会建立新连接。这对于“always”策略尤其如此。
将服务器名称添加到请求中。使用由 <header> 给出的头字符串。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<header> 用于发送服务器名称的头字符串。
“http-send-name-header”语句导致目标服务器的名称被添加到 HTTP 请求的头中。该名称会与提供的头字符串一起添加。
为代理设置一个持久 ID。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
为代理设置一个持久 ID。此 ID 必须是唯一的正数。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 当前仅在统计信息中返回。
声明一个忽略持久性的条件
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
默认情况下,当启用 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
允许 HAProxy 的无缝重载
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
此指令指示 HAProxy 到一个文件,其中已保存了之前运行进程的服务器状态。这样,在启动时,在处理流量之前,新进程可以像没有发生重新加载一样将旧状态应用于服务器。“load-server-state-from-file”指令的目的是告诉 haproxy 使用哪个文件。目前,只有两个参数可以防止加载状态或从包含所有后端和服务器的文件加载状态。状态文件可以通过在统计套接字上运行“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
启用事件和流量的每个实例日志记录。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
前缀:当必须清除记录器列表时,应使用 no。例如,如果您不想从默认记录器列表继承。此前缀不允许有参数。
当实例的日志参数与全局参数相同时,应使用 global。这是最常见的用法。“global”会将 <address>、<facility> 和 <level> 替换为在“global”部分找到的日志条目的参数。每个实例只能使用一个“log global”语句,并且此形式不带其他参数。<address> 指示日志发送到的位置。它采用与“global”部分的日志相同的格式,可以是以下之一:- IPv4 地址,后跟冒号(“:”)和 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- IPv6 地址,后跟冒号(“:”)和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。- 到 UNIX 域套接字的 filesystem 路径,请牢记 chroot 的考虑因素(确保路径在 chroot 内可访问)和 uid/gid(确保路径可写)。您可能希望在 address 参数中引用一些环境变量,请参阅第 2.3 节关于环境变量的内容。<length> 是一个可选的最大行长度。大于此值的日志行将在发送前被截断。原因是 syslog 服务器对日志行长度的处理方式不同。所有服务器都支持 1024 的默认值,但有些服务器会丢弃较大的行,而其他服务器会记录它们。如果服务器支持长行,则在此处设置此值以避免截断长行可能很有意义。同样,如果服务器丢弃长行,则最好在发送之前截断它们。接受的值范围是 80 到 65535。1024 的默认值通常适用于所有标准用法。某些特定情况的长捕获或 JSON 格式的日志可能需要更大的值。<facility> 必须是 24 个标准 syslog facilities 之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7<level> 是可选的,可以指定以过滤传出的消息。默认情况下,所有消息都会发送。如果指定了级别,则只发送严重性至少与此级别一样重要的消息。可以指定一个最小级别。如果设置了该级别,则严重性比此级别更高的日志将被限制为此级别。这用于避免在某些默认 syslog 配置上将“emerg”消息发送到所有终端。已知有八个级别:emerg alert crit err warning notice info debug
重要的是要记住,是由前端决定要从连接中记录什么,并且在内容切换的情况下,来自后端的日志条目将被忽略。连接以 "info" 级别记录。然而,后端日志声明定义了服务器状态更改将如何以及在何处被记录。级别 "notice" 将用于指示服务器启动,"warning" 将用于终止信号和最终的服务终止,而 "alert" 将用于服务器宕机时。 注意:根据 RFC3164,消息在发出前会被截断为 1024 字节。
log global log 127.0.0.1:514 local0 notice # 只发送重要事件 log 127.0.0.1:514 local0 notice notice # 相同但限制输出级别 log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器
指定用于流量日志的日志格式字符串
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
此指令指定了将用于所有通过此行所在前端的流量产生的日志的日志格式字符串。如果在 defaults 部分使用此指令,所有后续的前端都将使用相同的日志格式。请参阅深入介绍日志格式字符串的第 8.2.4 节。"log-format" 指令会覆盖之前的 "option tcplog"、"log-format" 和 "option httplog" 指令。
指定 RFC5424 结构化数据日志格式字符串
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
此指令指定了 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\"]
指定用于所有传出日志的日志标签
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
将 syslog 头中的 tag 字段设置为此字符串。默认值为全局部分设置的 log-tag,否则为从命令行启动的程序名称,通常是“haproxy”。有时区分同一主机上运行的多个进程,或区分同一进程中运行的客户实例会很有用。在后端,关于服务器 up/down 的日志将使用此 tag。作为提示,可以在 defaults 部分中设置与托管客户相关的 log-tag,然后将该客户的所有前端和后端放在一起,然后在一个新的 defaults 部分中启动另一个客户。另请参阅全局“log-tag”指令。设置用于维护 keep-alive 连接的最大服务器队列大小
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
HTTP keep-alive 尝试在可能的情况下重用同一服务器连接,但有时可能会适得其反,例如,如果一个服务器有很多连接而其他服务器处于空闲状态。这对于静态服务器尤其如此。此设置的目的是在 HAProxy 停止尝试重用同一服务器并更倾向于寻找另一台服务器的排队连接数上设置一个阈值。默认值 -1 表示没有限制。值为零表示 keep-alive 请求永远不会被排队。对于延迟很低且对中断 keep-alive 不敏感的非常接近的服务器,建议使用较低的值(例如,本地静态服务器可以使用 10 或更低的值)。对于遭受高延迟的远程服务器,可能需要更高的值来覆盖延迟和/或选择不同服务器的成本。请注意,这不会影响对同一服务器连续响应 401 响应的响应。即使它们需要排队,它们仍将转到同一服务器。
固定前端的最大并发连接数
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
如果系统支持,对于大型网站来说,将此限制设置得非常高可能很有用,这样 haproxy 就可以管理连接队列,而不是让客户端面临未应答的连接尝试。此值不应超过全局 maxconn。此外,请记住,一个连接包含两个 tune.bufsize(默认为 16kB)的缓冲区,以及一些其他数据,导致每个已建立的连接消耗约 33 kB 的 RAM。这意味着,一个配备 1GB RAM 的中型系统,如果经过适当调优,可以承受大约 20000-25000 个并发连接。此外,当 <conns> 设置为较大值时,服务器的规模可能无法接受如此大的负载,因此,为它们分配一些合理的连接限制通常是明智的。默认情况下,此值设置为 2000。
设置实例的运行模式或协议
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
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
添加一个条件以向监控 HTTP 请求报告失败。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
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
声明一个仅限于监控请求的源网络
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<source> 是源 IPv4 地址或网络,该网络只能对任何请求获取监控响应。它可以是 IPv4 地址、主机名或后跟斜杠('/')和掩码的地址。
在 TCP 模式下,任何来自与 <source> 匹配的源的连接都将导致连接立即关闭,而不会进行任何日志记录。这允许其他设备探测端口并验证它是否仍在监听,而无需将连接转发到远程服务器。在 HTTP 模式下,来自与 <source> 匹配的源的连接将被接受,将发送以下响应而不等待请求,然后连接将被关闭:“HTTP/1.0 200 OK”。这通常足以让任何前端 HTTP 探测器检测到服务已启动并正在运行,而无需将请求转发到后端服务器。请注意,此响应以原始格式发送,没有任何转换。这很重要,因为它意味着它不会在 SSL 监听器上进行 SSL 加密。监视请求处理得非常早,紧随 TCP 请求连接 ACL 之后,而 TCP 请求连接 ACL 是唯一能够阻止它们的。这些连接的生命周期很短,并且从不等待来自客户端的任何数据。它们无法被记录,这也是其预期用途。它们仅用于向上层组件报告 HAProxy 的运行状况,仅此而已。请注意,“monitor fail”规则不适用于被“monitor-net”拦截的连接。最后,请注意,在前端只能指定一个“monitor-net”语句。如果找到多个,则只有最后一个将被考虑。
# 地址 .252 和 .253 只是在探测我们。 frontend www monitor-net 192.168.0.252/31
拦截外部组件监控请求使用的 URI
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
当在前端收到一个引用 <uri> 的 HTTP 请求时,HAProxy 不会转发它,也不会记录它,而是会返回“HTTP/1.0 200 OK”或“HTTP/1.0 503 Service unavailable”,具体取决于使用“monitor fail”定义的失败条件。这通常足以让任何前端 HTTP 探测器检测到服务已启动并正在运行,而无需将请求转发到后端服务器。请注意,HTTP 方法、版本和所有标头都被忽略,但请求至少必须在 HTTP 级别有效。此关键字只能与 HTTP 模式的前端一起使用。监视请求处理得非常早。无法使用 ACL 阻止或重定向它们。它们也无法被记录,这也是其预期用途。它们仅用于向更高组件报告 HAProxy 的运行状况,仅此而已。但是,可以使用“monitor fail”和 ACL 添加任意数量的条件,以便结果可以根据任何可想象的检查进行调整(最常见的是后端中可用服务器的数量)。
# 使用 /haproxy_test 来报告 haproxy 的状态 frontend www mode http monitor-uri /haproxy_test
启用或禁用对队列中待处理的已中止请求的提前丢弃。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
在高负载下,服务器将花费一些时间来响应。每个实例的连接队列将膨胀,响应时间将相对于队列大小乘以平均每会话响应时间而增加。当客户端等待几秒钟以上时,他们将经常点击浏览器上的“停止”按钮,在队列中留下一个无用的请求,并减慢其他用户的速度,以及服务器的速度,因为该请求最终会被服务,然后在传递响应时遇到的第一个错误时被中止。由于无法区分完全停止和客户端侧的简单输出关闭,HTTP 代理应保守,并认为客户端可能只在其等待响应时关闭了其输出通道。但是,这会引入大量用户执行相同操作时的拥塞风险,并且在如今完全没有用,因为几乎没有客户端会在等待响应时关闭会话。一些 HTTP 代理支持此行为(Squid、Apache、HAProxy),而其他代理不支持(TUX、大多数基于硬件的负载均衡器)。因此,关闭输入通道代表用户点击“停止”按钮的概率接近 100%,而成为唯一破坏罕见但有效流量的组件的风险极低,这增加了在仍未得到服务且不会污染服务器的情况下能够尽早中止会话的诱惑。在 HAProxy 中,用户可以选择所需的行为,使用选项“abortonclose”。默认情况下(没有选项),行为是符合 HTTP 的,并且中止的请求将被服务。但是,当指定该选项时,具有传入通道关闭的会话将在可能时被中止,要么在队列中等待连接槽,要么在连接建立期间,如果服务器尚未确认连接请求。这大大减小了队列大小和饱和服务器在用户点击“停止”时的负载,进而减小了其他用户的响应时间。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。
启用或禁用放宽 HTTP 请求解析
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,HAProxy 在消息解析方面符合 RFC7230。这意味着标头名称中不允许存在无效字符,并且会导致向客户端返回错误。这是期望的行为,因为此类禁止字符主要用于构建利用服务器弱点的攻击,并绕过安全过滤。有时,有缺陷的浏览器或服务器会出于任何原因(配置、实现)发出无效的标头名称,并且问题不会立即修复。在这种情况下,可以通过指定此选项来放宽 HAProxy 的标头名称解析器,以接受任何字符,即使这没有意义。类似地,RFC3986 很好地定义了允许出现在 URI 中的字符列表,而字符 0-31、32(空格)、34('\"')、60('<')、62('>')、92('\\')、94('^')、96('`')、123('{')、124('|')、125('}')、127(删除)以及以上所有字符都是不允许的。Haproxy 始终会阻止其中的一些(0..32、127)。除非启用此选项,否则其余字符默认会被阻止。此选项还放宽了对 HTTP 版本的要求,它允许 HTTP/0.9 请求通过(未指定版本),并且主版本和次版本都可以是多个数字。此选项绝不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。它仅应在确认问题后部署。启用此选项后,请求中的错误标头名称仍将被接受,但将捕获完整的请求,以便稍后使用 UNIX 统计套接字上的“show errors”请求进行分析。类似地,包含 URI 部分中无效字符的请求将被记录。这样做也有助于确认问题已解决。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。启用或禁用放宽 HTTP 响应解析
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在消息解析方面符合 RFC7230。这意味着标头名称中不允许存在无效字符,并且会导致向客户端返回错误。这是期望的行为,因为此类禁止字符主要用于构建利用服务器弱点的攻击,并绕过安全过滤。有时,有缺陷的浏览器或服务器会出于任何原因(配置、实现)发出无效的标头名称,并且问题不会立即修复。在这种情况下,可以通过指定此选项来放宽 HAProxy 的标头名称解析器,以接受任何字符,即使这没有意义。此选项还放宽了对 HTTP 版本格式的要求,它允许主版本和次版本都可以是多个数字。此选项绝不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。它仅应在确认问题后部署。启用此选项后,响应中的错误标头名称仍将被接受,但将捕获完整的响应,以便稍后使用 UNIX 统计套接字上的“show errors”请求进行分析。这样做也有助于确认问题已解决。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。
一次使用所有备用服务器,或仅使用第一个
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,当所有正常服务器都宕机时,第一个可用的备用服务器将获得所有流量。有时,可能希望一次使用多个备用服务器,因为一个可能不够用。当启用 "option allbackups" 时,当所有正常服务器都不可用时,将在所有备用服务器之间执行负载均衡。将使用相同的负载均衡算法,并遵守服务器的权重。因此,备用服务器之间将不再有任何优先级顺序。此选项主要用于专用于在应用程序完全离线时返回“抱歉”页面的静态服务器群。 如果此选项已在 "defaults" 部分中启用,可以通过在其前面添加 "no" 关键字来在特定实例中禁用它。
分析所有服务器响应并阻止带有可缓存 cookie 的响应
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
一些高级框架在所有地方都设置应用程序 Cookie,并且并不总是让开发人员有足够的控制来管理响应应该如何被缓存。当缓存对象返回会话 Cookie 时,用户穿越相同缓存时会出现会话交叉或盗用的高风险。在某些情况下,阻止响应比让一些敏感会话信息泄露要好。选项“checkcache”启用对所有服务器响应的深度检查,以严格遵守 HTTP 规范中关于可缓存性的规定。它仔细检查服务器响应中的“Cache-control”、“Pragma”和“Set-cookie”标头,以检查在客户端代理上缓存 Cookie 的风险。启用此选项后,可以传递给客户端的唯一响应是:-所有没有“Set-Cookie”标头的响应;-所有返回代码不是 200、203、206、300、301、410 的响应,前提是服务器没有设置“Cache-control: public”标头;-所有来自 POST 请求的响应,前提是服务器没有设置“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 之后有其他字段)。如果响应不遵守这些要求,那么它将被阻止,就像它来自“rspdeny”过滤器一样,并返回“HTTP 502 bad gateway”。会话状态显示“PH--”,表示代理在标头处理过程中阻止了响应。此外,将在日志中发送警报,以便管理员知道需要修复某些内容。由于对应用程序的高影响,在部署到生产环境之前,应在启用该选项的情况下对应用程序进行深入测试。即使在生产中不使用它,也建议始终在测试期间激活它,因为它将报告潜在危险的应用程序行为。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。
启用或禁用在客户端发送 TCP keepalive 数据包
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
当客户端和服务器之间存在防火墙或任何有状态组件时,并且当协议涉及非常长的会话和长时间的空闲期时(例如:远程桌面),则存在其中一个中间组件决定过期由于空闲时间过长而无响应的会话的风险。启用套接字级别的 TCP keep-alive 会使系统定期发送数据包到连接的另一端,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,并且取决于操作系统及其调整参数。重要的是要理解,keep-alive 数据包既不会在应用程序级别发出,也不会在应用程序级别接收。只有网络堆栈会看到它们。因此,即使代理的一侧已经使用 keep-alive 来保持其连接活动,这些 keep-alive 数据包也不会被转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用选项“clitcpka”可在连接的客户端侧启用 TCP keep-alive 探测的发送,这在 HAProxy 与客户端之间出现会话过期时会有所帮助。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。
启用连续流量统计更新
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,用于统计计算的计数器仅在会话完成时递增。处理小型对象时效果很好,但处理大型对象(例如大型图像或存档)或 A/V 流时,从 haproxy 计数器生成的图看起来会像刺猬。启用此选项后,计数器会频繁地在会话期间递增,通常每 5 秒一次,这足以生成清晰的图表。重新计数直接触及热路径,因此默认情况下不启用它,因为它可能会导致会话计数非常大的情况下大量唤醒并导致性能略有下降。
启用或禁用对正常、成功连接的日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有些大型网站每秒处理数千个连接,日志记录对它们来说是一个主要的痛点。其中一些甚至被迫关闭日志,无法调试生产问题。设置此选项可确保正常的连接,即那些没有经历错误、超时、重试或重新分派的连接,将不会被记录。这为异常情况留下了磁盘空间。在 HTTP 模式下,会检查响应状态码,返回码为 5xx 的仍将被记录。 强烈建议不要使用此选项,因为大多数情况下,复杂问题的关键在于正常的日志中,而这些日志在这里不会被记录。如果您需要分离日志,请改用 "log-separate-errors" 选项。
启用或禁用对空连接的日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
在某些环境中,存在一些组件会定期连接到各种系统以确保它们仍然处于活动状态。这可能是来自另一个负载均衡器,也可能来自监控系统。默认情况下,即使是简单的端口探测或扫描也会产生日志。如果这些连接过多地污染了日志,可以通过启用选项“dontlognull”来指示未传输任何数据的连接将不会被记录,这通常对应于这些探测。请注意,错误仍将返回给客户端并在统计信息中进行统计。如果这不是期望的行为,则可以使用 http-ignore-probes 选项代替。通常建议不要在不受控制的环境(例如:互联网)中使用此选项,否则扫描和其他恶意活动将不会被记录。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。
启用或禁用在响应传输后主动关闭连接。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
一些 HTTP 服务器并不一定会在收到“option httpclose”设置的“Connection: close”时关闭连接,如果客户端也不关闭,那么连接将保持打开状态直到超时过期。这会导致服务器上的并发连接数很高,并在日志中显示很高的全局会话时间。发生这种情况时,可以使用“option forceclose”。它将在服务器完成响应后主动关闭出站服务器通道,并比使用“option httpclose”更早地释放一些资源。此选项也可以与“option http-pretend-keepalive”结合使用,后者将禁用发送“Connection: close”标头,但仍会在接收到整个响应后关闭连接。此选项会禁用并替换任何先前的“option httpclose”、“option http-server-close”、“option http-keep-alive”或“option http-tunnel”。如果此选项已在“defaults”部分中启用,则可以通过在前面加上“no”关键字来禁用它。
启用向发送到服务器的请求中插入 X-Forwarded-For 头部
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<network> 是一个可选参数,用于对匹配 <network> 的源禁用此选项。<name> 是一个可选参数,用于指定一个不同的 "X-Forwarded-For" 头部名称。
由于 HAProxy 以反向代理模式工作,服务器将其 IP 地址视为客户端地址。当服务器日志中需要客户端 IP 地址时,这有时会带来不便。为了解决这个问题,HAProxy 可以在所有发送到服务器的请求中添加一个众所周知的 HTTP 头部“X-Forwarded-For”。此头部包含一个代表客户端 IP 地址的值。由于此头部始终附加在现有头部列表的末尾,因此服务器必须配置为仅使用此头部的最后一次出现。请参阅服务器手册,了解如何启用此标准头部的使用。请注意,只能使用头部的最后一次出现,因为客户端实际上可能已经带有一个。关键字“header”可用于提供一个不同的头部名称来替换默认的“X-Forwarded-For”。当您可能已经从其他应用程序(例如 stunnel)获得“X-Forwarded-For”头部,并且需要保留它时,这会很有用。另外,如果您的后端服务器不使用“X-Forwarded-For”头部并且需要不同的头部(例如,Zeus Web 服务器需要“X-Cluster-Client-IP”)。有时,同一个 HAProxy 实例可能由直接客户端访问和反向代理访问共享(例如,当使用 SSL 反向代理解密 HTTPS 流量时)。通过添加关键字“except”,后跟网络地址,可以为已知的源地址或网络禁用添加头部。在这种情况下,任何匹配该网络的源 IP 都不会导致添加此头部。最常见的用途是与私有网络或 127.0.0.1 一起使用。另外,关键字“if-none”表示仅在头部不存在时才添加此头部。这仅应在完全受信任的环境中使用,因为如果到达 haproxy 的头部由最终用户控制,这可能会导致安全问题。此选项可以在前端或后端指定。如果其中至少一个使用它,则会添加头部。请注意,后端对头部子参数的设置将优先于前端的设置(如果两者都已定义)。对于“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 请求体
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
有时需要在做出决策前等待 HTTP 请求的主体。例如,"balance url_param" 就是这样做的。第一个用例是在连接到服务器之前,缓冲来自慢速客户端的请求。另一个用例是根据请求主体的内容来做出路由决策。此选项放置在前端或后端中,强制 HTTP 处理等待直到接收到整个主体,或者请求缓冲区已满,或者在分块编码的情况下第一个块已完成。它可能会对某些滥用 HTTP、期望前端和后端之间进行非缓冲传输的应用程序产生不希望的副作用,因此绝对不应默认使用。
启用或禁用空连接和请求超时的日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
最近,一些浏览器开始实现“预连接”功能,该功能可以推测性地连接到最近访问过的某些网站,以防用户想访问它们。这会导致与网站建立许多连接,这些连接最终会因请求超时(408)而失败,或者在浏览器首先关闭它们时出现错误的请求(400)。这些连接会污染日志并增加错误计数器。已经有“option dontlognull”,但在此情况下不足。相反,此选项执行以下操作:- 如果在连接关闭之前未通过连接接收到任何内容,则阻止向客户端发送任何 400/408 消息;- 在此情况下阻止发出任何日志;- 阻止任何错误计数器递增。这样,空连接将被静默忽略。请注意,最好不要使用此选项,除非明确需要它,因为它会隐藏实际问题。未收到请求并看到 408 的最常见原因是客户端和中间元素(如 VPN)之间的 MTU 不一致,后者会阻止过大的数据包。这些问题通常会出现在 POST 请求以及带有大 cookie 的 GET 请求中。日志通常是检测它们的唯一方法。如果在“defaults”部分启用了此选项,则可以通过在特定实例前加上“no”关键字来禁用它。
启用或禁用从客户端到服务器的 HTTP keep-alive
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以保持活动模式运行:对于每个连接,它都会处理每个请求和响应,并在响应结束和新请求开始之间将连接置于空闲状态。此模式可以通过几个选项进行更改,例如“option http-server-close”、“option forceclose”、“option httpclose”或“option http-tunnel”。此选项允许恢复保持活动模式,当在 defaults 部分使用了其他模式时,这可能很有用。“option http-keep-alive”设置会在客户端和服务器端启用 HTTP 保持活动模式。这可以降低客户端(慢速网络)的延迟,并加快服务器端的会话重用,但代价是维护与服务器的空闲连接。通常,使用此选项可以达到大约是“http-server-close”选项在小对象上实现的两倍的请求速率。此选项主要在两种情况下有用:- 当服务器不符合 HTTP 标准并验证连接而不是请求时(例如,NTLM 身份验证);- 当与服务器建立连接的成本与从服务器检索关联对象相比很高时。后一种情况可能发生在服务器是快速静态服务器或缓存时。在这种情况下,服务器需要进行适当的调优以支持足够高的连接数,因为连接将一直保持到客户端发送新请求为止。如果由于内容切换或负载均衡算法,客户端请求必须转到另一个后端或另一个服务器,则空闲连接将立即关闭并重新打开。可以使用“prefer-last-server”选项来尝试优化服务器选择,以便如果当前连接到空闲连接的服务器可用,它将被使用。目前,日志不会显示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。保持活动请求时间仍然受限于“timeout http-keep-alive”或(如果未设置)“timeout http-request”定义的超时。此选项会禁用并替换任何以前的“option httpclose”、“option http-server-close”、“option forceclose”或“option http-tunnel”。当后端和前端选项不同时,所有这 4 个选项都优先于“option http-keep-alive”。
指示系统在 HTTP 中优先考虑低交互延迟而非性能
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
在 HTTP 中,每个有效负载是单向的,没有交互性的概念。期望任何代理都会在合理延迟内对数据进行排队。存在一些非常罕见的服务器到服务器应用程序滥用 HTTP 协议,并期望有效负载阶段高度交互,在单个请求中双向传输许多交错的数据块。这绝对不受 HTTP 规范的支持,并且在大多数代理或服务器上都无法正常工作。当此类应用程序尝试通过 haproxy 进行此操作时,它会起作用,但由于网络优化(通过指示系统等待足够的数据可用以仅发送完整数据包来提高性能)而会遇到高延迟。典型的延迟约为每次往返 200 毫秒。请注意,这仅在异常使用时发生。正常的用法,如 CONNECT 请求或 WebSockets,不受影响。当“option http-no-delay”存在于连接使用的前端或后端时,所有此类优化都将被禁用,以使交换尽可能快。当然,这不保证功能正常,因为它可能会在其他地方出现问题。但如果它通过 HAProxy 工作,它将以尽可能快的速度工作。此选项默认情况下绝不应使用,除非发现了此类有错误的应用,否则永远不应使用。使用此选项的影响是带宽使用和 CPU 使用的增加,这可能会在延迟较高的环境中显着降低性能。
定义 haproxy 是否向服务器宣告 keep-alive
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
在使用“option http-server-close”或“option forceclose”运行时,haproxy 会向转发到服务器的请求添加“Connection: close”头部。不幸的是,当某些服务器看到此头部时,它们会自动停止使用未知长度响应的分块编码,而这完全无关。直接影响是阻止 haproxy 保持客户端连接活动。第二个影响是客户端或缓存可能会收到不完整的响应而不知情,并认为响应已完成。通过设置“option http-pretend-keepalive”,haproxy 将使服务器相信它将保持连接活动。然后,服务器将不会回退到上述异常的、不希望的行为。当 haproxy 获取整个响应时,它将像使用“forceclose”选项一样关闭与服务器的连接。这样,客户端会收到正常响应,并且服务器端的连接也会正确关闭。建议不要默认启用此选项,因为大多数服务器会更有效地在最后一个数据包后关闭连接,并稍早地释放其缓冲区。此外,网络上添加的数据包可能会略微降低整体峰值性能。然而,值得注意的是,当启用此选项时,haproxy 的工作量会略微减少。因此,如果 haproxy 是整个架构的瓶颈,启用此选项可能会节省一些 CPU 周期。此选项可以在前端和后端设置。如果持有连接的前端或后端至少有一个启用了它,它就会被启用。此选项可以与“option httpclose”结合使用,这将导致向服务器宣告保持活动并向客户端宣告关闭。但这种做法不被提倡。如果在“defaults”部分启用了此选项,则可以通过在特定实例前加上“no”关键字来禁用它。
启用或禁用服务器端的 HTTP 连接关闭
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以保持活动模式运行:对于每个连接,它都会处理每个请求和响应,并在响应结束和新请求开始之间将连接置于空闲状态。此模式可以通过几个选项进行更改,例如“option http-server-close”、“option forceclose”、“option httpclose”或“option http-tunnel”。设置“option http-server-close”会在服务器端启用 HTTP 连接关闭模式,同时保留支持客户端的 HTTP 保持活动和流水线的能力。这可以降低客户端(慢速网络)的延迟,并加快服务器端的会话重用以节省服务器资源,这与“option forceclose”类似。它还允许非保持活动服务器以保持活动模式服务客户端,前提是它们符合 RFC7230 的要求。请注意,当某些服务器看到请求中的“Connection: close”时,它们并不总是符合这些要求。其效果将是永远不会使用保持活动。一种解决方法是启用“option http-pretend-keepalive”。目前,日志不会显示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。保持活动请求时间仍然受限于“timeout http-keep-alive”或(如果未设置)“timeout http-request”定义的超时。此选项可以在前端和后端设置。如果持有连接的前端或后端至少有一个启用了它,它就会被启用。它会禁用并替换任何以前的“option httpclose”、“option forceclose”、“option http-tunnel”或“option http-keep-alive”。请检查 第 4 节(“代理”)以了解当前端和后端选项不同时此选项如何与其他选项组合。如果在“defaults”部分启用了此选项,则可以通过在特定实例前加上“no”关键字来禁用它。
禁用或启用第一次事务后的 HTTP 连接处理
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以保持活动模式运行:对于每个连接,它都会处理每个请求和响应,并在响应结束和新请求开始之间将连接置于空闲状态。此模式可以通过几个选项进行更改,例如“option http-server-close”、“option forceclose”、“option httpclose”或“option http-tunnel”。“http-tunnel”选项会禁用第一个请求和第一个响应之后的所有 HTTP 处理。这是 1.0 到 1.5-dev21 版本中默认使用的模式。它是处理开销最低的模式,通常不再需要,除非在非常特殊的情况下,例如使用看起来像 HTTP 但不兼容的内部协议,或者只是记录每个客户端的请求以减少日志大小。请注意,在 HTTP 级别上工作的所有内容,包括头部解析/添加、cookie 处理或内容切换,仅对第一个请求有效,并在第一个响应后被忽略。如果在“defaults”部分启用了此选项,则可以通过在特定实例前加上“no”关键字来禁用它。
使用非标准的 Proxy-Connection 标头代替 Connection
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
虽然 RFC7230 明确规定 HTTP/1.1 代理必须使用 Connection 头部来指示其对持久或非持久连接的意愿,但浏览器和代理都会忽略代理连接的此头部,而是使用未记录的、非标准的 Proxy-Connection 头部。当尝试在浏览器和此类代理之间放置负载均衡器时,问题就开始了,因为 haproxy 的理解与客户端和代理之间的约定将存在差异。通过在前端设置此选项,haproxy 可以自动切换到使用该非标准头部,如果它看到代理请求的话。这里定义的代理请求是指 URI 既不以 '/' 也不以 '*' 开头的请求。这与 HTTP 隧道模式不兼容。请注意,此选项只能在前段指定,并且会影响请求的整个生命周期。此外,当设置此选项时,需要身份验证的请求将自动切换到使用代理身份验证头部,如果它本身是一个代理请求。这使得在现有代理前面检查或强制执行身份验证成为可能。此选项通常永远不应使用,除非是在代理前面。
启用 HTTP 协议以检查服务器健康状况
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<method> 是与请求一起使用的可选 HTTP 方法。未设置时,使用 "OPTIONS" 方法,因为它通常需要较低的服务器处理,并且易于从日志中过滤掉。可以使用任何方法,但不建议发明非标准方法。<uri> 是 HTTP 请求中引用的 URI。它默认为 " / ",几乎所有服务器默认都可访问,但可以更改为任何其他 URI。允许使用查询字符串。<version> 是可选的 HTTP 版本字符串。它默认为 "HTTP/1.0",但某些服务器在 HTTP 1.0 下行为可能不正确,因此将其设置为 HTTP/1.1 有时会有所帮助。请注意,"Host" 字段在 HTTP/1.1 中是必需的,作为一种技巧,可以在版本字符串后面的 "\r\n" 之后传递它。
默认情况下,服务器运行状况检查仅包括尝试建立 TCP 连接。当指定 "option httpchk" 时,会在建立 TCP 连接后发送一个完整的 HTTP 请求,响应 2xx 和 3xx 被视为有效,而所有其他响应则表示服务器失败,包括没有任何响应。端口和间隔在服务器配置中指定。此选项不一定需要 HTTP 后端,它也适用于纯 TCP 后端。这对于使用 inetd 守护进程检查绑定到某些专用端口的简单脚本特别有用。
# 将 HTTPS 流量中继到 Apache 实例并使用 HTTP 请求 "OPTIONS * HTTP/1.1" 检查端口 80 上的服务可用性 backend https_relay mode tcp option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www server apache1 192.168.1.1:443 check port 80
启用或禁用被动 HTTP 连接关闭
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以保持活动模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间使双方的连接保持空闲。此模式可以通过多个选项进行更改,例如 "option http-server-close"、"option forceclose"、"option httpclose" 或 "option http-tunnel"。如果设置了 "option httpclose",HAProxy 将以 HTTP 隧道模式运行,并检查每个方向是否已设置 "Connection: close" 头,如果缺少则会添加一个。每一方应对此做出反应,在每次传输后主动关闭 TCP 连接,从而切换到 HTTP 关闭模式。任何不同于 "close" 的 "Connection" 头也将被移除。请注意,此选项已弃用,因为它所做的事情成本很低但不可靠。强烈建议改用 "option http-server-close" 或 "option forceclose"。一些服务器错误地忽略此头并且不关闭连接,即使它们回复 "Connection: close",这种情况很少发生。因此,它们与旧的 HTTP 1.0 浏览器不兼容。如果发生这种情况,可以使用 "option forceclose",它会在服务器响应后主动关闭请求连接。选项 "forceclose" 也会更早地释放服务器连接,因为它不必等待客户端确认。此选项可以在前端和后端设置。如果至少有一个拥有连接的前端或后端启用了它,它就会被启用。它会禁用并替换任何先前的 "option http-server-close"、"option forceclose"、"option http-keep-alive" 或 "option http-tunnel"。请查看 第 4 节("代理")了解当前端和后端选项不同时此选项如何与其他选项结合使用。如果在 "defaults" 部分中启用了此选项,则可以通过在其前面加上 "no" 关键字在其特定实例中禁用它。
启用 HTTP 请求、会话状态和计时器的日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
clf 如果添加了 "clf" 参数,则输出格式将是 CLF 格式,而不是 HAProxy 的默认 HTTP 格式。当您需要将 HAProxy 的日志馈送到仅支持 CLF 格式且不可扩展的特定日志分析器时,可以使用此选项。
默认情况下,日志输出格式非常简陋,仅包含源地址和目标地址以及实例名称。通过指定 "option httplog",每行日志将变成一个更丰富的格式,包括但不限于 HTTP 请求、连接计时器、会话状态、连接数、捕获的头和 Cookie、前端、后端和服务器名称,当然还有源地址和端口。此选项可以在前端或后端设置。仅指定 "option httplog" 将自动清除如果默认设置的 'clf' 模式。 "option httplog" 覆盖任何先前的 "log-format" 指令。
启用或禁用纯 HTTP 代理模式
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
有时人们需要一个纯粹的 HTTP 代理,它能理解基本的代理请求,而不需要缓存或任何花哨的功能。在这种情况下,设置一个启用了 "option http_proxy" 的 HAProxy 实例可能是值得的。在这种模式下,不声明任何服务器,连接被转发到 URL 中 "http://" 方案后的 IP 地址和端口。不执行主机地址解析,因此这仅在传递纯 IP 地址时有效。由于此选项的使用范围相当有限,它可能只会被那些知道自己确切需要它的专家使用。这与 HTTP 隧道模式不兼容。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
# 此后端理解 HTTP 代理请求并直接转发它们。 backend direct_forward option httpclose option http_proxy
启用或禁用对两个方向的独立超时处理
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,当数据通过套接字发送时,套接字上的写入超时和读取超时都会被刷新,因为我们认为套接字上有活动,并且我们无法猜测是否应该接收数据。虽然这种默认行为对于几乎所有应用程序都是可取的,但在某些情况下,禁用它,并且仅在有传入数据时刷新读取超时是可取的。这发生在会话具有较长超时且交换数据量较少的情况下,例如 telnet 会话。如果服务器突然消失,输出数据会累积在系统的套接字缓冲区中,两个超时都会被正确刷新,并且无法知道服务器未收到数据,因此我们不会超时。但是,当底层协议始终回显发送的数据时,仅使用读取超时就足以检测到问题。请注意,对于更详细的协议,不会发生此问题,因为数据不会长时间累积在套接字缓冲区中。当此选项在前端设置时,它将禁用发送到客户端的数据的读取超时更新。这种情况很少有用。当选项在后端设置时,它将禁用发送到服务器的数据的读取超时更新。这样做通常会破坏来自慢速线路的大型 HTTP POST 请求,因此请谨慎使用。注意:早期版本曾以拼写错误的方式称此设置为 "option independant-streams"。此拼写仍然支持但已弃用。
使用 LDAPv3 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 LDAPv3 通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 LDAPv3 匿名简单绑定消息,并分析响应以查找 LDAPv3 绑定响应消息。只有当 LDAP 响应包含成功 resultCode (http://tools.ietf.org/html/rfc4511#section-4.1.9) 时,服务器才被认为是有效的。绑定请求的日志记录取决于服务器,请参阅您的文档如何配置它。
option ldap-check
使用外部进程进行服务器健康检查
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以使用外部命令测试服务器的健康状况。这是通过运行使用 "external-check command" 设置的可执行文件来实现的。需要设置全局的 "external-check"。
启用或禁用健康检查状态更新的日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,仅当服务器 UP 时记录失败的运行状况检查,并且当服务器 DOWN 时记录成功的运行状况检查,因此附加信息的数量有限。启用此选项后,将记录运行状况检查状态的任何更改或服务器的运行状况,以便能够知道服务器在崩溃前偶尔出现故障检查,或者确切知道何时未响应有效的 HTTP 状态,然后端口开始拒绝连接,然后服务器完全停止响应。请注意,此选项故意不记录非运行状况检查引起的状态更改(例如,在 CLI 上启用/禁用)。
更改非完全成功连接的日志级别
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有时在日志中查找错误并不容易。此选项使 haproxy 提高包含潜在有趣信息(如错误、超时、重试、重新分派或 HTTP 状态码 5xx)的日志级别。级别从 "info" 变为 "err"。这使得可以使用大多数 syslog 守护进程将它们单独记录到不同的文件中。注意不要将它们从原始文件中删除,否则你会丢失提供非常重要信息的顺序。使用此选项,处理每秒数千个连接的大型站点可以将正常流量记录到循环缓冲区中,并只归档较小的错误日志。
启用或禁用 HTTP 请求的早期日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,HTTP 请求在终止时进行日志记录,以便总传输时间和字节数出现在日志中。传输大型对象时,在请求出现在日志中之前可能需要一段时间。使用 "option logasap",一旦服务器发送了完整的头信息,请求就会被记录下来。日志中唯一缺失的信息是字节总数,它会显示除传输数据量之外的所有内容,以及总时间,它将不包括传输时间。在这种情况下,捕获 "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"
使用 MySQL 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 MySQL 服务器时将使用的用户名。 post-41 发送与 v4.1 后版本客户端兼容的检查
如果您指定了用户名,检查将包括发送两个 MySQL 数据包:一个客户端身份验证数据包和一个 QUIT 数据包,以正确关闭 MySQL 会话。然后,我们解析 MySQL Handshake Initialisation 数据包和/或 Error 数据包。这是一项基本但有用的测试,不会在服务器上产生错误或中止连接。但是,它需要像这样在 MySQL 表中添加授权:USE mysql; INSERT INTO user (Host,User) values ('<haproxy 的 ip>','<用户名>'); FLUSH PRIVILEGES; 如果您不指定用户名(已弃用且不推荐),检查仅包括解析 MySQL Handshake Initialisation 数据包或 Error 数据包,我们不会在此模式下发送任何内容。据报道,如果检查过于频繁和/或流量不足,可能会导致锁定。实际上,在这种情况下,您需要检查 MySQL 的 "max_connect_errors" 值,因为如果在上次连接中断后的 "max_connect_errors" 次尝试内成功建立连接,则该主机的错误计数将被清除为零。如果 HAProxy 的服务器被阻止,"FLUSH HOSTS" 语句是唯一的解除阻止方法。请记住,这不会检查数据库是否存在或数据库一致性。要做到这一点,您可以使用 xinetd 等外部检查。该检查需要 MySQL >=3.22,对于旧版本,请使用 TCP 检查。大多数情况下,入站 MySQL 服务器需要查看客户端的 IP 地址,以用于各种目的,包括 IP 权限匹配和连接日志记录。在可能的情况下,通常明智的做法是使用 "source" 关键字的 "usesrc" 参数来假冒客户端 IP 地址,这需要编译透明代理功能,并且 MySQL 服务器需要通过托管 haproxy 的机器路由客户端。启用或禁用关闭后立即清理会话资源
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当客户端或服务器以肮脏的方式中止连接时(例如,它们物理断开连接),会话超时会被触发,并且会话被关闭。但它会在系统中以 FIN_WAIT1 状态保持一段时间,占用一些资源,并可能限制建立新连接的能力。发生这种情况时,可以激活 "option nolinger",它会强制系统在关闭时立即删除套接字的任何待处理数据。因此,会话会立即从系统的表中清除。这通常会产生副作用,例如由于旧的重传被立即拒绝而导致 TCP 重置数量增加。一些防火墙有时也会为此抱怨。因此,当绝对不需要时,不建议使用此选项。当您的系统上有数千个 FIN_WAIT1 会话时(TIME_WAIT 的不计在内),您就知道您需要它。此选项可用于前端和后端,具体取决于需要它的那一侧。对于客户端,请在前端使用它;对于服务器,请在后端使用它。如果在 "defaults" 部分中启用了此选项,则可以通过在其前面加上 "no" 关键字在其特定实例中禁用它。
启用向发送到服务器的请求插入 X-Original-To 标头
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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 一起使用。此选项可以在前端或后端指定。如果至少其中一个使用了它,将添加该头。请注意,如果前端和后端都定义了头子参数,则后端设置的头子参数优先于前端。
# 原始目标地址 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
启用或禁用对故障服务器的强制持久性
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当 HTTP 请求到达一个带有引用故障服务器的 cookie 的后端时,默认情况下它会被重新分派到另一台服务器。如果绝对需要,可以使用 "option persist" 强制将请求首先发送到故障服务器。一个常见的用例是当服务器处于极端负载下并不断地出现状态切换时。在这种情况下,用户仍将被导向到他们打开会话的服务器,希望他们能得到正确的服务。建议将 "option redispatch" 与此选项结合使用,以便在无法连接到服务器的情况下(服务器确定故障),客户端最终将被重定向到另一台有效的服务器。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 PostgreSQL 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 PostgreSQL 服务器时将使用的用户名。
此检查发送一个 PostgreSQL StartupMessage 并等待认证请求或 ErrorResponse 消息。这是一个基本但有用的测试,不会在服务器上产生错误或中止连接。此检查与 "mysql-check" 相同。
允许多个负载均衡的请求保留在同一台服务器上
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当使用的负载均衡算法不是确定性的,并且之前的请求被发送到一个 haproxy 仍然持有连接的服务器时,有时希望同一会话的后续请求尽可能地发送到同一台服务器。请注意,这与持久性不同,因为我们只指示一个偏好,haproxy 会尝试应用它,但不提供任何形式的保证。实际用途是发送到服务器的保持活动连接。当使用此选项时,haproxy 将尝试重用连接到服务器的同一个连接,而不是重新平衡到另一个服务器,从而导致连接关闭。这对于静态文件服务器可能很有意义。与哈希算法结合使用意义不大。注意,haproxy 已经自动尝试坚持发送 401 的服务器或发送 407(身份验证所需)的代理。这对于损坏的 NTLM 身份验证挑战是必需的,并且在排查某些有故障的应用程序方面非常有帮助。在这种环境中,prefer-last-server 选项也可能是有益的,以避免在每次其他响应后重新分配流量。如果在 "defaults" 部分中启用了此选项,则可以通过在其前面加上 "no" 关键字在其特定实例中禁用它。
启用或禁用连接失败时的会话重新分发
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<interval> 控制重试连接时发生重新分发的频率的可选整数值。正值 P 表示每 P 次重试都希望进行一次重新分发,负值 N 表示在最后一次重试之前的第 N 次重试时希望进行一次重新分发。例如,默认值 -1 保留了在最后一次重试时进行重新分发的历史行为,值为 1 表示每次重试都进行重新分发,值为 3 表示每三次重试进行一次重新分发。您可以将值设置为 0 来禁用重新分发。
在 HTTP 模式下,如果由 Cookie 指定的服务器宕机,客户端可能会永久性地卡在它上面,因为他们无法刷新 Cookie,因此他们将无法再访问该服务。指定 "option redispatch" 将允许代理打破其持久性并将它们重新分发到正在工作的服务器。它还允许在多次连接失败的情况下重试连接到另一台服务器。当然,这需要将 "retries" 设置为非零值。这种形式是首选形式,它取代了 "redispatch" 和 "redisp" 关键字。如果在 "defaults" 部分中启用了此选项,则可以通过在其前面加上 "no" 关键字在其特定实例中禁用它。
使用 Redis 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
可以测试服务器是否正确地使用 REDIS 协议通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,会向服务器发送一个 PING redis 命令,并分析响应以查找 "+PONG" 响应消息。
option redis-check
使用 SMTP 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<hello> 是一个可选参数。它是要使用的“hello”命令。它可以是“HELO”(用于 SMTP)或“EHLO”(用于 ESMTP)。所有其他值都将转换为默认命令(“HELO”)。<domain> 是要呈现给服务器的域名。只有在指定了 hello 命令时才能指定(并且是强制性的)。默认情况下,使用“localhost”。
当设置了“option smtpchk”时,健康检查将包括 TCP 连接和 SMTP 命令。默认情况下,此命令是“HELO localhost”。服务器的返回码将被分析,只有以“2”开头的返回码才会被视为有效。所有其他响应,包括无响应,都将被视为错误,并表示服务器已死。此测试适用于 SMTP 服务器或中继。根据请求的不同,某些服务器可能不会记录每次连接尝试,因此您可能需要进行实验以改进行为。使用 telnet 连接到 25 端口通常比调整配置更容易。大多数情况下,传入的 SMTP 服务器需要查看客户端的 IP 地址,以满足多种目的,包括垃圾邮件过滤、反欺骗和日志记录。在可能的情况下,连接到服务器时使用“source”关键字的“usesrc”参数来伪装客户端 IP 地址通常是明智的,这需要编译透明代理功能。
option smtpchk HELO mydomain.org
启用或禁用为每个套接字收集并提供单独的统计信息。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
启用或禁用双向套接字上的自动内核加速
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当此选项在前端或后端启用时,haproxy 将自动评估是否可以使用内核 TCP 拼接来转发客户端和服务器之间的数据,双向均可。Haproxy 使用启发式方法来估算内核拼接是否会提高性能。双向独立处理。请注意,所使用的启发式方法并不非常激进,以限制拼接的过度使用。此选项需要在编译时启用拼接,并且可以使用全局选项“nosplice”全局禁用。由于 splice 使用管道,因此使用它需要有足够的可用管道。重要提示:基于内核的 TCP 拼接是一项 Linux 特有的功能,最早出现在内核 2.6.25 中。它提供了基于内核的加速,用于在套接字之间传输数据,而无需将这些数据复制到用户空间,从而带来显著的性能提升和 CPU 周期节省。由于许多早期实现都存在 bug、数据损坏和/或效率低下,因此此功能默认不启用,并且应极其谨慎地使用。虽然无法检测实现的正确性,但 2.6.29 是第一个提供正确实现的版本。如有疑问,可以使用全局“nosplice”关键字全局禁用拼接。
option splice-auto
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用请求套接字上的自动内核加速
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当在前台或后台启用此选项时,haproxy 将尽可能使用内核 TCP 拼接来转发从客户端到服务器的数据。如果没有备用管道,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于 splice 使用管道,使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅 "option splice-auto"。
option splice-request
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
启用或禁用响应套接字上的自动内核加速
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当在前台或后台启用此选项时,haproxy 将尽可能使用内核 TCP 拼接来转发从服务器到客户端的数据。如果没有备用管道,它可能仍会使用 recv/send 方案。此选项需要在编译时启用拼接,并且可以通过全局选项 "nosplice" 全局禁用。由于 splice 使用管道,使用它需要有足够的备用管道。重要说明:有关使用限制,请参阅 "option splice-auto"。
option splice-response
如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字在特定实例中禁用它。
使用 SPOP 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 否![]() | 是![]() |
可以测试服务器是否正确地使用 SPOP 协议进行通信,而不仅仅是测试它是否接受 TCP 连接。设置此选项后,HAProxy 和服务器之间会执行 HELLO 握手,并分析响应以检查是否报告了错误。
option spop-check
启用或禁用在服务器端发送 TCP keepalive 数据包
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当客户端和服务器之间存在防火墙或任何会话感知组件,并且协议涉及非常长的会话且存在很长的空闲时间(例如,远程桌面)时,中间组件可能会决定过期一个长时间处于空闲状态的会话。启用套接字级别的 TCP keep-alive 会使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,取决于操作系统及其调优参数。重要的是要理解,keep-alive 数据包既不会在应用程序级别发出,也不会在应用程序级别接收。只有网络堆栈能看到它们。因此,即使代理的一侧已经使用 keep-alive 来维持其连接,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用“option srvtcpka”选项可在连接的服务器端启用 TCP keep-alive 探测的发出,这在注意到 HAProxy 和服务器之间的会话过期时应有所帮助。如果此选项已在“defaults”部分启用,则可以通过在其前面加上“no”关键字在其特定实例中禁用它。
使用 SSLv3 客户端 hello 健康检查进行服务器测试
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当一些基于 SSL 的协议在 TCP 模式下通过 HAProxy 中继时,可以测试服务器是否正确地使用 SSL 通信,而不仅仅是测试它是否接受 TCP 连接。设置 "option ssl-hello-chk" 后,一旦与服务器建立连接,就会发送纯 SSLv3 客户端 hello 消息,并分析响应以查找 SSL 服务器 hello 消息。只有当响应包含此服务器 hello 消息时,服务器才被认为是有效的。到目前为止测试的所有服务器都能正确回复 SSLv3 客户端 hello 消息,并且大多数测试的服务器甚至不记录仅包含 hello 消息的请求,这是值得赞赏的。请注意,即使 haproxy 未内置 SSL 支持,此检查也能正常工作,因为它会伪造 SSL 消息。当 SSL 支持可用时,最好使用原生 SSL 健康检查而不是这个。
使用 tcp-check 发送/期望序列执行健康检查
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
此健康检查方法旨在与“option tcp-check”命令列表结合使用,以支持发送/期望类型的健康检查序列。TCP 检查目前支持 4 种操作模式:- 未指定“tcp-check”指令:健康检查仅包括连接尝试,这是默认模式。- 仅指定“tcp-check send”或“tcp-check send-binary”:用于在打开连接时发送字符串。对于某些协议,这有助于发送“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”指令,后跟一个字符串。此字符串将在日志和 debug 模式下的 stderr 中报告。这对于提供用户友好的错误报告非常有用。“comment”当然是可选的。
# 执行 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 数据包
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
当收到 HTTP 连接请求时,系统会代表 HAProxy 确认它,然后客户端立即发送其请求,系统在通知 HAProxy 新连接的同时也确认它。然后 HAProxy 读取请求并响应。这意味着系统发送了一个不必要的 TCP ACK,因为当 HAProxy 发送其响应时,请求完全可以被它确认。因此,在 HTTP 模式下,HAProxy 会自动要求系统在支持它的平台(目前至少有 Linux)上避免发送这个无用的 ACK。这不应该造成任何问题,因为如果响应所需时间超过预期,系统仍将在 40 毫秒后发送它。在复杂的网络调试会话中,可能希望禁用此优化,因为延迟的 ACK 会使故障排除更加复杂,难以确定数据包延迟的位置。然后可以通过指定“no option tcp-smart-accept”来恢复到正常行为。也可以通过简单地指定“option tcp-smart-accept”来强制非 HTTP 代理使用它。例如,它可能适用于某些服务,如 SMTP,其中服务器先说话。建议避免在 defaults 部分强制使用此选项。如有疑问,请考虑将其恢复到自动值,方法是在前面加上“default”关键字,或使用“no”关键字禁用它。
启用或禁用在连接序列期间节省一个 ACK 数据包
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
在某些系统(至少是 Linux)上,HAProxy 可以请求内核在收到连接请求时不立即发送一个空的 ACK,而是直接发送带有数据的请求。这可以在网络上节省一个数据包,从而提高性能。这对某些服务器也很有用,因为它们可以立即随传入连接一起获取请求。当在后端设置了 "option tcp-smart-connect" 时,此功能被启用。默认情况下不启用,因为它会使网络故障排除变得更加复杂。只在客户端先说话的协议(如 HTTP)中启用它才有意义。在其他情况下,如果没有数据可以代替 ACK 发送,则会发送一个正常的 ACK。如果此选项已在 "defaults" 部分启用,可以通过在其前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用在两侧发送 TCP keepalive 数据包
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
当客户端和服务器之间存在防火墙或任何会话感知组件,并且协议涉及非常长的会话且存在很长的空闲时间(例如,远程桌面)时,中间组件可能会决定过期一个长时间处于空闲状态的会话。启用套接字级别的 TCP keep-alive 会使系统定期向连接的另一端发送数据包,使其保持活动状态。keep-alive 探测之间的延迟仅由系统控制,取决于操作系统及其调优参数。重要的是要理解,keep-alive 数据包既不会在应用程序级别发出,也不会在应用程序级别接收。只有网络堆栈能看到它们。因此,即使代理的一侧已经使用 keep-alive 来维持其连接,这些 keep-alive 数据包也不会转发到代理的另一侧。请注意,这与 HTTP keep-alive 无关。使用“option tcpka”选项可在连接的客户端和服务器两侧发出 TCP keep-alive 探测。请注意,这仅在“defaults”或“listen”部分有意义。如果此选项用于前端,则只有客户端才会收到 keep-alive;如果此选项用于后端,则只有服务器才会收到 keep-alive。因此,强烈建议在配置拆分到前端和后端时,明确使用“option clitcpka”和“option srvtcpka”。
启用包含会话状态和计时器的 TCP 连接高级日志记录
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,日志输出格式非常简陋,它只包含源和目标地址以及实例名称。通过指定“option tcplog”,每行日志将变成更丰富的格式,包括但不限于连接计时器、会话状态、连接数、前端、后端和服务器名称,当然还有源地址和端口。此选项对于纯 TCP 代理非常有用,可以找出是客户端还是服务器断开连接或超时。对于常规 HTTP 代理,最好使用“option httplog”,它更完整。此选项可以在前端或后端设置。“option tcplog”将覆盖任何先前“log-format”指令。
启用客户端透明代理
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
引入此选项是为了给第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力,将针对远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一台设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。请注意,与普遍看法相反,此选项不会使 HAProxy 在建立连接时向服务器呈现客户端的 IP。
执行外部检查时要运行的可执行文件
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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”设置。如果执行的命令退出状态为零,则认为检查通过,否则认为检查失败。
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<path> 是执行外部命令时使用的路径
默认路径为 ""。
external-check path "/usr/bin:/bin"
启用基于 RDP cookie 的持久性
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<name> 是要检查的可选 RDP cookie 的名称。如果省略,将使用默认的 cookie 名称 "msts"。目前没有更改此名称的有效理由。
此语句基于 RDP cookie 启用持久性。RDP cookie 包含查找已知服务器列表中服务器所需的所有信息。因此,当此选项在 backend 中设置时,将分析请求,如果找到 RDP cookie,则对其进行解码。如果它与一个已知且仍然 UP 的服务器匹配(或者如果设置了“option persist”),则连接将被转发到该服务器。请注意,这仅在 TCP backend 中有意义,但为了使其正常工作,前端必须等待足够长的时间以确保请求缓冲区中存在 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
设置前端每秒接受的新会话数限制
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<rate> <rate> 参数是一个整数,指定前端每秒接受的最大新会话数。
当前端达到每秒指定的新会话数时,它将停止接受新连接,直到速率再次降至限制以下。在此期间,挂起的会话将保留在套接字的 backlog 中(在系统缓冲区中),haproxy 甚至不会意识到有会话挂起。在对高负载服务应用非常低的限制时,增加套接字 backlog 可能是有意义的,方法是使用“backlog”关键字。此功能在阻止连接型攻击或对脆弱服务器的服务滥用方面特别有效。由于会话速率以每毫秒为单位进行测量,因此它非常准确。此外,限制立即生效,无需任何延迟即可检测到阈值。将 SMTP 的连接速率限制为最大每秒 10 个listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025
注意:当达到最大速率时,前端的状态不会改变,但如果启用了 "socket-stats" 选项,其套接字在统计信息中将显示为 "WAITING"。
如果/除非条件匹配,则返回 HTTP 重定向
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
如果/除非条件匹配,HTTP 请求将导致重定向响应。如果未指定条件,则重定向无条件适用。
<loc> 使用 "redirect location" 时,<loc> 中的确切值将被放入 HTTP "Location" 标头中。当在 "http-request" 规则中使用时,<loc> 值遵循日志格式规则,并且可以包含一些动态值(参见 8.2.4 节中的自定义日志格式)。<pfx> 使用 "redirect prefix" 时,"Location" 标头将由 <pfx> 和完整的 URI 路径(包括查询字符串)连接而成,除非指定了 "drop-query" 选项(见下文)。作为一种特殊情况,如果 <pfx> 等于 "/",则不会在原始 URI 前插入任何内容。这允许重定向到相同的 URL(例如,插入 cookie)。当在 "http-request" 规则中使用时,<pfx> 值遵循日志格式规则,并且可以包含一些动态值(参见 8.2.4 节中的自定义日志格式)。<sch> 使用 "redirect scheme" 时,"Location" 标头将通过连接 <sch>、"://"、"Host" 标头的第一次出现,然后是 URI 路径(包括查询字符串,除非指定了 "drop-query" 选项,见下文)来构建。如果没有找到路径,或者路径是 "*",则使用 "/" 代替。如果没有找到 "Host" 标头,则会返回一个空的 host 组件,大多数现代浏览器会将其解释为重定向到同一 host。此指令主要用于将 HTTP 重定向到 HTTPS。当在 "http-request" 规则中使用时,<sch> 值遵循日志格式规则,并且可以包含一些动态值(参见 8.2.4 节中的自定义日志格式)。<code> code 是可选的。它指示所需 HTTP 重定向的类型。仅支持 301、302、303、307 和 308 代码,如果未指定代码,则默认使用 302。301 表示“永久移动”,浏览器可能会缓存 Location。302 表示“临时移动”,意味着浏览器不应缓存重定向。303 等同于 302,但浏览器会使用 GET 方法获取 location。307 就像 302,但明确表示必须重用相同的方法。同样,如果必须使用相同的方法,308 将替换 301。<option> 有几个选项可以指定,以调整重定向的预期行为:- "drop-query" 当此关键字在基于前缀的重定向中使用时,location 将不包含任何可能的查询字符串,这对于将用户定向到非安全页面很有用。它对 location 类型重定向没有影响。- "append-slash" 此关键字可与 "drop-query" 结合使用,将 URL 不以 '/' 结尾的用户重定向到以 '/' 结尾的同一 URL。这对于确保搜索引擎只看到一个 URL 可能很有用。为此,首选返回代码 301。- "set-cookie NAME[=value]" 将把一个 "Set-Cookie" 标头添加到响应中,其中包含 NAME(以及可选的 "=value")。这有时用于指示已见过用户,例如,以防止某些类型的 DoS 攻击。没有添加其他 cookie 选项,因此 cookie 将是会话 cookie。请注意,对于浏览器来说,仅带有名称的 cookie 与带有名称和值的 cookie 不同。- "clear-cookie NAME[=]" 将把一个 "Set-Cookie" 标头添加到响应中,其中包含 NAME(以及可选的 "="),但 "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 节。
启用或禁用连接失败时的会话重新分发
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
在 HTTP 模式下,如果由 cookie 指定的服务器宕机,客户端可能会因为无法清除 cookie 而一直固守在该服务器上,从而无法再访问该服务。指定 "redispatch" 将允许代理打破它们的持久性,并将它们重新分配到一个正常工作的服务器。它还允许在多次连接失败的情况下重试最后一次连接到另一台服务器。当然,这需要将 "retries" 设置为非零值。此形式已弃用,请不要在任何新配置中使用它,而应使用新的 "option redispatch"。
在 HTTP 请求的末尾添加一个头部
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<string> 是要添加的完整行。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。有关 HTTP 头部操作的更多信息,请参阅第 6 节。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
一个由 <string> 后跟一个换行符组成的新行将被添加到 HTTP 请求的最后一个头部之后。头部转换仅适用于通过 HAProxy 的流量,而不适用于由 HAProxy 生成的流量,例如健康检查或错误响应。
向来自端口 81 的请求添加 "X-Proto: SSL"acl is-ssl dst_port 81 reqadd X-Proto:\ SSL if is-ssl
如果某行匹配正则表达式,则明确允许该 HTTP 请求
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和请求行的正则表达式。这是一个扩展正则表达式。支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"reqallow" 关键字严格区分大小写,而 "reqiallow" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
包含任何匹配扩展正则表达式 <search> 的行的请求将被标记为允许,即使任何后续测试会导致拒绝。该测试同时适用于请求行和请求头部。请记住,请求行中的 URL 是区分大小写的,而头部名称则不是。使用 ACL 来编写访问策略更容易、更快、更强大。在新设计中应避免使用 Reqdeny、reqallow 和 reqpass。
# 允许 www.* 但拒绝 *.local reqiallow ^Host:\ www\. reqideny ^Host:\ .*\.local
删除 HTTP 请求中所有匹配正则表达式的头部
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和请求行的正则表达式。这是一个扩展正则表达式。支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"reqdel" 关键字严格区分大小写,而 "reqidel" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
请求中任何匹配扩展正则表达式 <search> 的头部行将被完全删除。此功能最常见的用途是在将请求传递给下一个服务器之前,从请求中删除不需要和/或危险的头部或 cookie。头部转换仅适用于通过 HAProxy 的流量,而不适用于由 HAProxy 生成的流量,例如健康检查或错误响应。请记住,头部名称不区分大小写。
# 删除 X-Forwarded-For 头部和 SERVER cookie reqidel ^X-Forwarded-For:.* reqidel ^Cookie:.*SERVER=
如果某行匹配正则表达式,则拒绝该 HTTP 请求
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和请求行的正则表达式。这是一个扩展正则表达式。支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"reqdeny" 关键字严格区分大小写,而 "reqideny" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
包含任何匹配扩展正则表达式 <search> 的行的请求将被标记为拒绝,即使任何后续测试会导致允许。该测试同时适用于请求行和请求头部。请记住,请求行中的 URL 是区分大小写的,而头部名称则不是。一旦解析完整个请求,被拒绝的请求将生成一个“HTTP 403 forbidden”响应。这与使用 ACL 的实践是一致的。使用 ACL 来编写访问策略更容易、更快、更强大。在新设计中应避免使用 Reqdeny、reqallow 和 reqpass。
# 拒绝 *.local, 然后允许 www.* reqideny ^Host:\ .*\.local reqiallow ^Host:\ www\.
在后续规则中忽略任何匹配正则表达式的 HTTP 请求行
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和请求行的正则表达式。这是一个扩展正则表达式。支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"reqpass" 关键字严格区分大小写,而 "reqipass" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
包含任何匹配扩展正则表达式 <search> 的行的请求将跳过后续规则,而不会分配任何拒绝或允许的裁决。该测试同时适用于请求行和请求头部。请记住,请求行中的 URL 是区分大小写的,而头部名称则不是。使用 ACL 来编写访问策略更容易、更快、更强大。在新设计中应避免使用 Reqdeny、reqallow 和 reqpass。
# 拒绝 *.local, 然后允许 www.*, 但忽略 "www.private.local" reqipass ^Host:\ www.private\.local reqideny ^Host:\ .*\.local reqiallow ^Host:\ www\.
在 HTTP 请求行中用一个字符串替换一个正则表达式
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和请求行的正则表达式。这是一个扩展正则表达式。支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"reqrep" 关键字严格区分大小写,而 "reqirep" 则忽略大小写。<string> 是要添加的完整行。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。可以使用常见的 \N 形式引用匹配的模式组,其中 N 是 0 到 9 之间的一个数字。有关 HTTP 头部操作的更多信息,请参阅第 6 节。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
请求中任何匹配扩展正则表达式 <search> 的行(包括请求行和头部行)都将被完全替换为 <string>。此功能最常见的用途是在 "Host" 头部中重写 URL 或域名。头部转换仅适用于通过 HAProxy 的流量,而不适用于由 HAProxy 生成的流量,例如健康检查或错误响应。请注意,为了提高可读性,建议在请求和响应之间添加足够的空格。请记住,请求行中的 URL 是区分大小写的,而头部名称则不是。
# 在任何请求路径的开头将 "/static/" 替换为 "/"。 reqrep ^([^\ :]*)\ /static/(.*) \1\ /\2 # 在主机名中将 "www.mydomain.com" 替换为 "www"。 reqirep ^Host:\ www.mydomain.com Host:\ www
对包含匹配正则表达式的行的 HTTP 请求进行 tarpit 操作
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和请求行的正则表达式。这是一个扩展正则表达式。支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"reqtarpit" 关键字严格区分大小写,而 "reqitarpit" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
包含任何匹配扩展正则表达式 <search> 的行的请求将被 tarpit,这意味着它将连接到无处,保持打开预定义的时间,然后返回一个 HTTP 错误 500,这样攻击者就不会怀疑它已被 tarpit。状态 500 将在日志中报告,但完成标志将指示 "PT"。延迟由 "timeout tarpit" 定义,如果前者未设置,则由 "timeout connect" 定义。tarpit 的目标是减慢使用可识别请求攻击服务器的机器人。许多机器人限制其传出连接数,并保持连接等待可能需要几分钟才能到来的回复。根据环境和攻击情况,这在减少网络和防火墙负载方面可能特别有效。
# 忽略报告任何“Mozilla”或“MSIE”风格的用户代理,但 # 阻止所有其他人。 reqipass ^User-Agent:\.*(Mozilla|MSIE) reqitarpit ^User-Agent: # 阻止坏人 acl badguys src 10.1.0.3 172.16.13.20/28 reqitarpit . if badguys
设置连接失败后在服务器上执行的重试次数
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<value> 是当连接被拒绝或超时时,应在服务器上重试连接尝试的次数。默认值为 3。
重要的是要理解,此值适用于连接尝试的次数,而不是完整的请求。当与服务器有效建立连接后,将不再进行重试。为了避免立即重新连接到正在重启的服务器,在重试发生之前会应用一个 min("timeout connect", 一秒) 的周转计时器。当设置了 "option redispatch" 时,即使 cookie 引用了不同的服务器,最后一次重试也可能在另一台服务器上执行。在 HTTP 响应的末尾添加一个头部
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<string> 是要添加的完整行。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。有关 HTTP 头部操作的更多信息,请参阅第 6 节。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
一个由 <string> 后跟一个换行符组成的新行将被添加到 HTTP 响应的最后一个头部之后。头部转换仅适用于通过 HAProxy 的流量,而不适用于由 HAProxy 生成的流量,例如健康检查或错误响应。
删除 HTTP 响应中所有匹配正则表达式的头部
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和响应行的正则表达式。这是一个扩展正则表达式,因此支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"rspdel" 关键字严格区分大小写,而 "rspidel" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
响应中任何匹配扩展正则表达式 <search> 的头部行将被完全删除。此功能最常见的用途是在将响应传递给客户端之前,从响应中删除不需要和/或敏感的头部或 cookie。头部转换仅适用于通过 HAProxy 的流量,而不适用于由 HAProxy 生成的流量,例如健康检查或错误响应。请记住,头部名称不区分大小写。
# 从响应中删除 Server 头部 rspidel ^Server:.*
如果某行匹配正则表达式,则阻止该 HTTP 响应
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和响应行的正则表达式。这是一个扩展正则表达式,因此支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"rspdeny" 关键字严格区分大小写,而 "rspideny" 则忽略大小写。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
包含任何匹配扩展正则表达式 <search> 的行的响应将被标记为拒绝。该测试同时适用于响应行和响应头部。请记住,头部名称不区分大小写。此关键字的主要用途是防止敏感信息泄露,并在响应到达客户端之前阻止它。如果响应被拒绝,它将被替换为 HTTP 502 错误,以便客户端永远不会检索到任何敏感数据。使用 ACL 来编写访问策略更容易、更快、更强大。在新设计中应避免使用 Rspdeny。
# 确保没有匹配 ms-word 的内容类型会泄露 rspideny ^Content-type:\.*/ms-word
在 HTTP 响应行中用一个字符串替换一个正则表达式
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<search> 是应用于 HTTP 头部和响应行的正则表达式。这是一个扩展正则表达式,因此支持括号分组,并且不需要预先的反斜杠。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。该模式一次应用于一整行。"rsprep" 关键字严格区分大小写,而 "rspirep" 则忽略大小写。<string> 是要添加的完整行。任何空格或已知的定界符都必须使用反斜杠 ('\') 进行转义。可以使用常见的 \N 形式引用匹配的模式组,其中 N 是 0 到 9 之间的一个数字。有关 HTTP 头部操作的更多信息,请参阅第 6 节。<cond> 是一个可选的匹配条件,由 ACL 构建。当其他条件不满足时,它使得可以忽略此规则。
响应中任何匹配扩展正则表达式 <search> 的行(包括响应行和头部行)都将被完全替换为 <string>。此功能最常见的用途是重写 Location 头部。头部转换仅适用于通过 HAProxy 的流量,而不适用于由 HAProxy 生成的流量,例如健康检查或错误响应。请注意,为了提高可读性,建议在请求和响应之间添加足够的空格。请记住,头部名称不区分大小写。
# 将 "Location: 127.0.0.1:8080" 替换为 "Location: www.mydomain.com" rspirep ^Location:\ 127.0.0.1:8080 Location:\ www.mydomain.com
在后端中声明一个服务器
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<name> 是分配给此服务器的内部名称。此名称将出现在日志和警报中。如果设置了 "http-send-name-header",则会将其添加到发送到服务器的请求头中。<address> 是服务器的 IPv4 或 IPv6 地址。或者,支持可解析的主机名,但将在启动期间解析此名称。地址 "0.0.0.0" 或 "*" 具有特殊含义。它表示连接将被转发到与客户端连接相同的 IP 地址。这在透明代理体系结构中很有用,其中客户端连接被拦截,并且 haproxy 必须转发到原始目标地址。这或多或少是 "transparent" 关键字的作用,不同之处在于使用服务器可以限制并发连接并报告统计信息。可以选择在地址前使用地址系列前缀来强制指定系列,而不考虑地址格式,这在指定没有斜杠 ('/') 的 Unix 套接字路径时很有用。目前支持的前缀是:- 'ipv4@' -> 地址始终为 IPv4- 'ipv6@' -> 地址始终为 IPv6- 'unix@' -> 地址是本地 Unix 套接字的路径- 'abns@' -> 地址在抽象命名空间(仅限 Linux)您可能希望在地址参数中引用某些环境变量,有关环境变量,请参见 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 兼容。
设置要读取、加载并应用于此后端中可用服务器的服务器状态文件。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
它仅在指令 "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
设置出站连接的源地址
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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”关键字在允许仅特定地址连接到服务器的复杂环境中非常有用。例如,当必须通过公共网关使用私有地址,并且系统无法自行确定适当的源地址时,可能需要它。在某些修补过的 Linux 内核上可用的扩展可以通过可选的“usesrc”关键字使用。它使得可以使用不属于系统本身的 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 农场 source 192.168.1.200 usesrc clientip backend transparent_ssl2 # 从客户端的源地址和端口连接到 SSL 农场 # 如果本地机器上有 IP conntrack,则不推荐。 source 192.168.1.200 usesrc client backend transparent_ssl3 # 从客户端的源地址连接到 SSL 农场。 # 它对 conntrack 更友好。 source 192.168.1.200 usesrc clientip backend transparent_smtp # 使用 Tproxy 版本 4 的客户端源地址/端口连接到 SMTP 农场。 source 0.0.0.0 usesrc clientip backend transparent_http # 使用上一个代理看到的客户端 IP 连接到服务器。 source 0.0.0.0 usesrc hdr_ip(x-forwarded-for,-1)
设置服务器端的最大不活动时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
不活动超时适用于服务器预期确认或发送数据时。在 HTTP 模式下,此超时在服务器响应的第一个阶段(当它必须发送标头时)尤其重要,因为它直接代表服务器处理请求的时间。要确定在此处放置的值,通常最好从被认为是不可接受的响应时间开始,然后检查日志以观察响应时间分布,并相应地调整值。默认情况下,该值以毫秒为单位指定,但如果数字后面带有单位,则可以是任何其他单位,如本文档顶部所述。在 TCP 模式下(以及在 HTTP 模式下,程度较小),强烈建议客户端超时等于服务器超时,以避免复杂的调试情况。无论预期的服务器响应时间如何,最好通过指定略高于 3 秒倍数(例如,至少 4 或 5 秒)的超时来涵盖至少一次或多次 TCP 数据包丢失。此参数特定于后端,但可以在“defaults”部分一次性指定。实际上,这是不忘记它的最简单的解决方案之一。未指定的超时将导致无限超时,不推荐这样做。此类用法被接受并能正常工作,但在启动时会报告警告,因为它可能导致系统中的过期会话累积,如果系统的超时未配置的话。此参数是为了兼容性而提供的,但目前已弃用。请使用“timeout server”代替。
如果/除非条件匹配,则启用统计信息管理级别
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
此语句启用统计管理员级别,前提是匹配/不匹配某个条件。管理员级别允许从 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
启用带身份验证的统计信息,并为一个账户授予访问权限
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
使用默认设置启用统计报告
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
此语句使用构建时定义的默认设置启用统计报告。除非另有说明,否则将使用以下设置:- 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 版本报告
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,统计页面会报告一些有用的状态信息以及统计数据。其中包括 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
统计信息的访问控制
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
与“http-request”一样,这组选项允许对统计信息的访问进行精细控制。每个选项后面都可以跟 if/unless 和 acl。第一个匹配的选项(或不带条件的选项)是最终的。对于“deny”,将返回 403 错误;对于“allow”,将执行正常处理;对于“auth”,将返回 401/407 错误代码,因此应要求客户端输入用户名和密码。每个实例的 http-request 语句的数量没有固定限制。
启用统计信息并设置身份验证领域
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
启用带自动刷新的统计信息
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
启用统计信息并限制访问范围
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
在统计页面上启用描述的报告。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<desc> 是一个可选的要报告的描述。如果未指定,则自动使用全局部分的描述。此语句对于向客户提供共享服务的用户非常有用,其中每个客户的节点或描述应该不同。尽管此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不明显参数。默认情况下不显示描述。
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-desc Master node for Europe, Asia, Africa stats uri /admin?stats stats refresh 5s
在统计页面上启用额外信息的报告
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
在统计页面上启用报告附加信息:- cap:功能(代理)- mode:tcp、http 或 health(代理)之一- id:SNMP ID(代理、套接字、服务器)- IP(套接字、服务器)- cookie(后端、服务器)虽然此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不显眼参数。默认行为是不显示此信息。
在统计页面上启用主机名的报告。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<name> 是一个可选的要报告的名称。如果未指定,则自动使用全局部分的节点名称。
此语句对于提供共享服务给客户的用户很有用,因为每个客户提供的统计页面上的节点或描述可能不同。默认行为是不显示主机名。虽然此语句本身足以启用统计报告,但建议设置所有其他设置,以避免依赖默认的不显眼参数。
# 内部监控访问(无限制) backend private_monitoring stats enable stats show-node Europe-1 stats uri /admin?stats stats refresh 5s
启用统计信息并定义访问它们的 URI 前缀
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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
定义一个请求模式匹配条件,以将用户粘滞到一台服务器上
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<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
定义一个请求模式,将用户与服务器关联起来
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
注意:此形式与“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
定义一个用于在粘滞表中创建条目的请求模式
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<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
为当前部分配置粘滞表
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
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 字节,加上任何字符串的大小。大小支持 "k"、"m"、"g" 后缀,分别表示 2^10、2^20 和 2^30 的因子。[nopurge] 表示当表已满时,我们拒绝清除旧条目。未指定且当 haproxy 想要在该表中存储一个条目时表已满时,它将刷新一些最旧的条目以释放一些空间以容纳新条目。这通常是期望的行为。在某些特定情况下,可能希望拒绝新条目而不是清除旧条目。当要存储的数据量远超硬件限制时,可能会出现这种情况,我们宁愿不向新客户端提供访问权限,而不是拒绝已连接的客户端。使用此参数时,请务必正确设置 "expire" 参数(见下文)。<peersect> 是用于复制的 peers 部分的名称。将键与服务器 ID 关联的条目会与此部分中声明的远程对等体保持同步。在软重启期间,所有条目还会从本地对等体(旧进程)自动学习。注意:每个 peers 部分只能被属于同一唯一进程的表引用。<expire> 定义了条目自上次创建、刷新或匹配以来的最大持续时间。到期延迟使用标准的 time 格式定义,类似于各种超时。最大持续时间略高于 24 天。有关更多信息,请参阅 第 2.4 节。如果未指定此延迟,会话不会自动过期,但当表已满时,旧条目将被删除。如果未指定到期延迟,请务必不要使用 "nopurge" 参数。<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 的请求)。- 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 请求速率,以每周期请求数表示(请参阅上面的 http_req_cnt,了解哪些被计为请求)。结果是一个整数,可以使用 ACL 进行匹配。无论它们是否是有效请求,都不重要。请注意,这与使用客户端保持连接 (keep-alive) 时的会话不同。- http_err_cnt:HTTP 错误计数。这是一个正数 32 位整数,用于计算来自匹配此条目的客户端引起的 HTTP 请求错误的总数。错误计数包括无效和截断的请求,以及被拒绝或延迟的请求,还有认证失败。如果服务器响应 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)
定义一个用于在粘滞表中创建条目的响应模式
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<pattern> 是 第 7.3 节 中描述的示例表达式规则。它描述了在选择服务器后,将分析、提取并存储在表中的响应或连接的哪些元素。<table> 是一个可选的粘性表名。如果未指定,则使用同一后端的表。粘性表使用 "stick-table" 语句声明。<cond> 是一个可选的存储条件。它使得仅当满足(或不满足)某些条件时才可能存储某些标准。例如,它可以用于仅在响应为 SSL 服务器问候 (SSL server 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 rep_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 payload_lv(43,1) if clienthello # 如果是服务器 hello,则在响应中学习。 stick store-response payload_lv(43,1) if serverhello server s1 192.168.1.1:443 server s2 192.168.1.1:443
打开一个新连接
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
当一个应用程序依赖于多个 TCP 端口,或者当 HAProxy 在单个后端中负载均衡多个服务时,有必要在将服务器视为可操作之前单独探测所有服务。当服务器行上没有配置 TCP 端口,也没有服务器端口指令时,'tcp-check connect port <port>' 必须是序列的第一步。在 tcp-check 规则集中,'connect' 是必需的,并且也必须以 'connect' 规则开始规则集。目的是确保管理员知道他们在做什么。参数:它们是可选的,可用于描述 HAProxy 应如何打开和使用 TCP 连接。port 如果未设置,则使用检查端口或服务器端口。它告诉 HAProxy 在哪里打开连接。<port> 必须是有效的 TCP 端口源整数,从 1 到 65535。send-proxy 发送一个 PROXY 协议字符串 ssl 打开一个加密连接
# 检查服务器上的 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 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
指定在通用健康检查期间要收集和分析的数据
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<match> 是一个关键字,指示如何在响应中查找特定模式。关键字可以是 "string"、"rstring" 或 binary。关键字前面可以有一个感叹号 ("!") 来否定匹配。感叹号和关键字之间允许有空格。有关支持的关键字的更多详细信息,请参阅下文。<pattern> 是要查找的模式。它可以是字符串或正则表达式。如果模式包含空格,则必须使用通常的反斜杠 ('\') 进行转义。如果匹配设置为 binary,则模式必须作为十六进制数字序列传递,且长度为偶数。每两位数字将代表一个字节。十六进制数字可以使用大写或小写。
可用的匹配项在意图上与它们的 http-check 伴侣相似:string <string>:测试响应缓冲区中的精确字符串匹配。如果响应缓冲区包含此精确字符串,则健康检查响应将被视为有效。如果 "string" 关键字前缀为 "!",则如果响应包含此字符串,响应将被视为无效。这可用于查找协议响应中的强制模式,或在协议横幅中出现特定错误时检测故障。rstring <regex>:在响应缓冲区上测试正则表达式。如果响应缓冲区匹配此表达式,则健康检查响应将被视为有效。如果 "rstring" 关键字前缀为 "!",则如果响应匹配表达式,响应将被视为无效。binary <hexstring>:在响应缓冲区中以其十六进制形式测试精确字符串匹配。如果响应缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是匹配二进制协议上的数据。需要注意的是,响应将受限于全局 "tune.chksize" 选项定义的特定大小,该选项默认为 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
在通用健康检查期间指定一个要作为问题发送的字符串
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<data>:在通用健康检查会话期间要作为问题发送的数据。目前,<data> 必须是字符串。
# 查找 redis 主服务器 option tcp-check tcp-check send info\ replication\r\n tcp-check expect string role:master
指定一个十六进制数字字符串,作为原始 TCP 健康检查期间发送的二进制问题
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<data>:在通用健康检查会话期间作为问题发送的数据。目前,<data> 必须是字符串。<hexastring>:在响应缓冲区中以其十六进制形式测试精确字符串匹配。如果响应缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是向二进制协议发送二进制数据进行查询。
# 二进制 redis 检查 option tcp-check tcp-check send-binary 50494e470d0a # PING\r\n tcp-check expect binary 2b504F4e47 # +PONG
根据第 4 层条件对传入连接执行操作
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的仅第 4 层的基于 ACL 的条件(见第 7 节)。
在新传入连接接受后,可以立即评估某些条件以决定是否必须接受或丢弃此连接,或跟踪其计数器。这些条件不能利用任何数据内容,因为连接尚未读取,缓冲区尚未分配。这用于非常快速地选择性地接受或丢弃来自各种源的连接,且开销非常低。如果需要检查任何内容以做出决定,则必须改用 "tcp-request content" 语句。"tcp-request connection" 规则按其声明的顺序进行评估。如果没有规则匹配或没有规则,默认操作是接受传入的连接。插入的规则数量没有特定限制。支持四种操作:- accept:如果条件为真(与 "if" 一起使用)或为假(与 "unless" 一起使用),则接受连接。第一个执行的此类规则会结束规则评估。- reject:如果条件为真(与 "if" 一起使用)或为假(与 "unless" 一起使用),则拒绝连接。第一个执行的此类规则会结束规则评估。拒绝的连接甚至不会成为一个会话,因此它们在统计信息中被单独计为“拒绝的连接”。它们不被计入会话速率限制,也不会被记录。原因是这些规则应仅用于过滤极高的连接速率,例如在大量 DDoS 攻击期间遇到的速率。在这些极端条件下,记录每个事件的简单操作将使系统崩溃,并显着降低过滤能力。如果绝对需要记录,则应改用 "tcp-request content" 规则,因为 "tcp-request session" 规则也不会记录。- expect-proxy layer4:配置客户端连接,在从套接字读取任何字节之前接收 PROXY 协议头。这等同于在 "bind" 行上使用 "accept-proxy" 关键字,不同之处在于使用 TCP 规则允许仅为使用 ACL 的特定 IP 地址范围接受 PROXY 协议。这在流量来自公共主机时,经过多层负载均衡器时非常方便。- expect-netscaler-cip layer4:配置客户端连接,在从套接字读取任何字节之前接收 NetScaler 客户端 IP 插入协议头。这等同于在 "bind" 行上使用 "accept-netscaler-cip" 关键字,不同之处在于使用 TCP 规则允许仅为使用 ACL 的特定 IP 地址范围接受 PROXY 协议。这在流量来自公共主机时,经过多层负载均衡器时非常方便。- capture <sample> len <length>:这仅适用于 "tcp-request content" 规则。它从请求缓冲区捕获样本表达式 <sample>,并将其转换为最多 <len> 个字符的字符串。结果字符串存储在下一个请求 "capture" 插槽中,因此它可能会出现在某些捕获的 HTTP 标头旁边。然后它将自动显示在日志中,并且可以使用样本提取规则将其提取以馈入标头或其他内容。长度应该受到限制,因为此大小将在会话的整个生命周期内为每次捕获分配。请参阅 第 7.3 节(提取样本)和“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> 是必需的,并且是 第 7.3 节中所述的样本表达式规则。它描述了哪些传入请求或连接的元素将被分析、提取、组合并用于选择更新计数器的哪个表条目。请注意,"tcp-request connection" 不能使用基于内容的提取。<table> 是一个可选表,用于替代当前代理中声明的粘性表。然后,密钥的所有计数器将在此表中执行匹配和更新,直到会话结束。一旦执行了 "track-sc*" 规则,就会在表中查找密钥,如果找不到,则为其分配一个条目。然后,该条目的指针将在会话的整个生命周期内保留,并且该条目的计数器会尽可能频繁地更新,每次会话的计数器更新时,以及在会话结束时系统性地更新。计数器仅为跟踪开始后发生的事件更新。例如,当跟踪第 7 层信息时,连接计数器不会被更新,因为连接事件发生在提取第 7 层信息之前。如果条目跟踪并发连接计数器,则一个连接在跟踪条目期间被计算一次,并且在此期间条目不会过期。与仅检查密钥相比,跟踪计数器还提供了性能优势,因为所有使用它的 ACL 检查只执行一次表查找。- sc-inc-gpc0(<sc-id>):“sc-inc-gpc0”根据 <sc-id> 指定的粘性计数器递增 GPC0 计数器。如果发生错误,此操作将静默失败,并且操作评估将继续。- sc-set-gpt0(<sc-id>) <int>:此操作根据 <sc-id> 指定的粘性计数器和 <int> 的值设置 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 表达式,由一个 sample-fetch 后跟一些转换器组成。
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 节。
根据第 4-7 层条件对新会话执行操作
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<action> 定义了如果条件适用要执行的操作。见下文。<condition> 是一个标准的第 4-7 层基于 ACL 的条件(见第 7 节)。
请求的内容可以在请求处理的早期阶段进行分析,称为“TCP内容检查”。在此阶段,每次更新请求内容时都会评估基于ACL的规则,直到匹配到“accept”或“reject”规则,或者TCP请求检查延迟到期且没有匹配的规则。这些规则与“tcp-request connection”规则的第一个区别在于,“tcp-request content”规则可以利用内容来做决策。最常见的是,这些决策会考虑协议识别或有效性。第二个区别是,基于内容的规则可以在前端和后端使用。在与客户端进行HTTP保持连接的情况下,所有tcp-request content规则都会被重新评估,因此haproxy会记录下由“tcp-request connection”规则与“tcp-request content”规则分配的粘性计数器,并在处理完HTTP请求后刷新所有与内容相关的计数器,以便它们可以被下一个请求的规则重新评估。当规则跟踪某些L7信息或由基于L7的ACL条件化时,这一点尤其重要,因为跟踪信息在请求之间可能会发生变化。基于内容的规则按照其声明的精确顺序进行评估。如果没有规则匹配或没有规则,默认操作是接受内容。可以插入的规则数量没有特定限制。支持几种类型的操作:- accept:接受请求- reject:拒绝请求并关闭连接- capture:捕获指定的样本表达式- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]- sc-inc-gpc0(<sc-id>)- sc-set-gpt0(<sc-id>) <int>- set-var(<var-name>) <expr>- unset-var(<var-name>)- silent-drop它们的意思与其在“tcp-request connection”中的对应项相同,请参考该部分以获得完整描述。虽然没有强制要求,但建议在“tcp-request connection”规则中使用track-sc0,在前端的“tcp-request content”规则中使用track-sc1,在后端的“tcp-request content”规则中使用track-sc2,因为这使得配置更具可读性,更容易排查问题,但这只是一项指南,所有计数器都可以随处使用。请注意,“if/unless”条件是可选的。如果没有为操作设置条件,它将被无条件执行。这对于“track-sc*”操作以及更改默认操作为reject非常有用。使用“tcp-request content”规则完全可以匹配第7层内容,因为HTTP特定的ACL匹配能够初步解析缓冲区内容,然后提取所需数据。如果缓冲的内容无法解析为有效的HTTP消息,则ACL不匹配。那里涉及的解析器与所有其他HTTP处理过程完全相同,因此没有以不同方式解析的风险。在与HTTP前端连接的HTTP后端中,当首次评估规则时,可以保证HTTP内容始终可用。跟踪第7层信息也是可能的,前提是信息在规则处理时可用。当要跟踪的数据尚不可用时,规则处理引擎能够等待直到检查延迟到期。“set-var”用于设置变量的内容。变量是内联声明的。对于“tcp-request session”规则,只能使用会话级别的变量,而不包含任何第7层内容。<var-name>变量的名称以其作用域的指示开始。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。<expr>是一个标准的HAProxy表达式,由一个样本获取器后跟一些转换器组成。“unset-var”用于取消设置变量。有关<var-name>的详细信息,请参阅上文。
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 节。
设置在内容检测期间等待数据的最大允许时间
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
主要将haproxy用作TCP中继的人们通常担心存在将任何类型的协议传递给服务器而不进行任何分析的风险。为了能够分析请求内容,我们必须首先暂留数据,然后进行分析。此语句仅启用数据暂留,最多暂留指定的时间。TCP内容检查在连接到达前端时非常早地应用,然后当连接转发到后端时也非常早地应用。这意味着如果前端和后端都有tcp-request规则,连接可能会在前端经历第一个延迟,然后在后端经历第二个延迟。请注意,在执行内容检查时,haproxy将评估每个新块进入的所有规则,同时考虑到这些数据是部分的。如果在上述延迟之前没有规则匹配,则会在延迟到期时执行最后一次检查,此时认为内容是确定的。如果未设置延迟,haproxy将完全不等待,并立即根据可用信息应用判决。显然,这不太可能有太大用处,甚至可能存在竞态条件,因此不建议这样配置。一旦匹配到规则,请求将被释放并照常继续。如果达到超时时间且没有规则匹配,默认策略是让它不受影响地通过。对于大多数协议,设置几秒钟就足够了,因为大多数客户端在连接后立即发送完整请求。增加3秒或更多秒以覆盖TCP重传,但这就可以了。对于某些协议,使用较大的值可能有意义,例如,以确保客户端在服务器之前从不说话(例如,SMTP),或者在将数据传递给服务器之前等待客户端说话(例如,SSL)。请注意,客户端超时必须至少覆盖检查延迟,否则它将先到期。如果客户端关闭连接或缓冲区已满,延迟会立即到期,因为内容将无法再更改。
根据第 4-7 层条件对会话响应执行操作
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<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-set-gpt0(<sc-id>) <int>:此操作根据由<sc-id>指定的粘性计数器和<int>的值来设置GPT0标签。预期的结果是一个布尔值。如果发生错误,此操作将静默失败,并且继续评估操作。- “silent-drop”:这会停止规则评估,并使面向客户端的连接突然消失,使用系统依赖的方式来阻止客户端收到通知。效果是客户端仍然看到一个已建立的连接,而HAProxy上实际上没有。目的是达到与“tarpit”类似的效果,除了它不使用运行HAProxy的机器上的任何本地资源。它可以承受比“tarpit”更高的负载,并减慢更强大的攻击者。理解使用此机制的影响很重要。位于客户端和HAProxy之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此操作而受到影响。在具有足够权限的现代Linux系统上,TCP_REPAIR套接字选项用于阻止TCP重置的发出。在其他系统上,套接字的TTL减至1,以便TCP重置不会穿过第一个路由器,尽管它仍然传递到本地网络。除非您完全理解其工作原理,否则请勿使用它。请注意,“if/unless”条件是可选的。如果没有为操作设置条件,它将被无条件执行。这对于更改默认操作为reject可能很有用。使用“tcp-response content”规则完全可以匹配第7层内容,但那时确保已缓冲完整的响应非常重要,否则任何内容都不会匹配。为了实现这一点,最佳解决方案是在检查期间检测HTTP协议。“set-var”用于设置变量的内容。变量是内联声明的。<var-name>变量的名称以其作用域的指示开始。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。<expr>是一个标准的HAProxy表达式,由一个样本获取器后跟一些转换器组成。
tcp-request content set-var(sess.my_var) src
“unset-var”用于取消设置变量。有关<var-name>的详细信息,请参阅上文。
tcp-request content unset-var(sess.my_var)
有关 ACL 的用法,请参见第 7 节。
根据第 5 层条件对已验证的会话执行操作
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<动作> 定义了如果条件适用时要执行的动作。见下文。 <条件> 是一个标准的仅第 5 层的基于 ACL 的条件(见第 7 节)。
一旦会话得到验证(即,所有握手完成后),就可以评估某些条件来决定此会话必须被接受还是被丢弃,或者其计数器是否被跟踪。这些条件不能使用任何数据内容,因为此时还没有分配缓冲区,并且处理不能等待。主要用例是将一些早期信息复制到变量中(因为变量在会话中可访问),或者跟踪在握手后收集的某些信息,例如SSL级别的元素(SNI、密码、客户端证书的CN)或来自PROXY协议头的信息(例如:跟踪以这种方式转发的源)。因此,提取的信息可以复制到变量或使用“track-sc”规则进行跟踪。当然,也可以像其他规则集一样决定接受/拒绝。这里执行的大多数操作也可以在“tcp-request content”规则中执行,不同之处在于HTTP中这些规则对每个新请求都会进行评估,而这可能并不总是可接受的。例如,一个规则可能在每次评估时增加一个计数器。还可以通过地理位置从源IP地址解析国家/地区,将其分配给一个会话范围的变量,然后为所有请求重写HTTP头中的源地址。如果需要检查某些内容来做出决策,则必须改用“tcp-request content”语句。“tcp-request session”规则按照其声明的精确顺序进行评估。如果没有规则匹配或没有规则,默认操作是接受传入的会话。可以插入的规则数量没有特定限制。支持几种类型的操作:- accept:接受请求- reject:拒绝请求并关闭连接- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]- sc-inc-gpc0(<sc-id>)- sc-set-gpt0(<sc-id>) <int>- set-var(<var-name>) <expr>- unset-var(<var-name>)- silent-drop这些操作的意思与其在“tcp-request connection”和“tcp-request content”中的对应项相同,请参考这些部分以获得完整描述。请注意,“if/unless”条件是可选的。如果没有为操作设置条件,它将被无条件执行。这对于“track-sc*”操作以及更改默认操作为reject可能很有用。
默认跟踪原始源地址,或者对于来自本地代理的连接,跟踪 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 节。
设置内容检测期间等待响应的最大允许时间
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
设置额外的检查超时,但仅在连接已经建立之后。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<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”部分一次性指定。这实际上是最简单的解决方案之一,以免忘记它。
设置客户端侧的最大不活动时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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" 部分一次性设置。实际上,这是最简单的避免忘记设置它的方法之一。未设置的超时将导致无限超时,不推荐这样做。虽然这种用法被接受并有效,但在启动时会报告警告,因为如果系统超时未配置,可能会导致过期的会话在系统中堆积。此参数替换了旧的、已弃用的 "clitimeout"。建议使用它来编写新配置。 "timeout clitimeout" 的形式仅为向后兼容而提供,但强烈不建议使用。
为半关闭连接设置客户端侧的不活动超时。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
非活动超时应用于一个方向已关闭的连接,此时客户端需要确认或发送数据。此超时与 "timeout client" 不同,因为它仅适用于一个方向已关闭的连接。这对于避免连接长时间停留在 FIN_WAIT 状态(当客户端未干净地断开连接时)特别有用。这个问题在长连接(如 RDP 或 WebSocket)中尤其常见。请注意,当连接在一个方向上关闭时,此超时可以覆盖 "timeout tunnel"。此参数特定于前端,但可以在 "defaults" 部分一次性设置。默认情况下,它未设置,因此半关闭连接将使用其他超时(timeout.client 或 timeout.tunnel)。
设置等待服务器连接尝试成功的最大时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果服务器与 haproxy 位于同一 LAN 上,连接应该是即时的(小于几毫秒)。无论如何,一种好的做法是设置略高于 3 秒倍数的超时时间(例如 4 或 5 秒),以涵盖一个或多个 TCP 数据包丢失。默认情况下,connect 超时还会将 queue 超时和 tarpit 超时设置为相同的值,如果它们未被指定。此参数特定于后端,但可以在 "defaults" 部分一次性设置。实际上,这是最简单的避免忘记设置它的方法之一。未设置的超时将导致无限超时,不推荐这样做。虽然这种用法被接受并有效,但在启动时会报告警告,因为如果系统超时未配置,可能会导致失败的会话在系统中堆积。此参数替换了旧的、已弃用的 "contimeout"。建议使用它来编写新配置。 "timeout contimeout" 的形式仅为向后兼容而提供,但强烈不建议使用。
设置等待新 HTTP 请求出现的最大允许时间
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
默认情况下,在 keep-alive 模式下等待新请求的时间由 "timeout http-request" 设置。然而,这并不总是方便,因为有些人希望非常短的 keep-alive 超时以便更快地释放连接,而另一些人则希望更长的超时,但一旦请求开始出现,超时仍然很短。"http-keep-alive" 超时满足了这些需求。它定义了在发送响应后等待新 HTTP 请求开始发送的时间。一旦看到请求的第一个字节,就会使用 "http-request" 超时来等待整个请求的到来。请注意,新请求之前的空行不会刷新超时,也不会被计为新请求。这两个超时之间还有另一个区别:当连接在 http-keep-alive 超时期间过期时,不会返回错误,连接只是关闭。如果在等待连接完成期间,连接在 http-request 超时期间过期,则会返回 HTTP 408 错误。通常,将此值设置为几十到几百毫秒是最佳的,以便用户可以一次性获取页面上的所有对象,而无需等待进一步的点击。此外,如果设置为非常小的值(例如 1 毫秒),它可能只会接受管道化请求,而不是非管道化请求。对于运行数十万到数百万客户端的大型网站来说,这可能是一个不错的折衷方案。如果未设置此参数,则应用 http-request 超时,如果两者都未设置,则在较低级别仍会应用 timeout.client。它应该在前端设置才能生效,除非前端处于 TCP 模式,在这种情况下将使用 HTTP 后端的超时。
设置等待完整 HTTP 请求的最大允许时间
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<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 后端的超时。
设置在队列中等待可用连接槽的最大时间
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当服务器的 maxconn 达到时,连接会留在队列中等待,该队列可能是服务器特定的或后端全局的。为了避免无限期等待,会对队列中的待处理请求应用超时。如果达到超时,则认为该请求几乎永远不会被处理,因此会丢弃它并向客户端返回 503 错误。" timeout queue" 语句允许固定请求在队列中等待的最长时间。如果未指定,则使用与后端连接超时("timeout connect")相同的值,以与没有 "timeout queue" 参数的旧版本向后兼容。
设置服务器端的最大不活动时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
非活动超时应用于服务器需要确认或发送数据时。在 HTTP 模式下,此超时在服务器响应的第一阶段(发送头部时)尤其重要,因为它直接代表了服务器对请求的处理时间。要确定要设置的值,通常最好从不可接受的响应时间开始考虑,然后检查日志以观察响应时间分布,并相应地调整值。默认情况下,值以毫秒为单位,但如果数字带有单位后缀,则可以是任何其他单位,如本文档顶部所述。在 TCP 模式下(以及在 HTTP 模式下,程度较小),强烈建议客户端超时与服务器超时保持一致,以避免复杂的调试情况。无论预期的服务器响应时间如何,一种好的做法是设置略高于 3 秒倍数的超时时间(例如,至少 4 或 5 秒),以至少涵盖一个或多个 TCP 数据包丢失。如果将长连接会话与短连接会话(例如 WebSocket 和 HTTP)混合使用,则值得考虑 "timeout tunnel",它会覆盖隧道使用的 "timeout client" 和 "timeout server"。此参数特定于后端,但可以在 "defaults" 部分一次性设置。实际上,这是最简单的避免忘记设置它的方法之一。未设置的超时将导致无限超时,不推荐这样做。虽然这种用法被接受并有效,但在启动时会报告警告,因为如果系统超时未配置,可能会导致过期的会话在系统中堆积。此参数替换了旧的、已弃用的 "srvtimeout"。建议使用它来编写新配置。 "timeout srvtimeout" 的形式仅为向后兼容而提供,但强烈不建议使用。
为半关闭连接设置服务器侧的不活动超时。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
当一个方向已经关闭,但期望服务器确认或发送数据时,适用此不活动超时。此超时与 "timeout server" 的不同之处在于,它仅适用于单向关闭的连接。这对于避免在远程服务器未正常断开连接时将连接长时间保持在 FIN_WAIT 状态特别有用。此问题在 RDP 或 WebSocket 等长连接中尤为常见。请注意,当连接在一个方向上关闭时,此超时可以覆盖 "timeout tunnel"。提供此设置是为了完整性,但在大多数情况下,应该不需要它。此参数特定于后端,但可以在 "defaults" 部分中为所有后端一次性指定。默认情况下不设置,因此半关闭连接将使用其他超时(timeout.server 或 timeout.tunnel)。
设置被tarpit的连接将维持的时间
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是 tarpit 的持续时间,默认以毫秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。
当使用 "http-request tarpit" 或 "reqtarpit" 对连接进行 tarpit 处理时,连接会在一段时间内保持打开状态但没有任何活动,然后关闭。" timeout tarpit" 定义了它将保持打开的时间。默认情况下,该值以毫秒为单位指定,但如果数字后跟单位后缀,也可以是任何其他单位,如本文档开头所述。如果未指定,则使用与后端连接超时("timeout connect")相同的值,以与没有 "timeout tarpit" 参数的旧版本向后兼容。
为隧道设置客户端和服务器侧的最大不活动时间。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
隧道超时应用于客户端和服务器之间建立的、并且在两个方向上都保持不活动的双向连接。一旦连接变成隧道,此超时将取代客户端和服务器超时。在 TCP 中,只要没有分析器附加到任何连接(例如,接受了 tcp content 规则),就会使用此超时。在 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 的超时
启用客户端透明代理
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
引入此关键字是为了向第 3 层负载均衡器提供第 7 层持久性。其思想是利用操作系统的能力将远程地址的传入连接重定向到本地进程(此处为 HAProxy),并让该进程知道最初请求的地址。使用此选项时,没有 cookie 的会话将被转发到传入请求的原始目标 IP 地址(该地址应与另一设备的地址匹配),而带有 cookie 的请求仍将被转发到适当的服务器。" transparent" 关键字已弃用,请改用 "option transparent"。请注意,与普遍看法相反,此选项在建立连接时并不会使 HAProxy 向服务器呈现客户端的 IP。
为每个请求生成一个唯一的 ID。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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 头部。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<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"
如果/除非匹配基于 ACL 的条件,则切换到特定的后端。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 否![]() |
<backend> 是一个有效的后端或 "listen" 部分的名称,或一个解析为后端名称的 "log-format" 字符串。<condition> 是由 ACL 组成的条件,如 第 7 节 所述。如果省略,则无条件应用该规则。
进行内容切换时,连接到达前端,然后根据多个条件分发到各种后端。条件与后端之间的关系使用 "use_backend" 关键字进行描述。虽然它通常与 HTTP 处理一起使用,但它也可以用于纯 TCP,无论是没有内容(使用无状态 ACLs,例如源地址验证)还是与 "tcp-request" 规则结合使用以等待某些有效负载。可以拥有任意数量的 "use_backend" 规则。所有这些规则都按照其声明顺序进行评估,第一个匹配的规则将分配后端。在第一种形式中,如果满足条件,则使用后端。在第二种形式中,如果不满足条件,则使用后端。如果没有条件有效,则使用 "default_backend" 定义的后端。如果没有定义默认后端,则使用同一部分中的服务器(在 "listen" 部分的情况下),或者,在前端的情况下,不使用服务器,并返回 503 服务不可用的响应。请注意,可以从 TCP 前端切换到 HTTP 后端。在这种情况下,要么前端已经检查过协议是 HTTP,然后后端处理将立即开始,要么后端会等待完整的 HTTP 请求进入。当一个前端需要在单个端口上解码多种协议,其中一种是 HTTP 时,此功能非常有用。当 <backend> 是简单名称时,它在配置时解析,如果指定的后端不存在,则会报告错误。如果 <backend> 是日志格式字符串,则在配置时可能不会进行检查,因此后端名称在运行时动态解析。如果生成的后端名称与任何有效后端都不匹配,则不会评估其他规则,而是应用 default_backend 指令。请注意,在使用动态后端名称时,强烈建议使用其他后端未使用的前缀,以确保无法从请求中强制设置未经授权的后端。值得一提的是,具有显式名称的 "use_backend" 规则用于检测前端和后端之间的关联,以计算后端的 "fullconn" 设置。对于动态名称,无法做到这一点。
仅在匹配/不匹配基于 ACL 的条件时才使用特定的服务器。
可在节中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<server> 是同一后端部分中有效服务器的名称。<condition> 是由 ACL 组成的条件,如 第 7 节 所述。
默认情况下,到达后端的连接会根据配置的算法在可用服务器之间进行负载均衡,除非使用了如 cookie 等持久性机制并且在请求中找到。有时希望将特定请求转发到特定服务器,而无需为此服务器声明专用后端。这可以使用 "use-server" 规则来实现。这些规则在 "redirect" 规则之后、评估 cookie 之前进行评估,并且具有优先权。可以有任意数量的 "use-server" 规则。所有这些规则都按照其声明顺序进行评估,第一个匹配的规则将分配服务器。如果规则指定了一个正在运行的服务器,并且未使用 "option persist" 且没有强制持久性规则生效,则该规则将被忽略,评估将继续进行下一个规则,直到有一个匹配。在第一种形式中,如果满足条件,则使用服务器。在第二种形式中,如果不满足条件,则使用服务器。如果没有条件有效,处理将继续,服务器将根据其他持久性机制进行分配。请注意,即使匹配了规则,仍会执行 cookie 处理,但不会分配服务器。这允许剥离前缀 cookie 的前缀。"use-server" 语句在 HTTP 和 TCP 模式下都有效。这使其适用于基于内容的检查。例如,可以根据 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:587 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
"bind"、"server" 和 "default-server" 关键字支持多个设置,具体取决于某些构建选项和 HAProxy 构建所在的系统。这些设置通常由一个单词组成,有时后面跟着一个值,写在与 "bind" 或 "server" 行相同的行上。本节描述了所有这些选项。
"bind" 关键字支持一定数量的设置,这些设置都作为参数在同一行上传递。这些参数出现的顺序无关紧要,只要它们出现在绑定地址之后即可。所有这些参数都是可选的。其中一些由单个单词组成(布尔值),而另一些则在其后需要一个值。在这种情况下,值必须紧跟在设置名称之后提供。当前支持的设置如下。
强制在同一行上声明的任何 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" 以更精细地设置允许哪些客户端使用该协议。
这会启用 TLS ALPN 扩展,并声明列表中指定的协议支持 ALPN。协议列表是以逗号分隔的协议名称列表,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库已构建并支持 TLS 扩展(通过 haproxy -vv 检查)。ALPN 扩展取代了初始的 NPN 扩展。
将套接字的 backlog 设置为此值。如果未指定,则使用前端的 backlog,通常默认为 maxconn 值。
此设置仅在内置 OpenSSL 支持时可用。它设置用于生成 ECDH 临时密钥的命名曲线(RFC 4492)。默认情况下,使用的命名曲线是 prime256v1。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的 CA 证书。
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 > 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,其中包含用于创建和签署服务器证书的 CA 证书和 CA 私钥。当启用证书动态生成时,这是一个强制性设置。有关详细信息,请参见 'generate-certificates'。
此设置仅在内置 OpenSSL 支持时可用。它是 CA 私钥的密码。此设置是可选的,仅在启用证书动态生成时使用。有关详细信息,请参见 'generate-certificates'。
此设置仅在构建时支持 OpenSSL 时可用。它设置了在 SSL/TLS 握手期间协商的密码算法(“密码套件”)的描述字符串。字符串的格式定义在 OpenSSL man 页的“man 1 ciphers”中,例如:“AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH”(不带引号)。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的证书吊销列表。
此设置仅在构建时支持 OpenSSL 时可用。它指定一个包含所需证书及相关私钥的 PEM 文件。此文件可以通过将多个 PEM 文件连接在一起构建(例如:cat cert.pem key.pem > combined.pem)。如果您的 CA 需要中间证书,也可以将其连接到此文件中。如果使用的 OpenSSL 支持 Diffie-Hellman,则会加载此文件中存在的参数。如果使用目录名而不是 PEM 文件,则会按字母顺序加载目录中的所有文件,除非其名称以 '.issuer'、'.ocsp' 或 '.sctl'(保留扩展名)结尾。此指令可以指定多次,以从多个文件或目录加载证书。证书将呈现给提供与其中一个 CN 或 alt subject 匹配的有效 TLS 服务器名称指示(SNI)字段的客户端。支持通配符,其中通配符字符 '*' 用于替换第一个主机名组件(例如:*.example.org 匹配 www.example.org 但不匹配 www.sub.example.org)。如果客户端未提供 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 文件中找不到颁发者证书,则会从与 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 也无法提供多证书支持。假设上面的示例中的包包含以下内容。
| 文件名 | CN | SAN |
|---|---|---|
| example.pem.rsa | www.example.com | rsa.example.com |
| example.pem.ecdsa | www.example.com | ecdsa.example.com |
使用 SNI “www.example.com”连接的用户将能够使用 RSA 和 ECDSA 密码套件。使用 SNI “rsa.example.com”连接的用户将只能使用 RSA 密码套件,而使用“ecdsa.example.com”的用户将只能使用 ECDSA 密码套件。如果将目录名作为 <cert> 参数给出,haproxy 将自动在该目录中搜索并加载捆绑的文件。OSCP 文件(.ocsp)和颁发者文件(.issuer)支持多证书捆绑。每个证书都可以有自己的 .ocsp 和 .issuer 文件。目前,sctl 不支持多证书捆绑。
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 == 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
此设置仅在构建时支持 OpenSSL 时可用。它指定一个 PEM 文件列表,每个文件可选地带有每个证书的 SNI 过滤器,每行的格式如下:<crtfile> [[!]<snifilter> ...] SNI 过滤器支持通配符。可以在配置中指定否定过滤器,但它们仅用作提示,没有实际作用。(这在较新版本的 haproxy 中有所改变)。如果要排除某个通配符中的 SNI,请在另一行上使用此正 SNI。(如示例所示)。证书将呈现给提供与 SNI 过滤器之一匹配的有效 TLS 服务器名称指示字段的客户端。如果未指定 SNI 过滤器,则使用 CN 和备用主题。此指令可以指定多次。有关更多信息,请参阅“crt”选项。默认证书仍然需要满足 OpenSSL 的期望。如果未使用它,则可以使用“strict-sni”选项。多证书捆绑(请参阅“crt”)支持 crt-list,只要 crt-list 中只提供了基本名称。SNI 过滤器将对所有捆绑的证书执行相同的操作。
这是一个可选关键字,仅在某些 Linux 内核上受支持。它声明一个连接将在收到一些数据后被接受,或者最迟在第一次重传后被接受。这应该只用于客户端先通信的协议(例如 HTTP)。通过确保在接受连接时大部分请求已可用,它可以略微提高性能。另一方面,它无法检测到不通信的连接。重要的是要注意,此选项在所有内核版本 2.6.31 之前都存在缺陷,因为在客户端通信之前连接永远不会被接受。这可能导致前端防火墙看到已建立的连接,而代理仅看到 SYN_RECV 状态。此选项仅在 TCPv4/TCPv6 套接字上受支持,其他套接字将被忽略。
此选项强制从此侦听器实例化的 SSL 连接仅使用 SSLv3。对于高连接速率,SSLv3 通常比 TLS 对应项成本更低。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“no-tlsv*”和“no-sslv3”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.0。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“no-tlsv*”和“no-sslv3”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.1。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“no-tlsv*”和“no-sslv3”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.2。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“no-tlsv*”和“no-sslv3”。
此设置仅在构建时支持 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 的内存占用,以降低相同证书多次使用时的延迟。
将 UNIX 套接字的组设置为指定的系统 gid。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "group" 设置等效,不同之处在于它使用组 ID 而不是组名。此设置对非 UNIX 套接字无效。
将 UNIX 套接字的组设置为指定的系统组。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "gid" 设置等效,不同之处在于它使用组名而不是组 ID。此设置对非 UNIX 套接字无效。
固定套接字 ID。默认情况下,套接字 ID 是自动分配的,但有时为了方便监控而固定它们会更方便。此值必须是严格正数,并且在侦听器/前端内是唯一的。此选项只能在定义单个套接字时使用。
将套接字限制到特定接口。指定后,只有从该特定接口接收的数据包才会由套接字处理。目前仅在 Linux 上受支持。该接口必须是主系统接口,而不是别名接口。如果多个前端绑定到不同的接口,也可以将它们绑定到同一地址。请注意,绑定到网络接口需要 root 权限。此参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使配置了通过不同接口的显式路由也是如此。当同一客户端 IP 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
此设置仅与 stats 套接字一起使用,用于限制可在套接字上发出的命令的性质。其他套接字会忽略此设置。<level> 可以是以下之一:- “user”是权限最低的级别;只能读取非敏感统计信息,并且不允许进行任何更改。这在难以限制对套接字访问的系统上有意义。- “operator”是默认级别,适用于大多数常见用途。可以读取所有数据,但只允许进行非敏感的更改(例如:清除最大计数器)。- “admin”应谨慎使用,因为允许进行所有操作(例如:清除所有计数器)。
将套接字限制为此数量的并发连接。多余的连接将保留在系统的 backlog 中,直到释放一个连接。如果未指定,限制将与前端的 maxconn 相同。请注意,在端口范围或多个地址的情况下,相同的值将应用于每个套接字。此设置允许对昂贵的套接字进行不同的限制,例如 SSL 条目,它们很容易耗尽所有内存。
设置用于定义 UNIX 套接字访问权限的八进制模式。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置对非 UNIX 套接字无效。
设置要在传入连接上通告的 TCP 最大段大小(MSS)值。这可用于为某些特定端口强制使用较低的 MSS,例如用于通过 VPN 的连接。请注意,这依赖于一个内核功能,理论上在 Linux 下受支持,但在 2.6.28 之前的所有版本中都有错误。它可能在其他操作系统上工作,也可能不工作。它也可能不改变通告的值,而是改变传出段的有效大小。在以太网网络上,TCPv4 的通常通告值为 1460 = 1500(MTU) - 40(IP+TCP)。如果此值为正,它将用作通告的 MSS。如果为负,它将指示传出段应比传入连接的通告 MSS 减少多少。此参数仅与 TCP v4/v6 套接字兼容。
为这些套接字设置一个可选名称,该名称将在统计页面上报告。
在 Linux 上,可以指定套接字将属于哪个网络命名空间。此指令使得可以显式地将侦听器绑定到不同于默认命名空间的命名空间。请参考您的操作系统文档以了解有关网络命名空间的更多详细信息。
设置从套接字发起的连接的“友好度”(niceness)。值必须在 -1024 到 1024(含)之间,默认为零。正值意味着此类连接对其他连接更友好,并且容易在调度器中让出位置。相反,负值意味着连接希望以比其他连接更高的优先级运行。这种差异仅在高负载下,当系统接近饱和时才会发生。负值适用于低延迟或管理服务,而高值通常推荐用于 CPU 密集型任务,如 SSL 处理或对延迟不那么敏感的批量传输。例如,为 SMTP 套接字使用正值,为 RDP 套接字使用负值可能是有意义的。
此设置仅在构建时支持 OpenSSL 时可用。它在支持 SSL 的侦听器实例化的任何套接字上禁用 SSLv3 支持。请注意,SSLv2 在代码中被强制禁用,并且无法通过任何配置选项启用。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“force-tls*”和“force-sslv3”。
此设置仅在构建时支持 OpenSSL 时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复会增加 CPU 使用率。此选项也可用在全局语句“ssl-default-bind-options”上。
此设置仅在构建时支持 OpenSSL 时可用。它在支持 SSL 的侦听器实例化的任何套接字上禁用 TLSv1.0 支持。请注意,SSLv2 在代码中被强制禁用,并且无法通过任何配置选项启用。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“force-tlsv*”和“force-sslv3”。
此设置仅在构建时支持 OpenSSL 时可用。它在支持 SSL 的侦听器实例化的任何套接字上禁用 TLSv1.1 支持。请注意,SSLv2 在代码中被强制禁用,并且无法通过任何配置选项启用。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“force-tlsv*”和“force-sslv3”。
此设置仅在构建时支持 OpenSSL 时可用。它在支持 SSL 的侦听器实例化的任何套接字上禁用 TLSv1.2 支持。请注意,SSLv2 在代码中被强制禁用,并且无法通过任何配置选项启用。此选项也可用在全局语句“ssl-default-bind-options”上。另请参阅“force-tlsv*”和“force-sslv3”。
这会启用 NPN TLS 扩展,并声明列表中指定的协议支持 NPN。协议列表是以逗号分隔的协议名称列表,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库已构建并支持 TLS 扩展(通过 haproxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(请参阅“alpn”关键字)。
这限制了此监听器允许运行的进程列表。它不会强制执行任何进程,而是消除不匹配的进程。如果前端使用“bind-process”设置,则会应用两者之间的交集。如果最终监听器不允许在任何剩余进程上运行,则会发出警告,监听器将运行在监听器的单个进程上(如果指定了单个进程),或运行在其所有进程上(如果指定了多个进程)。对于需要几个范围的不太可能的情况,可以重复此指令。此指令的主要目的是与统计套接字一起使用,并为每个进程提供一个不同的套接字。第二个目的是允许多个绑定行共享相同的 IP:port,但监听器中的进程不同,以便系统可以将传入连接分发到多个队列,并允许更平滑的进程间负载均衡。目前已知 Linux 3.9 及更高版本支持此功能。另请参阅“bind-process”和“nbproc”。
此设置仅在已构建 OpenSSL 支持时可用。它启用由此监听器实例化的连接上的 SSL 解密。需要一个证书(请参阅上面的“crt”)。缓冲区中的所有内容都将以明文显示,因此 ACL 和 HTTP 处理只能访问解密的内容。此设置仅在内置 OpenSSL 支持时可用。仅当客户端提供的 SNI 与证书匹配时,才允许 SSL/TLS 协商。不使用默认证书。有关更多信息,请参见 "crt" 选项。设置此监听套接字实例化的所有传入连接的 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 密钥文件以从中加载密钥。密钥长度需为 48 字节,并使用 base64 编码(例如 openssl rand -base64 48)。密钥数量由 TLS_TICKETS_NO 构建选项指定(默认为 3),并且文件中必须至少存在同样数量的密钥。最后的 TLS_TICKETS_NO 个密钥将用于解密,倒数第二个密钥用于加密。这使得通过简单地将新密钥附加到文件并重新加载进程即可轻松轮换密钥。密钥必须定期轮换(例如,每 12 小时一次),否则会危及完全正向保密性(Perfect Forward Secrecy)。将密钥保存在任何永久性存储(如硬盘)之外也是一个好主意(提示:使用 tmpfs 并且不要交换这些文件)。生命周期提示可以使用 tune.ssl.timeout 进行更改。
是一个可选关键字,仅在某些 Linux 内核上受支持。它表示即使地址不属于本地机器,也会绑定这些地址,并且目标为这些地址的数据包将被截获,就好像这些地址是本地配置的一样。这通常需要启用 IP 转发。注意!不要将此与默认地址 '*' 一起使用,因为它会重定向指定端口的所有流量。此关键字仅在 HAProxy 使用 USE_LINUX_TPROXY=1 构建时可用。此参数仅与 TCPv4 和 TCPv6 套接字兼容,具体取决于内核版本。一些发行版的内核包含该功能的向后移植版本,因此请向您的供应商查询支持情况。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字同时绑定到 IPv4 和 IPv6。在默认情况下仅绑定到 IPv6 的系统上,这样做有时是必要的。它对非 IPv6 套接字没有影响,并被“v6only”选项覆盖。
是一个可选关键字,仅在包括 Linux 内核版本 >= 2.4.21 在内的大多数最新系统上受支持。它用于在使用默认地址时将套接字仅绑定到 IPv6。这样做有时比系统范围的设置更受欢迎,因为它是针对每个监听器的。它对非 IPv6 套接字没有影响,并优先于“v4v6”选项。
将 UNIX 套接字的所有者设置为指定的系统 uid。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“user”设置等效,不同之处在于使用的是用户的数字 ID 而不是其名称。此设置被非 UNIX 套接字忽略。
将 UNIX 套接字的所有者设置为指定的系统用户。它也可以在全局部分的“unix-bind”语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与“uid”设置等效,不同之处在于使用的是用户名而不是其 uid。此设置被非 UNIX 套接字忽略。
此设置仅在构建时包含 OpenSSL 支持时可用。如果设置为 'none',则不请求客户端证书。这是默认设置。在其他情况下,会请求客户端证书。如果客户端在请求后未提供证书,并且 'verify' 设置为 'required',则握手将中止,而如果设置为 'optional',则会成功。客户端提供的证书始终使用来自 'ca-file' 的 CA 和来自 'crl-file' 的可选 CRL 进行验证。验证失败时,握手将中止,无论 'verify' 选项如何设置,除非错误代码与 'ca-ignore-err' 或 'crt-ignore-err' 中列出的错误代码完全匹配。
“server”和“default-server”关键字支持一系列设置,这些设置都作为参数传递给服务器行。这些参数出现的顺序不重要,并且都是可选的。其中一些设置是单个词(布尔值),而另一些则需要其后的一个或多个值。在这种情况下,值必须紧跟在设置名称后面。除了 default-server 之外,所有这些设置都必须在服务器地址之后指定(如果使用):server <name> <address>[:port] [settings ...] default-server [settings ...] 当前支持的设置如下。
使用“addr”参数,可以使用不同的 IP 地址发送健康检查或探测代理检查。在某些服务器上,可能希望将一个 IP 地址专用于能够执行复杂测试的特定组件,这些测试比应用程序更适合健康检查。如果未设置“check”参数,则会忽略此参数。另请参阅“port”参数。支持 default-server:否
启用辅助代理检查,该检查独立于常规健康检查运行。代理健康检查是通过连接到“agent-port”参数设置的端口并读取 ASCII 字符串来执行的。字符串由一系列由空格、制表符或逗号分隔的单词组成,顺序任意,可选地以 '\r' 和/或 '\n' 结尾,每个单词由以下组成: - 正整数百分比的 ASCII 表示,例如“75%”。此格式的值将设置权重,该权重与 haproxy 启动时配置的服务器的初始权重成比例。请注意,由于对服务器具有相同的影响(将其从负载均衡池中移除),因此零权重在统计页面上报告为“DRAIN”。 - 字符串“maxconn:”后跟一个整数(之间没有空格)。此格式的值将设置服务器的最大连接数。需要将广告的最大连接数乘以负载均衡器和使用此健康检查的不同后端数量,以获得服务器可能接收的总连接数。例如:maxconn:30 - 单词“ready”。这将把服务器的管理状态设置为 READY 模式,从而取消任何 DRAIN 或 MAINT 状态。 - 单词“drain”。这将把服务器的管理状态设置为 DRAIN 模式,因此它不会接受除通过持久性接受的连接之外的任何新连接。 - 单词“maint”。这将把服务器的管理状态设置为 MAINT 模式,因此它根本不会接受任何新连接,并且健康检查将停止。 - 单词“down”、“fail”或“stopped”,可选地后跟一个井号('#')后的描述字符串。所有这些都会将服务器的操作状态标记为 DOWN,但由于单词本身会显示在统计页面上,因此区别允许管理员知道情况是否符合预期:服务可能被故意停止,可能出现但未能通过某些有效性测试,或者可能被视为 DOWN(例如:缺少进程或端口无响应)。 - 单词“up”将服务器的操作状态重新设置为 UP,前提是健康检查也报告服务可访问。代理未广告的参数不会改变。例如,代理可能旨在监视 CPU 使用情况,并且仅报告相对权重,并且从不与操作系统状态交互。同样,代理可以设计成用户界面,带有 3 个单选按钮,允许管理员仅更改管理状态。但是,重要的是要考虑到只有代理可以撤销自己的操作,因此如果服务器使用代理设置为 DRAIN 模式或 DOWN 状态,则代理必须实现其他等效操作才能使服务恢复运行。连接到代理失败不被视为错误,因为连接性由“check”参数启用的常规健康检查进行测试。但请注意,在代理报告“down”后停止代理不是个好主意,因为只有报告“up”的代理才能使服务器再次变为“up”。请注意,Unix 统计套接字上的 CLI 也能够强制代理的结果,以便在需要时绕过有问题的代理。需要设置“agent-port”参数。另请参阅“agent-inter”参数。支持 default-server:否
如果指定了此选项,haproxy 将在连接时将给定的字符串(按原样)发送到代理服务器。例如,您可以将后端名称编码到此字符串中,这将使您的代理能够根据后端发送不同的响应。请确保包含 `\n`,如果您想以换行符终止您的请求。
“agent-inter”参数设置两次代理检查之间的时间间隔为 <delay> 毫秒。如果未指定,则延迟默认为 2000 毫秒。就像所有其他基于时间的参数一样,它可以以任何其他显式单位输入,例如 { us, ms, s, m, h, d }。“agent-inter”参数也用作代理检查的超时值,“timeout check”未设置。为了减少托管在同一硬件上的多个服务器的“共振”效应,所有服务器的代理和健康检查都以它们之间的一个小时间偏移量开始。使用全局“spread-checks”关键字,还可以为代理和健康检查间隔添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。另请参阅“agent-check”和“agent-port”参数。支持 default-server:是
“agent-port”参数设置用于代理检查的 TCP 端口。另请参阅“agent-check”和“agent-inter”参数。支持 default-server:是
当服务器行中存在“backup”时,只有当所有其他非备份服务器都不可用时,该服务器才会在负载均衡中使用。但是,带有引用该服务器的持久性 cookie 的请求将始终得到服务。默认情况下,只有第一个可操作的备份服务器被使用,除非在后端设置了“allbackups”选项。另请参阅“allbackups”选项。支持 default-server:否
此设置仅在已构建 OpenSSL 支持时可用。它指定一个 PEM 文件,从中加载 CA 证书,用于验证服务器的证书。支持 default-server:否
此选项在服务器上启用健康检查。默认情况下,服务器始终被视为可用。如果设置了“check”,则当服务器接受周期性 TCP 连接时,服务器被视为可用,以确保它确实能够处理请求。用于发送测试的默认地址和端口是服务器的地址和端口,默认源与后端中定义的源相同。可以通过“addr”参数更改地址,通过“port”参数更改端口,通过“source”地址更改源地址,并使用“inter”、“rise”和“fall”参数更改间隔和计时器。请求方法在后端使用“httpchk”、“smtpchk”、“mysql-check”、“pgsql-check”和“ssl-hello-chk”选项定义。有关更多信息,请参阅这些选项和参数。支持 default-server:否
此选项强制为传出的健康检查发出 PROXY 协议行,无论服务器是否为正常流量使用 send-proxy。默认情况下,如果 PROXY 协议已为正常流量启用且未出现“port”或“addr”指令,则 PROXY 协议会为健康检查启用。但是,如果出现此类指令,则需要使用“check-send-proxy”选项来强制使用该协议。有关更多信息,请参阅“send-proxy”选项。支持 default-server:否
此选项强制对所有健康检查进行 SSL 加密,无论服务器是否为正常流量使用 SSL。这通常在指定了显式“port”或“addr”指令且未继承 SSL 健康检查时使用。重要的是要理解,此选项在检查下方插入 SSL 传输层,因此简单的 TCP 连接检查会变成 SSL 连接,从而取代旧的 ssl-hello-chk。最常见的用法是通过将“httpchk”与 SSL 检查结合来发送 HTTPS 检查。所有 SSL 设置对于健康检查和流量都是通用的(例如,密码)。有关更多信息,请参阅“ssl”选项。支持 default-server:否
此选项设置在与服务器的 SSL/TLS 握手期间协商的密码算法列表的描述字符串。字符串的格式在“man 1 ciphers”中定义。当使用 SSL 与本地网络上的服务器通信时,通常会看到比互联网上使用的密码集更弱的集合。这样做可以减少服务器和 haproxy 上的 CPU 使用率,同时保持与已部署软件的兼容性。一些算法(如 RC4-SHA1)相对便宜。如果根本不需要安全性,只需要连接性,使用 DES 可能就足够了。支持 default-server:否
“cookie”参数将分配给服务器的 cookie 值设置为 <value>。此值将在传入请求中进行检查,并且第一个具有相同值的可操作服务器将被选中。反过来,在 cookie 插入或重写模式下,此值将分配给发送给客户端的 cookie。让多个服务器共享相同的 cookie 值并没有什么坏处,实际上在正常服务器和备份服务器之间相当常见。另请参阅后端部分中的“cookie”关键字。支持 default-server:否
此设置仅在已构建 OpenSSL 支持时可用。它指定一个 PEM 文件,从中加载证书吊销列表,用于验证服务器的证书。支持 default-server:否
此设置仅在已构建 OpenSSL 支持时可用。它指定一个 PEM 文件,从中加载证书和关联的私钥。通过将两个 PEM 文件连接成一个文件来构建此文件。如果服务器发送客户端证书请求,则会发送此证书。支持 default-server:否
“disabled”关键字将服务器启动到“disabled”状态。这意味着它在维护模式下被标记为 DOWN,除了持久性模式允许的连接外,任何其他连接都不会到达它。这非常适合设置新服务器,因为常规流量永远不会到达它们,同时仍然可以通过使用强制持久性机制来测试服务。支持 default-server:否
如果启用了健康观察,则“error-limit”参数指定触发由“on-error”选项选择的事件的连续错误次数。默认情况下,它设置为 10 次连续错误。支持 default-server:是。另请参阅“check”、“error-limit”和“on-error”。
“fall”参数规定,在 <count> 次连续不成功的健康检查后,服务器将被视为已死。如果未指定,此值默认为 3。另请参阅“check”、“inter”和“rise”参数。支持 default-server:是
此选项仅在 SSL 用于与服务器通信时强制使用 SSLv3。对于高连接率,SSLv3 通常比 TLS 对应项成本更低。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "no-tlsv*"、"no-sslv3"。在 default-server 中支持:否
此选项仅在 SSL 用于与服务器通信时强制使用 TLSv1.0。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "no-tlsv*"、"no-sslv3"。在 default-server 中支持:否
此选项仅在 SSL 用于与服务器通信时强制使用 TLSv1.1。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "no-tlsv*"、"no-sslv3"。在 default-server 中支持:否
此选项仅在 SSL 用于与服务器通信时强制使用 TLSv1.2。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "no-tlsv*"、"no-sslv3"。在 default-server 中支持:否
为服务器设置持久 ID。此 ID 必须为正数且对于代理是唯一的。如果未设置,将自动分配一个未使用的 ID。首次分配的值将为 1。此 ID 目前仅在统计信息中返回。在 default-server 中支持:否
指示在启动时应如何解析服务器地址,如果它使用 FQDN。尝试通过依次应用逗号分隔列表中提到的每种方法来解析地址。成功的第一种方法将被使用。如果到达列表末尾仍未找到有效的方法,则会抛出错误。方法 "last" 建议选择状态文件中出现的地址(请参阅 "server-state-file")。方法 "libc" 使用 libc 的内部解析器(取决于操作系统和构建选项,为 gethostbyname() 或 getaddrinfo())。方法 "none" 特别指出服务器应在没有有效 IP 地址的情况下启动,处于关闭状态。这有助于在启动时忽略某些 DNS 问题,等待情况稍后得到修复。最后,可以提供 IP 地址(IPv4 或 IPv6)。它可以是服务器当前已知的地址(例如,由配置生成器填充),也可以是一个用于捕获旧会话并向其显示合理错误消息的虚拟服务器的地址。当使用 "first" 负载均衡算法时,此 IP 地址可以指向一个假服务器,用于动态触发新实例的创建。此选项默认为 "last,libc",表示首先使用状态文件中找到的前一个地址(如果存在),否则使用 libc 的解析器。这确保了与历史行为的持续兼容性。
defaults # 地址解析永不失败 default-server init-addr last,libc,none
在 default-server 中支持:是
"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 }。如果未设置 "timeout check",则 "inter" 参数也用作发送到服务器的健康检查的超时。为了减少托管在同一硬件上的多个服务器之间的 "共振" 效应,代理和所有服务器的健康检查都以它们之间微小的时间偏移开始。还可以使用全局 "spread-checks" 关键字在代理和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这样做是有意义的。在 default-server 中支持:是"maxconn" 参数指定将发送到此服务器的最大并发连接数。如果传入的并发请求数超过此值,它们将被排队,等待连接释放。此参数非常重要,因为它可以保护脆弱的服务器免于在极端负载下崩溃。如果指定了 "minconn" 参数,则限制将变为动态。默认值为 "0",表示无限制。另请参阅 "minconn" 和 "maxqueue" 参数,以及后端 'fullconn' 关键字。在 default-server 中支持:是
"maxqueue" 参数指定将在此服务器队列中等待的最大连接数。如果达到此限制,下一个请求将被重新分派到其他服务器,而不是无限期地等待被服务。这将破坏持久性,但可能会允许用户在尝试连接的服务器即将崩溃时快速重新登录。默认值为 "0",表示队列是无限制的。另请参阅 "maxconn" 和 "minconn" 参数。在 default-server 中支持:是
当设置 "minconn" 参数时,maxconn 限制将变为一个动态限制,遵循后端的负载。服务器将始终接受至少 <minconn> 个连接,最多不超过 <maxconn> 个连接,并且当后端并发连接少于 <fullconn> 时,限制将在两者之间上下波动。这使得在正常负载下限制服务器的负载成为可能,但在重要负载下可以进一步提高负载,而不会在异常负载下使服务器过载。另请参阅 "maxconn" 和 "maxqueue" 参数,以及 "fullconn" 后端关键字。在 default-server 中支持:是
在 Linux 上,可以指定套接字属于哪个网络命名空间。此指令使得可以明确地将服务器绑定到不同于默认命名空间的命名空间。有关网络命名空间的更多详细信息,请参阅您的操作系统文档。
此选项在 SSL 用于与服务器通信时禁用 SSL 会话重用。它将强制服务器为每个新连接执行完全握手。这可能只对基准测试、故障排除和偏执用户有用。在 default-server 中支持:否
此选项在 SSL 用于与服务器通信时禁用对 SSLv3 的支持。请注意,SSLv2 在代码中已禁用,并且无法通过任何配置选项启用。另请参阅 "force-sslv3"、"force-tlsv*"。在 default-server 中支持:否此设置仅在已构建 OpenSSL 支持时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复对服务器的 CPU 使用率要求更高。此选项也可在全局语句 "ssl-default-server-options" 中使用。在 default-server 中支持:否
此选项在 SSL 用于与服务器通信时禁用对 TLSv1.0 的支持。请注意,SSLv2 在代码中已禁用,并且无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是明智的。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "force-sslv3"、"force-tlsv*"。在 default-server 中支持:否
此选项在 SSL 用于与服务器通信时禁用对 TLSv1.1 的支持。请注意,SSLv2 在代码中已禁用,并且无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是明智的。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "force-sslv3"、"force-tlsv*"。在 default-server 中支持:否
此选项在 SSL 用于与服务器通信时禁用对 TLSv1.2 的支持。请注意,SSLv2 在代码中已禁用,并且无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是明智的。此选项也可在全局语句 "ssl-default-server-options" 中使用。另请参阅 "force-sslv3"、"force-tlsv*"。在 default-server 中支持:否
永远不要将分配给此服务器的连接添加到 stick-table。这可以与 backup 结合使用,以确保为备份服务器禁用 stick-table 持久性。在 default-server 中支持:否
此选项通过观察与服务器的通信来启用基于健康的调整。默认情况下,此功能是禁用的,启用它还需要启用健康检查。有两种支持的模式:"layer4" 和 "layer7"。在 layer4 模式下,只有成功的/不成功的 tcp 连接是重要的。在 layer7 模式下(仅允许用于 http 代理),会验证从服务器收到的响应,例如有效/无效的 http 代码、无法解析的头部、超时等。有效的状态码包括 100 到 499、501 和 505。在 default-server 中支持:否。另请参阅 "check"、"on-error" 和 "error-limit"。
选择在检测到足够多的连续错误时应该执行什么操作。目前有四种模式可用:- fastinter:强制 fastinter - fail-check:模拟一个失败的检查,也强制 fastinter(默认) - sudden-death:模拟一个预致命的失败健康检查,再多一次失败的检查会将服务器标记为关闭,强制 fastinter - mark-down:立即将服务器标记为关闭并强制 fastinter。在 default-server 中支持:是。另请参阅 "check"、"observe" 和 "error-limit"。
修改服务器被标记为关闭时发生的情况。目前有一种可用操作:- shutdown-sessions:关闭对等会话。启用此设置后,当服务器关闭时,到服务器的所有连接都将立即终止。当健康检查检测到比简单连接状态更复杂的情况,并且长时间的超时会导致服务长时间无响应时,可以使用此功能。例如,健康检查可能会检测到数据库已卡住,并且没有机会重用现有连接。以此方式终止的连接将以 'D'(表示 "Down")终止代码记录。操作默认禁用。在 default-server 中支持:是
修改服务器被标记为启动时发生的情况。目前有一种可用操作:- shutdown-backup-sessions:关闭所有备份服务器上的会话。仅当服务器不在备份状态且未被禁用时(其有效权重必须大于 0)才会执行此操作。有时可以使用此功能来强制活动服务器在恢复后(处理长会话时,例如 LDAP、SQL 等)重新承担所有流量。这样做可能会导致比尝试解决的问题更多(例如,不完整的事务),因此请谨慎使用此功能。由于服务器启动而终止的会话将以 'U'(表示 "Up")终止代码记录。操作默认禁用。在 default-server 中支持:是
使用 "port" 参数,可以为健康检查使用不同的端口。在某些服务器上,可能希望将某个端口专门用于能够执行复杂测试的组件,这些测试比应用程序更适合进行健康检查。例如,通常在 inetd 中运行一个简单的脚本。如果未设置 "check" 参数,则忽略此参数。另请参阅 "addr" 参数。在 default-server 中支持:是
参数 "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
在 default-server 中支持:否
参数 "rise" 指示服务器在经过 <count> 次连续成功的健康检查后将被视为正常运行。如果未指定,此值默认为 2。另请参阅 "check"、"inter" 和 "fall" 参数。在 default-server 中支持:是
当为服务器启用 DNS 解析且返回了来自不同族的多个 IP 地址时,HAProxy 将优先使用 "resolve-prefer" 参数中提到的族的 IP 地址。可用族:“ipv4”和“ipv6”。默认值:ipv6。在 default-server 中支持:是
server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6
此选项优先选择匹配网络的 IP 地址。这对于云环境很有用,可以优先选择本地 IP。在某些情况下,云高可用服务可以通过许多不同数据中心上的许多 IP 地址进行公告。数据中心之间的延迟不可忽略,因此此补丁允许优先选择本地数据中心。如果没有地址匹配已配置的网络,则会选择另一个地址。在 default-server 中支持:是
server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8
指向一个现有的 "resolvers" 部分以解析当前服务器的主机名。要正常运行,DNS 解析要求服务器已启用健康检查。实际上,健康检查会触发 DNS 解析。您必须在需要 DNS 解析的每个服务器行上指定一个“resolvers”参数。在 default-server 中支持:否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 协议。另请参阅 "bind" 关键字的 "accept-proxy" 和 "accept-netscaler-cip" 选项。在 default-server 中支持:否
参数 "send-proxy-v2" 强制对与此服务器建立的任何连接使用 PROXY 协议版本 2。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它知道客户端的地址或它访问的公共地址,而不管上层协议是什么。如果服务器不了解该协议的此版本,则不得使用此设置。另请参阅 "bind" 关键字的 "send-proxy" 选项。在 default-server 中支持:否
参数 "send-proxy-v2-ssl" 强制对与此服务器建立的任何连接使用 PROXY 协议版本 2。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它知道客户端的地址或它访问的公共地址,而不管上层协议是什么。此外,PROXY 协议的 SSL 信息扩展将被添加到 PROXY 协议头中。如果服务器不了解该协议的此版本,则不得使用此设置。另请参阅 "bind" 关键字的 "send-proxy-v2" 选项。在 default-server 中支持:否
参数 "send-proxy-v2-ssl" 强制对与此服务器建立的任何连接使用 PROXY 协议版本 2。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它知道客户端的地址或它访问的公共地址,而不管上层协议是什么。此外,PROXY 协议的 SSL 信息扩展以及客户端证书主题(如果有)中的通用名称将被添加到 PROXY 协议头中。如果服务器不了解该协议的此版本,则不得使用此设置。另请参阅 "bind" 关键字的 "send-proxy-v2" 选项。在 default-server 中支持:否
服务器的 "slowstart" 参数接受一个以毫秒为单位的值,该值指示刚恢复的服务器将在多长时间后以全速运行。与所有其他基于时间的时间参数一样,它可以使用 { us, ms, s, m, h, d } 中的任何其他显式单位输入。在此期间,速度从 0% 线性增长到 100%。限制适用于两个参数:- maxconn:服务器接受的连接数将从 1% 增长到通常由 (minconn,maxconn,fullconn) 定义的动态限制的 100%。- weight:当后端使用动态加权算法时,权重将从 1% 线性增长到 100%。在这种情况下,权重在每次健康检查时都会更新。因此,"inter" 参数小于 "slowstart" 很重要,以最大化步骤数。slowstart 永远不会在 HAProxy 启动时应用,否则会对正在运行的服务器造成麻烦。它仅在服务器先前被视为失败时应用。在 default-server 中支持:是参数 "sni" 评估样本获取表达式,将其转换为字符串,并将结果用作发送到服务器的 SNI TLS 扩展中的主机名。典型的用例是在桥接 HTTPS 场景中发送从客户端接收到的 SNI,将 "ssl_fc_sni" 样本获取用于表达式,尽管像 req.hdr(host) 这样的替代方案也可能是有意义的。在 default-server 中支持:否
参数 "source" 设置连接服务器时将使用的源地址。它遵循与后端 "source" 关键字完全相同的参数和原则,只是它仅适用于引用它的服务器。有关详细信息,请查阅 "source" 关键字。此外,服务器行上的 "source" 语句允许通过指示由连字符 ('-') 分隔的下限和上限来指定源端口范围。某些操作系统在指定源端口范围时可能需要有效的 IP 地址。允许多个服务器具有相同的 IP/范围。这样做可以绕过总共 64k 并发连接的最大值。然后,限制将达到每个服务器 64k 连接。自 Linux 4.2/libc 2.23 以来,对于指定源地址但不带端口的连接,将设置 IP_BIND_ADDRESS_NO_PORT。在 default-server 中支持:否此选项启用连接到服务器的 SSL 加密。在使用 SSL 连接到服务器时,使用 "verify" 验证服务器证书至关重要,否则通信容易受到简单的中间人攻击,使 SSL 无效。使用此选项时,健康检查会自动以 SSL 形式发送,除非有 "port" 或 "addr" 指令指示检查应发送到不同位置。请参阅 "check-ssl" 选项以强制 SSL 健康检查。在 default-server 中支持:否
设置到此服务器的所有出站连接的 TCP 用户超时。此选项在 Linux 2.6.37 及更高版本中可用。它允许 HAProxy 为包含在配置延迟内未收到确认的数据的套接字配置超时。这对于经历长空闲期的长期连接特别有用,例如远程终端或数据库连接池,其中客户端和服务器超时必须保持很高以允许长时间空闲,但重要的是要检测到服务器已消失,以便释放与其连接(以及客户端会话)相关的所有资源。另一个典型用例是在健康检查太慢或在软重新加载期间强制死服务器连接关闭,因为那时健康检查被禁用。参数默认以毫秒为单位表示延迟。这仅适用于常规 TCP 连接,而对于其他协议则被忽略。
此选项通过跟踪另一个服务器来启用设置服务器当前状态的能力。可以跟踪一个服务器,该服务器本身又跟踪另一个服务器,前提是链的末端有一个启用了健康检查的服务器。如果省略 <proxy>,则使用当前服务器。如果使用 disable-on-404,则必须在两个代理上都启用它。在 default-server 中支持:否
此设置仅在支持 OpenSSL 的情况下可用。如果设置为 'none',则不验证服务器证书。在其他情况下,使用 'ca-file' 中的 CA 和可选的 'crl-file' 中的 CRL 来验证服务器提供的证书。如果在全局部分未指定 'ssl_server_verify',则这是默认设置。验证失败时,握手将被中止。在使用 SSL 连接到服务器时,验证服务器证书至关重要,否则通信容易受到简单的中间人攻击,使 SSL 完全无效。在 default-server 中支持:否
此设置仅在支持 OpenSSL 的情况下可用,并且仅在还指定了 'verify required' 时才生效。设置后,将检查服务器提供的证书中的主体和主体备用名称中的主机名。如果证书中的任何主机名与指定的主机名不匹配,则握手将被中止。服务器提供的证书中的主机名可能包含通配符。在 default-server 中支持:否
参数 "weight" 用于调整服务器相对于其他服务器的权重。所有服务器将接收与其权重相对于所有权重总和成比例的负载,因此权重越高,负载越高。默认权重为 1,最大值为 256。值为 0 表示服务器不参与负载均衡,但仍接受持久连接。如果使用此参数根据服务器容量分配负载,建议从可以增长和收缩的值开始,例如 10 到 100 之间,以便在上方和下方留出足够的空间供以后调整。在 default-server 中支持:是
HAProxy 允许在服务器行上使用主机名通过名称服务器检索其 IP 地址。默认情况下,HAProxy 在解析配置文件时解析名称,并在进程生命周期内缓存结果。在某些情况下,例如在 Amazon 中,服务器的 IP 在重启后可能会更改,或者 ELB 虚拟 IP 会根据当前工作负载而更改。本章介绍了 HAProxy 如何配置为在运行时处理服务器的名称解析。无论是否启用了运行时服务器名称解析,HAProxy 在解析配置时都会继续进行首次解析。请记住,DNS 解析是由健康检查触发的。这使得健康检查对于允许 DNS 解析是强制性的。
正如我们在介绍中看到的,HAProxy 中的名称解析发生在进程生命周期的两个不同阶段:1. 启动时,HAProxy 解析服务器行定义并匹配主机名。它使用 libc 函数来解析主机名。此解析依赖于 /etc/resolv.conf 文件。2. 运行时,当 HAProxy 准备好对服务器进行健康检查时,它会验证当前名称解析是否仍被视为有效。如果不是,它会在健康检查的同时处理新的解析。其他一些事件可能会在运行时触发名称解析:- 当服务器的健康检查最终导致连接超时时:这可能是因为服务器具有新的 IP 地址。因此,我们需要触发名称解析以了解此新 IP。一些重要的事情需要注意:- 所有名称服务器都会同时被查询。HAProxy 将处理第一个有效响应。- 当所有服务器都返回错误时,解析将被视为无效(NX、超时、拒绝)。
本节专门介绍与 HAProxy 中的名称解析相关的主机信息。可以根据需要创建任意数量的 resolvers 部分。每个部分可以包含多个名称服务器。当在 resolvers 部分配置了多个名称服务器时,HAProxy 会使用第一个有效响应。对于无效响应,只考虑最后一个。目的是为了让慢速服务器在快速的错误或过时服务器之后有机会提供有效答案。当每台服务器返回不同类型的错误时,HAProxy 仅使用最后一个错误来决定应用何种行为。可以应用两种行为:1. 停止 DNS 解析 2. 使用新的查询类型重放 DNS 查询 在这种情况下,将按以下确切顺序应用以下类型:1. ANY 查询类型 2. 由 resolve-prefer 服务器参数指向的系列对应的查询类型 3. 剩余系列类型 当发生以下错误时,HAProxy 将停止 DNS 解析:- 无效的 DNS 响应数据包 - 响应的查询部分名称错误 - NX 域 - 服务器拒绝查询 - CNAME 未指向 IP 地址 当发生以下错误时,HAProxy 会尝试新的查询类型:- 响应中没有 Answer 记录 - DNS 响应被截断 - DNS 响应错误 - 响应中未找到预期的 DNS 记录 - 名称服务器超时 例如,在一个 resolvers 部分配置了 2 个名称服务器:- 第一个响应有效并直接应用,第二个响应被忽略 - 第一个响应无效,第二个响应有效,则应用第二个响应; - 第一个响应是 NX 域,第二个是截断响应,则 HAProxy 使用新的类型重放查询; - 第一个响应被截断,第二个是 NX 域,则 HAProxy 停止解析。
创建一个新的名称服务器列表,标记为 <resolvers id> resolvers 部分接受以下参数
DNS 服务器描述: <id> :服务器的标签,应唯一 <ip> :服务器的 IP 地址 <port> :DNS 服务实际运行的端口
定义 <period>,根据最后一个解析 <status> 的结果,保留最后一个名称解析的持续时间 <status>:最后一个名称解析的状态。可接受的值为 "nx"、"other"、"refused"、"timeout"、"valid"。<period>:当最后一个答案是 <status> 时,两次连续名称解析之间的时间间隔。它遵循 HAProxy 的时间格式。<period> 默认为毫秒。默认值为 "valid" 为 10 秒,其他为 30 秒。注意:由于名称解析是由健康检查触发的,因此在 <period> 模 <inter> 健康检查参数后会触发新的解析。定义在放弃之前为解析服务器名称而发送的查询次数 <nb>。默认值:3。当名称服务器超时或完整的 DNS 查询类型故障转移序列结束并且我们需要从默认的 ANY 查询类型重新开始时,会发生重试。
定义与名称解析相关的超时 <event>:<time> 超时适用的事件。可用事件为:- retry:在未收到响应时,两次 DNS 查询之间的时间。默认值:1 秒 <time>:与事件相关的时间。它遵循 HAProxy 的时间格式。<time> 以毫秒为单位。
resolvers mydns nameserver dns1 10.0.0.1:53 nameserver dns2 10.0.0.2:53 resolve_retries 3 timeout retry 1s hold other 30s hold refused 30s hold nx 30s hold timeout 30s hold valid 10s
在 HTTP 模式下,可以根据正则表达式重写、添加或删除请求和响应标头中的某些内容。如果某个标头与正则表达式匹配,还可以阻止请求或响应,这足以停止大多数基本的协议攻击,并防止内部网络的信息泄露。如果 HAProxy 遇到“信息响应”(状态码 1xx),它可以处理所有 rsp* 规则,这些规则可以允许、拒绝、重写或删除标头,但会拒绝向任何此类消息添加标头,因为这不符合 HTTP 标准。仍然处理这些响应中的标头的原因是为了停止和/或修复可能发生的任何信息泄露,例如因为另一个下游设备会无条件地添加标头,或者服务器名称出现在其中。当看到此类消息时,对下一个非信息性消息仍会进行正常处理。本节涵盖了以下关键字的常见用法,详细描述在 第 4.2 节:- reqadd <string> - reqallow <search> - reqiallow <search> - reqdel <search> - reqidel <search> - reqdeny <search> - reqideny <search> - reqpass <search> - reqipass <search> - reqrep <search> <replace> - reqirep <search> <replace> - reqtarpit <search> - reqitarpit <search> - rspadd <string> - rspdel <search> - rspidel <search> - rspdeny <search> - rspideny <search> - rsprep <search> <replace> - rspirep <search> <replace> 对于所有这些关键字,都使用相同的约定。<search> 参数是 POSIX 扩展正则表达式(regex),它支持通过圆括号(不带反斜杠)进行分组。空格和其他分隔符必须用反斜杠 ('\') 前缀,以避免与字段分隔符混淆。其他字符可能用反斜杠前缀以改变其含义:\t 表示制表符 \r 表示回车符 (CR) \n 表示换行符 (LF) \ 表示空格,以区别于分隔符 \# 表示井号,以区别于注释 \\ 表示在 regex 中使用反斜杠 \\\\ 表示在文本中使用反斜杠(regex 中为 *2,haproxy 中为 *2) \xXX 表示以 C 语言的十六进制格式 XX 写入 ASCII 码 <replace> 参数包含用于替换匹配 regex 的最大文本部分。它可以使用上述特殊字符,并通过写一个紧跟一个数字 0 到 9 的反斜杠(表示组位置,0 表示整行)来引用 regex 中由圆括号分隔的子字符串。这种做法对于 "sed" 程序用户来说非常普遍。<string> 参数表示将系统性地添加到最后一个标头行之后的字符串。它也可以使用上述特殊字符序列。
- 这些关键字并不总是方便地基于标头内容进行允许/拒绝。强烈建议使用带有 "block" 关键字的 ACL,从而获得更灵活、更易于管理的规则。 - 行总是被视为一个整体。无法仅引用标头名称或值。这很重要,因为标头的书写方式(特别是冒号后的空格数)。 - 第一行始终被视为标头,这使得重写或过滤 HTTP 请求 URI 或响应代码成为可能,但反过来也使得区分标头和请求行变得更加困难。正则表达式前缀 ^[^\ \t]*[\ \t] 匹配任何 HTTP 方法后跟一个空格,前缀 ^[^ \t:]*: 匹配任何标头名称后跟一个冒号。 - 出于性能考虑,添加到请求或响应中的字符数在构建时限制在 1 到 4 kB 之间。这通常对于大多数用法来说绰绰有余。如果在偶尔使用中太短,可以通过删除一些无用的标头后再添加新标头来获得一些空间。 - 以 "reqi" 和 "rspi" 开头的关键字与其不带 'i' 的对应关键字相同,只是在匹配模式时忽略大小写。 - 当请求通过前端再通过后端时,将评估前端的所有 req* 规则,然后评估后端的所有 req* 规则。响应应用相反的路径。 - req* 语句在 "block" 语句之后应用,因此 "block" 始终是第一个,但在 "use_backend" 之前应用,以便在切换之前进行重写。
Haproxy 能够从请求或响应流、客户端或服务器信息、表格、环境信息等中提取数据。提取此类数据的操作称为获取样本。一旦检索到,这些样本就可以用于各种目的,例如作为 stick-table 的键,但最常见的用法是将它们与预定义的常量数据(称为模式)进行匹配。
访问控制列表 (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 | +---------------------+-----------------+ | string | str | +---------------------+-----------------+ | binary | none, use "-m" | +---------------------+-----------------+ 注意,为了匹配二进制样本,必须指定匹配方法,见下文。ACL 引擎可以将这些类型与以下类型的模式进行匹配:- 布尔值- 整数或整数范围- IP 地址/网络- 字符串(精确、子字符串、后缀、前缀、子目录、域)- 正则表达式- 十六进制块目前支持以下 ACL 标志:-i : 在匹配所有后续模式时忽略大小写。-f : 从文件中加载模式。-m : 使用特定的模式匹配方法-n : 禁止 DNS 解析-M : 将 -f 指向的文件加载为 map 文件。-u : 强制 ACL 的唯一 ID-- : 强制标志结束。当字符串看起来像某个标志时很有用。“-f”标志后跟一个文件名,将从该文件中读取所有行作为单独的值。如果模式要从多个文件中加载,甚至可以传递多个“-f”参数。空行以及以井号 ('#') 开头的行将被忽略。所有前导空格和制表符都将被剥离。如果绝对有必要插入以井号开头的有效模式,只需在其前面加一个空格,使其不被视为注释。根据数据类型和匹配方法,haproxy 可能会将行加载到二叉树中,从而允许非常快速的查找。IPv4 和精确字符串匹配是这种情况。在这种情况下,重复项将自动删除。“-M”标志允许 ACL 使用 map 文件。如果设置了此标志,则该文件将被解析为两列文件。第一列包含 ACL 使用的模式,第二列包含样本。样本稍后可用于 map。在极少数情况下,ACL 仅用于在应用映射之前检查 map 中是否存在某个模式,此时这可能很有用。“-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_data A_type 的样本提取方法(例如:字符串或二进制),这是必需的。当指定“-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" : 域匹配:检查内容的点分隔部分是否与提供的字符串模式之一精确匹配。这可以与二进制或字符串样本一起使用。例如,要快速检测 HTTP 请求中是否存在 cookie“JSESSIONID”,可以这样做:acl jsess_present cook(JSESSIONID) -m found 为了在缓冲区的前 500 个字节上应用正则表达式,可以使用以下 ACL:acl script_tag payload(0,500) -m reg -i <script> 在正则表达式库在使用“-i”时速度较慢的系统上,可以将样本转换为小写再进行匹配,如下所示:acl script_tag payload(0,500),lower -m reg <script> 所有 ACL 特定的标准都暗示着默认的匹配方法。大多数情况下,这些标准是通过串联原始样本提取方法的名称和匹配方法来组成的。例如,“hdr_beg”将“beg”匹配应用于使用“hdr”提取方法检索的样本。由于所有 ACL 特定的标准都依赖于样本提取方法,因此始终可以选择使用原始样本提取方法和使用“-m”的显式匹配方法。如果使用“-m”在 ACL 特定的标准上指定了替代匹配,则该匹配方法将简单地应用于底层样本提取方法。例如,以下所有 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 | 字符串 | 二进制 | +----------------------+---------+---------+---------+---------+---------+ | none (仅存在) | found | found | found | found | found | +----------------------+---------+---------+---------+---------+---------+ | none (布尔值) |> 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 | +----------------------+---------+---------+---------+---------+---------+
为了匹配布尔值,不需要任何值,所有值都会被忽略。布尔匹配默认用于所有类型为“boolean”的获取方法。当使用布尔匹配时,获取的值会按原样返回,这意味着布尔值“true”将始终匹配,而布尔值“false”将永远不匹配。布尔匹配也可以通过在返回整数值的获取方法上使用“-m bool”来强制执行。然后,整数值 0 会被转换为布尔值“false”,所有其他值都会被转换为“true”。
整数匹配默认应用于整数提取方法。也可以通过使用“-m int”来强制对布尔提取进行整数匹配。在这种情况下,“false”被转换为整数 0,“true”被转换为整数 1。整数匹配还支持整数范围和运算符。请注意,整数匹配仅适用于正值。范围是使用下限和上限表示的值,用冒号分隔,两者都可以省略。例如,“1024:65535”是表示非特权端口范围的有效范围,“1024:”也可以。 “0:1023”是特权端口的有效表示,“:1023”也可以。作为特殊情况,某些 ACL 函数支持实际上是两个用点分隔的整数的十进制数。这用于某些版本检查等。所有整数属性都适用于这些十进制数,包括范围和运算符。为了更方便地使用,还支持比较运算符。请注意,将运算符与范围一起使用意义不大,强烈不建议这样做。同样,使用一组值执行顺序比较也没有多大意义。整数匹配的可用运算符是:eq : 如果测试值等于至少一个值,则为 truege : 如果测试值大于或等于至少一个值,则为 truet : 如果测试值大于至少一个值,则为 truele : 如果测试值小于或等于至少一个值,则为 truet : 如果测试值小于至少一个值,则为 true 例如,以下 ACL 匹配任何负的 Content-Length 标头:acl negative-length hdr_val(content-length) lt 0 这一个匹配 3.0 到 3.1(含)之间的 SSL 版本:acl sslv3 req_ssl_ver 3:3.1
字符串匹配适用于字符串或二进制获取方法,有 6 种不同的形式:- 精确匹配(-m str):提取的字符串必须与模式完全匹配;- 子字符串匹配(-m sub):在提取的字符串中查找模式,如果找到任何一个,ACL 就匹配;- 前缀匹配(-m beg):将模式与提取字符串的开头进行比较,如果任何一个模式匹配,ACL 就匹配。- 后缀匹配(-m end):将模式与提取字符串的结尾进行比较,如果任何一个模式匹配,ACL 就匹配。- 子目录匹配(-m dir):在提取的字符串中查找模式,并用斜杠(“/”)分隔,如果找到任何一个,ACL 就匹配。- 域匹配(-m dom):在提取的字符串中查找模式,并用点(“.”)分隔,如果找到任何一个,ACL 就匹配。字符串匹配适用于按原样传递的字面字符串,但反斜杠(“\”)除外,它可以用来转义某些字符,例如空格。如果在第一个字符串之前传递了“-i”标志,则匹配将忽略大小写。为了匹配字符串“-i”,请将其设置为第二个,或在第一个字符串之前传递“--”标志。当然,匹配字符串“--”也同样适用。对于可能包含空字节 (0x00) 的二进制获取,请勿使用字符串匹配,因为比较会在第一个空字节处停止。而是先使用十六进制转换器将二进制获取转换为十六进制字符串。
# 如果字符串 <tag> 存在于二进制样本中,则匹配 acl tag_found req.payload(0,0),hex -m sub 3C7461673E
与字符串匹配一样,正则表达式匹配也适用于按字面传递的字符串,但反斜杠("\")除外,它使得可以转义某些字符,如空格。如果在第一个正则表达式之前传递了“-i”标志,则匹配将忽略大小写。为了匹配字符串“-i”,要么将其放在第二个位置,要么在第一个正则表达式之前传递“--”标志。当然,匹配字符串“--”也适用相同的原则。
可以将一些提取的样本与一个可能无法安全地表示为字符串的二进制块进行匹配。为此,当匹配方法设置为二进制时,模式必须以偶数个十六进制数字的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
# 在输入流中匹配 "Hello\n" (\x48 \x65 \x6c \x6c \x6f \x0a) acl hello payload(0,6) -m bin 48656c6c6f0a
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 CIDR 地址表示法中,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 掩码。
某些操作仅在条件有效时执行。条件是 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 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 hdr_cnt(Content-length) eq 0 http-request deny if METH_POST missing_cl 也可以这样写:http-request deny if METH_POST { 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 节。
历史上,样本获取方法仅用于检索数据以使用 ACL 进行模式匹配。随着 stick-table 的出现,创建了一类新的样本获取方法,它们通常共享与它们的 ACL 对应项相同的语法。这些样本获取方法也称为“获取”。现在,ACL 和获取已统一。所有 ACL 获取方法都已作为获取方法提供,ACL 也可以使用任何样本获取方法。本节详细介绍了所有可用的样本获取方法及其输出类型。一些样本获取方法具有已弃用的别名,用于维护与现有配置的兼容性。它们将被明确标记为已弃用,并且不应在新设置中使用。当可用时,还会指示 ACL 派生项及其各自的匹配方法。这些方法都具有明确定义的默认模式匹配方法,因此无需(尽管允许)传递“-m”选项来指示如何使用 ACL 进行样本匹配。如上文样本类型与匹配兼容性矩阵所示,在 ACL 中使用通用样本获取方法时,除非样本类型是布尔值、整数、IPv4 或 IPv6 之一,否则“-m”选项是强制性的。当同一个关键字存在于 ACL 关键字和标准获取方法时,ACL 引擎将默认自动选择仅用于 ACL 的那个。其中一些关键字支持一个或多个强制参数,以及一个或多个可选参数。这些参数是强类型的,并在解析配置时进行检查,因此没有运行错误参数的风险(例如:未解析的后端名称)。获取函数参数用括号括起来,并用逗号分隔。当参数是可选的时,将在下方用方括号(“[ ]”)指示。当所有参数都可选时,可以省略括号。因此,标准样本获取方法的语法是以下之一:- name - name(arg1) - name(arg1,arg2)
样本获取方法可以与转换结合使用,以应用于获取的样本(也称为“转换器”)。这些组合形成了所谓的“样本表达式”,结果是“样本”。最初这仅由“stick on”和“stick store-request”指令支持,但现在已扩展到所有可以使用样本的地方(ACL、log-format、unique-id-format、add-header 等)。这些转换被列为样本获取方法之后的特定关键字。这些关键字也可以直接附加在获取关键字的参数之后,并用逗号分隔。这些关键字也可以支持一些参数(例如:网络掩码),必须用括号括起来。一类转换器是位运算符和算术运算符,它们支持对整数执行基本操作。支持一些位运算(and、or、xor、cpl)和一些算术运算(add、sub、mul、div、mod、neg)。提供了一些比较器(odd、even、not、bool),使得无需编写 ACL 即可报告匹配。当前可用的转换关键字列表包括
以字符串形式返回所请求属性的值,值之间由“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)]
将 <value> 添加到有符号整数类型的输入值中,并将结果作为有符号整数返回。<value> 可以是数值或变量名。变量名以作用域指示开头。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后面跟着一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
对 <value> 与输入的有符号整数值执行按位“AND”操作,并将结果作为有符号整数返回。 <value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将二进制输入样本转换为 base64 字符串。它用于以可可靠传输的方式记录或传输二进制内容(例如:SSL ID 可以复制到标头中)。
如果类型为有符号整数的输入值非空,则返回布尔值 TRUE,否则返回 FALSE。与 and() 结合使用,可用于报告位测试的真/假(例如:验证标志是否存在)。
从输入二进制样本中提取一些字节。结果是一个二进制样本,从原始样本的偏移量(以字节为单位)开始,并可选地在给定长度处截断。
获取类型为有符号整数的输入值,应用取反(翻转所有位)并以有符号整数的形式返回结果。
使用 CRC32 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用一个完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它提供与希望在某些输入键上计算 CRC32 的其他软件的兼容性,因此它遵循在以太网、Gzip、PNG 等中最常见的实现。它比其他算法慢,但可能提供更好或至少更难预测的分布。它不能用于安全目的,因为 32 位哈希很容易被破解。另请参阅 "djb2"、"sdbm"、"wt6" 和 "hash-type" 指令。
要求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)]
此转换器用作调试工具。它在屏幕上转储输入样本的内容和类型。样本在其输出上按原样返回。此转换器仅在 haproxy 启用调试构建时存在。
将输入的有符号整数值除以 <value>,并将结果作为有符号整数返回。如果 <value> 为 null,则返回最大的无符号整数(通常为 2^63-1)。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
使用 DJB2 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用一个完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘性表条目以收集粗略的统计信息。它不能用于安全目的,因为 32 位哈希很容易被破解。另请参阅 "crc32"、"sdbm"、"wt6" 和 "hash-type" 指令。
如果类型为有符号整数的输入值为偶数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "not,and(1),bool"。
根据给定的分隔符从输入字符串中提取给定索引处的子字符串。索引从 1 开始,分隔符是格式化为字符列表的字符串。
将二进制输入样本转换为十六进制字符串,每个输入字节包含两个十六进制数字。它用于以可可靠传输的方式记录或传输某些二进制输入数据的十六进制转储(例如:SSL ID 可以复制到标头中)。
将一个应包含自纪元以来日期的整数转换为表示该日期的字符串,格式适用于 HTTP 标头字段。如果指定了偏移值,则它是在转换操作之前添加到日期的秒数。这在发出 Date 标头字段、响应中的 Expires 值(当与正偏移结合时)或 Last-Modified 值(当偏移为负时)时特别有用。
使用输入样本的字符串表示形式在指定表中进行查找。如果表中未找到键,则返回布尔值 false。否则返回布尔值 true。这可以用来验证表中跟踪某些元素的某个键是否存在(例如:是否已看到源 IP 地址或 Authorization 标头)。
将掩码应用于 IPv4 地址,并使用结果进行查找和存储。这可以用于使某个掩码内的所有主机共享相同的表项,从而使用相同的服务器。掩码可以用点分形式(例如:255.255.255.0)或 CIDR 形式(例如:24)传入。
转义输入字符串,并生成一个 ASCII 输出字符串,可用于 JSON 字符串。转换器尝试根据参数解码输入字符串。它可以是“ascii”、“utf8”、“utf8s”、“utf8p”或“utf8ps”。“ascii”解码器从不失败。“utf8”解码器检测 3 种类型的错误:- 错误的 UTF-8 序列(单独的延续字节、错误的延续字节数等)- 无效范围(解码值在 UTF-8 禁止的范围内)- 编码过长(值使用比必要更多的字节进行编码)。UTF-8 JSON 编码可能产生“值太长”的错误,当 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"}从 "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
将字符串样本转换为小写。这只能放在字符串样本获取函数之后或返回字符串类型的转换关键字之后。结果类型为字符串。
将一个应包含自纪元以来日期的整数转换为表示该日期的本地时间的字符串,使用 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
map_<match_type>(<map_file>[,<default_value>]) map_<match_type>_<output_type>(<map_file>[,<default_value>]) 使用 <match_type> 匹配方法从 <map_file> 中搜索输入值,并返回转换为 <output_type> 类型的关联值。如果输入值在 <map_file> 中找不到,转换器将返回 <default_value>。如果未设置 <default_value>,转换器将失败,并表现为未获取到输入值。如果未设置 <match_type>,则默认为“str”。同样,如果未设置 <output_type>,则默认为“str”。为了方便起见,“map”关键字是“map_str”的别名,并将字符串映射到另一个字符串。避免键之间重叠很重要:IP 地址和字符串存储在树中,因此会使用最细粒度的第一个匹配。其他键存储在列表中,因此会使用第一个匹配的出现。以下数组包含按输入类型、匹配类型和输出类型排序的所有可用映射函数的列表。
| 输入类型 | 匹配方法 | 输出类型 str | 输出类型 int | 输出类型 ip |
|---|---|---|---|---|
| str | str | map_str | map_str_int | map_str_ip |
| str | beg | map_beg | map_beg_int | map_end_ip |
| str | sub | map_sub | map_sub_int | map_sub_ip |
| str | dir | map_dir | map_dir_int | map_dir_ip |
| str | dom | map_dom | map_dom_int | map_dom_ip |
| str | end | map_end | map_end_int | map_end_ip |
| str | reg | map_reg | map_reg_int | map_reg_ip |
| str | reg | map_regm | map_reg_int | map_reg_ip |
| int | int | map_int | map_int_int | map_int_ip |
| ip | ip | map_ip | map_ip_int | map_ip_ip |
名为“map_regm”的特殊映射在正则表达式中期望匹配区域,并修改输出,将反向引用(如“\1”)替换为相应的匹配文本。文件包含每行一个键+值。以“#”开头的行被忽略,空行也是如此。删除前导制表符和空格。然后,键是第一个“word”(一系列非空格/制表符字符),值是该系列空格/制表符之后直到行尾的内容,不包括尾随空格/制表符。
# 这是一条注释,会被忽略 2.22.246.0/23 United Kingdom \n <-><-----------><--><------------><----> | | | | `- 尾部空格被忽略 | | | `---------- 值 | | `-------------------- 中间空格被忽略 | `---------------------------- 键 `------------------------------------ 前导空格被忽略
将输入的有符号整数值除以 <value>,并将余数作为有符号整数返回。如果 <value> 为 null,则返回零。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将输入的有符号整数值乘以 <value>,并将乘积作为有符号整数返回。在溢出的情况下,将返回符号的最大可能值,以便操作不会环绕。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
获取类型为有符号整数的输入值,计算其相反值,并以有符号整数的形式返回余数。0 是单位元。此运算符用于反向减法:为了从一个常量中减去输入值,只需执行 "neg,add(value)"。
如果类型为有符号整数的输入值非空,则返回布尔值 FALSE,否则返回 TRUE。与 and() 结合使用,可用于报告位测试的真/假(例如:验证标志的缺失)。
如果类型为有符号整数的输入值为奇数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "and(1),bool"。
对 <value> 和输入的有符号整数值执行按位“OR”操作,并将结果作为有符号整数返回。<value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
对输入字符串应用基于正则表达式的替换。它的操作与众所周知的“sed”实用程序的“s/<regex>/<subst>/”相同。默认情况下,它将替换输入字符串中与正则表达式<regex>匹配的最大部分的第一个出现,替换为替换字符串<subst>。通过在第三个参数<flags>中添加标志“g”,可以替换所有出现。还可以通过在<flags>中添加标志“i”来使正则表达式不区分大小写。由于<flags>是一个字符串,它由所有所需标志的连接组成。因此,如果需要“i”和“g”,使用“gi”或“ig”将产生相同效果。需要注意的是,由于配置解析器的当前限制,一些字符,如右括号、右方括号或逗号,无法在参数中使用。此转换器的第一个用途是用其他字符或字符序列替换某些字符或字符序列。
# 在标头 "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)]
捕获请求槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
捕获响应槽 <id> 中的字符串条目,并按原样返回该条目。如果槽不存在,捕获将静默失败。
使用 SDBM 哈希函数将二进制输入样本哈希为无符号 32 位整数。可选地,如果可选的<avalanche>参数等于 1,则可以对输出应用全雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但也可以用作收集粗略统计信息的粘滞表条目。不应将其用于安全目的,因为 32 位哈希很容易被破解。另请参阅“crc32”、“djb2”、“wt6”和“hash-type”指令。set-var(<var name>) 使用输入内容设置变量,并按原样返回输出内容。变量保留值和关联的输入类型。变量名以指示其范围的指示开头。允许的范围包括:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
从输入的有符号整数值中减去 <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 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回布尔值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的标签的当前值。另请参阅 sc_get_gpt0 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中输入样本关联的第一个通用目的计数器的当前值。另请参阅 sc_get_gpc0 样本获取关键字。
使用输入样本的字符串表示形式在指定的表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在表中配置的周期内 gpc0 计数器递增的频率,与指定表中输入样本相关联。另请参阅 sc_get_gpc0_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 错误累积量。另请参阅 sc_http_err_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。另请参阅 sc_http_err_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 请求累积量。另请参阅 sc_http_req_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。另请参阅 sc_http_req_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的客户端到服务器数据累积量,以千字节为单位。该测试目前在 32 位整数上执行,这会将值限制为 4TB。另请参阅 sc_kbytes_in 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器到客户端数据累积量,以千字节为单位。该测试目前在 32 位整数上执行,这会将值限制为 4TB。另请参阅 sc_kbytes_out 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器 ID。通过“stick”规则在连接到服务器成功时将服务器 ID 与样本关联。服务器 ID 零表示没有服务器与此键关联。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的传入会话累积量。请注意,这里的会话是指被“tcp-request connection”规则集接受的传入连接。另请参阅 sc_sess_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中的输入样本关联的平均传入会话速率。请注意,此处的会话指的是被“tcp-request connection”规则集接受的传入连接。另请参阅 sc_sess_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在指定表中跟踪与输入样本相同键的当前并发连接数。它与 table_conn_cur 的不同之处在于,它不依赖任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。另请参阅 sc_trackers 样本提取关键字。
将字符串样本转换为大写。这只能放在字符串样本提取函数之后或返回字符串类型的转换关键字之后。结果为字符串类型。
获取 URL 编码的字符串作为输入,并将其解码后的版本作为输出返回。输入和输出的类型都是字符串。unset-var(<var name>) 如果输入内容已定义,则取消设置变量。变量名以指示其范围的指示开头。允许的范围包括:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将一个假定包含自纪元以来日期的整数,使用 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
根据给定的分隔符从输入字符串中提取第 n 个单词。索引从 1 开始,分隔符是一个字符串格式的字符列表。
使用 WT6 哈希函数将二进制输入样本哈希为一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完全雪崩哈希函数。此转换器使用的函数与各种基于哈希的负载均衡算法所使用的函数相同,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘性表条目来收集粗略的统计信息。由于 32 位哈希很容易被破解,因此不得用于安全目的。另请参阅“crc32”、“djb2”、“sdbm”以及“hash-type”指令。
对 <value> 和类型为有符号整数的输入值执行按位“XOR”(异或)操作,并将结果作为有符号整数返回。<value> 可以是数字值或变量名。变量名以指示其范围的指示符开头。允许的作用域是:“proc”:变量与整个进程共享;“sess”:变量与整个会话共享;“txn”:变量与事务(请求和响应)共享;“req”:变量仅在请求处理期间共享;“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
第一组样本提取方法适用于甚至不涉及任何客户端信息的内部信息。这些方法有时与“monitor-fail”指令一起使用,向外部监视器报告内部状态。本节描述的样本提取方法可在任何地方使用。
始终返回布尔值“false”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
始终返回布尔值“true”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
返回指定后端的排队连接总数除以活动服务器数量。如果未指定后端,则使用当前后端。这与“queue”非常相似,不同之处在于考虑了农场的规模,以便更准确地衡量新连接的处理时间。主要用途是与 ACL 一起使用,当可以确定新用户将获得降级服务时,向他们返回一个抱歉页面,或者在标头中传递给后端服务器,以便它们决定以降级模式工作或禁用某些功能以稍微加快处理速度。请注意,如果没有活动的服务器,则将考虑排队连接数的两倍作为测量值。这是一个合理的估计,因为我们预计会有服务器很快恢复,但我们仍然希望将新流量发送到状态更好的另一个后端。另请参阅“queue”、“be_conn”和“be_sess_rate”样本获取。
适用于后端上当前已建立的连接数,可能包括正在评估的连接。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器场已满时,它可用于使用特定的服务器场。另请参阅“fe_conn”、“queue”和“be_sess_rate”标准。
以每秒新会话的数量返回后端会话创建速率的整数值。这用于 ACL,以便在昂贵或易受攻击的后端达到过高的会话速率时切换到备用后端,或限制服务滥用(例如,防止在线字典的吸取)。将此元素添加到日志中使用 log-format 指令也可能很有用。
# 如果字典请求过于频繁,则重定向到错误页面 backend dynamic mode http acl being_scanned be_sess_rate gt 100 redirect location /denied.html if being_scanned
返回一个二进制链。输入是字符串的十六进制表示。
返回一个布尔值。<bool> 可以是 'true'、'false'、'1' 或 '0'。'false' 和 '0' 相同。'true' 和 '1' 相同。
返回一个整数值,该值对应于后端中仍可用的连接槽数,通过对所有服务器的最大连接数和最大队列大小进行总计。这可能只在 ACL 中使用。基本思想是能够测量仍然可用的连接“槽”(连接+队列)的数量,以便将超出该数量的任何内容(预期用途;请参阅“use_backend”关键字)重定向到另一个后端。“connslots”=可用服务器连接槽数 + 可用服务器队列槽数。请注意,虽然可以使用“fe_conn”,但在流量流向单个 IP、分成多个后端(可能使用 ACL 进行基于名称的负载均衡)并且您想区分不同后端及其可用“connslots”的情况下,“connslots”特别有用。此外,虽然“nbsrv”仅测量实际上*已关闭*的服务器,但此获取更精细,并且还会查看可用连接槽的数量。另请参阅“queue”和“avg_queue”。其他注意事项和说明:此时,代码不处理动态连接。此外,如果任何服务器 maxconn 或 maxqueue 为 0,则此获取显然没有意义,在这种情况下,返回的值将是 -1。
以纪元(自 1970 年 1 月 1 日以来的秒数)形式返回当前日期。如果指定了偏移值,则它是在返回值之前添加到当前日期的秒数。这对于计算相对日期特别有用,因为允许正负偏移。与 http_date 转换器结合使用很有用。
# 在每个响应中设置一个过期头为现在+1小时 http-response set-header Expires %[date(3600),http_date]
返回一个包含环境变量 <name> 值的字符串。提醒一下,环境变量是每个进程的,并在进程启动时采样。这对于将一些信息传递给下一跳服务器,或者与 ACL 结合使用以在进程以特定方式启动时采取特定操作很有用。
# 将带有本地主机名的 Via 头传递给下一跳 http-request add-header Via 1.1\ %[env(HOSTNAME)] # 当设置了 STOP 环境变量时,拒绝无 cookie 的请求 http-request deny if !{ cook(SESSIONID) -m found } { env(STOP) -m found }
返回前端上当前已建立的连接数,可能包括正在评估的连接。如果未指定前端名称,则使用当前前端。但也可以检查另一个前端。它可用于在硬阻塞之前返回一个“抱歉”页面,或者在服务器场被认为已满时使用特定的后端来处理新请求。这主要与 ACL 一起使用,但也可以用于在 HTTP 头中将一些统计信息传递给服务器。另请参阅“dst_conn”、“be_conn”、“fe_sess_rate”提取。
返回一个整数值,对应于每秒发送到前端的 HTTP 请求数。在启用客户端保持连接(keep-alive)的情况下,此数字可能与“fe_sess_rate”不同。
返回一个整数值,对应于前端上的会话创建速率,单位为每秒新会话数。这与 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
返回一个有符号整数。
返回一个 IPv4 地址。
返回一个 IPv6 地址。
返回一个方法。
返回一个整数值,对应于已启动的进程数(它等于全局“nbproc”设置)。这对于日志记录和调试目的很有用。返回一个整数值,对应于当前后端或指定后端的可用服务器数量。这主要与 ACL 一起使用,但在添加到日志中时也很有用。这通常用于在服务器数量过低而无法处理某些负载时切换到备用后端。当与“monitor fail”结合使用时,报告故障很有用。
返回一个整数值,对应于调用该函数的进程的位置,介于 1 和 global.nbproc 之间。这对于日志记录和调试目的很有用。
返回指定后端的排队连接总数,包括服务器队列中的所有连接。如果未指定后端名称,则使用当前后端,但也可以检查另一个后端。这对于 ACL 或将统计信息传递给后端服务器很有用。这可用于在排队超过已知水平时采取行动,这通常表示流量激增或服务器大规模减速。一个可能的操作是拒绝新用户但仍然接受老用户。另请参阅“avg_queue”、“be_conn”和“be_sess_rate”提取。
返回一个在 <range> 个可能值范围内的随机整数值,从零开始。如果未指定范围,则默认为 2^32,即数字介于 0 和 4294967295 之间。例如,传递一些需要用于做出某些路由决策的值可能很有用,或者仅仅用于调试目的。此随机数不得用于安全目的。
返回一个整数值,对应于指定服务器上当前已建立的连接数,可能包括正在评估的连接。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器场,或通知服务器我们对其活动连接数的看法。另请参阅“fe_conn”、“be_conn”和“queue”提取方法。
当指定的服务器处于 UP 状态时返回 true,当服务器处于 DOWN 或维护模式时返回 false。如果省略<backend>,则在当前后端中查找服务器。它主要用于根据通过健康检查报告的外部状态(例如,地理位置网站的可用性)采取行动。另一种可能的用途(更像是一种 hack)是使用虚拟服务器作为布尔变量,可以从 CLI 启用或禁用它们,以便可以实时调整依赖于这些 ACL 的规则。
返回一个整数,对应于指定服务器的会话创建速率,即每秒新会话的数量。如果省略<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
如果调用该函数的进程当前正在停止,则返回 TRUE。这对于日志记录,或在优雅关闭时放宽某些检查或帮助关闭某些连接很有用。
返回一个字符串。
返回当前代理的粘性表或指定粘性表中可用条目的总数。另请参阅 table_cnt。
返回当前代理的粘性表或指定粘性表中当前使用的条目总数。有关其他条目计数方法,请参阅 src_conn_cnt 和 table_avl。
返回带有存储类型变量。如果变量未设置,则采样获取失败。变量名以其范围的指示开始。允许的范围是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
第 4 层通常只描述传输层,在 haproxy 中,它最接近连接,此时还没有内容可用。此处描述的获取方法可用于低至“tcp-request connection”规则集,除非它们需要未来信息。这些通常包括 TCP/IP 地址和端口,以及与传入连接相关的粘滞表中的元素。要从粘滞计数器检索值,可以使用预定义的“sc0_”、“sc1_”或“sc2_”前缀显式设置为 0、1 或 2。这三个预定义前缀只能在 MAX_SESS_STKCTR 值不超过 3 时使用,否则可以使用“sc_”前缀,并将计数器号指定为第一个整数参数。从“sc_0”到“sc_N”,其中 N 是(MAX_SESS_STKCTR-1)。当使用“sc*”形式时,可以指定一个可选表,在这种情况下,将在此备用表中查找当前跟踪的键,而不是当前正在跟踪的表。
返回一个包含当前后端 ID 的整数。它可以在前端的响应中使用,以检查哪个后端处理了请求。
返回一个包含当前后端名称的字符串。它可以在前端与响应一起使用,以检查哪个后端处理了请求。
这是客户端的连接目标 IPv4 地址,即客户端连接到的地址。在透明模式下运行时可能很有用。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效地址。当传入连接经过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,如果设置了 nf_conntrack_tcp_loose sysctl,源地址和目标地址可能会很少出现颠倒,因为晚期响应可能会重新打开一个已超时连接并切换被认为是源地址和目标地址的地址。
返回一个整数值,对应于同一套接字上当前建立的连接数,包括正在评估的连接。它通常与 ACL 一起使用,但也可以用于在 HTTP 头中或日志中将信息传递给服务器。它可以用于在硬阻塞之前返回一个“抱歉”页面,或者在套接字被认为饱和时使用特定的后端来处理新请求。这提供了为不同的侦听端口或地址分配不同限制的能力。另请参阅“fe_conn”和“be_conn”提取。
如果传入连接的目标地址是本地系统,则返回 true,如果地址不存在于系统中(这意味着它在透明模式下被拦截),则返回 false。这对于默认将某些规则应用于转发流量,而将其他规则应用于目标为机器真实地址的流量可能很有用。例如,统计页面可以仅在此地址上提供,或者 SSH 访问可以本地重定向。请注意,该检查涉及一些系统调用,因此最好每个连接只执行一次。
返回一个整数值,对应于客户端侧连接的目标 TCP 端口,即客户端连接到的端口。这可能在透明模式下运行、为某些客户端的整个应用程序会话分配动态端口、将所有用户粘滞到同一台服务器,或使用 HTTP 头将目标端口信息传递给服务器时使用。
如果客户端使用 PROXY 协议头启动连接,则返回 true。
返回内核为客户端连接测量的往返时间(RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的往返时间(RTT)方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的未确认计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的 sacked 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的重传计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的 fack 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的丢失计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的重排序计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回一个包含当前前端 ID 的整数。它可以在后端使用,以检查它是从哪个前端调用的,或将通过同一前端进入的所有用户粘滞到同一台服务器。
返回当前前端名称的字符串。它可以在后端用于检查它是由哪个前端调用的,或者将来自同一前端的所有用户粘性到同一服务器。
返回当前跟踪的计数器中客户端到服务器的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_in_rate。
返回当前跟踪的计数器中服务器到客户端的平均字节速率,以表中配置的时间段内的字节量来衡量。另请参阅 src_bytes_out_rate。
清除当前跟踪的计数器关联的第一个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 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
返回当前跟踪的计数器的传入连接总数。另请参阅 src_conn_cnt。
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。另请参阅 src_conn_cur。
返回当前跟踪的计数器中的平均连接速率,以表中配置的时间段内的连接数量来衡量。另请参阅 src_conn_rate。
返回与当前跟踪的计数器关联的第一个通用计数器的值。另请参阅 src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。
返回与当前跟踪的计数器关联的第一个通用标签(General Purpose Tag)的值。另请参阅 src_get_gpt0。
返回与当前跟踪的计数器关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 src_gpc0_rate、sc/sc0/sc1/sc2_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
返回当前跟踪的计数器的 HTTP 错误总数。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_cnt。
返回当前跟踪的计数器中 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。另请参阅 src_http_err_rate。
返回当前跟踪的计数器的 HTTP 请求总数。这包括每个开始的请求,无论是否有效。另请参阅 src_http_req_cnt。
返回当前跟踪的计数器中 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。另请参阅 src_http_req_rate。
递增当前跟踪的计数器关联的第一个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用将将其增加到 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
返回当前跟踪的计数器中客户端到服务器的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_in。
返回当前跟踪的计数器中服务器到客户端的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_out。
返回从当前跟踪的计数器转变为会话的传入连接总数,这意味着它们已被“tcp-request connection”规则接受。一个后端可能计算比连接更多的会话,因为每个连接可能导致多个后端会话,如果客户端连接上执行了 HTTP 长连接。另请参阅 src_sess_cnt。
返回当前跟踪的计数器中的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request connection”规则的连接。一个后端可能会计算比连接更多的会话,因为如果通过与客户端的连接执行了 HTTP 保持连接(keep-alive),每个连接可能会导致多个后端会话。另请参阅 src_sess_rate。
如果指定的会话计数器当前正被当前会话跟踪,则返回 true。这在决定是否要在传递给服务器的头中设置某些值时很有用。
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。它与 sc0_conn_cur 的不同之处在于,它不依赖于任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。
返回一个包含当前侦听套接字 ID 的整数。在涉及许多“bind”行的前端中,或将通过同一套接字进入的所有用户粘滞到同一台服务器时,这很有用。
这是会话的源 IPv4 地址。它是 IP 类型,并且可以在 IPv4 和 IPv6 表上工作。在 IPv6 表上,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效地址。请注意,使用的是 TCP 级别的源地址,而不是代理后面的客户端的地址。但是,如果使用了“accept-proxy”或“accept-netscaler-cip”绑定指令,则可以是从其他 PROXY-protocol 兼容组件后面的客户端的地址,适用于所有规则集,除了“tcp-request connection”规则集,它可以看到真实地址。当传入连接经过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,由于 late response 可能会重新打开已超时的连接并切换被认为是源和目标的地址,如果设置了 nf_conntrack_tcp_loose sysctl,源和目标可能偶尔会出现颠倒。
# 在请求中添加一个带有源地址国家的 HTTP 头 http-request set-header X-Country %[src,map_ip(geoip.lst)]
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均字节速率,以表中配置的时间段内的字节量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_bytes_in_rate。
返回当前代理的粘性表或指定粘性表中,发往传入连接源地址的平均字节速率,以表中配置的时间段内的字节量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_bytes_out_rate。
清除当前代理的粘滞表或指定粘滞表中的当前跟踪的计数器关联的第一个通用计数器,并返回其先前的值。如果找不到该地址,则会创建一个条目并返回 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
返回在当前代理的粘滞表或指定粘滞表中的当前传入连接的源地址发起的连接总数。如果找不到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_cnt。
返回当前代理的粘性表或指定粘性表中,从当前传入连接的源地址发起的当前并发连接数。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_cur。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均连接速率,以表中配置的时间段内的连接数量来衡量。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_conn_rate。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc0 和 src_inc_gpc0。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用标签的值。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpt0。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用计数器的平均增量速率。它报告在配置的时间段内 gpc0 计数器递增的频率。另请参阅 sc/sc0/sc1/sc2_gpc0_rate、src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。请注意,必须在粘性表中存储“gpc0_rate”计数器才能返回值,因为“gpc0”仅保存事件计数。
返回当前代理的 stick-table 或指定 stick-table 中,来自传入连接源地址的 HTTP 错误累积数量。这包括请求错误和 4xx 错误响应。另请参阅 sc/sc0/sc1/sc2_http_err_cnt。如果未找到地址,则返回零。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。这包括请求错误和 4xx 错误响应。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_err_rate。
返回当前代理的 stick-table 或指定 stick-table 中,来自传入连接源地址的 HTTP 请求累积数量。这包括所有已启动的请求,无论是否有效。如果未找到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_cnt。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。这包括每个已启动的请求,无论其有效与否。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_http_req_rate。
增加当前代理的 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
如果传入连接的源地址是本地系统地址,则返回 true,如果地址不存在于系统中(表示它来自远程计算机),则返回 false。请注意,UNIX 地址被视为本地地址。根据客户端的来源应用某些访问限制(例如,为远程计算机要求身份验证或 HTTPS)可能会很有用。请注意,此检查涉及一些系统调用,因此最好每个连接仅执行一次。
返回当前代理的粘性表或指定粘性表中,从传入连接源地址接收的总数据量,以千字节为单位。如果找不到地址,则返回零。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 sc/sc0/sc1/sc2_kbytes_in。
返回当前代理的粘性表或指定粘性表中,发送到传入连接源地址的总数据量,以千字节为单位。如果找不到地址,则返回零。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 sc/sc0/sc1/sc2_kbytes_out。
返回一个整数值,对应于客户端侧连接的 TCP 源端口,即客户端连接的来源端口。此函数的用途非常有限,因为现代协议如今不太关心源端口。
返回当前代理的 stick-table 或指定 stick-table 中,来自传入连接源 IPv4 地址的、已转换为会话的连接的累积数量,这意味着它们已被“tcp-request”规则接受。如果未找到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_sess_cnt。
返回当前代理的粘性表或指定粘性表中,来自传入连接源地址的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request”规则的连接。如果找不到地址,则返回零。另请参阅 sc/sc0/sc1/sc2_sess_rate。
在当前代理的粘滞表或指定的粘滞表中,为传入连接的源地址创建或更新关联的条目。此表必须配置为存储 "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
在处理响应时,返回一个包含服务器 ID 的整数。虽然它几乎只用于 ACL,但也可用于日志记录或调试。
第 5 层通常仅描述会话层,在 haproxy 中,这最接近于所有连接握手完成但尚无内容可用时的会话。这里描述的获取方法最低可在 "tcp-request content" 规则集使用,除非它们需要某些未来的信息。这些信息通常包括 SSL 协商的结果。
以字符串形式返回请求的属性值,值之间用“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/TLS 传输层建立并且在本地解密时,返回 true。这意味着传出连接是向带有 "ssl" 选项的服务器建立的。当传出连接通过 SSL/TLS 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
当传出连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
当传出连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当传出连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。该唯一 ID 可以使用转换器 "ssl_bc_unique_id,base64" 编码为 base64。
当传出连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL ID。如果我们想知道会话是否被重用,记录此信息会很有用。
当传出连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证深度 > 0 的客户端证书期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果在验证客户端证书期间检测到第一个错误,则返回该错误在 CA 链中的深度。如果未遇到错误,则返回 0。
当传入连接通过 SSL/TLS 传输层建立时,返回由客户端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,如果在深度为 0 的验证期间检测到第一个错误,则返回该错误的 ID;如果在此验证过程中未遇到错误,则返回 0。请参考您的 SSL 库文档以查找完整的错误代码列表。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回客户端证书颁发者的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_c_i_dn(OU,2)" 获取第二个组织单位,而 "ssl_c_i_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成客户端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回客户端证书主体的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_c_s_dn(OU,2)" 获取第二个组织单位,而 "ssl_c_s_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的 SHA-1 指纹。这可用于将客户端粘滞到某个服务器,或将此信息传递给服务器。请注意,输出是二进制格式,因此如果要将该签名传递给服务器,您需要将其编码为十六进制或 base64,如下例所示:
http-request set-header X-SSL-Client-SHA1 %[ssl_c_sha1,hex]
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署客户端证书的算法名称。
如果当前 SSL 会话使用了客户端证书,则返回 true,即使当前连接使用的是 SSL 会话恢复。另请参阅 "ssl_fc_has_crt"。
当传入连接通过 SSL/TLS 传输层建立时,返回验证结果的错误 ID;如果未遇到错误,则返回零。有关完整的错误代码列表,请参考您的 SSL 库文档。
当传入连接通过 SSL/TLS 传输层建立时,返回客户端证书的版本。
当传入连接通过 SSL/TLS 传输层建立时,返回前端提供的 DER 格式证书。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回前端证书颁发者的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_f_i_dn(OU,2)" 获取第二个组织单位,而 "ssl_f_i_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回用于生成前端证书密钥的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的结束日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书中显示的开始日期,格式为 YYMMDDhhmmss[Z] 字符串。
当传入连接通过 SSL/TLS 传输层建立时,如果未指定 <entry>,则返回前端证书主体的完整专有名称 (DN);否则返回从 DN 开头找到的第一个给定条目的值。如果指定了正/负出现次数作为可选的第二个参数,则返回从 DN 开头/结尾算起的第 n 个给定条目的值。例如,"ssl_f_s_dn(OU,2)" 获取第二个组织单位,而 "ssl_f_s_dn(CN)" 获取通用名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的序列号。当用于 ACL 时,用于匹配的值可以以十六进制形式传递。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的 SHA-1 指纹。这可用于了解使用 SNI 选择了哪个证书。
当传入连接通过 SSL/TLS 传输层建立时,返回用于签署前端证书的算法名称。
当传入连接通过 SSL/TLS 传输层建立时,返回前端证书的版本。
当前端连接通过 SSL/TLS 传输层建立并且在本地解密时,返回 true。这意味着它匹配了一个带有 "ssl" 选项的 "bind" 行声明的套接字。
# 当客户端通过 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 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
此函数从通过 TLS 传输层建立并由 haproxy 本地解密的传入连接中提取应用层协议协商 (ALPN) 字段。结果是一个包含客户端通告的协议名称的字符串。SSL 库必须在构建时启用了对 TLS 扩展的支持(请检查 haproxy -vv)。请注意,除非在 "bind" 行上的 "alpn" 关键字指定了协议列表,否则不会通告 TLS ALPN 扩展。此外,没有任何机制强制客户端从此列表中选择一个协议,它可能会请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅 "ssl_fc_npn"。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
如果传入的 SSL/TLS 传输层连接中存在客户端证书,则返回 true。在 'verify' 语句设置为 'optional' 时很有用。注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中不存在客户端证书,但可以从缓存或票据中检索。因此,如果您想检查当前 SSL 会话是否使用了客户端证书,请优先使用 "ssl_c_used"。
此函数检查通过 SSL/TLS 传输层建立的传入连接中是否存在服务器名称指示 (SNI) TLS 扩展。当传入连接提供 TLS SNI 字段时返回 true。这要求 SSL 库在构建时启用了对 TLS 扩展的支持(请检查 haproxy -vv)。
如果通过 SSL/TLS 传输层传入的连接上,SSL/TLS 会话已通过使用 SSL 会话缓存或 TLS 票据得到恢复,则返回 true。
此函数从通过 TLS 传输层建立并由 haproxy 本地解密的传入连接中提取下一代协议协商 (NPN) 字段。结果是一个包含客户端通告的协议名称的字符串。SSL 库必须在构建时启用了对 TLS 扩展的支持(请检查 haproxy -vv)。请注意,除非在 "bind" 行上的 "npn" 关键字指定了协议列表,否则不会通告 TLS NPN 扩展。此外,没有任何机制强制客户端从此列表中选择一个协议,它可能会请求任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当传入连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。该唯一 ID 可以使用转换器 "ssl_bc_unique_id,base64" 编码为 base64。
当传入连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL ID。这对于将给定客户端粘滞到某个服务器很有用。需要注意的是,某些浏览器每隔几分钟就会刷新其会话 ID。
此函数从通过 SSL/TLS 传输层建立并由 haproxy 本地解密的传入连接中提取服务器名称指示 (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)。ACL 派生词:ssl_fc_sni_end:后缀匹配 ssl_fc_sni_reg:正则表达式匹配
当传入连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
从缓冲区内容获取样本与上述的样本获取方法有些不同,因为采样的数据是短暂的。这些数据只有在可用时才能使用,并且在转发后会丢失。因此,例如,在请求期间从缓冲区内容获取的样本不能在响应中使用。即使在获取数据时,它们也可能发生变化。有时需要设置一些延迟或组合多种样本获取方法,以确保预期的数据是完整和可用的,例如通过 TCP 请求内容检查。有关该主题的更多详细信息,请参阅 "tcp-request content" 关键字。
在请求的上下文中(例如,“stick on”、“stick match”),这是“req.payload”的别名;在响应的上下文中(例如,“stick store response”),这是“res.payload”的别名。
在请求的上下文中(例如,“stick on”、“stick match”),这是“req.payload_lv”的别名;在响应的上下文中(例如,“stick store response”),这是“res.payload_lv”的别名。
返回一个整数值,对应于请求缓冲区中存在的字节数。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着在会话开始时,等于零的检查几乎总是会立即匹配,而检查更多数据的测试将等待数据进入,并且仅当 haproxy 确定不会有更多数据进入时才会返回 false。此测试旨在与 TCP 请求内容检查一起使用。
此函数从请求缓冲区中提取一个从字节 <offset> 开始,长度为 <length> 字节的二进制块。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到缓冲区末尾的整个部分。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。ACL 替代方案:payload(<offset>,<length>):十六进制二进制匹配
此函数提取一个二进制块,其大小在 <offset1> 处指定,长度为 <length> 字节,如果指定了 <offset2>,则从 <offset2> 开始,否则紧跟在长度之后开始。<offset2> 参数也支持相对偏移量,如果前缀为 '+' 或 '-' 符号。ACL 替代方案:payload_lv(<offset1>,<length>[,<offset2>]):十六进制二进制匹配
请参考 "stick store-response" 关键字中的示例。
当请求缓冲区中的数据看起来像 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
当请求缓冲区看起来像 RDP 协议时,提取名为 <name> 的 RDP cookie;如果未指定名称,则提取任何 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
尝试将请求缓冲区解析为 RDP 协议,然后返回一个整数,对应于找到的 RDP cookie 的数量。如果传递了可选的 cookie 名称,则仅考虑与此名称匹配的 cookie。这主要用于 ACL。ACL 派生词:req_rdp_cookie_cnt([<name>]):整数匹配
返回一个布尔值,标识客户端是否在 SSL ClientHello 消息中发送了 RFC4492 第 5.1 节中定义的“支持的椭圆曲线扩展”。这可用于在同一 IP 地址上,向 ECC 兼容的客户端提供 EC 证书,并为所有其他客户端使用 RSA。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。
如果请求缓冲区中的数据可以解析为完整的 SSL(v3 或更高版本)客户端 hello 消息,则返回一个包含该 SSL hello 消息类型的整数值。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "bind" 行。这主要用于 ACL 中,以检测是否存在应该包含可用于粘性的 SSL 会话 ID 的 SSL hello 消息。
返回一个包含服务器名称 TLS 扩展的值的字符串,该扩展由客户端在通过请求缓冲区的 TLS 流中发送,前提是缓冲区包含可解析为完整 SSL(v3 或更高版本)客户端 hello 消息的数据。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过 SSL 数据层解析的内容,因此对于带有“ssl”选项的“bind”行无效。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
如果客户端未发送 SessionTicket TLS 扩展(RFC5077),则返回 0。如果客户端发送了 SessionTicket TLS 扩展,则返回 1。如果客户端还发送了非零长度的 TLS SessionTicket,则返回 2。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过 SSL 数据层解析的内容,因此对于带有“ssl”选项的“bind”行无效。例如,这可用于检测客户端是否发送了 SessionTicket,并相应地进行粘连,如果没有 SessionTicket,则粘连到 SessionID,或者由于在使用 SessionTicket 时不存在服务器端状态而不进行粘连。
返回一个整数值,包含请求缓冲区中存在的流的 SSL/TLS 协议版本。SSLv2 hello 消息和 SSLv3 消息都受支持。TLSv1 被宣布为 SSL 版本 3.1。该值由主版本乘以 65536,加上次版本组成。请注意,这仅适用于请求缓冲区中找到的原始内容,而不适用于通过 SSL 数据层解析的内容,因此对于带有“ssl”选项的“bind”行无效。ACL 版本测试匹配的格式为主.次(例如 3.1)的十进制表示。此获取主要用于 ACL。ACL 派生:req_ssl_ver:十进制匹配
返回一个整数值,对应于响应缓冲区中存在的字节数。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着在会话开始时,等于零的检查几乎总是会立即匹配,而检查更多数据的测试将等待数据进入,并且仅当 haproxy 确定不会有更多数据进入时才会返回 false。此测试旨在与 TCP 响应内容检查一起使用。
此函数从响应缓冲区中提取一个从字节 <offset> 开始,长度为 <length> 字节的二进制块。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到缓冲区末尾的整个部分。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。
此函数提取一个二进制块,其大小在 <offset1> 处指定,长度为 <length> 字节,如果指定了 <offset2>,则从 <offset2> 开始,否则紧跟在长度之后开始。<offset2> 参数也支持相对偏移量,如果前缀为 '+' 或 '-' 符号。
请参考 "stick store-response" 关键字中的示例。
如果响应缓冲区中的数据可以解析为完整的 SSL(v3 或更高版本)hello 消息,则返回一个包含该 SSL hello 消息类型的整数值。请注意,这仅适用于响应缓冲区中找到的原始内容,而不适用于通过 SSL 数据层解密的内容,因此这不适用于带有 "ssl" 选项的 "server" 行。这主要用于 ACL 中,以检测是否存在应该包含可用于粘性的 SSL 会话 ID 的 SSL hello 消息。
此获取在检查周期结束时返回 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
可以从 HTTP 内容、请求和响应中获取样本。这个应用层也称为第 7 层。只有当完整的 HTTP 请求或响应已从其各自的请求或响应缓冲区中解析出来时,才可能获取本节中的数据。对于所有 HTTP 特定规则和以 "mode http" 运行的部分,情况总是如此。使用 TCP 内容检查时,可能需要支持检查延迟,以便让请求或响应首先进入。这些获取可能需要比第 4 层获取更多的 CPU 资源,但由于请求和响应已被索引,所以不会多太多。
此函数返回第一个 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:子串匹配
此函数返回上面 "base" 获取方法返回值的 32 位哈希值。这对于在高流量网站上跟踪每个 URL 的活动很有用,而无需存储所有 URL。相反,存储一个更短的哈希值,可以节省大量内存。输出类型是无符号整数。使用的哈希函数是 SDBM,输出具有完全雪崩效应。技术上,base32 完全等同于 "base,sdbm(1)"。
此函数返回上面 base32 获取结果和下面 src 获取结果的拼接。结果类型为 binary,大小为 8 或 20 字节,具体取决于源地址族。这可用于跟踪每个 IP、每个 URL 的计数器。
此函数提取由 "capture request header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。
此函数提取 HTTP 请求的 METHOD。它可以在请求和响应中使用。与 "method" 不同,因为它被分配了内存,所以可以在请求和响应中使用。
capture.req.uri : string
此函数提取请求的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "req.ver" 不同,因为它依赖于一个持久性标志,所以可以在请求、响应和日志中使用。
此函数提取由 "capture response header" 捕获的头部内容,idx 是 capture 关键字在配置中的位置。第一个条目的索引为 0。
此函数提取响应的 HTTP 版本,并返回 "HTTP/1.0" 或 "HTTP/1.1"。与 "res.ver" 不同,因为它依赖于一个持久性标志,所以可以在日志中使用。
此函数以数据块形式返回 HTTP 请求的可用正文。它要求请求正文已使用 "option http-buffer-request" 进行了缓冲并可用。对于分块编码的正文,目前只分析第一个分块。
此获取假设 POST 请求的正文是 url-encoded 的。用户可以检查 "content-type" 是否包含值 "application/x-www-form-urlencoded"。此函数提取正文中参数 <name> 的第一次出现,该参数在 '&' 之前结束。参数名称区分大小写。如果未给出名称,则任何参数都会匹配,并返回第一个。结果是一个字符串,对应于请求正文中呈现的参数 <name> 的值(不执行 URL 解码)。请注意,此获取的 ACL 版本会遍历多个参数,如果未给出名称,则会迭代报告所有参数值。
此函数返回 HTTP 请求的可用正文长度(以字节为单位)。如果正文大于缓冲区,则该值可能低于通告的长度。它要求请求正文已使用 "option http-buffer-request" 进行了缓冲并可用。
此函数返回 HTTP 请求正文的通告长度(以字节为单位)。它将表示通告的 Content-Length 头部,或者在分块编码的情况下,表示第一个分块的大小。为了解析分块,它要求请求正文已使用 "option http-buffer-request" 进行了缓冲并可用。
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值作为字符串返回。如果未指定名称,则返回第一个 cookie 的值。与 ACL 一起使用时,将评估所有匹配的 cookie。根据 Cookie 头部规范 (RFC6265) 的要求,名称和值周围的空格将被忽略。cookie 名称区分大小写。空 cookie 是有效的,因此如果存在空 cookie,很可能会返回一个空值。使用 "found" 匹配来检测是否存在。对于服务器发送的响应 cookie,请使用 res.cook() 变体。ACL 派生词:cook([<name>]):精确字符串匹配 cook_beg([<name>]):前缀匹配 cook_dir([<name>]):子目录匹配 cook_dom([<name>]):域名匹配 cook_end([<name>]):后缀匹配 cook_len([<name>]):长度匹配 cook_reg([<name>]):正则表达式匹配 cook_sub([<name>]):子串匹配
返回一个整数值,表示名为 <name> 的 cookie 在请求中出现的次数;如果未指定 <name>,则表示所有 cookie 的数量。
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 的值。在 ACL 中使用时,将遍历所有匹配的名称,直到找到一个匹配的值。
此函数从请求的 "Cookie" 头部行或响应的 "Set-Cookie" 头部中提取名为 <name> 的 cookie 的最后一次出现,并将其值作为字符串返回。一个典型的用途是让多个共享相同配置文件的客户端使用同一台服务器。这可能类似于 "appsession" 通过 "request-learn" 语句所做的,但支持多对等体同步和跨重启的状态保持。如果未指定名称,则返回第一个 cookie 的值。此获取不应再使用,应替换为 req.cook() 或 res.cook(),因为它根据使用上下文模糊地确定方向。
在请求上使用时,此函数等同于 req.hdr();在响应上使用时,等同于 res.hdr()。有关更多详细信息,请参考这些各自的获取。如果不确定获取方向,请使用明确的函数。请注意,与 hdr() 样本获取方法相反,hdr_* ACL 关键字明确地应用于请求头部。
此函数提取 HTTP 请求中名为 <name> 的头部的最后一次出现。从 ACL 使用时,将遍历所有出现,直到找到匹配项。可选地,可以指定一个特定的出现次数作为位置编号。正值表示从第一次出现开始的位置,1 是第一个。负值表示相对于最后一次出现的位置,-1 是最后一个。它与 req.hdr() 的不同之处在于,值中存在的任何逗号都会被返回,并且不会用作分隔符。这对于像 User-Agent 这样的头部有时很有用。
返回一个整数值,表示请求头字段名 <name> 的出现次数;如果未指定 <name>,则返回头字段的总数。与其 req.hdr_cnt() 类似函数不同,此函数返回完整行头部的数量,并且不会在逗号处停止。
这会提取 HTTP 请求中头信息 <name> 的最后一次出现。当在 ACL 中使用时,会迭代所有出现的内容,直到找到匹配项。还可以选择指定一个特定的出现位置。正值表示从第一次出现开始的位置,1 是第一次出现。负值表示相对于最后一次出现的位置,-1 是最后一次出现。常见用法是与 X-Forwarded-For 头信息一起使用,转换为 IP 后与 IP stick-table 相关联。该函数将任何逗号视为分隔符来分隔不同的值。如果要获取完整的头信息行,请使用 req.fhdr()。请仔细查阅 RFC7231 以了解某些头信息是如何解析的。此外,其中一些是不区分大小写的(例如 Connection)。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>]]):子字符串匹配
返回一个整数值,表示请求头字段名 <name> 的出现次数;如果未指定 <name>,则表示头字段值的总数。重要的是要记住,一个头部行如果包含多个值,可能会被计为多个头部。该函数将任何逗号视为不同值的分隔符。如果需要完整的行头部,应改用 req.fhdr_cnt()。通过 ACL,它可用于检测特定头部的存在、缺失或滥用,以及通过拒绝包含多个某些头部的请求来阻止请求走私攻击。有关头部匹配的更多信息,请参阅 "req.hdr"。
这会提取 HTTP 请求中标题的最后一次出现,将其转换为 IPv4 或 IPv6 地址并返回该地址。当与 ACL 一起使用时,会检查所有出现,如果省略了 ,则检查每个标头的所有值。解析器严格遵循 RFC7239 中描述的格式,并扩展了 IPv4 地址可以可选地后跟冒号 (':') 和有效十进制端口号(0 到 65535),这些端口号将被静默删除。所有其他格式均不匹配,并将导致地址被忽略。还可以选择指定一个特定的出现作为位置号。正值表示从第一次出现开始的位置,1 是第一次出现。负值表示相对于最后一次出现的位置,-1 是最后一次出现。典型的用法是与 X-Forwarded-For 和 X-Client-IP 标头一起使用。
此函数提取 HTTP 请求中名为 <name> 的头部的最后一次出现,并将其转换为整数值。与 ACL 一起使用时,会检查所有出现;如果省略 <name>,则会检查每个头部的每个值。可选地,可以指定一个特定的出现次数作为位置编号。正值表示从第一次出现开始的位置,1 是第一个。负值表示相对于最后一次出现的位置,-1 是最后一个。一个典型的用途是与 X-Forwarded-For 头部一起使用。
返回一个布尔值,指示从客户端收到的身份验证数据是否与指定用户列表中存储的用户名和密码匹配。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。
如果从客户端收到的身份验证数据中的用户名和密码根据指定用户列表均有效,则返回一个对应于该用户名的字符串。其主要目的是在 ACL 中使用,然后检查该用户是否属于列表中的任何组。此获取函数在 ACL 之外并不真正有用。目前仅支持 http 基本身份验证。ACL 派生词:http_auth_group(<userlist>) : group ... 当从请求中提取的用户(其密码根据指定用户列表有效)属于至少一个组时返回 true。
当正在处理的请求是连接的第一个请求时返回 true。这可用于添加或删除在请求不是第一个时某些请求中可能缺少的头部,或帮助在日志中对请求进行分组。
返回一个对应于 HTTP 请求中方法的整数值。例如,"GET" 等于 1(检查源代码以确定匹配关系)。值 9 表示“其他方法”,并可能转换为从流中提取的字符串。这不应直接用作样本,它仅用于 ACL,ACL 会透明地将方法从模式转换为这些整数 + 字符串值。一些预定义的 ACL 已经检查了最常见的方法。ACL 派生词:method:不区分大小写的方法匹配
# 只接受 GET 和 HEAD 请求 acl valid_method method GET HEAD http-request deny if ! valid_method
这会提取请求的 URL 路径,该路径从第一个斜杠开始,在问号(不包括主机部分)之前结束。常见用法是与预取缓存以及需要从数据库聚合多个信息并将其保留在缓存中的门户一起使用。请注意,对于出站缓存,最好使用“url”。在 ACL 中,通常用于匹配精确的文件名(例如 "/login.php")或使用派生形式匹配目录部分。另请参阅“url”和“base”获取方法。ACL 派生:path:精确字符串匹配 path_beg:前缀匹配 path_dir:子目录匹配 path_dom:域匹配 path_end:后缀匹配 path_len:长度匹配 path_reg:正则表达式匹配 path_sub:子字符串匹配
此函数提取请求的查询字符串,它从第一个问号之后开始。如果没有问号,此获取不返回任何内容。如果存在问号但后面没有任何内容,则返回一个空字符串。这意味着可以使用 "found" 匹配方法轻松地知道是否存在查询字符串。此获取是 "path" 的补充,后者在问号之前停止。
此函数构建一个字符串,该字符串由规则评估时请求中出现的所有头部名称拼接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。从 HTTP 请求中返回版本字符串,例如 "1.1"。这对于日志很有用,但主要用于 ACL。一些预定义的 ACL 已经检查了版本 1.0 和 1.1。ACL 派生词:req_ver:精确字符串匹配
如果响应已被 HAProxy 压缩,则返回布尔值 "true",否则返回布尔值 "false"。这可用于在日志中添加信息。
如果响应被 HAProxy 压缩,则返回一个包含所用算法名称的字符串,例如:“deflate”。这可用于在日志中添加一些信息。
此函数从响应的 "Set-Cookie" 标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值作为字符串返回。如果未指定名称,则返回第一个 cookie 的值。ACL 派生:scook([<name>] : 精确字符串匹配
返回一个整数值,表示 cookie <name> 在响应中出现的次数,如果未指定 <name>,则表示所有 cookie 的数量。这在与 ACL 结合使用以检测可疑响应时非常有用。
此函数从响应的 "Set-Cookie" 标头行中提取 cookie 名称 <name> 的最后一次出现,并将其值转换为整数后返回。如果未指定名称,则返回第一个 cookie 的值。
此函数提取 HTTP 响应中标头 <name> 的最后一次出现,如果未指定 <name>,则提取最后一个标头。可以选择性地将特定出现指定为位置编号。正值表示从第一次出现开始的位置,1 代表第一次。负值表示相对于最后一次出现的位置,-1 代表最后一次。它与 res.hdr() 的不同之处在于,值中存在的任何逗号都会被返回,而不会被用作分隔符。如果不需要此行为,应改用 res.hdr() 提取。这对于像 Date 或 Expires 这样的标头有时很有用。
返回一个整数值,表示响应标头字段名 <name> 的出现次数,如果未指定 <name>,则返回标头字段的总数。与其对应的 res.hdr_cnt() 函数不同,此函数返回完整行标头的数量,并且不会在逗号处停止。如果不需要此行为,应改用 res.hdr_cnt() 提取。
这会提取 HTTP 响应中头信息 <name> 的最后一次出现,或者在未指定 <name> 时提取最后一个头信息。还可以选择指定一个特定的出现位置。正值表示从第一次出现开始的位置,1 是第一次出现。负值表示相对于最后一次出现的位置,-1 是最后一次出现。这对于在 stick-table 中学习某些数据很有用。该函数将任何逗号视为分隔符来分隔不同的值。如果不需要这样做,则应改用 res.fhdr() 获取。ACL 派生:shdr([<name>[,<occ>]]):精确字符串匹配 shdr_beg([<name>[,<occ>]]):前缀匹配 shdr_dir([<name>[,<occ>]]):子目录匹配 shdr_dom([<name>[,<occ>]]):域匹配 shdr_end([<name>[,<occ>]]):后缀匹配 shdr_len([<name>[,<occ>]]):长度匹配 shdr_reg([<name>[,<occ>]]):正则表达式匹配 shdr_sub([<name>[,<occ>]]):子字符串匹配
返回一个整数值,表示响应标头字段名 <name> 的出现次数,如果未指定 <name>,则返回标头字段的总数。该函数将任何逗号都视作不同值的分隔符。如果不需要此行为,应改用 res.fhdr_cnt() 提取。
此函数提取 HTTP 响应中标头 <name> 的最后一次出现,将其转换为 IPv4 或 IPv6 地址并返回该地址。可以选择性地将特定出现指定为位置编号。正值表示从第一次出现开始的位置,1 代表第一次。负值表示相对于最后一次出现的位置,-1 代表最后一次。这对于将一些数据学习到粘性表中很有用。
此函数构建一个字符串,该字符串由规则评估时响应中出现的所有标头名称连接而成。默认分隔符是逗号 (','),但可以通过可选参数 <delim> 进行覆盖。在这种情况下,只考虑 <delim> 的第一个字符。此函数提取 HTTP 响应中标头 <name> 的最后一次出现,并将其转换为一个整数值。可以选择性地将特定出现指定为位置编号。正值表示从第一次出现开始的位置,1 代表第一次。负值表示相对于最后一次出现的位置,-1 代表最后一次。这对于将一些数据学习到粘性表中很有用。
从 HTTP 响应中返回版本字符串,例如 "1.1"。这对于日志很有用,但主要用于 ACL。ACL 派生:resp_ver : 精确字符串匹配
此函数从响应的 "Set-Cookie" 标头行中提取 cookie 名称 <name> 的最后一次出现,并使用相应的值进行匹配。这可以与 "appsession" 在默认选项下的行为相媲美,但支持多对等体同步和跨重启状态保持。此提取函数已弃用,并已被 "res.cook" 提取函数取代。此关键字将很快消失。
返回一个包含 HTTP 响应中 HTTP 状态码的整数,例如 302。它主要用于 ACL 和整数范围内,例如,如果响应不是 3xx,则移除任何 Location 标头。
返回附加到请求的唯一 ID。必须设置“unique-id-format”指令。如果未设置,则 unique-id 样本获取将失败。请注意,unique-id 通常与 HTTP 请求一起使用,但是此样本获取也可以与其他协议一起使用。显然,如果它与 HTTP 以外的协议一起使用,unique-id-format 指令不应包含 HTTP 部分。另请参阅:unique-id-format 和 unique-id-header
此函数提取请求中呈现的 URL。典型用途是与支持预取功能的缓存一起使用,以及与需要从数据库聚合多个信息并将其保存在缓存中的门户网站一起使用。对于 ACL,首选使用 "path" 而不是 "url",因为客户端可能会发送完整的 URL,就像通常对代理所做的那样。唯一真正的用途是匹配 "*",这在 "path" 中不匹配,并且已经有预定义的 ACL。另请参阅 "path" 和 "base"。ACL 派生:url : 精确字符串匹配 url_beg : 前缀匹配 url_dir : 子目录匹配 url_dom : 域名匹配 url_end : 后缀匹配 url_len : 长度匹配 url_reg : 正则表达式匹配 url_sub : 子字符串匹配
当主机部分以 IP 地址形式呈现时,此函数从请求的 URL 中提取 IP 地址。其用途非常有限。例如,监控系统可能会使用此字段作为源 IP 的替代方案,以测试给定源地址将遵循的路径,或为给定源地址在表中强制创建一个条目。对于 ACL,它可以用于限制通过代理访问某些系统,例如与选项 "http_proxy" 结合使用时。
此函数从请求的 URL 中提取端口部分。请注意,如果请求中未指定端口,则假定为端口 80。对于 ACL,它可以用于限制通过代理访问某些系统,例如与选项 "http_proxy" 结合使用时。
这会提取查询字符串中参数 <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"。此函数提取请求中的 URL 参数 <name> 并将其转换为整数值。例如,这可用于基于用户 ID 的会话粘性,或与 ACL 一起匹配页码或价格。
此函数返回一个 32 位哈希值,该值由连接第一个 Host 标头和整个 URL(包括参数,而不仅仅是请求的路径部分,如上面的 "base32" 提取)得到。这对于跟踪每个 URL 的活动很有用。存储一个较短的哈希值可以节省大量内存。输出类型是无符号整数。
此函数返回 "url32" 提取和 "src" 提取的连接结果。结果类型为 binary,大小为 8 或 20 字节,具体取决于源地址族。这可用于跟踪每个 IP、每个 URL 的计数器。
一些预定义的 ACL 是硬编码的,因此不必在每个需要它们的前端中声明。它们的名称都使用大写字母,以避免混淆。下面提供了它们的等效项。
| ACL 名称 | 等效于 | 用法 |
|---|---|---|
| FALSE | always_false | 从不匹配 |
| HTTP | req_proto_http | 如果协议是有效的 HTTP 则匹配 |
| HTTP_1.0 | req_ver 1.0 | 匹配 HTTP 版本 1.0 |
| HTTP_1.1 | req_ver 1.1 | 匹配 HTTP 版本 1.1 |
| HTTP_CONTENT | hdr_val(content-length) gt 0 | 匹配一个存在的 content-length |
| HTTP_URL_ABS | url_reg ^[^/:]*:// | 匹配带协议方案的绝对 URL |
| HTTP_URL_SLASH | url_beg / | 匹配以 "/" 开头的 URL |
| HTTP_URL_STAR | url * | 匹配等于 "*" 的 URL |
| LOCALHOST | src 127.0.0.1/8 | 匹配来自本地主机的连接 |
| METH_CONNECT | method CONNECT | 匹配 HTTP CONNECT 方法 |
| METH_DELETE | method DELETE | 匹配HTTP DELETE方法 |
| METH_GET | method GET HEAD | 匹配 HTTP GET 或 HEAD 方法 |
| METH_HEAD | method HEAD | 匹配 HTTP HEAD 方法 |
| METH_OPTIONS | method OPTIONS | 匹配 HTTP OPTIONS 方法 |
| METH_POST | method POST | 匹配 HTTP POST 方法 |
| METH_PUT | method PUT | 匹配HTTP PUT方法 |
| METH_TRACE | method TRACE | 匹配 HTTP TRACE 方法 |
| RDP_COOKIE | req_rdp_cookie_cnt gt 0 | 匹配 RDP cookie 的存在 |
| REQ_CONTENT | req_len gt 0 | 匹配请求缓冲区中的数据 |
| TRUE | always_true | 总是匹配 |
| WAIT_END | wait_end | 等待内容分析结束 |
HAProxy 的强大之处无疑在于其精确的日志记录。它可能提供了此类产品可用的最高级别的信息,这对于对复杂环境进行故障排除至关重要。日志中提供的标准信息包括客户端端口、TCP/HTTP 状态计时器、终止时的精确会话状态和精确的终止原因、有关将流量导向服务器的决策的信息,以及当然还有捕获任意标头信息的能力。为了提高管理员的响应速度,它提供了对遇到的内部和外部问题的极大透明度,并且可以与不同的级别过滤器一起将日志发送到不同的源:- 全局进程级日志(系统错误、启动/停止等)- 每个实例的系统和内部错误(资源不足、错误等)- 每个实例的外部问题(服务器在线/离线、最大连接数)- 每个实例的活动(客户端连接),无论是在建立时还是在终止时。- 每个请求的日志级别控制,例如:http-request set-log-level silent if sensitive_request 将不同级别的日志分发到不同的日志服务器,允许多个生产团队进行交互,并尽快修复他们的问题。例如,系统团队可以监控系统范围的错误,而应用程序团队可以实时监控其服务器的在线/离线状态,安全团队可以分析带有一小时延迟的活动日志。
可以记录 TCP 和 HTTP 连接的信息,例如日期、时间、源 IP 地址、目标地址、连接持续时间、响应时间、HTTP 请求、HTTP 返回码、传输的字节数、会话结束的条件,甚至交换的 cookie 值。例如,跟踪特定用户的问题。所有消息最多可以发送到两个 syslog 服务器。有关日志设施的更多信息,请查看 第 4.2 节 中的 "log" 关键字。
HAProxy 支持 5 种日志格式。这些格式之间有几个字段是通用的,将在以下部分详细介绍。其中一些字段可能会因配置的不同而略有变化,因为它们包含某些选项的特定指示符。支持的格式如下:- 默认格式,非常基本,很少使用。它只提供在接受传入连接时非常基本的信息:源 IP:端口、目标 IP:端口和前端名称。此模式最终将消失,因此不会进行详细描述。- TCP 格式,更高级。当在前端设置“option tcplog”时,将启用此格式。HAProxy 通常会等待连接终止后再进行日志记录。此格式提供了更丰富的信息,例如计时器、连接计数、队列大小等。此格式推荐用于纯 TCP 代理。- HTTP 格式,对于 HTTP 代理来说是最先进的。当在前端设置“option httplog”时,将启用此格式。它提供与 TCP 格式相同的信息,并包含一些 HTTP 特定字段,例如请求、状态码以及标头和 cookie 的捕获。此格式推荐用于 HTTP 代理。- CLF HTTP 格式,等同于 HTTP 格式,但字段顺序与 CLF 格式相同。在此模式下,所有计时器、捕获、标志等都会出现在通用字段末尾的每个字段中,顺序与标准 HTTP 格式相同。- 自定义日志格式,允许您创建自己的日志行。接下来的部分将详细介绍每种格式。格式的指定将基于“field”。除非另有说明,否则字段是分隔任意数量空格的文本部分。由于 syslog 服务器可能会在行首插入字段,因此始终假定第一个字段包含进程名称和标识符。注意:由于日志行可能非常长,以下部分的日志示例可能会分为多行。示例日志行将以 3 个闭合的尖括号(“>>>”)为前缀,每次日志分成多行时,非最终行将以反斜杠(“\”)结尾,下一行将缩进两个字符。
当没有设置特定选项时,使用此格式。日志在连接被接受后立即发出。需要注意的是,这目前是唯一记录请求目标 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 相同)。建议不要在新安装中使用此已弃用的格式,因为它最终会消失。当在前端指定“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
Field Format Extract from the example above 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 Detailed fields description : - "client_ip" is the IP address of the client which initiated the TCP connection to haproxy. If the connection was accepted on a UNIX socket instead, the IP address would be replaced with the word "unix". Note that when the connection is accepted on a socket configured with "accept-proxy" and the PROXY protocol is correctly used, or with a "accept-netscaler-cip" and the NetScaler Client IP insetion protocol is correctly used, then the logs will reflect the forwarded connection's information. - "client_port" is the TCP port of the client which initiated the connection. If the connection was accepted on a UNIX socket instead, the port would be replaced with the ID of the accepting socket, which is also reported in the stats interface. - "accept_date" is the exact date when the connection was received by haproxy (which might be very slightly different from the date observed on the network if there was some queuing in the system's backlog). This is usually the same date which may appear in any upstream firewall's log. - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "backend_name" is the name of the backend (or listener) which was selected to manage the connection to the server. This will be the same as the frontend if no switching rule has been applied, which is common for TCP applications. - "server_name" is the name of the last server to which the connection was sent, which might differ from the first one if there were connection errors and a redispatch occurred. Note that this server belongs to the backend which processed the request. If the connection was aborted before reaching a server, "<NOSRV>" is indicated instead of a server name. - "Tw" is the total time in milliseconds spent waiting in the various queues. It can be "-1" if the connection was aborted before reaching the queue. See "Timers" below for more details. - "Tc" is the total time in milliseconds spent waiting for the connection to establish to the final server, including retries. It can be "-1" if the connection was aborted before a connection could be established. See "Timers" below for more details. - "Tt" is the total time in milliseconds elapsed between the accept and the last close. It covers all possible processing. There is one exception, if "option logasap" was specified, then the time counting stops at the moment the log is emitted. In this case, a '+' sign is prepended before the value, indicating that the final one will be larger. See "Timers" below for more details. - "bytes_read" is the total number of bytes transmitted from the server to the client when the log is emitted. If "option logasap" is specified, the this value will be prefixed with a '+' sign indicating that the final one may be larger. Please note that this value is a 64-bit counter, so log analysis tools must be able to handle it without overflowing. - "termination_state" is the condition the session was in when the session ended. This indicates the session state, which side caused the end of session to happen, and for what reason (timeout, error, ...). The normal flags should be "--", indicating the session was closed by either end with no data remaining in buffers. See below "Session state at disconnection" for more details. - "actconn" is the total number of concurrent connections on the process when the session was logged. It is useful to detect when some per-process system limits have been reached. For instance, if actconn is close to 512 when multiple connection errors occur, chances are high that the system limits the process to use a maximum of 1024 file descriptors and that all of them are used. See section 3 "Global parameters" to find how to tune the system. - "feconn" is the total number of concurrent connections on the frontend when the session was logged. It is useful to estimate the amount of resource required to sustain high loads, and to detect when the frontend's "maxconn" has been reached. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "beconn" is the total number of concurrent connections handled by the backend when the session was logged. It includes the total number of concurrent connections active on servers as well as the number of connections pending in queues. It is useful to estimate the amount of additional servers needed to support high loads for a given application. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "srv_conn" is the total number of concurrent connections still active on the server when the session was logged. It can never exceed the server's configured "maxconn" parameter. If this value is very often close or equal to the server's "maxconn", it means that traffic regulation is involved a lot, meaning that either the server's maxconn value is too low, or that there aren't enough servers to process the load with an optimal response time. When only one of the server's "srv_conn" is high, it usually means that this server has some trouble causing the connections to take longer to be processed than on other servers. - "retries" is the number of connection retries experienced by this session when trying to connect to the server. It must normally be zero, unless a server is being stopped at the same moment the connection was attempted. Frequent retries generally indicate either a network problem between haproxy and the server, or a misconfigured system backlog on the server preventing new connections from being queued. This field may optionally be prefixed with a '+' sign, indicating that the session has experienced a redispatch after the maximal retry count has been reached on the initial server. In this case, the server name appearing in the log is the one the connection was redispatched to, and not the first one, though both may sometimes be the same in case of hashing for instance. So as a general rule of thumb, when a '+' is present in front of the retry count, this count should not be attributed to the logged server. - "srv_queue" is the total number of requests which were processed before this one in the server queue. It is zero when the request has not gone through the server queue. It makes it possible to estimate the approximate server's response time by dividing the time spent in queue by the number of requests in the queue. It is worth noting that if a session experiences a redispatch and passes through two server queues, their positions will be cumulated. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "backend_queue" is the total number of requests which were processed before this one in the backend's global queue. It is zero when the request has not gone through the global queue. It makes it possible to estimate the average queue length, which easily translates into a number of missing servers when divided by a server's "maxconn" parameter. It is worth noting that if a session experiences a redispatch, it may pass twice in the backend's queue, and then both positions will be cumulated. A request should not pass through both the server queue and the backend queue unless a redispatch occurs.
The HTTP format is the most complete and the best suited for HTTP proxies. It is enabled by when "option httplog" is specified in the frontend. It provides the same level of information as the TCP format with additional features which are specific to the HTTP protocol. Just like the TCP format, the log is usually emitted at the end of the session, unless "option logasap" is specified, which generally only makes sense for download sites. A session which matches the "monitor" rules will never logged. It is also possible not to log sessions for which no data were sent by the client by specifying "option dontlognull" in the frontend. Successful connections will not be logged if "option dontlog-normal" is specified in the frontend. Most fields are shared with the TCP log, some being different. A few fields may slightly vary depending on some configuration options. Those ones are marked with a star ('*') after the field name below.
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"
Field Format Extract from the example above 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" Detailed fields description : - "client_ip" is the IP address of the client which initiated the TCP connection to haproxy. If the connection was accepted on a UNIX socket instead, the IP address would be replaced with the word "unix". Note that when the connection is accepted on a socket configured with "accept-proxy" and the PROXY protocol is correctly used, or with a "accept-netscaler-cip" and the NetScaler Client IP insetion protocol is correctly used, then the logs will reflect the forwarded connection's information. - "client_port" is the TCP port of the client which initiated the connection. If the connection was accepted on a UNIX socket instead, the port would be replaced with the ID of the accepting socket, which is also reported in the stats interface. - "request_date" is the exact date when the first byte of the HTTP request was received by haproxy (log field %tr). - "frontend_name" is the name of the frontend (or listener) which received and processed the connection. - "backend_name" is the name of the backend (or listener) which was selected to manage the connection to the server. This will be the same as the frontend if no switching rule has been applied. - "server_name" is the name of the last server to which the connection was sent, which might differ from the first one if there were connection errors and a redispatch occurred. Note that this server belongs to the backend which processed the request. If the request was aborted before reaching a server, "<NOSRV>" is indicated instead of a server name. If the request was intercepted by the stats subsystem, "<STATS>" is indicated instead. - "TR" is the total time in milliseconds spent waiting for a full HTTP request from the client (not counting body) after the first byte was received. It can be "-1" if the connection was aborted before a complete request could be received or the a bad request was received. It should always be very small because a request generally fits in one single packet. Large times here generally indicate network issues between the client and haproxy or requests being typed by hand. See "Timers" below for more details. - "Tw" is the total time in milliseconds spent waiting in the various queues. It can be "-1" if the connection was aborted before reaching the queue. See "Timers" below for more details. - "Tc" is the total time in milliseconds spent waiting for the connection to establish to the final server, including retries. It can be "-1" if the request was aborted before a connection could be established. See "Timers" below for more details. - "Tr" is the total time in milliseconds spent waiting for the server to send a full HTTP response, not counting data. It can be "-1" if the request was aborted before a complete response could be received. It generally matches the server's processing time for the request, though it may be altered by the amount of data sent by the client to the server. Large times here on "GET" requests generally indicate an overloaded server. See "Timers" below for more details. - "Ta" is the time the request remained active in haproxy, which is the total time in milliseconds elapsed between the first byte of the request was received and the last byte of response was sent. It covers all possible processing except the handshake (see Th) and idle time (see Ti). There is one exception, if "option logasap" was specified, then the time counting stops at the moment the log is emitted. In this case, a '+' sign is prepended before the value, indicating that the final one will be larger. See "Timers" below for more details. - "status_code" is the HTTP status code returned to the client. This status is generally set by the server, but it might also be set by haproxy when the server cannot be reached or when its response is blocked by haproxy. - "bytes_read" is the total number of bytes transmitted to the client when the log is emitted. This does include HTTP headers. If "option logasap" is specified, the this value will be prefixed with a '+' sign indicating that the final one may be larger. Please note that this value is a 64-bit counter, so log analysis tools must be able to handle it without overflowing. - "captured_request_cookie" is an optional "name=value" entry indicating that the client had this cookie in the request. The cookie name and its maximum length are defined by the "capture cookie" statement in the frontend configuration. The field is a single dash ('-') when the option is not set. Only one cookie may be captured, it is generally used to track session ID exchanges between a client and a server to detect session crossing between clients due to application bugs. For more details, please consult the section "Capturing HTTP headers and cookies" below. - "captured_response_cookie" is an optional "name=value" entry indicating that the server has returned a cookie with its response. The cookie name and its maximum length are defined by the "capture cookie" statement in the frontend configuration. The field is a single dash ('-') when the option is not set. Only one cookie may be captured, it is generally used to track session ID exchanges between a client and a server to detect session crossing between clients due to application bugs. For more details, please consult the section "Capturing HTTP headers and cookies" below. - "termination_state" is the condition the session was in when the session ended. This indicates the session state, which side caused the end of session to happen, for what reason (timeout, error, ...), just like in TCP logs, and information about persistence operations on cookies in the last two characters. The normal flags should begin with "--", indicating the session was closed by either end with no data remaining in buffers. See below "Session state at disconnection" for more details. - "actconn" is the total number of concurrent connections on the process when the session was logged. It is useful to detect when some per-process system limits have been reached. For instance, if actconn is close to 512 or 1024 when multiple connection errors occur, chances are high that the system limits the process to use a maximum of 1024 file descriptors and that all of them are used. See section 3 "Global parameters" to find how to tune the system. - "feconn" is the total number of concurrent connections on the frontend when the session was logged. It is useful to estimate the amount of resource required to sustain high loads, and to detect when the frontend's "maxconn" has been reached. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "beconn" is the total number of concurrent connections handled by the backend when the session was logged. It includes the total number of concurrent connections active on servers as well as the number of connections pending in queues. It is useful to estimate the amount of additional servers needed to support high loads for a given application. Most often when this value increases by huge jumps, it is because there is congestion on the backend servers, but sometimes it can be caused by a denial of service attack. - "srv_conn" is the total number of concurrent connections still active on the server when the session was logged. It can never exceed the server's configured "maxconn" parameter. If this value is very often close or equal to the server's "maxconn", it means that traffic regulation is involved a lot, meaning that either the server's maxconn value is too low, or that there aren't enough servers to process the load with an optimal response time. When only one of the server's "srv_conn" is high, it usually means that this server has some trouble causing the requests to take longer to be processed than on other servers. - "retries" is the number of connection retries experienced by this session when trying to connect to the server. It must normally be zero, unless a server is being stopped at the same moment the connection was attempted. Frequent retries generally indicate either a network problem between haproxy and the server, or a misconfigured system backlog on the server preventing new connections from being queued. This field may optionally be prefixed with a '+' sign, indicating that the session has experienced a redispatch after the maximal retry count has been reached on the initial server. In this case, the server name appearing in the log is the one the connection was redispatched to, and not the first one, though both may sometimes be the same in case of hashing for instance. So as a general rule of thumb, when a '+' is present in front of the retry count, this count should not be attributed to the logged server. - "srv_queue" is the total number of requests which were processed before this one in the server queue. It is zero when the request has not gone through the server queue. It makes it possible to estimate the approximate server's response time by dividing the time spent in queue by the number of requests in the queue. It is worth noting that if a session experiences a redispatch and passes through two server queues, their positions will be cumulated. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "backend_queue" is the total number of requests which were processed before this one in the backend's global queue. It is zero when the request has not gone through the global queue. It makes it possible to estimate the average queue length, which easily translates into a number of missing servers when divided by a server's "maxconn" parameter. It is worth noting that if a session experiences a redispatch, it may pass twice in the backend's queue, and then both positions will be cumulated. A request should not pass through both the server queue and the backend queue unless a redispatch occurs. - "captured_request_headers" is a list of headers captured in the request due to the presence of the "capture request header" statement in the frontend. Multiple headers can be captured, they will be delimited by a vertical bar ('|'). When no capture is enabled, the braces do not appear, causing a shift of remaining fields. It is important to note that this field may contain spaces, and that using it requires a smarter log parser than when it's not used. Please consult the section "Capturing HTTP headers and cookies" below for more details. - "captured_response_headers" is a list of headers captured in the response due to the presence of the "capture response header" statement in the frontend. Multiple headers can be captured, they will be delimited by a vertical bar ('|'). When no capture is enabled, the braces do not appear, causing a shift of remaining fields. It is important to note that this field may contain spaces, and that using it requires a smarter log parser than when it's not used. Please consult the section "Capturing HTTP headers and cookies" below for more details. - "http_request" is the complete HTTP request line, including the method, request and HTTP version string. Non-printable characters are encoded (see below the section "Non-printable characters"). This is always the last field, and it is always delimited by quotes and is the only one which can contain quotes. If new fields are added to the log format, they will be added before this field. This field might be truncated if the request is huge and does not fit in the standard syslog buffer (1024 characters). This is the reason why this field must always remain the last one.The directive log-format allows you to customize the logs in http mode and tcp mode. It takes a string as argument. HAproxy understands some log format variables. % precedes log format variables. Variables can take arguments using braces ('{}'), and multiple arguments are separated by commas within the braces. Flags may be added or removed by prefixing them with a '+' or '-' sign. Special variable "%o" may be used to propagate its flags to all other variables on the same format string. This is particularly handy with quoted ("Q") and escaped ("E") string formats. If a variable is named between square brackets ('[' .. ']') then it is used as a sample expression rule (see section 7.3). This it useful to add some less common information such as the client's SSL certificate's DN, or to log the key that would be used to store an entry into a stick table. Note: spaces must be escaped. A space character is considered as a separator. In order to emit a verbatim '%', it must be preceded by another '%' resulting in '%%'. HAProxy will automatically merge consecutive separators. Note: when using the RFC5424 syslog message format, the characters '"', '\' and ']' inside PARAM-VALUE should be escaped with '\' as prefix (see https://tools.ietf.org/html/rfc5424#section-6.3.3 for more details). In such cases, the use of the flag "E" should be considered. Flags are : * Q: quote a string * X: hexadecimal representation (IPs, Ports, %Ts, %rt, %pid) * E: escape characters '"', '\' and ']' in a string with '\' as prefix (intended purpose is for the RFC5424 structured-data log formats)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 | field name (8.2.2 and 8.2.3 for description) | type | +---+------+-----------------------------------------------+-------------+ | | %o | special variable, apply flags on all next var | | +---+------+-----------------------------------------------+-------------+ | | %B | bytes_read (from server to client) | numeric | | H | %CC | captured_request_cookie | string | | H | %CS | captured_response_cookie | string | | | %H | hostname | string | | H | %HM | HTTP method (ex: POST) | string | | H | %HP | HTTP request URI without query string (path) | string | | H | %HQ | HTTP request URI query string (ex: ?bar=baz) | string | | H | %HU | HTTP request URI (ex: /foo?bar=baz) | string | | H | %HV | HTTP version (ex: HTTP/1.0) | string | | | %ID | unique-id | string | | | %ST | status_code | numeric | | | %T | gmt_date_time | date | | | %Ta | Active time of the request (from TR to end) | numeric | | | %Tc | Tc | numeric | | | %Td | Td = Tt - (Tq + Tw + Tc + Tr) | numeric | | | %Tl | local_date_time | date | | | %Th | connection handshake time (SSL, PROXY proto) | numeric | | H | %Ti | idle time before the HTTP request | numeric | | H | %Tq | Th + Ti + TR | numeric | | H | %TR | time to receive the full request from 1st byte| numeric | | H | %Tr | Tr (response time) | numeric | | | %Ts | timestamp | numeric | | | %Tt | Tt | numeric | | | %Tw | Tw | numeric | | | %U | bytes_uploaded (from client to server) | numeric | | | %ac | actconn | numeric | | | %b | backend_name | string | | | %bc | beconn (backend concurrent connections) | numeric | | | %bi | backend_source_ip (connecting address) | IP | | | %bp | backend_source_port (connecting address) | numeric | | | %bq | backend_queue | numeric | | | %ci | client_ip (accepted address) | IP | | | %cp | client_port (accepted address) | numeric | | | %f | frontend_name | string | | | %fc | feconn (frontend concurrent connections) | numeric | | | %fi | frontend_ip (accepting address) | IP | | | %fp | frontend_port (accepting address) | numeric | | | %ft | frontend_name_transport ('~' suffix for 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 (left-padded with 0) | numeric | | | %pid | PID | numeric | | H | %r | http_request | string | | | %rc | retries | numeric | | | %rt | request_counter (HTTP req or TCP session) | numeric | | | %s | server_name | string | | | %sc | srv_conn (server concurrent connections) | numeric | | | %si | server_IP (target address) | IP | | | %sp | server_port (target address) | numeric | | | %sq | srv_queue | numeric | | S | %sslc| ssl_ciphers (ex: AES-SHA) | string | | S | %sslv| ssl_version (ex: TLSv1) | string | | | %t | date_time (with millisecond resolution) | date | | H | %tr | date_time of HTTP request | date | | H | %trg | gmt_date_time of start of HTTP request | date | | H | %trl | local_date_time of start of HTTP request | date | | | %ts | termination_state | string | | H | %tsc | termination_state with cookie status | string | +---+------+-----------------------------------------------+-------------+ R = Restrictions : H = mode http only ; S = SSL only当传入连接因SSL握手或无效的PROXY协议头而失败时,haproxy将使用一个较短的固定行格式记录该事件。默认情况下,日志以LOG_INFO级别发出,除非在后端设置了选项"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 这些字段仅提供最少的信息来帮助调试连接故障。
一些高级日志记录选项经常被寻找,但仅通过查看各种选项不容易找到。这里是几个可以实现更好日志记录的选项的入口点。有关其用法的更多信息,请参考关键字参考。
拥有一些监控工具对haproxy进行健康检查是很常见的。有时会是像LVS这样的三层负载均衡器或任何商业负载均衡器,有时则只是像Nagios这样的更完整的监控系统。当测试非常频繁时,用户经常会问如何禁用对这些检查的日志记录。有三种可能性: - 如果连接来自各处并且只是TCP探针,通常希望通过在前端设置"option dontlognull"来禁用没有数据交换的连接的日志记录。这也会禁用端口扫描的日志记录,这可能是有益的,也可能不是。 - 如果连接来自已知的源网络,请使用"monitor-net"将此网络声明为仅用于监控。此网络中的任何主机将只能执行健康检查,并且不会记录其请求。这通常适用于指定一组设备,例如其他负载均衡器。 - 如果在已知的URI上执行测试,请使用"monitor-uri"将此URI声明为专用于监控。发送此请求的任何主机将仅获得健康检查的结果,并且不会记录请求。
在连接结束时记录日志的问题在于,对于很长的会话,如远程终端会话或大文件下载,您无从得知期间发生了什么。可以通过在前端指定"option logasap"来解决此问题。Haproxy将尽快记录日志,就在数据传输开始之前。这意味着,在TCP的情况下,它仍会记录连接状态到服务器,在HTTP的情况下,它将在处理完服务器头信息后立即记录。在这种情况下,报告的字节数是发送给客户端的头字节数。为了避免与正常日志混淆,总时间字段和字节数都带有'+'符号前缀,这意味着实际数字肯定更大。
有时,将正常流量与错误日志分开会更方便,例如,为了简化从日志文件中监控错误。当使用 "log-separate-errors" 选项时,遇到错误、超时、重试、重新分派或 HTTP 状态码为 5xx 的连接,其 syslog 级别将从 "info" 提高到 "err"。这将帮助 syslog 守护进程将日志存储在一个单独的文件中。将错误也保留在正常流量文件中非常重要,这样日志顺序就不会改变。如果您已经配置了 syslog 守护进程将所有高于 "notice" 的日志存储在 "admin" 文件中,您也应该小心,因为 "err" 级别高于 "notice"。
虽然这乍听起来可能很奇怪,但一些大型站点必须处理每秒数千条日志,并且在长时间保持其完整性或在其中检测错误方面遇到困难。如果在前端设置了 "dontlog-normal" 选项,所有正常的连接都不会被记录。在这方面,正常连接定义为没有任何错误、超时、重试或重新分派的连接。在 HTTP 中,状态码也会被检查,状态为 5xx 的响应不被认为是正常的,也会被记录。当然,这样做是强烈不鼓励的,因为它会从日志中删除大部分有用的信息。只有在没有其他选择的情况下才这样做。
计时器在排查网络问题时非常有用。所有值均以毫秒 (ms) 为单位报告。这些计时器应与会话终止标志结合使用。在 TCP 模式下,当在前端设置了“option tcplog”时,会以“Tw/Tc/Tt”的形式报告 3 个控制点;在 HTTP 模式下,会以“TR/Tw/Tc/Tr/Ta”的形式报告 5 个控制点。此外,还提供了另外三个度量:“Th”、“Ti”和“Tq”。HTTP 模式下的计时事件:第一次请求 第二次请求 |<-------------------------------->|<-------------- ... t tr t tr ... ---|----|----|----|----|----|----|----|----|-- : Th Ti TR Tw Tc Tr Td : Ti ... :<---- Tq ---->: : :<-------------- Tt -------------->: :<--------- Ta --------->: TCP 模式下的计时事件:TCP 会话 |<----------------->| t t ---|----|----|----|----|--- | Th Tw Tc Td | |<------ Tt ------->| - Th:接受 TCP 连接并执行低级协议握手所花费的总时间。目前,这些协议是 proxy-protocol 和 SSL。这在整个连接生命周期中可能只发生一次。此处时间过长可能表示客户端仅预先建立了连接而未进行通信,或者客户端正在经历网络问题,导致其无法在合理时间内完成握手(例如:MTU 问题),或者 SSL 握手计算成本非常高。 - Ti:HTTP 请求前的空闲时间(仅 HTTP 模式)。此计时器在握手结束和 HTTP 请求的第一个字节之间计数。在 Keep-Alive 模式下处理第二个请求时,它在传输完上一个响应结束后开始计数。一些浏览器会预先建立与服务器的连接,以减少未来请求的延迟,并保持连接挂起直到它们需要时。此延迟将报告为空闲时间。值为 -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”表示从未看到过最后一个响应标头(空行),最可能是因为服务器在服务器成功处理请求之前就超时了。 - Ta:HTTP 请求的总活动时间,介于代理接收到请求标头的第一个字节和响应主体的最后一个字节发出之间。例外情况是当指定了“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)。这些计时器提供了有关故障原因的宝贵线索。由于 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”设置。
TCP and HTTP logs provide a session termination indicator in the "termination_state" field, just before the number of active connections. It is 2-characters long in TCP mode, and is extended to 4 characters in HTTP mode, each of which has a special meaning : - On the first character, a code reporting the first event which caused the session to terminate : C : the TCP session was unexpectedly aborted by the client. S : the TCP session was unexpectedly aborted by the server, or the server explicitly refused it. P : the session was prematurely aborted by the proxy, because of a connection limit enforcement, because a DENY filter was matched, because of a security check which detected and blocked a dangerous error in server response which might have caused information leak (eg: cacheable cookie). L : the session was locally processed by haproxy and was not passed to a server. This is what happens for stats and redirects. R : a resource on the proxy has been exhausted (memory, sockets, source ports, ...). Usually, this appears during the connection phase, and system logs should contain a copy of the precise error. If this happens, it must be considered as a very serious anomaly which should be fixed as soon as possible by any means. I : an internal error was identified by the proxy during a self-check. This should NEVER happen, and you are encouraged to report any log containing this, because this would almost certainly be a bug. It would be wise to preventively restart the process after such an event too, in case it would be caused by memory corruption. D : the session was killed by haproxy because the server was detected as down and was configured to kill all connections when going down. U : the session was killed by haproxy on this backup server because an active server was detected as up and was configured to kill all backup connections when going up. K : the session was actively killed by an admin operating on haproxy. c : the client-side timeout expired while waiting for the client to send or receive data. s : the server-side timeout expired while waiting for the server to send or receive data. - : normal session completion, both the client and the server closed with nothing left in the buffers. - on the second character, the TCP or HTTP session state when it was closed : R : the proxy was waiting for a complete, valid REQUEST from the client (HTTP mode only). Nothing was sent to any server. Q : the proxy was waiting in the QUEUE for a connection slot. This can only happen when servers have a 'maxconn' parameter set. It can also happen in the global queue after a redispatch consecutive to a failed attempt to connect to a dying server. If no redispatch is reported, then no connection attempt was made to any server. C : the proxy was waiting for the CONNECTION to establish on the server. The server might at most have noticed a connection attempt. H : the proxy was waiting for complete, valid response HEADERS from the server (HTTP only). D : the session was in the DATA phase. L : the proxy was still transmitting LAST data to the client while the server had already finished. This one is very rare as it can only happen when the client dies while receiving the last packets. T : the request was tarpitted. It has been held open with the client during the whole "timeout tarpit" duration or until the client closed, both of which will be reported in the "Tw" timer. - : normal session completion after end of data transfer. - the third character tells whether the persistence cookie was provided by the client (only in HTTP mode) : N : the client provided NO cookie. This is usually the case for new visitors, so counting the number of occurrences of this flag in the logs generally indicate a valid trend for the site frequentation. I : the client provided an INVALID cookie matching no known server. This might be caused by a recent configuration change, mixed cookies between HTTP/HTTPS sites, persistence conditionally ignored, or an attack. D : the client provided a cookie designating a server which was DOWN, so either "option persist" was used and the client was sent to this server, or it was not set and the client was redispatched to another server. V : the client provided a VALID cookie, and was sent to the associated server. E : the client provided a valid cookie, but with a last date which was older than what is allowed by the "maxidle" cookie parameter, so the cookie is consider EXPIRED and is ignored. The request will be redispatched just as if there was no cookie. O : the client provided a valid cookie, but with a first date which was older than what is allowed by the "maxlife" cookie parameter, so the cookie is consider too OLD and is ignored. The request will be redispatched just as if there was no cookie. U : a cookie was present but was not used to select the server because some other server selection mechanism was used instead (typically a "use-server" rule). - : does not apply (no cookie set in configuration). - the last character reports what operations were performed on the persistence cookie returned by the server (only in HTTP mode) : N : NO cookie was provided by the server, and none was inserted either. I : no cookie was provided by the server, and the proxy INSERTED one. Note that in "cookie insert" mode, if the server provides a cookie, it will still be overwritten and reported as "I" here. U : the proxy UPDATED the last date in the cookie that was presented by the client. This can only happen in insert mode with "maxidle". It happens every time there is activity at a different date than the date indicated in the cookie. If any other change happens, such as a redispatch, then the cookie will be marked as inserted instead. P : a cookie was PROVIDED by the server and transmitted as-is. R : the cookie provided by the server was REWRITTEN by the proxy, which happens in "cookie rewrite" or "cookie prefix" modes. D : the cookie provided by the server was DELETED by the proxy. - : does not apply (no cookie set in configuration). The combination of the two first flags gives a lot of information about what was happening when the session terminated, and why it did terminate. It can be helpful to detect server saturation, network troubles, local system resource starvation, attacks, etc... The most common termination flags combinations are indicated below. They are alphabetically sorted, with the lowercase set just after the upper case for easier finding and understanding. Flags Reason -- Normal termination. CC The client aborted before the connection could be established to the server. This can happen when haproxy tries to connect to a recently dead (or unchecked) server, and the client aborts while haproxy is waiting for the server to respond or for "timeout connect" to expire. CD The client unexpectedly aborted during data transfer. This can be caused by a browser crash, by an intermediate equipment between the client and haproxy which decided to actively break the connection, by network routing issues between the client and haproxy, or by a keep-alive session between the server and the client terminated first by the client. cD The client did not send nor acknowledge any data for as long as the "timeout client" delay. This is often caused by network failures on the client side, or the client simply leaving the net uncleanly. CH The client aborted while waiting for the server to start responding. It might be the server taking too long to respond or the client clicking the 'Stop' button too fast. cH The "timeout client" stroke while waiting for client data during a POST request. This is sometimes caused by too large TCP MSS values for PPPoE networks which cannot transport full-sized packets. It can also happen when client timeout is smaller than server timeout and the server takes too long to respond. CQ The client aborted while its session was queued, waiting for a server with enough empty slots to accept it. It might be that either all the servers were saturated or that the assigned server was taking too long a time to respond. CR The client aborted before sending a full HTTP request. Most likely the request was typed by hand using a telnet client, and aborted too early. The HTTP status code is likely a 400 here. Sometimes this might also be caused by an IDS killing the connection between haproxy and the client. "option http-ignore-probes" can be used to ignore connections without any data transfer. cR The "timeout http-request" stroke before the client sent a full HTTP request. This is sometimes caused by too large TCP MSS values on the client side for PPPoE networks which cannot transport full-sized packets, or by clients sending requests by hand and not typing fast enough, or forgetting to enter the empty line at the end of the request. The HTTP status code is likely a 408 here. Note: recently, some browsers started to implement a "pre-connect" feature consisting in speculatively connecting to some recently visited web sites just in case the user would like to visit them. This results in many connections being established to web sites, which end up in 408 Request Timeout if the timeout strikes first, or 400 Bad Request when the browser decides to close them first. These ones pollute the log and feed the error counters. Some versions of some browsers have even been reported to display the error code. It is possible to work around the undesirable effects of this behaviour by adding "option http-ignore-probes" in the frontend, resulting in connections with zero data transfer to be totally ignored. This will definitely hide the errors of people experiencing connectivity issues though. CT The client aborted while its session was tarpitted. It is important to check if this happens on valid requests, in order to be sure that no wrong tarpit rules have been written. If a lot of them happen, it might make sense to lower the "timeout tarpit" value to something closer to the average reported "Tw" timer, in order not to consume resources for just a few attackers. LR The request was intercepted and locally handled by haproxy. Generally it means that this was a redirect or a stats request. SC The server or an equipment between it and haproxy explicitly refused the TCP connection (the proxy received a TCP RST or an ICMP message in return). Under some circumstances, it can also be the network stack telling the proxy that the server is unreachable (eg: no route, or no ARP response on local network). When this happens in HTTP mode, the status code is likely a 502 or 503 here. sC The "timeout connect" stroke before a connection to the server could complete. When this happens in HTTP mode, the status code is likely a 503 or 504 here. SD The connection to the server died with an error during the data transfer. This usually means that haproxy has received an RST from the server or an ICMP message from an intermediate equipment while exchanging data with the server. This can be caused by a server crash or by a network issue on an intermediate equipment. sD The server did not send nor acknowledge any data for as long as the "timeout server" setting during the data phase. This is often caused by too short timeouts on L4 equipments before the server (firewalls, load-balancers, ...), as well as keep-alive sessions maintained between the client and the server expiring first on haproxy. SH The server aborted before sending its full HTTP response headers, or it crashed while processing the request. Since a server aborting at this moment is very rare, it would be wise to inspect its logs to control whether it crashed and why. The logged request may indicate a small set of faulty requests, demonstrating bugs in the application. Sometimes this might also be caused by an IDS killing the connection between haproxy and the server. sH The "timeout server" stroke before the server could return its response headers. This is the most common anomaly, indicating too long transactions, probably caused by server or database saturation. The immediate workaround consists in increasing the "timeout server" setting, but it is important to keep in mind that the user experience will suffer from these long response times. The only long term solution is to fix the application. sQ The session spent too much time in queue and has been expired. See the "timeout queue" and "timeout connect" settings to find out how to fix this if it happens too often. If it often happens massively in short periods, it may indicate general problems on the affected servers due to I/O or database congestion, or saturation caused by external attacks. PC The proxy refused to establish a connection to the server because the process' socket limit has been reached while attempting to connect. The global "maxconn" parameter may be increased in the configuration so that it does not happen anymore. This status is very rare and might happen when the global "ulimit-n" parameter is forced by hand. PD The proxy blocked an incorrectly formatted chunked encoded message in a request or a response, after the server has emitted its headers. In most cases, this will indicate an invalid message from the server to the client. Haproxy supports chunk sizes of up to 2GB - 1 (2147483647 bytes). Any larger size will be considered as an error. PH The proxy blocked the server's response, because it was invalid, incomplete, dangerous (cache control), or matched a security filter. In any case, an HTTP 502 error is sent to the client. One possible cause for this error is an invalid syntax in an HTTP header name containing unauthorized characters. It is also possible but quite rare, that the proxy blocked a chunked-encoding request from the client due to an invalid syntax, before the server responded. In this case, an HTTP 400 error is sent to the client and reported in the logs. PR The proxy blocked the client's HTTP request, either because of an invalid HTTP syntax, in which case it returned an HTTP 400 error to the client, or because a deny filter matched, in which case it returned an HTTP 403 error. PT The proxy blocked the client's request and has tarpitted its connection before returning it a 500 server error. Nothing was sent to the server. The connection was maintained open for as long as reported by the "Tw" timer field. RC A local resource has been exhausted (memory, sockets, source ports) preventing the connection to the server from establishing. The error logs will tell precisely what was missing. This is very rare and can only be solved by proper system tuning. The combination of the two last flags gives a lot of information about how persistence was handled by the client, the server and by haproxy. This is very important to troubleshoot disconnections, when users complain they have to re-authenticate. The commonly encountered flags are : -- Persistence cookie is not enabled. NN No cookie was provided by the client, none was inserted in the response. For instance, this can be in insert mode with "postonly" set on a GET request. II A cookie designating an invalid server was provided by the client, a valid one was inserted in the response. This typically happens when a "server" entry is removed from the configuration, since its cookie value can be presented by a client when no other server knows it. NI No cookie was provided by the client, one was inserted in the response. This typically happens for first requests from every user in "insert" mode, which makes it an easy way to count real users. VN A cookie was provided by the client, none was inserted in the response. This happens for most responses for which the client has already got a cookie. VU A cookie was provided by the client, with a last visit date which is not completely up-to-date, so an updated cookie was provided in response. This can also happen if there was no date at all, or if there was a date but the "maxidle" parameter was not set, so that the cookie can be switched to unlimited time. EI A cookie was provided by the client, with a last visit date which is too old for the "maxidle" parameter, so the cookie was ignored and a new cookie was inserted in the response. OI A cookie was provided by the client, with a first visit date which is too old for the "maxlife" parameter, so the cookie was ignored and a new cookie was inserted in the response. DI The server designated by the cookie was down, a new server was selected and a new cookie was emitted in the response. VI The server designated by the cookie was not marked dead but could not be reached. A redispatch happened and selected another one, which was then advertised in the response.
为了在查阅日志时避免给日志分析工具或终端带来麻烦,不可打印的字符不会按原样发送到日志文件中,而是会转换为其 ASCII 码的两位十六进制表示,并以字符“#”为前缀。唯一可以不经转义直接记录的字符范围是 32 到 126(含)。显然,转义字符“#”本身也会被编码以避免任何歧义(“#23”)。字符“"”也是如此,它会变成“#22”,以及在记录头时,“{”、“|”和“}”也是如此。请注意,空格字符(' ')在头中不被编码,这可能会给依赖空格计数来定位字段的工具带来问题。一个包含空格的典型头是“User-Agent”。最后,据观察,一些 syslog 守护进程(如 syslog-ng)会用反斜杠('\')来转义引号('\"')。可以安全地执行反向操作,因为日志中其他任何地方都不会出现引号。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
标头捕获有助于跟踪上级代理设置的唯一请求标识符、虚拟主机名、用户代理、POST 内容长度、引荐来源等。在响应中,可以搜索有关响应长度、服务器如何指示缓存行为或重定向期间的对象位置的信息。标头捕获使用前端的“capture request header”和“capture response header”语句执行。有关更多详细信息,请参阅 第 4.2 节中的定义。可以同时包含请求标头和响应标头。不存在的标头会记录为空字符串,如果一个标头出现多次,则只记录其最后一次出现。请求标头用大括号“{”和“}”括起来,顺序与声明时相同,并用竖线“|”分隔,中间不带空格。响应标头遵循相同的表示方法,但在请求标头块之后显示一个空格。这些块显示在日志中的 HTTP 请求之前。作为特殊情况,可以在 TCP 前端指定 HTTP 标头捕获。目的是允许记录将在 HTTP 后端解析的标头,如果请求随后切换到此 HTTP 后端。
# 此实例链接到出站代理 listen proxy-out mode http option httplog option logasap log global server cache1 192.168.1.1:3128 # 记录虚拟服务器的名称 capture request header Host len 20 # 记录 POST 期间上传的数据量 capture request header Content-Length len 10 # 记录引荐来源的开头 capture request header Referer len 20 # 服务器名称(仅对出站代理有用) capture response header Server len 20 # 记录 content-length 对于“option logasap”很有用 capture response header Content-Length len 10 # 记录响应中预期的缓存行为 capture response header Cache-Control len 8 # Via 标头将报告下一个代理的名称 capture response header Via len 20 # 记录重定向期间的 URL 位置 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"
这些是带解释的真实日志示例。其中一些是手动编写的。为了便于阅读,已删除 syslog 部分。它们唯一的目的是解释如何解读它们。 >>> 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" => 长请求(6.5 秒)通过 'telnet' 手动输入。服务器在 147 毫秒内响应,会话正常结束('----') >>> 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" => 同上,但请求在全局队列中等待了 1230 毫秒,排在其他 9 个请求后面。 >>> 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" => 请求长数据传输。“logasap”选项被指定,因此日志在传输数据之前生成。服务器在 14 毫秒内响应,243 字节的头部被发送到客户端,从接受到第一个数据字节的总时间是 30 毫秒。 >>> 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" => 代理阻止了服务器响应,原因可能是“rspdeny”或“rspideny”过滤器,或者响应格式不正确且不符合 HTTP 标准,或者它阻止了可能被缓存的敏感信息。在这种情况下,响应被“502 bad gateway”替换。标志(“PH--”)告诉我们是 haproxy 决定返回 502,而不是服务器。 >>> 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 "" => 客户端从未完成其请求,并在 8.5 秒后自行中止(“C---”),而代理正在等待请求头部(“-R--”)。没有发送任何东西给任何服务器。 >>> 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 "" => 客户端从未完成其请求,该请求在 50 秒后因超时(“c---”)而被中止,而代理正在等待请求头部(“-R--”)。没有发送任何东西给任何服务器,但代理可以向客户端发送 408 返回码。 >>> 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 => 此日志是用“option tcplog”生成的。客户端在 5 秒后超时(“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" => 请求花费 3 秒完成(可能是网络问题),并且连接到服务器失败('SC--'),在 4 次尝试(每次 2 秒)后失败(配置显示为 'retries 3'),并且没有重新分派(否则我们会看到“/+3”)。状态码 503 被返回给客户端。此服务器上有 115 个连接,此代理上有 202 个连接,全局进程上有 205 个连接。服务器可能因为已有太多已建立的连接而拒绝了连接。
此处列出了官方支持的过滤器及其接受的参数。根据编译选项,其中一些过滤器可能不可用。可用过滤器的列表将在 haproxy -vv 中报告。
<name> 是将在消息中报告的任意名称。如果未提供名称,“TRACE”将被使用。“”启用客户端和服务器之间交换数据的随机解析。默认情况下,此过滤器解析所有可用数据。使用此参数,它仅解析可用数据的随机数量。“ ”启用解析数据的随机转发。默认情况下,此过滤器转发所有先前解析的数据。使用此参数,它仅转发解析数据的随机数量。“ ”将所有转发的数据转储到服务器和客户端。
此过滤器可用作开发新过滤器的基础。它定义了所有回调,并在标准错误流(stderr)上打印一条包含所有回调有用信息的消息。调试其他过滤器活动或 HAProxy 本身活动时可能很有用。使用 <;random-parsing> 和/或 <;random-forwarding> 参数是通过在处理中增加延迟来测试解析客户端和服务器之间交换数据的过滤器行为的好方法。
HAProxy 1.7 中已将 HTTP 压缩移至过滤器。“compression”关键字仍必须用于启用和配置 HTTP 压缩。当没有其他过滤器使用时,这已足够。但是,当为同一个监听器/前端/后端使用两个或多个过滤器时,必须显式使用过滤器行来启用 HTTP 压缩。了解过滤器的评估顺序非常重要。
<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.
流处理卸载引擎 (SPOE) 是一个与外部组件通信的过滤器。它允许在第三方应用程序的流上卸载一些特定的处理。这些外部组件以及与它们交换的信息大部分在专用文件中进行配置。它还需要在 HAProxy 配置中定义的专用后端。SPOE 使用专有二进制协议 Stream Processing Offload Protocol (SPOP) 与外部组件通信。有关 SPOE 配置和 SPOP 规范的所有信息,请参阅“doc/SPOE.txt”。重要提示:SPOE 过滤器目前高度实验性,未经大量测试。它远未达到生产就绪状态。请谨慎使用。