本文档涵盖了上述版本中实现的配置语言。它不提供任何提示、示例或建议。有关此类文档,请参阅参考手册或架构手册。以下摘要旨在帮助您按名称查找章节并在文档中导航。文档贡献者须知:本文档每行格式化为80列,使用偶数个空格进行缩进,不使用制表符。请严格遵守这些规则,以便在任何地方都能轻松打印。如果某行需要逐字打印且不适合,请在每行末尾加上反斜杠('\'),并在下一行继续,缩进两个字符。有时,为了强调输入和输出之间的差异,当它们可能模糊不清时,用三个闭合尖括号('>>>')作为所有输出行(日志、控制台输出)的前缀也很有用。如果添加新章节,请更新下面的摘要以便于搜索。
| 1. | 关于 HTTP 的快速提醒 | |
| 1.1. | ||
| 1.2. | ||
| 1.2.1. | ||
| 1.2.2. | ||
| 1.3. | ||
| 1.3.1. | ||
| 1.3.2. | ||
2. |
配置 HAProxy | |
| 2.1. | ||
| 2.2. | ||
| 2.3. | ||
| 2.4. | ||
| 2.5. | ||
3. |
全局参数 | |
| 3.1. | ||
| 3.2. | ||
| 3.3. | ||
| 3.4. | ||
| 3.5. | ||
| 3.6. | ||
| 3.7. | ||
4. |
代理 | |
| 4.1. | ||
| 4.2. | ||
5. |
绑定和服务器选项 | |
| 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. | ||
| 9.4. | ||
10. |
缓存 | |
| 10.1. | ||
| 10.2. | ||
| 10.2.1. | ||
| 10.2.2. |
当 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中没有办法将响应与相应的请求关联起来。因此,服务器必须以与请求接收到的顺序完全相同的顺序进行回复。下一个改进是多路复用模式,如HTTP/2中实现的。这一次,每个事务都被分配一个唯一的流标识符,并且所有流都通过现有连接进行多路复用。客户端可以并行发送许多请求,并且响应可以按任何顺序到达,因为它们也带有流标识符。默认情况下,HAProxy在持久连接方面以keep-alive模式运行:对于每个连接,它处理每个请求和响应,并在响应结束和新请求开始之间在双方空闲连接。当它从客户端接收HTTP/2连接时,它会并行处理所有请求,并使连接保持空闲,等待新请求,就像它是keep-alive HTTP连接一样。HAProxy支持4种连接模式:- keep alive:处理所有请求和响应(默认)- tunnel:仅处理第一个请求和响应,其余全部转发,无分析(已弃用)。- server close:面向服务器的连接将在响应后关闭。- 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中,识别出两个子部分。问号前面的部分称为“path”。它通常是服务器上静态对象的相对路径。问号后面的部分称为“查询字符串”。它主要与发送到动态脚本的GET请求一起使用,并且非常具体于所使用的语言、框架或应用程序。HTTP/2不随请求传递版本信息,因此假定版本与底层协议的版本相同(即“HTTP/2”)。
头部从第二行开始。它们由行开头的名称组成,后面紧跟着一个冒号(“:”)。传统上,冒号后会添加一个LWS,但这不是必需的。然后是值。多个相同的头部可以折叠成一行,用逗号分隔值,前提是它们的顺序得到尊重。这通常在“Cookie:”字段中遇到。如果后续行的开头是LWS,则头部可以跨越多行。在1.2的示例中,第4行和第5行定义了“Accept:”头部的总共3个值。与普遍的误解相反,头部名称不区分大小写,并且当它们引用其他头部名称时(如“Connection:”头部),它们的值也不区分大小写。在HTTP/2中,头部名称始终以小写形式发送,就像在调试模式下运行时一样。在内部,所有头部名称都标准化为小写,以便HTTP/1.x和HTTP/2使用完全相同的表示,并且它们按原样发送到另一端。这解释了为什么键入驼峰式大小写的HTTP/1.x请求以小写形式传递。头部结束由第一个空行指示。人们经常说它是双换行符,这是不准确的,即使双换行符是一种有效的空行形式。幸运的是,HAProxy在索引头部、检查值和计数时会处理所有这些复杂的组合,因此没有理由担心它们可能的书写方式,但不要因为应用程序执行了不寻常但有效的事情而指责它存在缺陷。重要提示:根据RFC7231的建议,HAProxy通过在头部中间替换换行符为LWS来规范化头部,以便连接多行头部。这对于正确分析至关重要,并有助于能力较弱的HTTP解析器正常工作,并且不会被这种复杂的结构欺骗。
HTTP响应在外观上与HTTP请求非常相似。两者都被称为HTTP消息。我们来看这个HTTP响应:行 内容编号1 HTTP/1.1 200 OK2 Content-length: 3503 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”过滤器禁止的请求时404 请求的资源未找到时408 请求超时,在请求完成之前发生410 请求的资源不再可用且不会再次可用时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"
一些变量由 HAProxy 定义,它们可以在配置文件中使用,或者可以被程序继承(参见 3.7. 程序): * HAPROXY_LOCALPEER:在进程启动时定义,包含本地对等体的名称。(参见管理指南中的 "-L"。) * HAPROXY_CFGFILES:由 HAProxy 加载的配置文件列表,以分号分隔。如果您指定了一个目录,这可能很有用。 * HAPROXY_MWORKER:在主-工作者模式下,此变量设置为 1。 * HAPROXY_CLI:为每个进程配置的统计套接字的监听地址,以分号分隔。 * HAPROXY_MASTER_CLI:在主-工作者模式下,主 CLI 的监听地址,以分号分隔。另请参见“external-check command”了解其他变量。
一些参数涉及表示时间的值,例如超时。这些值通常以毫秒表示(除非另有明确说明),但也可以通过在数值后附加单位来以任何其他单位表示。考虑这一点很重要,因为每个关键字都不会重复说明。支持的单位有:- 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 - h1-case-adjust - h1-case-adjust-file - log - log-tag - log-send-hostname - lua-load - mworker-max-reloads - nbproc - nbthread - node - pidfile - presetenv - resetenv - uid - ulimit-n - user - set-dumpable - setenv - stats - ssl-default-bind-ciphers - ssl-default-bind-ciphersuites - ssl-default-bind-options - ssl-default-server-ciphers - ssl-default-server-ciphersuites - 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-cache-size * 性能调优 - max-spread-checks - maxconn - maxconnrate - maxcomprate - maxcompcpuusage - maxpipes - maxsessrate - maxsslconn - maxsslrate - maxzlibmem - noepoll - nokqueue - noevports - nopoll - nosplice - nogetaddrinfo - noreuseport - profiling.tasks - spread-checks - server-state-base - server-state-file - ssl-engine - ssl-mode-async - tune.buffers.limit - tune.buffers.reserve - tune.bufsize - tune.chksize - tune.comp.maxlevel - tune.h2.header-table-size - tune.h2.initial-window-size - tune.h2.max-concurrent-streams - tune.h2.max-frame-size - tune.http.cookielen - tune.http.logurilen - tune.http.maxhdr - tune.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.pool-high-fd-ratio - tune.pool-low-fd-ratio - tune.rcvbuf.client - tune.rcvbuf.server - tune.recv_enough - tune.runqueue-depth - 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.ssl.capture-cipherlist-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”。
在降低权限之前,将当前目录更改为 <jail dir> 并在那里执行 chroot()。这提高了安全级别,以防未知漏洞被利用,因为它会使攻击者很难利用系统。这仅在进程以超级用户权限启动时有效。确保 <jail_dir> 既为空又对任何人不可写非常重要。
在 Linux 2.6 及更高版本上,可以将进程或线程绑定到特定的 CPU 集合。这意味着该进程或线程永远不会在其他 CPU 上运行。“cpu-map”指令指定进程或线程集的 CPU 集合。第一个参数是进程集,后面可以跟线程集。这些集合的格式为 all | odd | even | number[-[number]]。必须是 1 到 32 或 64 之间的数字,具体取决于机器的字长。任何大于 nbproc 的进程 ID 和任何大于 nbthread 的线程 ID 都将被忽略。可以使用两个由连字符(“-”)分隔的数字指定一个范围。还可以使用“all”指定所有进程,“odd”指定奇数,“even”指定偶数,就像使用“bind-process”指令一样。第二个及后续参数是 CPU 集合。每个 CPU 集合要么是 0 到 31 或 63 之间的唯一数字,要么是由两个由连字符(“-”)分隔的数字组成的范围。可以指定多个 CPU 数字或范围,并且进程或线程将被允许绑定到所有这些 CPU。显然,可以指定多个“cpu-map”指令。每个“cpu-map”指令将在它们重叠时替换之前的指令。线程将被绑定到其映射与它所附加的进程的映射的交集。如果交集为空,则不会为该线程设置特定绑定。范围可以部分定义。最高边界可以省略。在这种情况下,它将被相应的最大值(32 或 64,取决于机器的字长)替换。前缀“auto:”可以添加到进程集之前,让 HAProxy 通过递增进程/线程和 CPU 集合来自动将进程或线程绑定到 CPU。为使之有效,两个集合的大小必须相同。无论 CPU 集合的声明顺序如何,它都将从最低边界绑定到最高边界。使用“auto:”前缀的进程和线程范围不支持。只支持一个范围,另一个必须是固定数字。
cpu-map 1-4 0-3 # 将进程 1 到 4 绑定到前 4 个 CPU cpu-map 1/all 0-3 # 将第一个进程的所有线程绑定到 # 前 4 个 CPU cpu-map 1- 0- # 将被替换为“cpu-map 1-64 0-63” # 或“cpu-map 1-32 0-31”,具体取决于机器的 # 字长。 # 所有这些行将进程 1 绑定到 CPU 0,进程 2 绑定到 CPU 1 # 等等。 cpu-map auto:1-4 0-3 cpu-map auto:1-4 0-1 2-3 cpu-map auto:1-4 3 2 1 0 # 所有这些行将线程 1 绑定到 CPU 0,线程 2 绑定到 CPU 1 # 等等。 cpu-map auto:1/1-4 0-3 cpu-map auto:1/1-4 0-1 2-3 cpu-map auto:1/1-4 3 2 1 0 # 使用 all/odd/even 关键字将每个进程绑定到精确一个 CPU cpu-map auto:all 0-63 cpu-map auto:even 0-31 cpu-map auto:odd 32-63 # 无效的 cpu-map,因为进程和 CPU 集合的大小不同。 cpu-map auto:1-4 0 # 无效 cpu-map auto:1 0-3 # 无效 # 无效的 cpu-map,因为自动绑定用于进程范围 # 和线程范围。 cpu-map auto:all/all 0 # 无效 cpu-map auto:all/1-4 0 # 无效 cpu-map auto:1-4/all 0 # 无效
当使用 "crtfile" 指令的相对路径时,分配一个用于获取 SSL 证书的默认目录。"crtfile" 后面指定的绝对位置优先,并忽略 "crt-base"。
使进程 fork 到后台运行。这是推荐的操作模式。它等同于命令行参数 "-D"。它可以通过命令行参数 "-db" 禁用。此选项在 systemd 模式下被忽略。
设置要由 API 加载的 DeviceAtlas JSON 数据文件的路径。该路径必须是一个有效的 JSON 数据文件,并且 HAProxy 进程可以访问。
设置 API 返回的信息级别。此指令是可选的,如果未设置,则默认为 0。
设置 API 属性结果的字符分隔符。此指令是可选的,如果未设置,则默认为 |。
设置用于检测请求期间是否使用了 DeviceAtlas 客户端组件的客户端 cookie 名称。此指令是可选的,如果未设置,则默认为 DAPROPS。
允许使用外部代理执行健康检查。作为安全预防措施,此功能默认禁用。请参阅 "option external-check"。
将进程的组 ID 更改为。建议将组 ID 分配给 HAProxy 或一小组类似的守护进程。HAProxy 必须以属于该组的用户或超级用户权限启动。请注意,如果 haproxy 是由具有辅助组的用户启动的,则只有在以超级用户权限启动时才能删除这些组。另请参阅“group”和“uid”。
与“gid”类似,但使用 /etc/group 中名为的组的 GID。另请参阅“gid”和“user”。
定义执行干净的软停止所允许的最长时间。
<time> 是实例在通过 SIGUSR1 信号接收到软停止时将保持活动的最长时间(默认为毫秒)。
这可用于确保即使在软停止期间连接保持打开(例如,在 tcp 模式下为代理设置了长超时),实例也会退出。它适用于 TCP 和 HTTP 模式。
global hard-stop-after 30s
定义在启用时应用于报头名称的大小写调整,在将其发送到 HTTP/1 客户端或服务器之前将其更改为 。 必须是小写,并且 和 除了大小写之外不得有其他差异。如果需要调整多个报头名称,可以重复此设置。不允许重复条目。如果需要调整大量报头名称,使用“h1-case-adjust-file”可能更方便。请注意,除非在代理中指定了“option h1-case-adjust-bogus-client”或“option h1-case-adjust-bogus-server”,否则不会应用任何转换。报头名称没有标准的大小写,因为如 RFC7230 所述,它们是大小写不敏感的。因此,应用程序必须以大小写不敏感的方式处理它们。但一些有问题的应用程序违反了标准,错误地依赖于浏览器最常用的大小写。这个问题对于 HTTP/2 至关重要,因为所有报头名称都必须以小写形式交换,HAProxy 也遵循相同的约定。无论 HTTP 版本如何,所有报头名称都将以小写形式发送给客户端和服务器。无法正确处理请求或响应的应用程序可能需要暂时使用此类解决方法来调整发送给它们的报头名称,直到应用程序得到修复为止。请注意,需要此类解决方法的应用程序可能容易受到内容走私攻击,必须绝对修复。
global h1-case-adjust content-length Content-Length
请参阅 "h1-case-adjust-file"、"option h1-case-adjust-bogus-client" 和 "option h1-case-adjust-bogus-server"。
定义一个文件,该文件包含用于在将某些报头名称发送到 HTTP/1 客户端或服务器之前调整其大小写的键/值对列表。文件每行必须包含 2 个报头名称。第一个必须是小写,两者除了大小写之外不得有其他差异。以“#”开头的行将被忽略,空行也是如此。前导和尾随的制表符和空格将被剥离。不允许重复条目。请注意,除非在代理中指定了“option h1-case-adjust-bogus-client”或“option h1-case-adjust-bogus-client”或“option h1-case-adjust-bogus-server”,否则不会应用任何转换。如果重复此指令,则只处理最后一个。如果需要调整大量报头名称,这是“h1-case-adjust”指令的替代方案。请阅读使用此设置的风险。请参阅“h1-case-adjust”、“option h1-case-adjust-bogus-client”和“option h1-case-adjust-bogus-server”。
添加一个全局 syslog 服务器。可以定义多个全局服务器。它们将接收启动和退出的日志,以及配置了“log global”的代理的所有日志。可以是以下之一: - IPv4 地址,后面可选地跟一个冒号和一个 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。 - IPv6 地址,后面跟一个冒号和一个可选的 UDP 端口。如果未指定端口,则默认使用 514(标准 syslog 端口)。 - 到 datagram UNIX 域套接字的系统路径,同时要考虑 chroot(确保路径在 chroot 内可访问)和 uid/gid(确保路径可正确写入)。 - 文件描述符编号,形式为“fd@”,可能指向管道、终端或套接字。在这种情况下,将使用无缓冲日志,并且每次日志调用都会执行一次 writev() 调用。这有点昂贵,但对于大多数工作负载来说是可以接受的。通过此方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,DroppedLogs 计数器将被增加。writev() 调用即使在管道上对于小于 PIPE_BUF 大小的消息也是原子的,POSIX 建议至少为 512,在大多数现代操作系统上为 4096 字节。任何更大的消息可能会与其他进程的消息交织在一起。特别为了调试目的,文件描述符也可以指向一个文件,但这样做会显著减慢 haproxy 的速度,因为非阻塞调用将被忽略。此外,在不重新启动进程的情况下,无法清除或轮换此文件。请注意,配置的 syslog 格式将保持不变,因此输出适合与 TCP syslog 服务器一起使用。另请参阅下面的“short”和“raw”格式。 - “stdout”/“stderr”,它们分别是“fd@1”和“fd@2”的别名,请参阅上文。您可能希望在地址参数中引用某些环境变量,有关环境变量的更多信息,请参阅第 2.3 节。 是可选的最大行长度。大于此值的日志行将在发送前被截断。原因是 syslog 服务器对日志行长度的处理方式不同。所有服务器都支持 1024 的默认值,但某些服务器会丢弃较大的行,而其他服务器则会记录它们。如果服务器支持长行,则在此处设置此值可能有助于避免截断长行。同样,如果服务器丢弃长行,最好在发送它们之前进行截断。接受的值为 80 到 65535(含)。1024 的默认值通常适用于所有标准用法。某些特定场景下的长捕获或 JSON 格式的日志可能需要更大的值。如果请求 URI 被截断,您可能还需要增加“tune.http.logurilen”。 是生成 syslog 消息时使用的日志格式。可以是以下格式之一: rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164) rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424) short 一个包含仅在尖括号内的级别(如“<3>”)后跟文本的消息。PID、日期、时间、进程名称和系统名称将被省略。这旨在与本地日志服务器一起使用。此格式与 systemd 日志记录器消耗的格式兼容。 raw 一个仅包含文本的消息。级别、PID、日期、时间、进程名称和系统名称将被省略。这旨在用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。 是逗号分隔的范围列表,用于标识要采样的日志。这用于平衡发送到日志服务器的日志负载。范围的上限不能为 null。它们从 1 开始编号。 必须大于或等于范围的高位上限的最大值。(另请参阅 参数)。 必须是 24 个标准 syslog 设施之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,对于“short”和“raw”格式,设施会被忽略,但仍需要作为位置字段。在这种情况下,建议使用“daemon”以明确其仅用于本地。可以指定一个可选级别来过滤传出的消息。默认情况下,所有消息都会发送。如果指定了最大级别,则只会发送严重性至少与该级别同等重要的消息。可以指定一个可选的最小级别。如果设置了此级别,则高于此级别的日志将被限制为此级别。这用于避免在某些默认 syslog 配置中将“emerg”消息发送到所有终端。已知有八个级别:emerg alert crit err warning notice info debug
设置 syslog 报头中的 hostname 字段。如果设置了可选的 "string" 参数,则报头将设置为该字符串内容,否则使用系统的主机名。通常在不通过中间 syslog 服务器中继日志或仅为自定义日志中打印的主机名时使用。
将 syslog 报头中的 tag 字段设置为此字符串。它默认为从命令行启动的程序名,通常是 "haproxy"。有时,区分同一主机上运行的多个进程会很有用。另请参阅每个代理的 "log-tag" 指令。此全局指令加载并执行一个 Lua 文件。此指令可以多次使用。
主-工作者模式。它等同于命令行参数“-W”。此模式将启动一个“主进程”,该进程将监控“工作进程”。使用此模式,您可以通过向主进程发送 SIGUSR2 信号来直接重新加载 HAProxy。主-工作者模式与前台或守护进程模式兼容。建议在多进程和 systemd 环境下使用此模式。默认情况下,如果一个工作进程以错误的返回码退出,例如在发生段错误的情况下,所有工作进程都将被杀死,主进程将退出。将此行为与 systemd 单元文件中的 Restart=on-failure 结合使用,以重新启动整个进程是很方便的。如果您不希望有此行为,则必须使用关键字“no-exit-on-failure”。另请参见管理指南中的“-W”。
在主-从模式下,此选项限制了工作进程可以承受的重载次数。如果工作进程在重载后没有退出,一旦其重载次数大于此数字,该工作进程将收到一个 SIGTERM 信号。此选项有助于控制工作进程的数量。另请参阅管理指南中的“show proc”。
创建 <number> 个进程以进入 daemon 模式。这需要“daemon”模式。默认情况下,只创建一个进程,这是推荐的操作模式。对于文件描述符数量有限的系统,可能需要派生多个守护进程。当设置为大于 1 的值时,线程会自动禁用。使用多个进程更难调试,并且强烈不推荐。另请参阅“daemon”和“nbthread”。
此设置仅在构建时支持线程时可用。它使 haproxy 在个线程上运行。这与“nbproc”互斥。虽然“nbproc”过去是使用多个处理器唯一的方式,但它也带来了一些与进程之间缺乏同步(健康检查、对等节点、stick-tables、stats 等)相关的问题,而这些问题不会影响线程。因此,强烈建议任何现代配置都从“nbproc”迁移到“nbthread”。“nbthread”在 HAProxy 在前台运行时也能正常工作。在支持 CPU 亲和性的某些平台上,当不使用 nbproc 时,默认的“nbthread”值会自动设置为进程在启动时绑定的 CPU 数量。这意味着线程数可以从调用进程使用“taskset”或“cpuset”等命令进行调整。否则,此值默认为 1。“haproxy -vv”的输出会报告默认值。另请参阅“nbproc”。
将所有守护进程的 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”。
此选项最好保持禁用状态,除非开发人员明确要求。它对性能或稳定性没有影响,但会尽力重新启用可能被文件大小限制(ulimit -f)、核心大小限制(ulimit -c)或进程在更改 UID/GID 后(如 Linux 上的 /proc/sys/fs/suid_dumpable)的“可转储性”所禁用的核心转储。核心转储可能仍然受当前目录权限(检查文件是从哪个目录启动的)、chroot 目录权限(可能需要暂时禁用 chroot 指令或将其移动到专用的可写位置)或任何其他系统特定约束的限制。例如,某些 Linux 发行版以用系统中未安装的可执行文件的路径替换默认核心文件而闻名(检查 /proc/sys/kernel/core_pattern)。通常,简单地写入“core”、“core.%p”或“/var/log/core/core.%p”可以解决问题。在尝试启用此选项以等待罕见问题再次出现时,通常最好先尝试通过例如向 haproxy 进程发出“kill -11”来获取此类转储,并验证它在退出时在预期位置留下核心文件。
此设置仅在构建时支持 OpenSSL 时可用。它设置了默认字符串,该字符串描述了在 SSL/TLS 握手中(直到 TLSv1.2)协商的密码套件列表,适用于所有未明确定义其密码套件的“bind”行。字符串的格式在 OpenSSL 手册页的“man 1 ciphers”中定义。有关背景信息和建议,请参见例如(https://wiki.mozilla.org/Security/Server_Side_TLS)和(https://mozilla.github.io/server-side-tls/ssl-config-generator/)。有关 TLSv1.3 密码配置,请检查“ssl-default-bind-ciphersuites”关键字。有关更多信息,请检查“bind”关键字。
此设置仅在构建时支持 OpenSSL 且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置了默认字符串,该字符串描述了在 TLSv1.3 握手中与服务器协商的密码算法(密码套件)列表,适用于所有未明确定义其密码套件的“bind”行。字符串的格式在 OpenSSL 手册页的“ciphersuites”部分下定义,请参阅“ciphersuites”。有关 TLSv1.2 及更早版本的密码配置,请检查“ssl-default-bind-ciphers”关键字。有关更多信息,请检查“bind”关键字。
仅当启用了 OpenSSL 支持时,此设置才可用。它为所有“bind”行设置了要强制使用的默认 ssl-options。有关可用选项,请检查“bind”关键字。
global ssl-default-bind-options ssl-min-ver TLSv1.0 no-tls-tickets
此设置仅在构建时支持 OpenSSL 时可用。它设置了默认字符串,该字符串描述了在与服务器的 SSL/TLS 握手中(直到 TLSv1.2)协商的密码算法列表,适用于所有未明确定义其密码算法的“server”行。字符串的格式在 OpenSSL 手册页的“man 1 ciphers”中定义。有关背景信息和建议,请参见例如(https://wiki.mozilla.org/Security/Server_Side_TLS)和(https://mozilla.github.io/server-side-tls/ssl-config-generator/)。有关 TLSv1.3 密码配置,请检查“ssl-default-server-ciphersuites”关键字。有关更多信息,请检查“server”关键字。
此设置仅在构建时支持 OpenSSL 且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置了默认字符串,该字符串描述了在与服务器的 TLSv1.3 握手中协商的密码算法列表,适用于所有未明确定义其密码算法的“server”行。字符串的格式在 OpenSSL 手册页的“ciphersuites”部分下定义,请参阅“ciphersuites”。有关 TLSv1.2 及更早版本的密码配置,请检查“ssl-default-server-ciphers”关键字。有关更多信息,请检查“server”关键字。
此设置仅在构建时支持 OpenSSL 时可用。它设置了默认的 ssl-options,强制应用于所有“server”行。有关可用选项,请检查“server”关键字。
此设置仅在构建时支持 OpenSSL 时可用。它设置了默认的 DH 参数,在所有未明确定义其 DH 参数的“bind”行中使用临时 Diffie-Hellman (DHE) 密钥交换时。如果绑定证书文件中包含自定义 DH 参数,则此设置将被覆盖。如果未使用 ssl-dh-param-file 或直接在证书文件中设置自定义 DH 参数,则将使用 tune.ssl.default-dh-param 指定大小的预生成 DH 参数。自定义参数已知更安全,因此建议使用它们。自定义 DH 参数可以通过使用 OpenSSL 命令“openssl dhparam”生成,其中 size 应至少为 2048,因为 1024 位 DH 参数不再被认为是安全的。
服务器端 SSL 验证的默认行为。如果指定为 'none',则不验证服务器证书。默认值为 'required',除非使用命令行选项 '-dV' 强制指定。
将 UNIX 套接字绑定到 <path> 或 TCPv4/v6 地址到 <address:port>。连接到此套接字将返回各种统计信息输出,甚至允许发出一些命令来更改一些运行时设置。有关详细信息,请参阅管理指南的第 9.3 节“Unix 套接字命令”。“bind”行支持的所有参数均可用于此,例如限制某些用户或其访问权限。有关更多信息,请参阅第 5.1 节。统计套接字的默认超时时间设置为 10 秒。可以使用 "stats timeout" 更改此值。该值必须以毫秒为单位传递,或者带有时间单位后缀,如 { us, ms, s, m, h, d }。
默认情况下,统计套接字限制为 10 个并发连接。可以使用 "stats maxconn" 更改此值。
将进程的用户 ID 更改为。建议将用户 ID 分配给 HAProxy 或一小组类似的守护进程。HAProxy 必须以超级用户权限启动才能切换到另一个用户 ID。另请参阅“gid”和“user”。
将每个进程的最大文件描述符数设置为 <number>。默认情况下,它是自动计算的,因此建议不要使用此选项。
为“bind”语句中声明的 UNIX 监听套接字设置常见的修复设置。这主要用于简化这些 UNIX 套接字的声明,并减少错误风险,因为这些设置通常是必需的,并且也是进程特定的。设置可用于强制所有套接字路径相对于该目录。这可能需要访问另一个组件的 chroot。请注意,这些路径在 haproxy chroot 之前解析,因此它们是绝对路径。 、 、 、 和 的含义与其在“bind”语句中使用的同名参数相同。如果同时指定了两者,“bind”语句优先,这意味着“unix-bind”设置可能被视为进程范围的默认设置。
删除参数中指定的环境变量。这对于隐藏某些操作期间偶尔从用户环境中继承的一些敏感信息很有用。不存在的变量会被静默忽略,因此操作后可以确定这些变量都不再存在。更改会立即生效,因此配置文件中的下一行将看不到这些变量。另请参阅 “setenv”、“presetenv” 和 “resetenv”。
与“uid”类似,但使用 /etc/passwd 中名为的用户的 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 请求附带的原始 User-Agent。 - wurfl_api_version 包含表示当前使用的 Libwurfl API 版本的字符串。 - wurfl_info 包含有关已解析的 wurfl.xml 及其完整路径的信息字符串。 - wurfl_last_load_time 包含 WURFL 上次成功加载的 UNIX 时间戳。 - wurfl_normalized_useragent 规范化的 User-Agent。请注意,此选项仅在 haproxy 使用 USE_WURFL=1 编译时可用。
用于分隔包含 WURFL 结果的响应标头中值的字符。如果未设置,则默认使用逗号 (',')。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。WURFL 补丁文件路径列表。请注意,补丁是在启动时加载的,因此在 chroot 之前加载。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
设置 WURFL 用户代理缓存大小。为了加快查找速度,已处理的用户代理会保留在 LRU 缓存中:-“0”:不使用缓存。- <size>:LRU 缓存的大小(以元素为单位)。请注意,只有当 haproxy 使用 USE_WURFL=1 编译时,此选项才可用。
在某些情况下,尤其是在处理支持可变频率的处理器的低延迟或在虚拟机内部运行时,每次进程使用 poller 等待 I/O 时,处理器都会返回睡眠状态或长时间提供给另一个 VM,这会导致过高的延迟。此选项提供了一种解决方案,通过始终对 poller 使用空超时来防止处理器进入睡眠状态。这会显著降低延迟(观察到 30 到 100 微秒),但存在处理器过热的风险。它甚至可以与线程一起使用,在这种情况下,不正确绑定的线程可能会发生严重冲突,导致性能下降,并且“show info”输出中 CPU 占用过高的字段值增加,表明哪些线程配置不当。使用此选项时,切勿让进程在与网络中断相同的处理器上运行。最好避免在共享同一核心的多个 CPU 线程上使用它。此选项默认禁用。如果已启用,仍可使用“no”关键字强制禁用。它会被“select”和“poll”轮询器忽略。在无缝重新加载的上下文中,此选项会自动禁用旧进程。它避免了多个进程长时间等待当前连接结束时过多的 CPU 冲突。
默认情况下,haproxy 会尝试将健康检查的开始时间分散到服务器场中所有服务器的最小健康检查间隔内。其原理是避免对同一服务器上运行的服务进行密集检查。但是当使用较大的检查间隔(10 秒或更长)时,服务器场中的最后几个服务器需要一些时间才能开始被测试,这可能是一个问题。此参数用于强制设置第一个和最后一个检查之间的延迟上限,即使服务器的检查间隔较大。当服务器以较短的间隔运行时,它们的间隔仍将得到尊重。
将每个进程的并发连接数最大值设置为 <number>。它等同于命令行参数“-n”。当达到此限制时,代理将停止接受连接。“ulimit-n”参数会根据此值自动调整。另请参阅“ulimit-n”。注意:在某些平台上,“select”轮询器无法可靠地使用超过 1024 个文件描述符。如果您的平台仅支持 select 并在启动时报告“select FAILED”,您需要减少 maxconn 直到它正常工作(通常略低于 500)。如果未设置此值,它将根据“ulimit -n”命令报告的当前文件描述符限制自动计算,如果强制执行内存限制,可能会根据缓冲区大小、分配给压缩的内存、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 使用过多内存并崩溃(因为不幸的是,它不能可靠地检查这种情况)。请注意,此限制同时适用于传入和传出连接,因此一个经过解密然后加密的连接会计算为 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"。
在源自 Solaris 10 及更高版本的 SunOS 系统上禁用事件端口(event ports)事件轮询系统的使用。它等同于命令行参数“-dv”。下一个使用的轮询系统通常是“poll”。另请参阅“nopoll”。
禁用“poll”事件轮询系统的使用。它等同于命令行参数“-dp”。下一个使用的轮询系统将是“select”。通常不需要禁用“poll”,因为它在 HAProxy 支持的所有平台上都可用。另请参阅“nokqueue”、“noepoll”和“noevports”。
禁用在 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"。
启用('on')或禁用('off')每个任务的 CPU 性能分析。当设置为 'auto' 时,当一个线程开始遭受平均延迟为 1000 微秒或更高(如“avg_loop_us”活动字段中所报告)时,性能分析会自动打开该线程,当延迟低于 990 微秒时会自动关闭(此值是过去 1024 次循环的平均值,因此它不会快速变化,并且会显著平滑短期峰值)。在过载系统、容器或虚拟机上,或者在系统进行交换(负载均衡器上绝对不应发生这种情况)时,它也可能不时自发触发。每个任务的 CPU 性能分析非常方便,可以报告时间花在哪里以及哪些请求对其他请求有什么影响。启用它通常会影响整体性能不到 1%,因此建议将其保留为默认的 'auto' 值,以便它仅在识别到问题时运行。此功能需要支持具有 CLOCK_MONOTONIC 和 CLOCK_THREAD_CPUTIME_ID 时钟标识符的 clock_gettime(2) 系统调用,否则报告的时间将为零。此选项可以在运行时通过 CLI 使用“set profiling”进行更改。
有时,希望避免以精确的间隔向服务器发送代理和健康检查,例如当许多逻辑服务器位于同一物理服务器上时。借助此参数,可以在检查间隔中添加 0 到 +/- 50% 之间的随机性。2 到 5 之间的值似乎效果很好。默认值仍为 0。
将 OpenSSL 引擎设置为 <name>。可以使用命令“openssl engine”获取 <name> 的有效值列表。此语句可以多次使用,它只会启用多个加密引擎。引用不支持的引擎将导致 haproxy 无法启动。请注意,许多引擎将导致 HTTPS 性能低于最新处理器上的纯软件。可选命令“algo”使用 OPENSSL 函数 ENGINE_set_default_string() 设置 ENGINE 将提供的默认算法。值为“ALL”时,引擎用于所有加密操作。如果未指定 algo 列表,则使用“ALL”的值。可以指定由不同算法组成的逗号分隔列表,包括:RSA、DSA、DH、EC、RAND、CIPHERS、DIGESTS、PKEY、PKEY_CRYPTO、PKEY_ASN1。这与 openssl 配置文件使用的格式相同:https://www.openssl.org/docs/man1.0.2/apps/config.html
将 SSL_MODE_ASYNC 模式添加到 SSL 上下文。如果使用支持异步的 SSL 引擎,这将启用异步 TLS I/O 操作。当前实现最多支持 32 个引擎。Openssl ASYNC API 不支持移动读/写缓冲区,并且不兼容 haproxy 的缓冲区管理。因此,异步模式在读/写操作时被禁用(它仅在初始握手和重新协商握手期间启用)。
为每个进程设置可分配缓冲区数量的硬限制。默认值为零,表示无限制。非零的最小值将始终大于“<a href="#tune.buffers.reserve">tune.buffers.reserve”,并且理想情况下应始终是其两倍大。强制设置此值对于限制进程可能占用的内存量同时保持正常行为特别有用。当达到此限制时,需要缓冲区的会话将等待另一个会话被另一个会话释放。由于缓冲区是动态分配和释放的,因此等待时间非常短且不可感知,前提是限制保持合理。实际上,有时减少限制可以通过提高 CPU 缓存的效率来提高性能。测试表明,在平均 HTTP 流量下,将限制设置为预期全局 maxconn 设置的 1/10 会获得良好结果,这还会显着降低内存使用量。内存节省来自于这样一个事实:许多连接不会分配 2*tune.bufsize。除非 haproxy 核心开发人员建议,否则最好不要更改此值。
设置预分配并保留的缓冲区数量,仅在内存分配失败导致的内存短缺情况下使用。最小值为 2,也是默认值。用户没有理由更改此值,它主要针对 haproxy 核心开发人员。
将缓冲区大小设置为此大小(以字节为单位)。较低的值允许更多会话存在于相同数量的 RAM 中,而较高的值允许某些具有非常大 cookie 的应用程序正常工作。默认值为 16384,可以在构建时更改。强烈建议不要更改此默认值,因为非常低的值会破坏某些服务(如统计信息),而大于默认尺寸的值会增加内存使用量,可能导致系统内存不足。至少应将全局 maxconn 参数与此参数增加的相同因子进行减小。此外,HTTP/2 的使用要求此值必须为 16384 或更高。如果 HTTP 请求大于 (tune.bufsize - tune.maxrewrite),haproxy 将返回 HTTP 400 (Bad Request) 错误。同样,如果 HTTP 响应大于此大小,haproxy 将返回 HTTP 502 (Bad Gateway) 错误。请注意,使用此参数设置的值将在 32 位机器上自动向上舍入到下一个 8 的倍数,在 64 位机器上自动向上舍入到下一个 16 的倍数。
将检查缓冲区大小设置为此大小(以字节为单位)。较高的值可能有助于在非常大的页面中查找字符串或正则表达式模式,但这可能意味着更多的内存和 CPU 使用。默认值为 16384,可以在构建时更改。不建议更改此值,而应尽可能使用更好的检查方法。
设置最大压缩级别。压缩级别影响压缩期间的 CPU 使用率。此值影响压缩期间的 CPU 使用率。每个使用压缩的会话都使用此值初始化压缩算法。默认值为 1。
如果使用 DEBUG_FAIL_ALLOC 编译,则给出分配尝试失败的百分比几率。必须介于 0(无失败)和 100(无成功)之间。这对于调试和确保内存故障得到妥善处理非常有用。
设置 HTTP/2 动态头表大小。默认为 4096 字节,不能大于 65536 字节。较大的值可能有助于某些客户端发送更紧凑的请求,具体取决于它们的能力。每个 HTTP/2 连接都会消耗此数量的内存。建议不要更改它。
设置 HTTP/2 的初始窗口大小,即客户端在等待 haproxy 确认之前可以上传的字节数。此设置仅影响有效负载内容(即 POST 请求的正文),而不影响标头。默认值为 65535,在大约 100 毫秒的 ping 时间的网络上,每位客户端的上传带宽约为 5 Mbps,在 1 毫秒的本地网络上约为 500 Mbps。增加此值以允许更快的上传,或在处理多个客户端时减小此值以增加公平性是有意义的。它不影响资源使用。
设置每个连接的 HTTP/2 最大并发流数(即单个连接上的未完成请求数)。默认值为 100。在具有高延迟的网络上访问时,更大的值可能会略微改善复杂站点的页面加载时间,但会增加单个客户端可能分配的资源量。值为零会禁用限制,因此单个客户端可以创建 haproxy 可分配的任意数量的流。强烈建议不要更改此值。
设置 haproxy 向其对等节点宣告愿意接收的最大帧大小。默认值是 16384 和缓冲区大小 (tune.bufsize) 之间的较大者。在任何情况下,haproxy 都不会宣告支持大于缓冲区的帧大小。此设置的主要目的是在配置大缓冲区时允许限制最大帧大小。过大的帧大小可能会影响性能或导致某些对等节点行为异常。强烈建议不要更改此值。
设置捕获的 cookie 的最大长度。"capture cookie xxx len yyy" 允许的最大值将是此值,任何更高的值都将自动截断为此值。重要的是不要设置太高的值,因为所有 cookie 捕获无论其配置值如何都会分配此大小(它们共享一个池)。此值是每个请求每个响应的,因此每个连接分配的内存是此值的两倍。如果未指定,限制设置为 63 个字符。建议不要更改此值。
设置日志中请求 URI 的最大长度。这可以防止在日志行中截断带有有价值查询字符串的长请求 URI。这与 syslog 的限制无关。如果增加此限制,您可能还需要增加 'log ... len yyy' 参数。您的 syslog 守护进程可能也需要特定的配置指令。默认值为 1024。
设置请求中的最大报头数。当请求的报头数(包括第一行)大于此值时,它将被拒绝,并返回 "400 Bad Request" 状态码。同样,过大的响应将被阻止,并返回 "502 Bad Gateway"。默认值为 101,对于所有用途来说已经足够,考虑到广泛部署的 Apache 服务器也使用相同的限制。有时可以进一步提高此限制,以便在修复错误的应用程序之前临时允许其工作。可接受的范围是 1..32767。请记住,每个新报头都会为每个会话消耗 32 位的内存,因此不要将此限制设置得太高。
设置 haproxy 将认为空缓冲区可能与空闲流关联的时间。这用于在转发大量和小数据时优化某些数据包大小。使用 splice() 或在 SSL 中发送大缓冲区进行数据的决定受此参数的调节。该值以毫秒为单位,在 0 到 65535 之间。值为零表示 haproxy 不会尝试检测空闲流。默认值为 1000,它似乎能正确检测最终用户暂停(例如,在点击之前阅读页面)。没有理由更改此值。请查看下面的 tune.ssl.maxrecord。
启用('on')或禁用('off')侦听器的多队列接受,该接受会将传入流量分发到所有线程,而不是自己独占。这提供了更平滑的流量分发,并且扩展性更好,尤其是在线程可能由于外部活动(例如网络中断与某个线程冲突)而负载不均的环境中。此选项默认启用,但可以强制禁用以进行故障排除,或在估计操作系统已提供足够好的分发且连接寿命极短的情况下使用。
该指令强制 Lua 引擎每执行 <number> 条指令就执行一次让出(yield)。这允许中断一个长时间运行的脚本,并让 HAProxy 调度器处理其他任务,如接受连接或转发流量。默认值为 10000 条指令。如果 HAProxy 经常执行一些 Lua 代码但需要更高的响应性,可以降低这个值。如果 Lua 代码相当长,并且其结果对于处理数据是绝对必需的,可以增加这个 <number>。
设置 Lua 每个进程可用的最大 RAM 量(以兆字节为单位)。默认情况下为零,表示无限制。设置限制很重要,以确保脚本中的错误不会导致系统内存耗尽。
这是 Lua 会话的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
目的与 "tune.lua.session-timeout" 相同,但此超时专用于任务。默认情况下,此超时未设置,因为任务可能在 HAProxy 的整个生命周期内保持活动状态。例如,用于检查服务器的任务。
这是 Lua 服务的执行超时。这对于防止无限循环或在 Lua 中花费太多时间很有用。此超时仅计算纯 Lua 运行时。如果 Lua 执行了休眠,休眠时间不计入。默认超时为 4 秒。
设置一个进程在切换到其他工作之前可以连续接受的最大连接数。在单进程模式下,较高的数字在高连接率下性能更好。然而,在多进程模式下,在进程之间保持一点公平性通常能更好地提高性能。此值单独应用于每个侦听器,以便考虑到侦听器绑定的进程数。此值默认为 64。在多进程模式下,它除以侦听器绑定的进程数的两倍。将此值设置为 -1 将完全禁用此限制。通常不需要调整此值。
设置一次调用轮询系统可以处理的最大事件量。默认值根据操作系统进行调整。已经注意到,将其降低到 200 以下会略微降低延迟,但会牺牲网络带宽,而将其增加到 200 以上则会以延迟换取略微增加的带宽。
将保留的缓冲区空间设置为此大小(以字节为单位)。保留空间用于报头重写或追加。套接字上的第一次读取永远不会超过 bufsize-maxrewrite。历史上,它默认为 bufsize 的一半,但这没有太大意义,因为很少有大量的报头需要添加。设置得太高会妨碍处理大的请求或响应。设置得太低会妨碍向已有的较大请求或 POST 请求添加新报头。通常明智的做法是将其设置为大约 1024。如果大于 bufsize 的一半,它会自动调整为 bufsize 的一半。这意味着您在更改 bufsize 时不必担心它。
将模式查找缓存的大小设置为 <number> 个条目。这是一个 LRU 缓存,用于记住之前的查找及其结果。它由 ACL 和映射用于慢速模式查找,特别是使用“<a href="#sub">sub”、“reg”、“dir”、“dom”、“end”、“<a href="#bin">bin”匹配方法以及不区分大小写的字符串。它适用于模式表达式,这意味着它能够记忆配置行上所有指定模式(包括从文件中加载的所有模式)的查找结果。使用 HTTP 操作或 CLI 更新条目时,它会自动使条目失效。默认缓存大小设置为 10000 个条目,这限制了每个进程/线程在 32 位系统上约 5 MB 的占用空间,在 64 位系统上约 8 MB 的占用空间,因为缓存是线程/进程本地的。此缓存中存在非常低的冲突风险,该风险大致等于缓存大小除以 2^64。通常,在每秒 10000 次请求且默认缓存大小为 10000 个条目的情况下,暴力攻击在 60 年后可能导致单次冲突的概率为 1%,或在 6 年后为 0.1%。这被认为远低于老化组件造成的内存损坏风险。如果这不可接受,可以通过将此参数设置为 0 来禁用缓存。
将内核管道缓冲区大小设置为此大小(以字节为单位)。默认情况下,管道是系统的默认大小。但有时在使用 TCP 拼接时,增加管道大小可以提高性能,特别是在怀疑管道未被填满且执行了许多 splice() 调用时。这对内核的内存占用有影响,因此如果影响不明确,则不应更改此值。
此设置设置了haproxy全局使用的文件描述符数量(百分比)与haproxy可以使用但在此之前我们将开始在无法重用连接且必须创建新连接时杀死空闲连接的最大文件描述符数量之间的比率。默认值为25(四分之一的文件描述符意味着大约一半的最大前端连接可以保留一个空闲连接,超出此范围在一般情况下目标是连接重用时意义不大)。
此设置设置了haproxy全局使用的文件描述符数量(百分比)与haproxy可以使用但在此之前我们将停止将连接放入空闲池进行重用的最大文件描述符数量之间的比率。默认值为20。
强制将客户端或服务器端的内核套接字接收缓冲区大小设置为指定的字节值。此值适用于所有 TCP/HTTP 前端和后端。通常不应设置此值,默认大小(0)让内核根据可用内存量自动调整此值。但是,有时将其设置为非常低的值(例如 4096)有助于节省内核内存,因为它阻止内核缓冲过多的接收数据。不过,较低的值会显著增加 CPU 使用率。
HAProxy 使用一些提示来检测短读是否表示套接字缓冲区的末尾。其中之一是读取返回的字节数超过 <recv_enough>,默认为 10136(7 个 1448 字节的段)。此默认值可以通过此设置更改,以更好地处理涉及大量短消息的工作负载,例如 telnet 或 SSH 会话。
设置在运行任务时一次可以处理的最大任务数量。默认值为 200。增加它可能会在处理 I/O 时增加延迟,而将其设置得太小可能会增加额外的开销。
将客户端或服务器端的内核套接字发送缓冲区大小强制设置为指定的字节数。此值适用于所有TCP/HTTP前端和后端。通常不应设置它,默认大小(0)允许内核根据可用内存量自动调整此值。但是,有时将其设置为非常小的值(例如4096)可以通过阻止内核缓冲过多的接收数据来节省内核内存。然而,较低的值将显著增加CPU使用率。另一种用例是防止由于内核等待缓冲区的大部分被读取然后再次通知haproxy而导致的极慢客户端的写入超时。
以块的数量设置全局 SSL 会话缓存的大小。一个块足够大,可以包含没有对端证书的编码会话。带有对端证书的编码会话根据对端证书的大小存储在多个块中。一个块大约使用 200 字节的内存。默认值可能在构建时强制设置,否则默认为 20000。当缓存已满时,最空闲的条目将被清除并重新分配。较高的值会减少此类清除的发生次数,从而通过确保所有用户尽可能长时间地保留其会话来减少 CPU 密集型 SSL 握手的次数。所有条目在启动时预先分配,如果“<span class="dropdown">nbproc”大于 1,则在所有进程之间共享。将此值设置为 0 会禁用 SSL 会话缓存。
此选项禁用所有进程之间的 SSL 会话缓存共享。通常不应使用它,因为它会由于客户端命中随机进程而强制进行许多重新协商。但在某些操作系统上可能需要它,因为这些操作系统上可能无法使用任何 SSL 缓存同步方法。在这种情况下,在 SSL 层之前添加第一层基于哈希的负载均衡可能会限制缺少会话共享的影响。
设置缓存的 SSL 会话可以保持有效的时长。此时间以秒为单位表示,默认为 300(5 分钟)。重要的是要理解,这并不保证会话会持续那么长时间,因为如果缓存已满,最长时间空闲的会话将被清除,尽管它们配置了生命周期。此设置的真正用处是防止会话被使用太长时间。
设置一次传递给 SSL_write() 的最大字节数。默认值 0 表示没有限制。通过 SSL/TLS,客户端只有在接收到完整的记录后才能解密数据。对于大记录,这意味着客户端可能需要下载多达 16kB 的数据才能开始处理它们。限制该值可以改善位于高延迟或低带宽网络上的浏览器的页面加载时间。建议找到适合 1 或 2 个 TCP 段(在以太网上启用 TCP 时间戳时通常为 1448 字节,禁用时间戳时为 1460 字节)的最佳值,同时记住 SSL/TLS 会增加一些开销。测试期间,1419 和 2859 的典型值取得了良好结果。使用“strace -e trace=write”来找到最佳值。HAProxy 在检测到空闲流后将自动切换到此设置(请参阅上面的 tune.idletimer)。
在 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 个条目。
设置用于捕获客户端hello密码列表的缓冲区最大大小。如果值为0(默认值),则禁用捕获;否则,为每个SSL/TLS连接分配一个缓冲区。
这五个调优参数有助于管理变量系统使用的内存总量。“global”限制了所有范围可用的总内存量。“<a href="#proc">proc”限制了进程范围的内存,“sess”限制了会话范围的内存,“txn”限制了事务范围的内存,而“reqres”限制了每个请求或响应处理的内存。内存计费是分层的,这意味着更粗粒度的限制包括更细粒度的限制:“<a href="#proc">proc”包括“sess”,“sess”包括“txn”,“txn”包括“reqres”。例如,当“<a href="#tune.vars.sess-max-size">tune.vars.sess-max-size”限制为 100 时,“<a href="#tune.vars.txn-max-size">tune.vars.txn-max-size”和“<a href="#tune.vars.reqres-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 的密码加密方法。注意:请注意,使用加密密码可能会显着增加 CPU 使用量,具体取决于请求的数量和使用的算法。对于任何散列变体,每个请求的密码都必须通过所选算法进行处理,然后才能将其与配置文件中的值进行比较。大多数当前算法都经过精心设计,计算成本高昂,以抵抗暴力攻击。它们不是简单地对明文密码进行一次盐渍/哈希处理,而是进行数千次。这可能很快成为 haproxy 整体 CPU 消耗的一个主要因素!
userlist L1 group G1 users tiger,scott group G2 users xdb,scott user tiger password $6$k6y3o.eP$JlKBx9za9667qe4(...)xHSwRv6J.C0/D7cV91 user scott insecure-password elgato user xdb insecure-password hello userlist L2 group G1 group G2 user tiger password $6$k6y3o.eP$JlKBx(...)xHSwRv6J.C0/D7cV91 groups G1 user scott insecure-password elgato groups G1,G2 user xdb insecure-password hello groups G2
请注意,这两个列表在功能上是相同的。
可以在多个 haproxy 实例之间通过 TCP 连接以多主方式传播粘性表中的任何数据类型的条目。每个实例将其本地更新和插入推送到远程对等节点。推送的值会覆盖远程值,而不进行聚合。中断的交换会自动检测并从最后一个已知点恢复。此外,在软重启期间,旧进程使用这样的 TCP 连接连接到新进程,以在新进程尝试连接其他对等节点之前推送其所有条目。这确保了在重新加载期间的快速复制,即使对于大型表,通常也只需要几分之一秒。请注意,服务器 ID 用于远程识别服务器,因此重要的是配置看起来相似,或者至少在所有参与者上对每个服务器强制使用相同的 ID。
创建名为 <peersect> 的新对等节点列表。它是一个独立的部分,由一个或多个粘性表引用。
定义此“peers”部分中本地对等节点的绑定参数。在同一个“peers”部分中,此类行不支持与“peer”行同时使用。
禁用一个对等节点部分。它会禁用与此部分相关的侦听和任何同步。这用于禁用粘性表的同步,而无需注释掉所有 "peers" 引用。
定义本地对等节点的绑定参数,但不包括其地址。
更改“peers”部分中服务器的默认选项。
<param*> 是此服务器的参数列表。“<span class="dropdown">default-server”关键字接受大量选项,并专门为此设置了一个部分。在 peers 部分中,支持“<span class="dropdown">default-server”行的传输参数。请参阅第 5 节以获取更多详细信息,以及此部分下方的“<span class="dropdown">server”关键字以了解一些限制。
此选项重新启用一个先前通过“disabled”关键字禁用的 peers 部分。在 peers 部分中定义一个 peer。如果 <peername> 设置为本地 peer 名称(默认为主机名,或通过“-L”命令行选项强制设置),haproxy 将侦听所提供地址上的传入远程 peer 连接。否则,地址定义了连接到哪里以加入远程 peer,而 <peername> 用于协议级别以识别和验证服务器端的远程 peer。在软重新启动期间,旧实例使用本地 peer 地址连接新实例并启动完整的复制(教学过程)。强烈建议在所有 peer 上声明完全相同的 peer,并且仅依赖“-L”命令行参数来更改本地 peer 名称。这使得跨所有 peer 维护一致的配置文件更加容易。您可能希望在地址参数中引用某些环境变量,有关环境变量的第 2.3 节。注意:“<a href="#peer">peer”关键字可以被“<span class="dropdown">server”关键字透明替换(请参阅下面的“<span class="dropdown">server”关键字解释)。
如前所述,“<a href="#peer">peer”关键字可以被“<span class="dropdown">server”关键字替换,并支持 5.2 段中与传输设置相关的“<span class="dropdown">server”所有参数。如果底层 peer 是本地的,则地址参数不得存在;它必须在“<span class="dropdown">bind”行上提供(请参阅本“<a href="#peers">peers”部分的“<span class="dropdown">bind”关键字)。许多“<span class="dropdown">server”参数与“<a href="#peers">peers”部分无关。Peer 本质上不支持动态主机名解析或运行状况检查,因此“init_addr”、“<span class="dropdown">resolvers”、“<a href="#check">check”、“<a href="#agent-check">agent-check”或“<a href="#track">track”等参数不被支持。同样,没有负载均衡或粘性,因此“<a href="#weight">weight”或“<span class="dropdown">cookie”等参数无效。
# 旧方法。 peers mypeers peer haproxy1 192.168.0.1:1024 peer haproxy2 192.168.0.2:1024 peer haproxy3 10.2.0.1:1024 backend mybackend mode tcp balance roundrobin stick-table type ip size 20k peers mypeers stick on src server srv1 192.168.0.30:80 server srv2 192.168.0.31:80 示例: peers mypeers bind 192.168.0.1:1024 ssl crt mycerts/pem default-server ssl verify none server haproxy1 #本地对等节点 server haproxy2 192.168.0.2:1024 server haproxy3 10.2.0.1:1024
为当前部分配置粘性表。此行解析方式与“<a href="#stick-table">stick-table”关键字在其他部分中的解析方式完全相同,只是“<a href="#peers">peers”参数在这里不是必需的,并且增加了一个强制的第一个参数来指定 stick-table。与其他部分不同,可以在“<a href="#peers">peers”部分中有多个“<a href="#table">table”行(另请参阅“<a href="#stick-table">stick-table”关键字)。同时要注意,“<a href="#peers">peers”部分有自己的 stick-table 命名空间,以避免在不同的“<a href="#peers">peers”部分中名称相同的 stick-table 发生冲突。这在内部通过将“<a href="#peers">peers”部分名称加到 stick-table 名称前面,然后加上“/”字符来处理。如果在配置文件的其他地方必须引用在“<a href="#peers">peers”部分中声明的此类 stick-table,则必须使用加前缀的 stick-table 名称,如下所示:peers mypeers peer A ... peer B ... table t1 ... frontend fe1 tcp-request content track-sc0 src table mypeers/t1 CLI 中引用的 stick-table 名称也必须使用此加前缀的版本。关于“<a href="#peers">peers”协议,由于只有属于同一部分的“<a href="#peers">peers”才能相互通信,因此无需进行此类区分。几个“<a href="#peers">peers”部分可以声明名称相同的 stick-table。这是通过网络发送的 stick-table 名称的较短版本。只有一个“/”字符作为前缀,以避免在作为后端声明的 stick-table 和在“<a href="#peers">peers”部分中声明的 stick-table 之间发生名称冲突,如下面这种奇怪但受支持的配置:peers mypeers peer A ... peer B ... table t1 type string size 10m store gpc0 backend t1 stick-table type string size 10m store gpc0 peers mypeers 在这里,“mypeers”部分中声明的“t1”表具有“mypeers/t1”作为全局名称。“t1”表作为后端声明为“t1”作为全局名称。但在 peer 协议级别,前者表命名为“/t1”,后者再次命名为“t1”。
当服务器状态发生变化时,可以发送电子邮件警报。如果配置了电子邮件警报,则会发送到邮件发送器部分中配置的每个邮件发送器。电子邮件使用 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
在 master-worker 模式下,可以与 master 一起启动外部二进制文件,这些进程称为程序。这些程序的启动和管理方式与 worker 相同。在 HAProxy 重载期间,这些进程将经历与 worker 相同的序列: - master 被重新执行 - master 向程序发送一个 SIGUSR1 信号 - 如果没有禁用“option start-on-reload”,master 将启动一个新的程序实例 在停止或重启期间,会向程序发送一个 SIGTERM 信号。
这是一个新的程序部分,此部分将创建一个名为 <name> 的实例,该实例在 master CLI 的 "show proc" 中可见。(请参阅管理指南中的 "9.4. Master CLI")。
定义要启动的命令及可选参数。如果命令不包含绝对路径,则会在当前 PATH 中查找。这是 program 部分的一个强制选项。包含空格的参数必须用单引号或双引号括起来,或者以反斜杠为前缀。
在 master 重载时启动(或不启动)程序的新实例。默认是启动新实例。此选项只能在 program 部分使用。
代理配置可以位于一组部分中:- defaults [<name>] - frontend <name> - backend <name> - listen <name> “defaults”部分设置以下所有部分的默认参数。这些默认参数将在下一个“defaults”部分中重置。请参阅下面的参数列表,这些参数可以在“defaults”部分中设置。名称是可选的,但鼓励使用它以提高可读性。“frontend”部分描述了一组接受客户端连接的侦听套接字。“backend”部分描述了一组服务器,代理将连接到这些服务器以转发传入的连接。“listen”部分定义了一个完整的代理,其前端和后端部分合并在一个部分中。它通常对仅 TCP 流量有用。所有代理名称必须由大写和小写字母、数字、“-”号、“_”下划线、“.”点和“:”冒号组成。ACL 名称区分大小写,这意味着“www”和“WWW”是两个不同的代理。历史上,所有代理名称都可以重叠,这只会导致日志中的麻烦。自内容切换引入以来,具有重叠功能(前端/后端)的两个代理必须具有不同的名称。但是,前端和后端仍然可以共享相同的名称,因为这种配置似乎很常见。目前,支持两种主要的代理模式:“tcp”,也称为第 4 层,和“http”,也称为第 7 层。在第 4 层模式下,HAProxy 仅在两端之间转发双向流量。在第 7 层模式下,HAProxy 分析协议,并可以通过允许、阻止、切换、添加、修改或删除任意内容来与协议交互,基于任意标准。在 HTTP 模式下,在连接上传输的请求和响应上执行的处理取决于前端的 HTTP 选项和后端的组合。HAProxy 支持 3 种连接模式:- KAL:保持活动(“<a href="#option%20http-keep-alive">option http-keep-alive”),这是默认模式:所有请求和响应都被处理,连接在响应和新请求之间保持打开但空闲。- TUN:隧道(“<a href="#option%20http-tunnel">option http-tunnel”)が通販できます是从 1.0 到 1.5-dev21 版本开始的默认模式:只处理第一个请求和响应,所有其他内容都会被转发而没有任何分析。此模式不应使用,因为它会导致日志记录和 HTTP 处理出现大量问题。而且因为它不能在 HTTP/2 中工作,此选项已弃用,并且仅在旧版 HTTP 前端上支持。在 HTX 中,它会被忽略,并在 HAProxy 启动期间发出警告。- SCL:服务器关闭(“<a href="#option%20http-server-close">option http-server-close”)が通販できます:服务器连接在收到响应结束时关闭,但客户端连接保持打开状态。- CLO:关闭(“<a href="#option%20httpclose">option httpclose”)が通販できます:连接在收到响应结束后关闭,并在两个方向上都添加“Connection: close”标头。将应用于通过前端和后端连接的连接的有效模式可以根据上述矩阵由两个代理模式确定,但简而言之,模式是对称的,保持活动是最弱的选项,关闭是最强的。Backend mode | KAL | SCL | CLO ----+-----+-----+---- KAL | KAL | SCL | CLO ----+-----+-----+---- TUN | TUN | SCL | CLO Frontend ----+-----+-----+---- mode SCL | SCL | SCL | CLO ----+-----+-----+---- CLO | CLO | CLO | CLO
支持以下关键字列表。它们中的大多数只能在有限的段落类型中使用。其中一些被标记为“已弃用”,因为它们继承自一个可能令人困惑或功能有限的旧语法,并且有新的推荐关键字来替换它们。 标有“(*)”的关键字可以选择性地使用“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 节。
向系统提供关于期望的监听队列(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-check send-state”可以告知服务器的负载情况。source 源 IP 地址被哈希并除以运行服务器的总权重,以指定将接收请求的服务器。只要没有服务器宕机或启动,这就能确保相同的客户端 IP 地址始终到达同一台服务器。如果由于运行服务器数量的变化导致哈希结果发生变化,许多客户端将被重定向到不同的服务器。此算法通常在不支持插入 cookie 的 TCP 模式下使用。它也可以在 Internet 上使用,为拒绝会话 cookie 的客户端提供最佳的粘性。此算法默认是静态的,这意味着动态更改服务器权重将不起作用,但可以使用“hash-type”进行更改。uri 此算法哈希 URI 的左侧部分(问号之前)或整个 URI(如果存在“whole”参数),然后将哈希值除以运行服务器的总权重。结果指定将接收请求的服务器。只要没有服务器启动或宕机,这就能确保相同的 URI 始终被定向到同一台服务器。这与代理缓存和防病毒代理一起使用,以最大化缓存命中率。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着动态更改服务器权重将不起作用,但可以使用“hash-type”进行更改。此算法支持两个可选参数“len”和“depth”,后面都跟着一个正整数。当需要仅基于 URI 的开头来平衡服务器时,这些选项可能很有用。“len”参数表示算法在计算哈希时仅考虑 URI 开头的字符数。请注意,“len”设置为 1 很少有意义,因为大多数 URI 都以“/”开头。“depth”参数表示用于计算哈希的最大目录深度。每个斜杠计为一个级别。如果同时指定了这两个参数,则在达到其中一个时评估停止。url_param 参数将在每个 HTTP GET 请求的查询字符串中查找参数。如果使用“check_post”修饰符,则会在 HTTP POST 请求实体中搜索参数,当它未在 URL 中问号(?)之后的查询字符串中找到时。消息体将在收到广告数据量或请求缓冲区已满后才开始分析。在极少数情况下使用分块编码时,只扫描第一个分块。由分块边界分隔的参数值可能会随机平衡,如果存在的话。此关键字过去支持一个可选的 <max_wait> 参数,但现在已被忽略。如果找到参数后跟等号(=)和一个值,则该值将被哈希并除以运行服务器的总权重。结果指定将接收请求的服务器。这用于跟踪请求中的用户标识符,并确保只要没有服务器宕机或启动,相同的用户 ID 始终发送到同一台服务器。如果未找到值或未找到参数,则应用轮询算法。请注意,此算法只能在 HTTP 后端中使用。此算法默认是静态的,这意味着动态更改服务器权重将不起作用,但可以使用“hash-type”进行更改。hdr(<name>) 将在每个 HTTP 请求中查找 HTTP 标头 <name>。就像等效的 ACL 'hdr()' 函数一样,括号中的标头名称不区分大小写。如果标头不存在或不包含任何值,则改为应用轮询算法。可选的“use_domain_only”参数可用,用于将哈希算法简化为主域部分,适用于某些特定标头,如“Host”。例如,在“haproxy.1wt.eu”的 Host 值中,仅考虑“1wt”。此算法默认是静态的,这意味着动态更改服务器权重将不起作用,但可以使用“hash-type”进行更改。random random(<draws>) 将使用一个随机数作为一致性哈希函数的键。这意味着服务器的权重得到尊重,动态权重更改立即生效,新服务器的添加也如此。随机负载均衡在大型服务器场或服务器频繁添加或移除时可能很有用,因为它可以避免在此情况下可能出现的轮询或 leastconn 的冲击效应。“hash-balance-factor”指令可用于进一步提高负载均衡的公平性,尤其是在服务器显示高度可变响应时间的情况下。当存在参数 <draws> 时,它必须是一个大于或等于一的整数值,表示在选择这些服务器中负载最少的服务器之前的抽取次数。事实上,已证明选择两台服务器中负载最少的服务器足以显著提高算法的公平性,通过始终避免选择服务器场中最负载的服务器,并消除一致性列表不公平分布可能引起的任何偏差。较高的值 N 将以性能为代价移除 N-1 个负载最高的服务器。对于非常高的值,该算法将收敛到 leastconn 的结果,但速度慢得多。默认值为 2,通常显示非常好的分布和性能。此算法也称为“Power of Two Random Choices”,其描述如下:http://www.eecs.harvard.edu/~michaelm/postscripts/handbook2001.pdf rdp-cookie rdp-cookie(<name>) 将为每个传入的 TCP 请求查找并哈希 RDP cookie <name>(如果省略则为“mstshash”)。就像等效的 ACL 'req.rdp_cookie()' 函数一样,名称不区分大小写。此机制可用作降级持久性模式,因为它使得能够始终将同一用户(或同一会话 ID)发送到同一台服务器。如果未找到 cookie,则使用正常的轮询算法。请注意,要使此功能生效,前端必须确保 RDP cookie 已存在于请求缓冲区中。为此,您必须使用 'tcp-request content accept' 规则并结合 'req.rdp_cookie_cnt' ACL。此算法默认是静态的,这意味着动态更改服务器权重将不起作用,但可以使用“hash-type”进行更改。<arguments> 是某些算法可能需要的可选参数列表。目前,只有“url_param”和“uri”支持可选参数。
当没有设置其他算法、模式或选项时,后端的负载均衡算法被设置为 roundrobin。每个后端只能设置一次算法。对于需要相同连接的认证方案(如 NTLM),不得使用基于 URI 的算法,因为它们会导致后续请求被路由到不同的后端服务器,从而破坏 NTLM 所依赖的无效假设。
balance roundrobin balance url_param userid balance url_param session_id check_post 64 balance hdr(User-Agent) balance hdr(host) balance hdr(Host) use_domain_only
注意:使用“check_post”扩展与“url_param”的以下注意事项和限制必须予以考虑:- 所有 POST 请求都有资格被考虑,因为无法确定参数是否会在包含二进制数据的正文或实体中找到。因此,可能需要另一种方法来限制对正文中没有 URL 参数的 POST 请求的考虑。(请参阅 acl 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 必须已绑定,并且可能已监听,也可能尚未监听。- 'sockpair@<n>' -> 类似于 fd@,但您必须使用已连接的 Unix 套接字或 socketpair 的 fd。绑定会等待通过 Unix 套接字接收 FD,并将其用作 accept() 的 FD。应谨慎使用。您可能希望在地址参数中引用某些环境变量,请参阅第 2.3 节关于环境变量。<port_range> 是一个唯一的 TCP 端口,或者是一个端口范围,代理将接受指定 IP 地址的连接。对于 TCP 监听器,端口是强制性的。请注意,对于 IPv6 地址,端口始终是最后一个冒号 (':') 之后的数字。范围可以是:- 数字端口(例如:'80')- 以破折号分隔的端口范围,明确说明下限和上限(例如:'2000-2100'),这些端口都包含在范围内。对于端口范围必须格外小心,因为每个 <address:port> 对都会消耗一个套接字(=一个文件描述符),因此很容易通过一个简单的范围消耗大量描述符,并耗尽套接字。此外,每个 <address:port> 对在同一系统上运行的所有实例中只能使用一次。请注意,绑定到低于 1024 的端口通常需要特殊的权限才能启动程序,这与 'uid' 参数无关。<path> 是以斜杠 ('/') 开头的 UNIX 套接字路径。这是 TCP 监听端口的替代方案。HAProxy 然后将在该位置找到的套接字上接收 UNIX 连接。路径必须以斜杠开头,并且默认是绝对路径。它可以是相对于全局部分中由“unix-bind”定义的任何前缀。请注意,前缀加上套接字路径的总长度不能超过某些系统对 UNIX 套接字的限制,这些限制通常设置为 107 个字符。<param*> 是同一行上声明的所有套接字的通用参数列表。这些众多参数取决于操作系统和构建选项,并为此提供了一个完整的章节。请参阅第 5 节以获取更多详细信息。
可以指定由逗号分隔的地址:端口组合列表。然后前端将侦听所有这些地址。前端可以侦听的地址和端口数量没有固定限制,前端中的“bind”语句的数量也没有限制。listen http_proxy bind :80,:443 bind 10.0.0.1:10080,10.0.0.1:10443 bind /var/run/ssl-frontend.sock user root mode 600 accept-proxy listen http_https_proxy bind :80 bind :443 ssl crt /etc/haproxy/site.pem listen http_https_proxy_explicit bind ipv6@:80 bind ipv4@public_ssl:443 ssl crt /etc/haproxy/site.pem bind unix@ssl-frontend.sock user root mode 600 accept-proxy listen external_bind_app1 bind "fd@${FD_APP1}"
注意:关于 Linux 的抽象命名空间套接字,HAProxy 使用整个 sun_path 长度作为地址长度。其他一些程序,如 socat,默认只使用字符串长度。在 socat 中对任何抽象套接字定义传递选项 ",unix-tightsocklen=0",以使其与 HAProxy 兼容。
将一个实例的可见性限制在特定的进程号集合中。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
all 所有进程都将看到此实例。这是默认设置。它可用于覆盖默认值。 odd 此实例将在进程 1、3、5、...、63 上启用。此选项可与其他数字组合使用。 even 此实例将在进程 2、4、6、...、64 上启用。此选项可与其他数字组合使用。如果进程少于 2 个,请不要使用它,否则某些实例可能会在所有进程中都缺失。 process_num 此实例将在此进程号或范围内启用,其值必须全部在 1 到 32 或 64 之间,具体取决于机器的字长。范围可以部分定义。可以省略上限。在这种情况下,它将被相应的最大值替换。如果一个代理被绑定到大于配置的 global.nbproc 的进程号,如果指定了单个进程,它将被强制到进程 #1,否则将被强制到所有进程。
此关键字限制某些实例绑定到某些进程。这有助于避免太多进程监听同一端口。例如,在双核机器上,可以在全局部分设置 'nbproc 2',然后将监听器分布在 'odd' 和 'even' 实例之间。目前,无法使用此关键字引用超过 32 或 64 个进程,但这对于大多数设置来说应该绰绰有余。请注意,“all”确实意味着所有进程,无论机器的字长如何,并且不限于前 32 或 64 个。每个“bind”行可以进一步限制为代理进程的子集,请参阅第 5.1 节中的“process”绑定关键字。当一个前端没有显式的“bind-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 |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
如果匹配 <condition>(或除非匹配),HTTP 请求将在第 7 层处理过程中非常早地被阻止。如果请求被阻止,将返回 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 名称和值的应用服务器(例如 ASPSESSIONXXX)很有用。<length> 是日志中报告的最大字符数,包括 cookie 名称、等号和值,全部采用标准的 "name=value" 格式。如果字符串超过 <length>,它将被从右侧截断。
仅捕获第一个 cookie。请求标头“cookie”和响应标头“set-cookie”都会被监控。这对于检查导致用户之间会话交叉或盗用的应用程序错误特别有用,因为通常用户的 cookie 只能在登录页面上更改。当客户端未提供 cookie 时,关联的日志列将报告“-”。当请求未导致服务器分配 cookie 时,响应列中将报告“-”。捕获仅在前段执行,因为日志格式对于给定的前端不应因后端而改变。这将来可能会改变。请注意,每个前端只能有一个“capture cookie”语句。最大捕获长度由全局“tune.http.cookielen”设置确定,默认为 63 个字符。无法在“defaults”部分指定捕获。
capture cookie ASPSESSION len 32
捕获并记录指定请求头的最后一次出现。
可在以下部分中使用
| 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 模式下程度较轻),强烈建议客户端超时与服务器超时保持一致,以避免复杂的调试情况。良好的做法是覆盖一个或多个 TCP 数据包丢失,通过指定略高于 3 秒倍数的超时时间(例如 4 或 5 秒)。此参数特定于前端,但可以一次性在“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、201、202 或 203 之一* 响应既不包含“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”标头或多个 ETag 标头注意:压缩不会发出 Warning 标头。
compression algo gzip compression type text/html text/plain
设置等待服务器连接尝试成功的最大时间。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 超时值默认以毫秒为单位指定,但也可以是任何其他单位,如果数字后跟有单位后缀,如本文档开头所述。
如果服务器与 haproxy 位于同一局域网,连接应该是即时的(在几毫秒内)。无论如何,覆盖一个或多个 TCP 数据包丢失的良好做法是指定略高于 3 秒倍数的超时时间(例如 4 或 5 秒)。默认情况下,连接超时还会将队列超时设置为相同的值,如果该值未指定的话。历史上,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 在服务器响应中插入持久性 cookie。当不带“preserve”选项使用时,如果服务器发出同名 cookie,将在处理前将其删除。因此,此模式可用于升级在“rewrite”模式下运行的现有配置。cookie 将仅为会话 cookie,并且不会存储在客户端的磁盘上。默认情况下,除非添加了“indirect”选项,否则服务器将看到客户端发出的 cookie。由于缓存效果,通常明智的做法是添加“nocache”或“postonly”关键字(见下文)。“insert”关键字与“rewrite”和“prefix”不兼容。prefix 此关键字表示不是依赖于专用的 cookie 进行持久性,而是将完成一个现有的 cookie。当客户端不支持不止一个 cookie 并且应用程序已经需要它时,这在某些特定环境中可能是必需的。在这种情况下,每当服务器设置一个名为 <name> 的 cookie 时,它都会被服务器标识符和一个分隔符前缀。前缀将从所有客户端请求中删除,以便服务器仍然找到它发出的 cookie。由于所有请求和响应都可能被修改,因此此模式在隧道模式下不起作用。“prefix”关键字与“rewrite”和“insert”不兼容。注意:强烈建议不要将“indirect”与“prefix”一起使用,否则服务器 cookie 更新将不会发送给客户端。indirect 指定此选项时,如果客户端已经有一个有效的 cookie 用于处理请求的服务器,则不会向客户端发出 cookie。如果服务器自身设置了这样的 cookie,它将被删除,除非还设置了“preserve”选项。在“insert”模式下,这还会从传输到服务器的请求中删除 cookie,使持久性机制从应用程序的角度完全透明。注意:强烈建议不要将“indirect”与“prefix”一起使用,否则服务器 cookie 更新将不会发送给客户端。nocache 此选项建议与 insert 模式结合使用,当客户端和 HAProxy 之间存在缓存时,它确保可缓存的响应将被标记为不可缓存,如果需要插入 cookie。这很重要,因为如果所有持久性 cookie 都添加到可缓存的主页上,例如,那么所有客户将从外部缓存获取页面,并将共享相同的持久性 cookie,导致一台服务器接收的流量比其他服务器多得多。另请参阅“insert”和“postonly”选项。postonly 此选项确保 cookie 插入仅在 POST 请求的响应上执行。它是“nocache”选项的替代方案,因为 POST 响应不可缓存,因此可以确保持久性 cookie 永远不会被缓存。由于大多数站点在第一次 POST 请求(通常是登录请求)之前不需要任何形式的持久性,因此这是一种无需冒缓存风险即可优化缓存的非常有效的方法。另请参阅“insert”和“nocache”选项。preserve 此选项只能与“insert”和/或“indirect”一起使用。它允许服务器自身发出持久性 cookie。在这种情况下,如果在响应中找到 cookie,haproxy 将保持不变。这对于在注销请求后结束持久性很有用(例如)。为此,服务器只需发出一个具有无效值(例如空)或过去日期的 cookie。通过将此机制与“disable-on-404”检查选项结合使用,可以执行完全优雅的关闭,因为用户在注销后肯定会离开服务器。httponly 此选项指示 haproxy 在插入 cookie 时添加“HttpOnly”cookie 属性。此属性用于确保用户代理不会将 cookie 与非 HTTP 组件共享。请参阅 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 没有日期时,它总是被接受,但在响应中会刷新。这保持了管理员访问其网站的能力。未来日期超过 24 小时的 cookie 将被忽略。这样做可以让管理员修复时区问题,而不会冒险将用户踢出网站。maxlife 此选项允许在一定寿命后忽略插入的 cookie,无论它们是否在使用中。它仅适用于 insert 模式的 cookie。当 cookie 首次发送给客户端时,cookie 发出的日期也会发送。在后续呈现此 cookie 时,如果日期早于参数指示的延迟(以秒为单位),它将被忽略。如果请求中的 cookie 没有日期,它将被接受并设置日期。未来日期超过 24 小时的 cookie 将被忽略。这样做可以让管理员修复时区问题,而不会冒险将用户踢出网站。与 maxidle 不同,此值不会刷新,只有第一次访问日期才算。maxidle 和 maxlife 都可以同时使用。这对于防止从不关闭浏览器的用户在同一服务器上停留时间过长(例如,在服务器场大小更改后)特别有用。这比 maxidle 方法更强大,因为它强制在一定的绝对延迟后重新分派。dynamic 激活动态 cookie。使用时,将根据服务器的 IP 和端口以及在“dynamic-cookie-key”后端指令中指定的密钥,为每个服务器动态创建一个会话 cookie。每次 IP 地址更改时都会重新生成 cookie,并且仅为 IPv4/IPv6 生成。attr 此选项指示 haproxy 在插入 cookie 时添加一个额外的属性。属性值可以包含除控制字符或“;”之外的任何字符。此选项可以重复。
每个 HTTP 后端只能有一个持久性 Cookie,它可以在 defaults 部分声明。Cookie 的值将是 "cookie" 关键字后指示的值,在 "server" 语句中。如果未为特定服务器声明 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" 用于禁用实例,主要目的是释放监听端口或临时禁用服务。实例仍将被创建,其配置也将被检查,但它将以“已停止”状态创建,并在统计信息中显示。它不会接收任何流量,也不会发送任何健康检查或日志。通过在 "defaults" 部分添加关键字 "disabled" 可以一次禁用多个实例。
设置一个默认服务器地址
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<address> 是默认服务器的 IPv4 地址。或者,也支持可解析的主机名,但此名称将在启动期间解析。<ports> 是一个强制性的端口规范。所有连接都将发送到此端口,并且不允许像普通服务器那样使用端口偏移量。
关键字 "dispatch" 指定了一个默认服务器,用于在没有其他服务器可以接受连接时使用。过去,它曾用于将非持久性连接转发到辅助负载均衡器。由于其简单的语法,它也被用于简单的 TCP 转发。为了更清晰起见,不建议使用它,而应使用 "server" 指令代替。
为后端设置动态 cookie 的密钥。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
当启用动态 Cookie 时(请参阅 Cookie 的 "dynamic" 指令),系统会为每个服务器创建一个动态 Cookie(除非在 "server" 行上明确指定),使用服务器 IP 地址、TCP 端口和密钥的哈希值。这样,即使服务器动态添加或删除,我们也可以确保多个负载均衡器之间的会话持久性。启用一个 proxy、frontend 或 backend。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
关键字 "enabled" 用于显式启用一个实例,当默认设置为 "disabled" 时。这种情况很少使用。
返回文件内容以替代 HAProxy 生成的错误
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、403、404、405、408、410、413、425、429、500、502、503 和 504 代码。<file> 表示包含完整 HTTP 响应的文件。建议遵循将 ".http" 追加到文件名上的通用做法,以便人们不会将响应与 HTML 错误页面混淆,并且使用绝对路径,因为文件是在执行任何 chroot 之前读取的。
重要的是要理解,此关键字并非旨在重写服务器返回的错误,而是重写 HAProxy 检测并返回的错误。因此,支持的错误列表仅限于一小组。响应代码 200 会在匹配 "monitor-uri" 规则的请求中发出。文件将按原样返回到 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、404、405、408、410、413、425、429、500、502、503 和 504 代码。<url> 是 "Location" 标头的确切内容。它可以包含到同一站点上托管的错误页面的相对 URI,也可以包含指向其他站点上错误页面的绝对 URI。应特别注意相对 URI,以避免在 URI 本身可能产生相同错误(例如 500)时发生重定向循环。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 302 状态码,它告诉客户端使用相同的 HTTP 方法获取指定的 URL。对于非 GET 方法(如 POST),这可能会很有问题,因为发送给客户端的 URL 可能不允许 GET 以外的方法。要解决此问题,请使用“errorloc303”,它会发送 HTTP 303 状态码,指示客户端必须使用 GET 请求获取该 URL。
返回一个到某个 URL 的 HTTP 重定向,以替代 HAProxy 生成的错误
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
<code> 是 HTTP 状态码。目前,HAProxy 能够生成 200、400、403、404、405、408、410、413、425、429、500、502、503 和 504 代码。<url> 是 "Location" 标头的确切内容。它可以包含到同一站点上托管的错误页面的相对 URI,也可以包含指向其他站点上错误页面的绝对 URI。应特别注意相对 URI,以避免在 URI 本身可能产生相同错误(例如 500)时发生重定向循环。
重要的是要理解,此关键字并非用于重写服务器返回的错误,而是用于重写 HAProxy 检测并返回的错误。这就是为什么支持的错误列表仅限于一小部分。状态码 200 是为响应匹配“monitor-uri”规则的请求而发出的。请注意,这两个关键字都返回 HTTP 303 状态码,它告诉客户端使用相同的 HTTP GET 方法获取指定的 URL。这解决了与“errorloc”和 302 状态码相关的常见问题。一些在 HTTP/1.1 之前设计的非常旧的浏览器可能不支持它,但到目前为止还没有报告过此类问题。
声明用于电子邮件警报的信封和头部的发件人电子邮件地址。这是发送电子邮件警报的来源地址。
可在以下部分中使用
| 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”,如果设置了,则为该代理启用电子邮件警报发送功能。
声明邮件警报信封中的收件人地址和邮件头中的 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 会自动将其设置为可能连接到此后端的所有前端的最大连接数总和的 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。此设置也由 "balance random" 使用,它内部依赖于一致性哈希机制。
指定一种将哈希值映射到服务器的方法
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<method> 是用于从 <function> 计算的哈希中选择服务器的方法:基于映射的哈希表是一个包含所有活动服务器的静态数组。哈希将非常平滑,将考虑权重,但将是静态的,因为在服务器处于活动状态时更改权重将被忽略。这意味着不会有缓慢启动。此外,由于服务器是通过其在数组中的位置选择的,因此当服务器计数更改时,大多数映射都会被更改。这意味着当服务器启动或关闭,或者当服务器添加到某个服务器场时,大多数连接将被重新分发到不同的服务器。这可能不方便,例如对缓存而言。一致的哈希表是一个填充了服务器多个副本的树。在树中查找哈希键并选择最近的服务器。此哈希是动态的,它支持在服务器处于活动状态时更改权重,因此与缓慢启动功能兼容。它的优点是当服务器启动或关闭时,只有它的关联会被移动。当服务器添加到服务器场时,只有一小部分映射会被重新分发,这使其成为缓存的理想方法。但是,由于其原理,分布永远不会非常平滑,有时可能需要调整服务器的权重或其 ID 以获得更均衡的分布。为了在多个负载均衡器上获得相同的分布,所有服务器具有完全相同的 ID 非常重要。注意:如果未指定哈希函数,一致性哈希会使用 sdbm 和 avalanche。<function> 是要使用的哈希函数:sdbm 此函数最初是为 sdbm(ndbm 的公共领域重新实现)数据库库创建的。它在打乱位方面表现良好,导致键的分布更好,并且拆分更少。它碰巧也是一个好的通用哈希函数,分布良好,除非总服务器权重是 64 的倍数,在这种情况下,应用 avalanche 修改器可能会有帮助。djb2 此函数多年前由 Dan Bernstein 在 comp.lang.c 上首次提出。研究表明,对于某些工作负载,此函数比 sdbm 提供更好的分布。它通常适用于基于文本的输入,尽管它在仅数字输入或总服务器权重是 33 的倍数时可能表现非常差,除非还使用了 avalanche 修改器。wt6 此函数是在过去测试其他函数时为 haproxy 设计的。它不像其他函数那样平滑,但对输入数据集或服务器数量的敏感度要低得多。它可以作为 sdbm+avalanche 或 djb2+avalanche 的替代方案,用于一致性哈希或在哈希数字数据(如源 IP 地址或 URL 参数中的访问者标识符)时使用。crc32 这是以太网、gzip、PNG 等中使用的最常见的 CRC32 实现。它比其他函数慢,但在提供更好的分布或更不可预测的结果方面可能更好,尤其是在字符串上使用时。<modifier> 表示在哈希键之后应用的可选方法:avalanche 此指令表示上述哈希函数的结果不应以其原始形式使用,而应先应用一个 4 字节的完整 avalanche 哈希。此步骤的目的是混合前一个哈希的结果位,以避免在输入包含某些有限值或服务器数量是哈希组件之一(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 |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
hdr <name> <value> 在 HTTP 健康检查期间发送的请求中添加指定名称为 <name> 且值定义为 <value> 的 HTTP 头字段。body <string> 在 HTTP 健康检查期间发送的请求中添加由 <string> 定义的请求体。如果定义了,"Content-Length" 头将自动添加到请求中。
除了由 "option httpchk" 指令定义的请求行之外,这是在 HTTP 健康检查期间发送的请求中添加一些头并可选地添加正文的有效方法。如果定义了正文,则会自动添加关联的 "Content-Length" 头。在 "option httpchk" 行的协议版本字符串后添加头的老技巧现在已弃用。另请注意,如果定义了 "http-check expect" 指令(与此指令无关),则仍然会添加 "Connection: close" 头,就像如果定义了 "http-check send-state" 指令一样,也会添加状态头。
启用在 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 的条件,在这种情况下,只有当条件为真时才会对其进行评估。第一个关键字是规则的操作。支持的操作将在下面描述。每个实例的 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 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
此操作用于向 ACL 中添加一个新条目。ACL 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集新条目的内容。它在插入前会先在 ACL 中进行查找,以避免重复(或更多)的值。此查找通过线性搜索完成,对于大列表可能会很耗费资源!它等同于 stats socket 中的“add acl”命令,但可以由 HTTP 请求触发。
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循日志格式规则(请参阅 第 8.2.4 节 中的自定义日志格式)。这对于向服务器传递特定于连接的信息(例如,客户端的 SSL 证书)或将多个头部合并为一个特别有用。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
这会停止规则的评估,并允许请求通过检查。不会再评估任何 "http-request" 规则。这会停止规则的评估,并立即以 HTTP 401 或 407 错误代码响应,以提示用户提供有效的用户名和密码。不会再评估任何 "http-request" 规则。支持可选的 "realm" 参数,它设置返回响应的身份验证领域(通常是应用程序的名称)。acl auth_ok http_auth_group(L1) G1 http-request auth unless auth_ok
有关缓存设置,请参阅 第 10.2 节。
这会将样本表达式 <sample> 从请求缓冲区捕获,并将其转换为最多 <len> 个字符的字符串。生成的字符串存储在下一个请求的 "capture" 插槽中,因此它可能出现在一些捕获的 HTTP 标头旁边。然后它将自动显示在日志中,并且可以通过样本提取规则进行提取,将其馈送到标头或其他任何地方。长度应该受到限制,因为在整个会话生命周期中,每个捕获都需要分配此大小。有关更多信息,请检查 第 7.3 节(获取样本)和 "capture request header"。如果使用 "id" 关键字而不是 "len",则操作会尝试将捕获的字符串存储在先前声明的捕获插槽中。这在后端运行捕获时非常有用。插槽 ID 可以通过之前的指令 "http-request capture" 或使用 "declare capture" 关键字声明。在后端使用此操作时,请仔细检查相关的 frontend 是否具有所需的捕获插槽,否则,该规则将在运行时被忽略。由于 HAProxy 能够在运行时动态解析后端名称,因此在配置解析时无法检测到这一点。
此操作用于从 ACL 中删除一个条目。ACL 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集要删除的条目的内容。它等同于 stats socket 中的“del acl”命令,但可以由 HTTP 请求触发。
这会删除指定名称为 <name> 的所有 HTTP 头字段。
此操作用于从 MAP 中删除一个条目。MAP 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,该参数遵循日志格式规则,用于收集要删除的条目的内容。它接受一个参数:“file name”。它等同于 stats socket 中的“del map”命令,但可以由 HTTP 请求触发。
这会停止规则的评估,并立即拒绝请求并发出 HTTP 403 错误,或者可选地发出 "deny_status" 参数指定的状态码。允许的状态码列表仅限于可以通过 "errorfile" 指令覆盖的状态码。不会再评估任何 "http-request" 规则。
此操作会禁止任何因连接失败以外的原因而重试请求的尝试。例如,这对于确保 POST 请求在失败时不会被重试非常有用。
此操作对 <expr> 的输出执行 DNS 解析,并将结果存储在变量 <var> 中。它使用由 <resolvers> 指向的 DNS 解析器部分。可以使用可选参数 'ipv4' 或 'ipv6' 选择解析偏好。执行 DNS 解析时,客户端连接会暂停,等待解析结束。如果能找到 IP 地址,它将被存储到 <var> 中。如果发生任何类型的错误,则 <var> 不会被设置。可以使用此操作在运行时根据请求中的信息(即 Host 头部)发现服务器 IP 地址。如果此操作用于查找服务器的 IP 地址(使用 "set-dst" 操作),则后端中的服务器 IP 地址必须设置为 0.0.0.0。do-resolve 操作接受一个仅主机参数,任何端口都必须从字符串中移除。
resolvers mydns nameserver local 127.0.0.53:53 nameserver google 8.8.8.8:53 timeout retry 1s hold valid 10s hold nx 3s hold other 3s hold obsolete 0s accepted_payload_size 8192 frontend fe bind 10.42.0.1:80 http-request do-resolve(txn.myip,mydns,ipv4) hdr(Host),lower,regsub(:[0-9]*$,) http-request capture var(txn.myip) len 40 # 当变量未设置时返回 503, # 表示 DNS 解析错误 use_backend b_503 unless { var(txn.myip) -m found } default_backend be backend b_503 # 用于返回 503 的虚拟后端。 # 可以使用 errorfile 指令向最终用户发送一个友好的 # 503 错误页面 backend be # 防止 HAProxy 重新连接到本地网络上的服务 # (使用的伪造 DNS 名称用于扫描网络) http-request deny if { var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 } http-request set-dst var(txn.myip) server clear 0.0.0.0:0
注意:不要忘记设置“保护”规则,以确保 HAProxy 不会被用于扫描网络,或更糟糕的是,不会循环访问自身……
此操作用于在任何其他响应之前构建一个 HTTP 103 Early Hints 响应。此操作向此响应附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由 <fmt> 定义,<fmt> 遵循日志格式规则(请参阅 第 8.2.4 节 中的自定义日志格式)。这对于向客户端传递一些 Link 头部以预加载渲染 HTML 文档所需的资源特别有用。更多信息请参阅 RFC 8297。
这会根据重定向规则执行 HTTP 重定向。这与 "redirect" 语句完全相同,只是它插入了一个重定向规则,该规则可以在其他 "http-request" 规则的中间进行处理,并且这些规则使用 "log-format" 字符串。有关规则语法,请参阅 "redirect" 关键字。
这会停止规则的评估,并立即关闭连接而不发送任何响应。它的作用类似于“tcp-request content reject”规则。强制关闭 HTTP/2 连接可能很有用。
此操作将头部字段 <名称> 的所有出现的值与 <匹配正则表达式> 进行匹配。匹配是区分大小写的。匹配的值将被 <替换格式> 完全替换。在 <替换格式> 中允许使用格式化字符,其工作方式类似于“http-request add-header”中的 <fmt> 参数。支持使用反斜杠 ('\') 后跟数字的标准后向引用。此操作作用于整个头部行,无论它们可能包含多少个值。因此,它非常适合处理值中自然包含逗号的头部,例如 If-Modified-Since。包含逗号分隔值列表的头部,例如 Accept,应使用“http-request replace-value”进行处理。
http-request replace-header Cookie foo=([^;]*);(.*) foo=\1;ip=%bi;\2 # 应用于: Cookie: foo=foobar; expires=Tue, 14-Jun-2016 01:40:45 GMT; # 输出: Cookie: foo=foobar;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT; # 假设后端 IP 是 192.168.1.20 http-request replace-header User-Agent curl foo # 应用于: User-Agent: curl/7.47.0 # 输出: User-Agent: foo
此操作的工作方式类似于“replace-header”,但它作用于请求的路径组件而不是头部。路径组件从可选的协议+授权之后第一个'/'开始,到问号之前结束。因此,替换不会修改协议、授权和查询字符串。值得注意的是,正则表达式的评估可能比某些 ACL 更昂贵,因此对于罕见的替换,使用条件来避免在不匹配时执行评估可能会更有利。
# 在 /foo 前加上前缀:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-path (.*) /foo\1 # 去除 /foo:将 /foo/bar?q=1 变为 /bar?q=1 http-request replace-path /foo/(.*) /\1 # 或者如果只有部分请求匹配,这样更高效: http-request replace-path /foo/(.*) /\1 if { url_beg /foo/ }
这与 "replace-header" 的工作方式相同,只不过它作用于请求的 URI 部分而不是标头。URI 部分可以包含可选的方案、权限或查询字符串。这些被视为要匹配的值的一部分。值得注意的是,正则表达式的求值成本可能高于某些 ACL,因此稀疏替换可能需要一个条件来避免执行求值(如果它不匹配)。重要提示:历史上在 HTTP/1.x 中,绝大多数浏览器发送的请求都使用 "origin form",它与 "absolute form" 的不同之处在于它不包含 URI 部分中的方案或权限。主要是发送到代理的请求、手动伪造的请求以及某些应用程序发出的请求使用绝对形式。因此,在 HTTP/1.x 中,对于以 "/" 开头的规则,"replace-uri" 通常都可以正常工作。但对于 HTTP/2,鼓励客户端仅发送绝对 URI,这些 URI 的外观与 HTTP/1 客户端在与代理通信时使用的 URI 类似。因此,在 HTTP/2 中,部分 replace-uri 规则在 HTTP/1 中有效时可能会失败。要么需要修改规则以可选地匹配方案和权限,要么应该使用 replace-path。
# 将所有 "http" 绝对请求重写为 "https": http-request replace-uri ^http://(.*) https://\1 # 添加前缀 /foo:将 /bar?q=1 变为 /foo/bar?q=1: http-request replace-uri ([^/:]*://[^/]*)?(.*) \1/foo\2
此操作的工作方式类似于“replace-header”,但它将正则表达式与头部字段 <名称> 的每个逗号分隔的值进行匹配,而不是整个头部。这适用于所有允许携带多个值的头部。例如 Accept 头部。
http-request replace-value X-Forwarded-For ^192\.168\.(.*)$ 172.16.\1 # 应用于: X-Forwarded-For: 192.168.10.1, 192.168.13.24, 10.0.0.37 # 输出: X-Forwarded-For: 172.16.10.1, 172.16.13.24, 10.0.0.37
此操作根据由 <sc-id> 指定的粘性计数器来递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估继续。
此操作根据粘性计数器 (<sc-id>) 和值 (<int>) 设置 GPT0 标记。预期结果是一个布尔值。如果发生错误,此操作将静默失败,并且动作的评估将继续。
此操作用于将目标 IP 地址设置为指定表达式的值。当 HAProxy 前面的代理重写了目标 IP,但在 HTTP 标头中提供了正确的 IP 时,或者您想为隐私目的屏蔽 IP 时,这很有用。如果要连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
http-request set-dst hdr(x-dst) http-request set-dst dst,ipmask(24)
在可能的情况下,只要地址族允许,set-dst 会保留原始目标端口,否则目标端口将被设置为 0。
此操作用于将目标端口地址设置为指定表达式的值。如果要连接到新的地址/端口,请在后端中使用 '0.0.0.0:0' 作为服务器地址。
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
http-request set-dst-port hdr(x-port) http-request set-dst-port int(4000)
在可能的情况下,只要地址族支持端口,set-dst-port 就会保留原始目标地址,否则它会在重写端口之前将目标地址强制设置为 IPv4 "0.0.0.0"。
此操作与“http-request add-header”相同,只是如果头部名称已存在,则会首先删除它。这在向服务器传递安全信息时很有用,因为此时头部不应被外部用户操纵。请注意,新值是在删除之前计算的,因此可以将一个值连接到现有头部。
http-request set-header X-Haproxy-Current-Date %T http-request set-header X-SSL %[ssl_fc] http-request set-header X-SSL-Session_ID %[ssl_fc_session_id,hex] http-request set-header X-SSL-Client-Verify %[ssl_c_verify] http-request set-header X-SSL-Client-DN %{+Q}[ssl_c_s_dn] http-request set-header X-SSL-Client-CN %{+Q}[ssl_c_s_dn(cn)] http-request set-header X-SSL-Issuer %{+Q}[ssl_c_i_dn] http-request set-header X-SSL-Client-NotBefore %{+Q}[ssl_c_notbefore] http-request set-header X-SSL-Client-NotAfter %{+Q}[ssl_c_notafter]
这用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 种 syslog 级别(请参阅“log”关键字)加上特殊级别“silent”,该级别禁用此请求的日志记录。此规则不是最终规则,因此最后一个匹配的规则将生效。此规则可用于禁用来自其他设备的运行状况检查。此操作用于向 MAP 中添加一个新条目。MAP 必须从一个文件加载(即使是一个虚拟的空文件)。要更新的 MAP 的文件名在括号中传递。它需要 2 个参数:<键格式>,它遵循日志格式规则,用于收集 MAP 键;以及 <值格式>,它遵循日志格式规则,用于收集新条目的内容。它在插入前会进行一次 MAP 查找,以避免重复(或更多)的值。此查找通过线性搜索完成,对于大型列表可能会很耗时!它等同于 stats 套接字中的“set map”命令,但可以由 HTTP 请求触发。
在支持的平台上,此操作将 Netfilter MARK 设置为传递给 <mark> 的值,该值将发送到客户端的所有数据包上。该值是一个无符号 32 位值,netfilter 和路由表都可以匹配。它可以表示为十进制或十六进制格式(以“0x”为前缀)。这对于强制某些数据包采用不同的路由(例如,更便宜的批量下载网络路径)非常有用。这适用于 Linux 内核 2.6.32 及更高版本,并且需要管理员权限。
此操作使用格式化字符串 <fmt> 的求值结果来重写请求方法。这样做应该有极少数的正当理由,因为它更有可能破坏某些东西而不是修复它。
这会设置正在处理的当前请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级越低。较低的值会使请求比其他请求更重要。这有助于提高某些请求的速度,或降低不重要请求的优先级。未经事先试验而使用此设置可能会导致一些严重的减速。
此操作用格式字符串 <格式> 的评估结果重写请求路径。查询字符串(如果存在)保持不变。如果在路径之前找到协议和授权,它们也保持不变。如果请求没有路径(“*”),则此路径将被格式替换。例如,这可用于在路径前添加一个目录组件。另请参见“http-request set-query”和“http-request set-uri”。
# 在路径前添加主机名 http-request set-path /%[hdr(host)]%[path]
此操作用于设置当前请求的队列优先级类别。该值必须是一个样本表达式,其转换结果为 -2047 到 2047 范围内的整数。超出此范围的结果将被截断。优先级类别决定了排队请求的处理顺序。值越低,优先级越高。
此操作用于设置当前请求的队列优先级时间戳偏移量。该值必须是一个样本表达式,其转换结果为 -524287 到 524287 范围内的整数。超出此范围的结果将被截断。当一个请求进入队列时,它首先按优先级类别排序,然后按当前时间戳加上给定的偏移量(以毫秒为单位)进行排序。值越低,优先级越高。请注意,结果时间戳的跟踪精度仅足以表示 524,287 毫秒(8 分 44 秒 287 毫秒)。如果请求排队时间足够长,以至于调整后的时间戳超过此值,它将被错误地识别为最高优先级。因此,将“timeout queue”设置为一个值,使其与偏移量相加后不超过此限制,这一点很重要。
此操作用格式字符串 <格式> 的评估结果重写请求的查询字符串,即第一个问号(“?”)之后的部分。问号之前的部分保持不变。如果请求不包含问号且新值不为空,则在 URI 的末尾添加一个问号,后跟新值。如果问号已存在,即使值为空,它也永远不会被删除。这可用于从查询字符串中添加或删除参数。另请参见“http-request set-query”和“http-request set-uri”。
# 在查询字符串中将“%3D”替换为“=” http-request set-query %[query,regsub(%3D,=,g)]
此操作用于将源 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。
此操作用于将源端口地址设置为指定表达式的值。
<expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
http-request set-src-port hdr(x-port) http-request set-src-port int(4000)
在可能的情况下,只要地址族支持端口,set-src-port 就会保留原始源地址,否则它会在重写端口之前将源地址强制设置为 IPv4 "0.0.0.0"。
此操作用于在支持此功能的平台上,将发送给客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中传递的值。此值代表 IP TOS 字段的全部 8 位,可以用十进制或十六进制格式(以“0x”为前缀)表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的两位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474, 2597, 3260 和 4594。
这会使用格式字符串 <fmt> 的评估结果重写请求 URI。scheme、authority、path 和 query string 会同时被替换。这可以用于在代理前面重写主机,或对 URI 进行复杂修改,例如在 path 和 query string 之间移动部分。另请参阅 "http-request set-path" 和 "http-request set-query"。
此操作用于设置变量的内容。变量是内联声明的。
<var-name> 变量的名称以作用域指示符开头。允许的作用域有:"proc" : 变量在整个进程中共享 "sess" : 变量在整个会话中共享 "txn" : 变量在整个事务(请求和响应)中共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 该前缀后跟一个名称。分隔符是"."。名称只能包含字符 'a-z', 'A-Z', '0-9' 和 '_'。 <expr> 是一个标准的 HAProxy 表达式,由一个 sample-fetch 后跟一些转换器组成。
http-request set-var(req.my_var) req.fhdr(user-agent),lower
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
这会停止规则的评估,并使用系统依赖的方式突然断开面向客户端的连接,试图阻止客户端收到通知。其效果是客户端仍会看到一个已建立的连接,而 HAProxy 上已不存在。目的是实现与“tarpit”类似的效果,只是它根本不使用运行 HAProxy 的机器上的任何本地资源。它可以承受比“tarpit”高得多的负载,并减缓更强的攻击者。理解使用此机制的影响非常重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此受到此操作的影响。在具有足够权限运行的现代 Linux 系统上,将使用 TCP_REPAIR 套接字选项来阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 会减至 1,这样 TCP 重置就不会经过第一个路由器,尽管它仍然会发送到本地网络。请勿使用此功能,除非您完全了解其工作原理。
这会停止规则的评估,并立即阻止请求,在由 "timeout tarpit" 或 "timeout connect"(如果前者未设置)指定的延迟内不响应。在此延迟之后,如果客户端仍然连接,则会返回 HTTP 错误 500(或可选地由 "deny_status" 参数指定的响应码),以便客户端不会怀疑它已被 tarpitted。日志将报告标志 "PT"。tarpit 规则的目标是在攻击期间,当机器人受限于并发请求数量时,减慢其速度。它对非常愚蠢的机器人非常有效,并且与 "deny" 规则相比,可以显着减少防火墙的负载。但是,在面对 "正确" 开发的机器人时,它可能会使情况变得更糟,因为它会迫使 haproxy 和前端防火墙支持数量惊人的并发连接。另请参阅 "silent-drop" 操作。
此操作用于跟踪当前请求的粘性计数器。这些规则不会停止评估,也不会更改默认操作。同一连接可以同时跟踪的计数器数量在构建时设置为 MAX_SESS_STKCTR(在 haproxy -vv 中报告),默认为 3,因此 track-sc 编号在 0 到 (MAX_SESS_STCKTR-1) 之间。第一个执行的 "track-sc0" 规则将指定表的计数器作为第一组进行跟踪。第一个执行的 "track-sc1" 规则将指定表的计数器作为第二组进行跟踪。第一个执行的 "track-sc2" 规则将指定表的计数器作为第三组进行跟踪。建议使用第一组计数器用于 per-frontend 计数器,第二组用于 per-backend 计数器。但这只是一个指南,所有计数器都可以在任何地方使用。
<键> 是强制性的,并且是第 7.3 节中描述的样本表达式规则。它描述了将要分析、提取、组合和用于选择更新哪个表条目计数器的传入请求或连接的元素。 <表> 是一个可选的表,用于替代默认表,默认表是在当前代理中声明的粘性表。然后,所有匹配和更新键的计数器都将在该表中执行,直到会话结束。
一旦执行了“track-sc*”规则,将在表中查找该键,如果未找到,则会为其分配一个条目。然后,在整个会话生命周期内都会保留一个指向该条目的指针,并且该条目的计数器会尽可能频繁地更新,即每当会话的计数器更新时,以及在会话结束时系统性地更新。计数器只为跟踪开始后发生的事件更新。作为一个例外,连接计数器和请求计数器会系统性地更新,以反映有用的信息。如果该条目跟踪并发连接计数器,只要该条目被跟踪,就会计为一个连接,并且在此期间该条目不会过期。跟踪计数器相比仅检查键值还提供了性能优势,因为对于所有使用它的 ACL 检查,都只执行一次表查找。
此操作用于取消设置一个变量。有关 <变量名> 的详细信息,请参见上文。
http-request unset-var(req.my_var)
此指令执行配置的 HTTP 服务以响应请求并停止规则的评估。HTTP 服务可以选择通过发送任何有效的 HTTP 响应来响应,或者它可以立即关闭连接而不发送任何响应。除了本地服务(例如 Prometheus exporter)之外,还可以使用 Lua 编写自己的服务。不会再评估任何进一步的“http-request”规则。<service-name> 是必需的。它是要调用的服务。
http-request use-service prometheus-exporter if { path /metrics }
这会延迟请求的处理,直到 SSL 握手完成。这主要用于延迟处理早期数据,直到我们确定它们是有效的。
第 7 层响应的访问控制
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
http-response 语句定义了一组适用于第 7 层处理的规则。当在 frontend、listen 或 backend 部分遇到这些规则时,它们会按声明顺序进行评估。任何规则都可以选择性地后跟一个基于 ACL 的条件,在这种情况下,只有当条件为真时才会对其进行评估。由于这些规则适用于响应,因此 backend 规则会先应用,然后是 frontend 的规则。第一个关键字是规则的操作。支持的操作如下所述。每个实例的 http-response 语句的数量没有限制。重要的是要知道 http-response 规则在 HTTP 处理的非常早期进行处理,在“rspdel”或“rsprep”或“rspadd”规则之前。这样,几乎所有后续的 ACL 规则都能看到由“add-header”/“set-header”添加的标头。在较新版本(>= 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
这用于将新条目添加到 ACL 中。ACL 必须从文件中加载(即使是空的虚拟文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能会很昂贵!它等同于 stats socket 的 "add acl" 命令,但可以由 HTTP 响应触发。
此操作附加一个 HTTP 头部字段,其名称由 <name> 指定,其值由遵循日志格式规则的 <fmt> 定义(参见 第 8.2.4 节中的自定义日志格式)。例如,这可用于向客户端发送 cookie,或传递一些内部信息。此规则不是最终的,因此可以添加其他类似的规则。请注意,头部添加是立即执行的,因此一个规则可能会重用前一个规则产生的头部。
这会停止规则的评估,并允许响应通过检查。当前部分的任何进一步“http-response”规则都不会再被评估。有关缓存设置,请参阅 第 10.2 节。
这会从响应缓冲区捕获样本表达式 <sample>,并将其转换为字符串。生成的字符串存储在下一个请求的“capture”槽中,因此它可能会出现在某些捕获的 HTTP 标头旁边。然后它将自动出现在日志中,并且可以使用样本提取规则将其提取出来以馈送到标头或其他任何内容。请查看 第 7.3 节(提取样本)和“捕获响应标头”以获取更多信息。关键字“id”是用于存储字符串的捕获槽的 ID。捕获槽必须在关联的 frontend 中定义。这对于在 backend 中运行捕获非常有用。槽 ID 可以通过先前的指令“http-response capture”或使用“declare capture”关键字来声明。在 backend 中使用此操作时,请仔细检查相关的 frontend 是否具有所需的捕获槽,否则,此规则将在运行时被忽略。由于 HAProxy 能够动态解析 backend 名称,因此在配置解析时无法检测到这一点。
这用于从 ACL 中删除条目。ACL 必须从文件中加载(即使是空的虚拟文件)。要更新的 ACL 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它等同于 stats socket 的 "del acl" 命令,但可以由 HTTP 响应触发。
这会删除指定名称为 <name> 的所有 HTTP 头字段。
这用于从 MAP 中删除条目。MAP 必须从文件中加载(即使是空的虚拟文件)。要更新的 MAP 的文件名在括号中传递。它接受一个参数:<key fmt>,遵循 log-format 规则,用于收集要删除的条目的内容。它接受一个参数:"文件名" 它等同于 stats socket 的 "del map" 命令,但可以由 HTTP 响应触发。
这会停止规则的评估,立即拒绝响应并发出 HTTP 502 错误。任何进一步的“http-response”规则都不会再被评估。此操作基于重定向规则执行 HTTP 重定向。它支持与“http-request redirect”规则类似的格式字符串,但例外是响应上只可能进行“location”类型的重定向。有关规则的语法,请参见“redirect”关键字。当在响应期间应用重定向规则时,与服务器的连接将被关闭,以便无法将任何数据从服务器转发到客户端。
此操作的工作方式类似于“http-request replace-header”,但它作用于服务器的响应而不是客户端的请求。
http-response replace-header Set-Cookie (C=[^;]*);(.*) \1;ip=%bi;\2 # 应用于: Set-Cookie: C=1; expires=Tue, 14-Jun-2016 01:40:45 GMT # 输出: Set-Cookie: C=1;ip=192.168.1.20; expires=Tue, 14-Jun-2016 01:40:45 GMT # 假设后端 IP 是 192.168.1.20。
这与“http-response replace-value”的工作方式相同,只是它作用于服务器的响应而不是客户端的请求。
http-response replace-value Cache-control ^public$ private # 应用于: Cache-Control: max-age=3600, public # 输出: Cache-Control: max-age=3600, private
此操作根据 <sc-id> 指定的粘性计数器递增 GPC0 或 GPC1 计数器。如果发生错误,此操作将静默失败,并继续评估操作。
此操作根据粘性计数器 (<sc-id>) 和值 (<int>) 设置 GPT0 标记。预期结果是一个布尔值。如果发生错误,此操作将静默失败,并且动作的评估将继续。
此操作用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果在 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。
<engine-name> SPOE 引擎名称。 <group-name> 在引擎配置中指定的 SPOE 组名称。
这与 "add-header" 的作用相同,只是如果头名称已存在,会先将其删除。当向服务器传递安全信息,且该头不能被外部用户操纵时,这很有用。
这用于在满足特定条件时更改当前请求的日志级别。有效级别是 8 种 syslog 级别(请参阅“log”关键字)加上特殊级别“silent”,该级别禁用此请求的日志记录。此规则不是最终规则,因此最后一个匹配的规则将生效。此规则可用于禁用来自其他设备的运行状况检查。这用于将新条目添加到 MAP 中。MAP 必须从文件中加载(即使是空的虚拟文件)。要更新的 MAP 的文件名在括号中传递。它接受 2 个参数:<key fmt>,遵循 log-format 规则,用于收集 MAP 键,以及 <value fmt>,遵循 log-format 规则,用于收集新条目的内容。它在插入之前执行查找,以避免重复(或更多)值。此查找通过线性搜索完成,对于大型列表可能会很昂贵!它等同于 stats socket 的 "set map" 命令,但可以由 HTTP 响应触发。
在支持的平台上,此操作将 Netfilter MARK 设置为传递给 <mark> 的值,该值将发送到客户端的所有数据包上。该值是一个无符号 32 位值,netfilter 和路由表都可以匹配。它可以表示为十进制或十六进制格式(以“0x”为前缀)。这对于强制某些数据包采用不同的路由(例如,更便宜的批量下载网络路径)非常有用。这适用于 Linux 内核 2.6.32 及更高版本,并且需要管理员权限。
这会设置正在处理的当前请求的 "nice" 因子。它只对同时处理的其他请求有效。默认值为 0,除非在 "bind" 行上的 "nice" 设置进行了更改。可接受的范围是 -1024..1024。值越高,请求的优先级越低。较低的值会使请求比其他请求更重要。这有助于提高某些请求的速度,或降低不重要请求的优先级。未经事先试验而使用此设置可能会导致一些严重的减速。
这将用 <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".
此操作用于在支持此功能的平台上,将发送给客户端的数据包的 TOS 或 DSCP 字段值设置为 <tos> 中传递的值。此值代表 IP TOS 字段的全部 8 位,可以用十进制或十六进制格式(以“0x”为前缀)表示。请注意,DSCP 或 TOS 中仅使用较高的 6 位,而较低的两位始终为 0。这可用于根据请求中的某些信息调整边界路由器上的一些路由行为。有关更多信息,请参阅 RFC 2474, 2597, 3260 和 4594。
此操作用于设置变量的内容。变量是内联声明的。
<var-name> 变量名以其作用域的指示开头。允许的作用域有: “proc”:变量与整个进程共享 “sess”:变量与整个会话共享 “txn”:变量与事务(请求和响应)共享 “req”:变量仅在请求处理期间共享 “res”:变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。 <expr> 是一个标准的 HAProxy 表达式,由一个样本提取后跟一些转换器组成。
http-response set-var(sess.last_redir) res.hdr(location)
这会停止规则的评估,并使用系统依赖的方式突然断开面向客户端的连接,试图阻止客户端收到通知。其效果是客户端仍会看到一个已建立的连接,而 HAProxy 上已不存在。目的是实现与“tarpit”类似的效果,只是它根本不使用运行 HAProxy 的机器上的任何本地资源。它可以承受比“tarpit”高得多的负载,并减缓更强的攻击者。理解使用此机制的影响非常重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此受到此操作的影响。在具有足够权限运行的现代 Linux 系统上,将使用 TCP_REPAIR 套接字选项来阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 会减至 1,这样 TCP 重置就不会经过第一个路由器,尽管它仍然会发送到本地网络。请勿使用此功能,除非您完全了解其工作原理。
此操作用于跟踪当前响应的粘性计数器。请参阅 "http-request track-sc" 以获取完整描述。与 "http-request track-sc" 的唯一区别是 <key> 样本表达式只能使用响应中的样本(例如,res.*、status 等)以及第 6 层以下的样本(例如,SSL 相关样本,请参阅 第 7.3.4 节)。如果样本不支持,haproxy 在解析配置时将失败并发出警告。
这用于取消设置变量。有关 <var-name> 的详细信息,请参阅 "http-response set-var"。
http-response unset-var(sess.last_redir)
声明空闲的 HTTP 连接如何在请求之间共享
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
默认情况下,haproxy 和 backend 服务器之间建立的被认为可以安全重用的连接会被移回服务器的空闲连接池,以便任何其他请求都可以使用它。这是下面的“safe”策略。参数指示所需的连接重用策略:“never”:空闲连接永远不会在会话之间共享。此模式可能被强制执行以取消从 defaults 部分继承的其他策略或用于故障排除。例如,如果一个旧的无效应用程序认为同一个连接上的多个请求来自同一个客户端,并且无法修复该应用程序,那么在单个 backend 中禁用连接共享可能是可取的。一个这样的应用程序示例可能是一个旧的 haproxy,它在隧道模式下使用 cookie 插入,并且不检查任何请求(除了第一个)。“safe”:这是默认的也是推荐的策略。会话的第一个请求始终通过其自己的连接发送,只有后续请求可能在其他现有连接上分发。这确保了如果服务器在发送请求时关闭连接,浏览器可以决定静默重试。由于它与常规的 keep-alive 完全等效,因此应该没有副作用。“aggressive”:此模式在 webservices 环境中可能很有用,在这种环境中,并非所有服务器都被知晓,并且能够通过现有连接分发大多数第一个请求将是可取的。在这种情况下,第一个请求仅在已经至少重用过一次的现有连接上分发,这证明服务器正确支持连接重用。仅当确定客户端可以偶尔重试失败的请求,并且积极连接重用的好处远远大于罕见的连接故障的缺点时,才应使用它。“always”:此模式仅在到服务器的路径已知永远不会在释放连接后很快中断的情况下才推荐。它允许会话的第一个请求被发送到现有连接。当 backend 是缓存场时,这可以比“safe”策略提供显着的性能提升,因为这些组件倾向于表现出一致的行为,并将受益于连接共享。建议在此模式下将“http-keep-alive”超时保持较低,这样就不会有死连接保持可用。在大多数情况下,这将带来与“aggressive”相同的性能提升,但风险更高。仅当它比“aggressive”改善情况时才应使用。启用 HTTP 连接共享时,会非常小心地尊重连接属性和兼容性。具体来说:使用“usesrc”后跟客户端特定值(“client”、“clientip”、“hdr_ip”)建立的连接将被标记为私有,并且永远不会共享;发送到具有 TLS SNI 扩展的服务器的连接将被标记为私有,并且永远不会共享;会检测到依赖于连接的某些无效身份验证方案(如 NTLM),并将其标记为私有,并且永远不会共享;会涉及一个连接池,并且可以使用“pool-max-conn”进行配置。注意:连接重用提高了“server maxconn”设置的准确性,因为几乎不会建立新连接,而空闲连接仍然可用。这对于“always”策略尤其如此。决定保持空闲连接打开或在处理后关闭连接的规则也受“tune.pool-low-fd-ratio”(默认值:20%)和“tune.pool-high-fd-ratio”(默认值:25%)的控制。这些对应于空闲连接所占用的文件描述符总数的百分比,高于该百分比时,haproxy 将分别避免在响应后保持连接打开,并主动杀死空闲连接。一些使用非常高的空闲连接比例的设置,可能是由于全局“maxconn”值太低,或者由于 frontend 上的大量 HTTP/2 或 HTTP/3 流量(连接少)但在 backend 上是 HTTP/1 连接,可能会观察到较低的重用率,因为打开的连接太少了。在这种情况下,可能希望调整这些阈值或简单地增加全局“maxconn”值。类似地,当显式启用线程组时,理解空闲连接仅在同一组的线程之间可用非常重要。因此,可能会发生组之间不公平的负载导致需要更多的空闲连接,从而导致较低的重用率。然后可以应用相同的解决方案(增加全局“maxconn”或增加池比例)。
将服务器名称添加到请求中。使用由 <header> 给出的头字符串。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<header> 用于发送服务器名称的头字符串。
“http-send-name-header”语句会导致名为 <header> 的标头字段在请求即将发送到网络时设置为目标服务器的名称。任何此标头的现有出现都会被删除。在重试和重新分派时,标头字段会被更新以始终反映正在尝试连接的服务器。考虑到此标头在连接设置的后期被修改,它可能对已修改的标头产生意外的影响。例如,将其与传输层标头(如 connection、content-length、transfer-encoding 等)一起使用可能会导致发送到服务器的请求无效。此外,据报道,此指令目前正被用作覆盖传出请求中 Host 标头字段的一种方式;虽然这种技巧在一段时间内作为该功能的副作用一直有效,但它不受官方支持,并且在未来版本中可能会因该功能引起的技术困难而不再有效。更长期的解决方案是修复需要此技巧的应用程序,使其绑定到正确的域名。
为代理设置一个持久 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 使用哪个文件。目前,只有两个参数,它们可以防止加载状态或从包含所有后端和服务器的文件加载状态。状态文件可以通过在 stats socket 上运行“show servers state”命令并将输出重定向来生成。文件格式是版本化的,并且非常特定。要理解它,请阅读“show servers state”命令的文档(管理指南的第 9.3 章)。
global 加载由名为 "server-state-file" 的全局指令指向的文件的内容。 local 如果设置了 "server-state-file-name" 指令,则加载其指向的文件的内容。如果未设置,则使用后端名称作为文件名。 none 不为此后端加载任何状态
注意:- 默认情况下,服务器的 IP 地址在重载时会保留,但顺序可以通过服务器的“init-addr”设置来更改。这意味着在运行时通过 CLI 执行的 IP 地址更改将被保留,并且对本地解析器(例如 /etc/hosts)的任何更改可能不会有任何效果(如果正在使用状态文件)。- 除非在前一个和新的配置文件之间发生了变化,否则将应用前一个运行进程的服务器权重。
最小配置global stats socket /tmp/socket server-state-file /tmp/server_state defaults load-server-state-from-file global backend bk server s1 127.0.0.1:22 check weight 11 server s2 127.0.0.1:22 check weight 12
然后可以运行: socat /tmp/socket - <<< "show servers state" > /tmp/server_state 文件 /tmp/server_state 的内容将如下所示: 1 # <文档示例中省略了字段名称> 1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0 1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0
最小配置global stats socket /tmp/socket server-state-base /etc/haproxy/states defaults load-server-state-from-file local backend bk server s1 127.0.0.1:22 check weight 11 server s2 127.0.0.1:22 check weight 12
然后可以运行: socat /tmp/socket - <<< "show servers state bk" > /etc/haproxy/states/bk 文件 /etc/haproxy/states/bk 的内容将如下所示: 1 # <文档示例中省略了字段名称> 1 bk 1 s1 127.0.0.1 2 0 11 11 4 6 3 4 6 0 0 1 bk 2 s2 127.0.0.1 2 0 12 12 4 6 3 4 6 0 0
启用事件和流量的每个实例日志记录。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
前缀:当必须清除记录器列表时,应使用 no。例如,如果您不想从默认记录器列表继承。此前缀不允许有参数。
当实例的日志参数与全局参数相同时,应使用 global。这是最常见的用法。“global”会将 <address>、<facility> 和 <level> 替换为“global”部分中找到的日志条目的参数。每个实例只能使用一条“log global”语句,并且此形式不带其他参数。<address> 指示将日志发送到何处。它采用与“global”部分的日志相同的格式,并且可以是以下之一:- IPv4 地址,后跟可选的冒号 (':') 和 UDP 端口。如果未指定端口,则默认使用 514(标准的 syslog 端口)。- IPv6 地址,后跟冒号 (':') 和可选的 UDP 端口。如果未指定端口,则默认使用 514(标准的 syslog 端口)。- 到 UNIX 域套接字的文件系统路径,同时注意 chroot 的注意事项(确保路径在 chroot 内可访问)和 uid/gid(确保路径可写)。- 以“fd@<number>”形式的文件描述符编号,它可以指向管道、终端或套接字。在这种情况下,使用无缓冲日志,并且每次日志执行一个 writev() 调用。这有点昂贵,但对于大多数工作负载来说是可以接受的。以这种方式发送的消息不会被截断,但可能会被丢弃,在这种情况下,“DroppedLogs”计数器将增加。writev() 调用即使在管道上对于大小不超过 PIPE_BUF 的消息也是原子的,POSIX 建议该大小至少为 512,而在大多数现代操作系统上为 4096 字节。任何更大的消息可能会与其他进程的消息交错。异常地,为了调试目的,文件描述符也可以指向一个文件,但这样做会显着减慢 haproxy 的速度,因为将忽略非阻塞调用。此外,在没有重新启动进程的情况下,将无法清除或轮换此文件。请注意,配置的 syslog 格式会保留,因此输出适用于与 TCP syslog 服务器一起使用。另请参见下面的“short”和“raw”格式。-“stdout”/“stderr”,它们分别是“fd@1”和“fd@2”的别名,请参见上文。您可能希望在地址参数中引用一些环境变量,请参阅关于环境变量的 第 2.3 节。<length> 是可选的最大行长度。大于此值的日志行将在发送之前被截断。原因是 syslog 服务器对日志行长度的处理方式不同。所有服务器都支持 1024 的默认值,但有些服务器会简单地丢弃较大的行,而其他服务器则会记录它们。如果服务器支持长行,在此处设置此值可能很有意义,以避免截断长行。类似地,如果服务器丢弃长行,最好在发送之前将其截断。接受的值为 80 到 65535 之间。1024 的默认值对于所有标准用法通常都很好。某些特定情况下的长捕获或 JSON 格式的日志可能需要更大的值。<ranges> 逗号分隔的范围列表,用于标识要采样的日志。这用于平衡发送到日志服务器的日志负载。范围的限制不能为 null。它们从 1 开始编号。样本的大小或周期(按日志数)必须使用 <sample_size> 参数设置。<sample_size> 用于平衡发送到 syslog 服务器的日志负载的样本大小(按日志数)。此大小必须大于或等于范围的高限制的最大值。(另请参阅 <ranges> 参数)。<format> 是生成 syslog 消息时使用的日志格式。它可以是以下之一:rfc3164 RFC3164 syslog 消息格式。这是默认值。(https://tools.ietf.org/html/rfc3164)rfc5424 RFC5424 syslog 消息格式。(https://tools.ietf.org/html/rfc5424)short 包含一个介于尖括号之间的级别(例如 '<3>')的消息,后跟文本。PID、日期、时间、进程名和系统名被省略。这旨在与本地日志服务器一起使用。此格式与 systemd 日志记录器使用的格式兼容。raw 仅包含文本的消息。级别、PID、日期、时间、进程名和系统名被省略。这旨在用于容器或开发期间,其中严重性仅取决于使用的文件描述符(stdout/stderr)。<facility> 必须是 24 个标准 syslog 设施之一:kern user mail daemon auth syslog lpr news uucp cron auth2 ftp ntp audit alert cron2 local0 local1 local2 local3 local4 local5 local6 local7 请注意,对于“short”和“raw”格式,facility 会被忽略,但仍然是位置字段。建议在这种情况下使用“daemon”以明确其仅供本地使用。<level> 是可选的,可以指定以过滤传出的消息。默认情况下,所有消息都会被发送。如果指定了级别,则仅发送严重性至少与该级别一样重要的消息。可以指定可选的最小级别。如果设置了此级别,则以比此级别更严重的级别发出的日志将在此级别处截断。这用于避免在某些默认 syslog 配置中将“emerg”消息发送到所有终端。已知有八个级别:emerg alert crit err warning notice info debug
重要的是要记住,是由前端决定要从连接中记录什么,并且在内容切换的情况下,来自后端的日志条目将被忽略。连接以 "info" 级别记录。然而,后端日志声明定义了服务器状态更改将如何以及在何处被记录。级别 "notice" 将用于指示服务器启动,"warning" 将用于终止信号和最终的服务终止,而 "alert" 将用于服务器宕机时。 注意:根据 RFC3164,消息在发出前会被截断为 1024 字节。
log global log stdout format short daemon # 发送日志到 systemd log stdout format raw daemon # 发送所有内容到 stdout log stderr format raw daemon notice # 将重要事件发送到 stderr log 127.0.0.1:514 local0 notice # 只发送重要事件 log 127.0.0.1:514 local0 notice notice # 相同,但限制输出级别 log "${LOCAL_SYSLOG}:514" local0 notice # 发送到本地服务器
指定用于流量日志的日志格式字符串
可在以下部分中使用
| 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”。有时区分同一主机上运行的多个进程,或区分同一进程中运行的客户实例可能很有用。在 backend 中,有关服务器 up/down 的日志将使用此 tag。作为提示,在 defaults 部分中设置与托管客户相关的 log-tag,然后将该客户的所有 frontend 和 backend 放入其中,然后开始另一个客户,这在 defaults 部分中会很方便。另请参阅全局“log-tag”指令。设置用于维护 keep-alive 连接的最大服务器队列大小
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
HTTP keep-alive 试图在可能的情况下重用同一个服务器连接,但有时这可能会适得其反,例如,如果一个服务器有很多连接而其他服务器处于空闲状态。这对于静态服务器尤其如此。此设置的目的是在 HAProxy 停止尝试重用同一服务器并优先查找另一台服务器的排队连接数设置一个阈值。默认值 -1 表示没有限制。值为零表示 keep-alive 请求永远不会被排队。对于延迟非常低且对中断 keep-alive 不敏感的非常近的服务器,推荐使用较低的值(例如,本地静态服务器可以使用 10 或更少的值)。对于遭受高延迟的远程服务器,可能需要更高的值来弥补延迟和/或选择另一台服务器的成本。请注意,这不会影响响应,这些响应会连续发送到同一台服务器以响应 401 响应。即使它们需要排队,它们仍会转到同一台服务器。
设置对于给定的客户端会话,我们可以保持空闲的最大传出连接数。默认值为 5(它精确等于构建时定义的 MAX_SRV_LIST)。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
固定前端的最大并发连接数
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<conns> 是前端将接受服务的最大并发连接数。超出的连接将由系统在套接字的侦听队列中排队,并在一个连接关闭后得到服务。
如果系统支持,在大型站点上将此限制提高到非常高可能很有用,这样 haproxy 就可以管理连接队列,而不是让客户端面临未响应的连接尝试。此值不应超过全局 maxconn。此外,请记住,一个连接包含两个 tune.bufsize(默认为 16kB)缓冲区,以及一些其他数据,导致每个已建立的连接消耗约 33 kB 的 RAM。这意味着一个配备 1GB RAM 的中等系统,如果正确调整,可以承受大约 20000-25000 个并发连接。此外,当 <conns> 设置为较大的值时,服务器可能没有为接受如此大的负载进行调整,因此通常明智地为它们分配一些合理的连接限制。当此值设置为零(默认值)时,将使用全局“maxconn”值。
设置实例的运行模式或协议
可在以下部分中使用
| 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 探测检测到服务已启动并正在运行,而无需将请求转发到 backend 服务器。请注意,此响应以原始格式发送,没有任何转换。这一点很重要,因为它意味着它不会在 SSL 监听器上进行 SSL 加密。监视请求在非常早期进行处理,仅在 tcp-request connection ACL 之后,而 tcp-request connection ACL 是唯一能够阻止它们的。这些连接是短暂的,并且从不等待来自客户端的任何数据。它们无法被记录,这是预期用途。它们仅用于向上层组件报告 HAProxy 的运行状况,仅此而已。请注意,“monitor fail”规则不适用于被“monitor-net”拦截的连接。最后,请注意,在一个 frontend 中只能指定一个“monitor-net”语句。如果找到多个,则只考虑最后一个。
# 地址 .252 和 .253 只是在探测我们。 frontend www monitor-net 192.168.0.252/31
拦截外部组件监控请求使用的 URI
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<uri> 是我们想要拦截以返回 HAProxy 健康状态而不是转发请求的确切 URI。
当收到引用 <uri> 的 HTTP 请求时,HAProxy 不会将其转发或记录,而是会根据 "monitor fail" 定义的失败条件,返回 "HTTP/1.0 200 OK" 或 "HTTP/1.0 503 Service unavailable"。这通常足以让任何前端 HTTP 探测器检测到服务是否正常运行,而无需将请求转发到后端服务器。请注意,HTTP 方法、版本和所有标头都会被忽略,但请求至少必须在 HTTP 级别上是有效的。此关键字只能与 HTTP 模式的前端一起使用。监控请求在解析请求后,甚至在任何 "http-request" 或 "block" 规则集之前处理。唯一在此之前应用的规则集是 tcp-request。它们也不能被记录,这也是预期的目的。它们仅用于向更高级别的组件报告 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(delete)以及以上所有字符都不允许出现。HAProxy 始终阻止其中的一些(0..32、127)。其余的默认情况下会被阻止,除非启用此选项。此选项还放宽了对 HTTP 版本进行的测试,它允许 HTTP/0.9 请求通过(未指定版本)以及主版本和次版本都有多个数字。最后,此选项还允许传入的 URL 包含片段引用(路径后的 '#')。此选项永远不应默认启用,因为它会隐藏应用程序错误并打开安全漏洞。仅在确认问题后才应部署。启用此选项后,仍会接受请求中的错误标头名称,但会捕获完整的请求,以便稍后使用 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、204、206、300、301、404、405、410、414、501 的响应,前提是服务器没有设置 "Cache-control: public" 标头字段;- 所有由除 GET、HEAD、OPTIONS、TRACE 之外的方法发起的请求产生的响应,前提是服务器没有设置 "Cache-Control: public" 标头字段;- 具有 'Pragma: no-cache' 标头的响应- 具有 'Cache-control: private' 标头的响应- 具有 'Cache-control: no-store' 标头的响应- 具有 'Cache-control: max-age=0' 标头的响应- 具有 'Cache-control: s-maxage=0' 标头的响应- 具有 'Cache-control: no-cache' 标头的响应- 具有 'Cache-control: no-cache="set-cookie"' 标头的响应- 具有 'Cache-control: no-cache="set-cookie,' 标头的响应(允许 set-cookie 之后的其他字段)如果响应不符合这些要求,则它将被阻止,就像它来自 "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 秒一次,这足以生成清晰的图表。重新计数直接触及热路径,因此默认情况下不启用它,因为它可能会导致会话计数非常大的情况下大量唤醒并导致性能略有下降。
启用或禁用从 HTTP/1.x 客户端连接的隐式 HTTP/2 升级。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,HAProxy 能够通过 HTTP/1.x 客户端连接隐式升级到 HTTP/2 连接,前提是它从给定 HTTP 连接收到的第一个请求匹配 HTTP/2 连接前导(即字符串 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n")。这样,就可以在非 SSL 连接上支持 HTTP/1.x 和 HTTP/2 客户端。必须使用此选项来禁用隐式升级。请注意,此隐式升级仅支持 HTTP 代理,因此此选项也如此。另请注意,可以通过在 bind 行上指定 "proto h2" 来强制在明文连接上使用 HTTP/2。如果此选项已在 "defaults" 部分中启用,则可以通过在它前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用对正常、成功连接的日志记录
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
有些大型网站每秒处理数千个连接,日志记录对它们来说是一个主要的痛点。其中一些甚至被迫关闭日志,无法调试生产问题。设置此选项可确保正常的连接,即那些没有经历错误、超时、重试或重新分派的连接,将不会被记录。这为异常情况留下了磁盘空间。在 HTTP 模式下,会检查响应状态码,返回码为 5xx 的仍将被记录。 强烈建议不要使用此选项,因为大多数情况下,复杂问题的关键在于正常的日志中,而这些日志在这里不会被记录。如果您需要分离日志,请改用 "log-separate-errors" 选项。
启用或禁用对空连接的日志记录
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
在某些环境中,有些组件会定期连接到各种系统,以确保它们仍然存活。这可能是来自另一个负载均衡器以及监控系统的情况。默认情况下,即使是简单的端口探测或扫描也会产生一条日志。如果这些连接过多地污染了日志,可以启用选项“dontlognull”,以指示没有传输任何数据的连接将不会被记录,这通常对应于那些探测。请注意,错误仍将返回给客户端并在统计信息中计算。如果这不是期望的,可以使用 http-ignore-probes 选项。通常建议不要在不受控制的环境(例如互联网)中使用此选项,否则扫描和其他恶意活动将不会被记录。如果此选项已在“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 的标头由最终用户控制。仅支持 IPv4 地址。"http-request add-header" 或 "http-request set-header" 规则可用于解决此限制。此选项可以在前端或后端指定。如果其中至少一个使用它,则会添加标头。请注意,当后端和前端都定义时,后端设置标头子参数优先于前端。对于 "if-none" 参数,如果前端或后端至少一个不指定它,则表示需要强制添加,因此它会获胜。
# 公共 HTTP 地址,也由同一台机器上的 stunnel 使用 frontend www mode http option forwardfor except 127.0.0.1 # stunnel 已经添加了该标头 # 这些服务器希望在 X-Client 中获取 IP 地址 backend www mode http option forwardfor header X-Client
启用或禁用对发送给有问题的客户端的 HTTP/1 头部的大小写调整
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
标头名称没有标准的大小写,因为如 RFC7230 所述,它们是大小写不敏感的。因此,应用程序必须以大小写不敏感的方式处理它们。但一些不良应用程序违反了标准,并错误地依赖于浏览器最常用的情况。由于 HTTP/2 必须以小写形式交换所有标头名称,而 HAProxy 也遵循相同的约定,因此这个问题变得至关重要。所有标头名称都以小写形式发送给客户端和服务器,无论 HTTP 版本如何。当 HAProxy 收到 HTTP/1 响应时,其标头名称会被转换为小写并以这种方式进行处理和发送给客户端。如果已知客户端违反 HTTP 标准并且无法处理来自 HAProxy 的响应,则可以通过启用此选项并使用全局指令 "h1-case-adjust" 或 "h1-case-adjust-file" 指定要重新格式化的标头列表,在格式化响应并将其发送给客户端时,将小写标头名称转换为不同的格式。这只能作为一种临时解决方法,直到客户端得到修复为止,因为需要此类解决方法的客户端可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准要求的客户端。如果此选项已在 "defaults" 部分中启用,则可以通过在它前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用对发送给有问题的服务器的 HTTP/1 头部的大小写调整
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
标头名称没有标准的大小写,因为如 RFC7230 所述,它们是大小写不敏感的。因此,应用程序必须以大小写不敏感的方式处理它们。但一些不良应用程序违反了标准,并错误地依赖于浏览器最常用的情况。由于 HTTP/2 必须以小写形式交换所有标头名称,而 HAProxy 也遵循相同的约定,因此这个问题变得至关重要。所有标头名称都以小写形式发送给客户端和服务器,无论 HTTP 版本如何。当 HAProxy 收到 HTTP/1 请求时,其标头名称会被转换为小写并以这种方式进行处理和发送给服务器。如果已知服务器违反 HTTP 标准并且无法处理来自 HAProxy 的请求,则可以通过启用此选项并使用全局指令 "h1-case-adjust" 或 "h1-case-adjust-file" 指定要重新格式化的标头列表,在格式化请求并将其发送给服务器时,将小写标头名称转换为不同的格式。这只能作为一种临时解决方法,直到服务器得到修复为止,因为需要此类解决方法的服务器可能容易受到内容走私攻击,并且必须绝对修复。请注意,此选项不会影响符合标准要求的服务器。如果此选项已在 "defaults" 部分中启用,则可以通过在它前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用在处理前等待整个 HTTP 请求体
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
有时需要在做出决策前等待 HTTP 请求的主体。例如,"balance url_param" 就是这样做的。第一个用例是在连接到服务器之前,缓冲来自慢速客户端的请求。另一个用例是根据请求主体的内容来做出路由决策。此选项放置在前端或后端中,强制 HTTP 处理等待直到接收到整个主体,或者请求缓冲区已满,或者在分块编码的情况下第一个块已完成。它可能会对某些滥用 HTTP、期望前端和后端之间进行非缓冲传输的应用程序产生不希望的副作用,因此绝对不应默认使用。
启用或禁用空连接和请求超时的日志记录
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
最近一些浏览器开始实现 "pre-connect" 功能,即推测性地连接到最近访问过的某些网站,以防用户想访问它们。这会导致许多连接到网站,如果超时先发生,这些连接将导致 408 Request Timeout,如果浏览器先关闭它们,则会导致 400 Bad Request。这些会污染日志并填充错误计数器。已经有 "option dontlognull",但在此情况下不足。相反,此选项执行以下操作:- 在连接关闭之前,如果未收到任何信息,则阻止向客户端发送任何 400/408 消息;- 在此情况下阻止任何日志的发出;- 阻止任何错误计数器的增加。这样,空连接将被静默忽略。请注意,最好不要使用此选项,除非清楚需要它,因为它会隐藏真实问题。未收到请求并看到 408 的最常见原因是客户端与 VPN 等中间组件之间的 MTU 不一致,后者会阻止过大的数据包。这些问题通常与 POST 请求以及具有大型 cookie 的 GET 请求一起出现。日志通常是检测它们的唯一方法。如果此选项已在 "defaults" 部分中启用,则可以通过在它前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用从客户端到服务器的 HTTP keep-alive
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以 keep-alive 模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间将连接保持在双方空闲状态。此模式可以通过多个选项来更改,例如 "option http-server-close"、"option httpclose" 或 "option http-tunnel"。此选项允许恢复 keep-alive 模式,当在 defaults 部分使用了其他模式时,这可能很有用。设置 "option http-keep-alive" 可在客户端和服务器端启用 HTTP keep-alive 模式。这在客户端(慢速网络)上提供了最低的延迟,并且在服务器端实现了最快的会话重用,但代价是维护与服务器的空闲连接。一般来说,使用此选项可以实现 "http-server-close" 选项在小型对象上实现的请求速率大约两倍。此选项主要在两种情况下有用:- 当服务器不符合 HTTP 标准,并且通过连接而不是请求进行身份验证时(例如,NTLM 身份验证)- 当与服务器建立连接的成本与从服务器检索相关对象的成本相比很高时。后一种情况发生在服务器是一个快速的静态服务器或缓存时。在这种情况下,服务器需要进行适当的调优以支持足够高的连接数,因为连接将一直保持到客户端发送新请求为止。如果由于内容切换或负载均衡算法,客户端请求必须转到另一个后端或另一个服务器,则空闲连接将立即关闭并重新打开一个新连接。选项 "prefer-last-server" 可用于尝试优化服务器选择,以便如果当前连接到空闲连接的服务器可用,它将被使用。目前,日志不会显示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。keep-alive 请求时间仍然受 "timeout http-keep-alive" 或 "timeout http-request"(如果未设置)定义的超时限制。此选项禁用并替换任何以前的 "option httpclose"、"option http-server-close" 或 "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 httpclose"运行时,haproxy 会向转发到服务器的请求添加 "Connection: close" 标头。不幸的是,当某些服务器看到此标头时,它们会自动避免使用未知长度响应的分块编码,尽管这完全无关。直接影响是这会阻止 haproxy 保持客户端连接处于活动状态。第二个影响是客户端或缓存可能会收到不完整的响应而不知情,并将其视为完整的响应。通过设置 "option http-pretend-keepalive",haproxy 将使服务器相信它将保持连接处于活动状态。然后服务器将不会回退到上述异常的、不期望的行为。当 haproxy 获取整个响应时,它将关闭与服务器的连接,就像使用 "option httpclose" 时一样。这样,客户端将获得正常响应,并且服务器端的连接将被正确关闭。建议不要默认启用此选项,因为大多数服务器将在最后一个数据包后更有效地关闭连接,并稍微提前释放其缓冲区。此外,网络上添加的数据包可能会稍微降低整体峰值性能。然而,值得注意的是,当启用此选项时,haproxy 的工作量会略微减少。因此,如果 haproxy 是整个架构的瓶颈,启用此选项可能会节省一些 CPU 周期。此选项可以在后端和 listen 部分设置。在 frontend 部分使用它将被忽略,并在启动时报告警告。这是一个与后端相关的选项,因此在 frontend 上设置它没有实际意义。此选项可以与 "option httpclose" 结合使用,这将导致向服务器宣告 keepalive,并向客户端宣告关闭。然而,这种做法不被推荐。如果此选项已在 "defaults" 部分中启用,则可以通过在它前面加上 "no" 关键字来在特定实例中禁用它。
启用或禁用服务器端的 HTTP 连接关闭
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以 keep-alive 模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间将连接保持在双方空闲状态。此模式可以通过多个选项来更改,例如 "option http-server-close"、"option httpclose" 或 "option http-tunnel"。设置 "option http-server-close" 可在服务器端启用 HTTP 连接关闭模式,同时保持对客户端进行 HTTP keep-alive 和 Pipelining 的支持能力。这在客户端(慢速网络)上提供了最低的延迟,并且在服务器端实现了最快的会话重用以节省服务器资源,类似于 "option httpclose"。它还允许非 keep-alive 兼容的服务器以 keep-alive 模式为客户端提供服务,前提是它们符合 RFC7230 的要求。请注意,一些服务器在看到请求中的 "Connection: close" 时并不总是符合要求。效果是 keep-alive 永远不会被使用。解决方法包括启用 "option http-pretend-keepalive"。目前,日志不会显示请求是否来自同一会话。日志中报告的接受日期对应于上一个请求的结束,请求时间对应于等待新请求所花费的时间。keep-alive 请求时间仍然受 "timeout http-keep-alive" 或 "timeout http-request"(如果未设置)定义的超时限制。此选项可以在前端和后端设置。如果持有连接的前端或后端至少有一个启用了它,则启用它。它禁用并替换任何以前的 "option httpclose"、"option http-tunnel" 或 "option http-keep-alive"。请参阅 第 4 节("Proxies")以了解当前端和后端选项不同时此选项如何与其他选项组合。如果此选项已在 "defaults" 部分中启用,则可以通过在它前面加上 "no" 关键字来在特定实例中禁用它。
首次事务后禁用或启用 HTTP 连接处理。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
警告:由于它无法在 HTTP/2 中工作,此选项已被弃用,并且仅在旧版 HTTP 前端上受支持。在 HTX 中,它会被忽略,并在 HAProxy 启动时发出警告。默认情况下,HAProxy 在持久连接方面以保持活动模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间将连接保持在双方空闲状态。此模式可以通过多个选项进行更改,例如“option http-server-close”、“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 协议元素的新 HTX 内部表示
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
从历史上看,HTTP 协议是按原样处理的。插入、删除或修改标头字段需要重写缓冲区中受影响的部分并相应地移动缓冲区的尾部。此模式称为旧版 HTTP 模式。由于此原则已深入 HAProxy,因此 HTTP/2 协议在按此方式处理之前会被转换为 HTTP/1.1。这还导致无法建立到服务器的 HTTP/2 连接,因为在 HTTP/1 表示中丢失了 HTTP/2 语义。HTX 是 HTTP 协议的全新本地内部表示的名称,它与版本无关,并且旨在在整个链中保留语义。它依赖于快速解析、标记化和索引协议元素,因此不再需要内存移动,并且大多数元素都可以直接访问。它支持在任何一端使用 HTTP/1 或 HTTP/2,而无需考虑另一端的版本。它还支持从 TCP 到 HTTP 的升级,以及从 HTTP/1 到 HTTP/2 的隐式升级(匹配 HTTP/2 前导)。此选项表明需要使用 HTX。自 2.0-dev3 版本以来,HTX 是默认模式。要切换回旧版 HTTP 模式,必须通过在前面加上“no”前缀来显式禁用该选项。对于早期版本,该功能的功能覆盖不完整,因此默认不启用。
启用 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 中是强制性的,请使用 "http-check send" 指令来添加它。
默认情况下,服务器运行状况检查仅尝试建立 TCP 连接。当指定“option httpchk”时,在建立 TCP 连接后会发送一个完整的 HTTP 请求,响应 2xx 和 3xx 被视为有效,而所有其他响应都表示服务器失败,包括没有任何响应。端口和间隔在服务器配置中指定。此选项不一定需要 HTTP 后端,它也适用于纯 TCP 后端。这对于使用 inetd 守护程序检查绑定到特定端口的简单脚本特别有用。注意:有一段时间,无法在用于 HTTP 健康检查的请求中添加标头或正文。因此,一种变通方法是将其隐藏在版本字符串的末尾,并在版本后添加“\r\n”。现在已弃用。必须使用指令“http-check send”代替。
# 将 HTTPS 流量中继到 Apache 实例,并使用 HTTP 请求 "OPTIONS * HTTP/1.1" # 在端口 80 上检查服务可用性。 backend https_relay mode tcp option httpchk OPTIONS * HTTP/1.1 http-check send hdr Host www server apache1 192.168.1.1:443 check port 80
启用或禁用 HTTP 连接关闭
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 是![]() |
默认情况下,HAProxy 在持久连接方面以保持活动模式运行:对于每个连接,它会处理每个请求和响应,并在响应结束和新请求开始之间将连接保持在双方空闲状态。此模式可以通过多个选项进行更改,例如“option http-server-close”、“option httpclose”或“option http-tunnel”。如果设置了“option httpclose”,HAProxy 将在接收到请求和响应后立即关闭与服务器和客户端的连接。它还将检查是否已在任一方向上设置了“Connection: close”标头,如果缺少则添加一个。任何与“close”不同的“Connection”标头也将被删除。此选项还可以与“option http-pretend-keepalive”结合使用,该选项将禁用发送“Connection: close”标头,但仍会导致在接收完整个响应后关闭连接。此选项可以同时在前端和后端设置。如果持有连接的前端或后端至少有一个启用了它,则启用此选项。它禁用并替换任何先前的“option http-server-close”、“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 守护进程将它们单独记录到不同的文件中。注意不要将它们从原始文件中删除,否则你会丢失提供非常重要信息的顺序。使用此选项,处理每秒数千个连接的大型站点可以将正常流量记录到循环缓冲区中,并只归档较小的错误日志。
启用或禁用早期日志记录。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
默认情况下,当定义 log-format 字符串使用的所有日志格式变量和样本获取都返回值时,或者当会话终止时,会发出日志。这允许内置的 log-format 字符串在日志消息中计算传输时间或字节数。处理长连接(如大文件传输或 RDP)时,请求或连接可能需要一段时间才能出现在日志中。使用“option logasap”,日志消息会在服务器连接在 tcp 模式下建立时,或者在服务器发送完整标头在 http 模式下建立时立即创建。日志中缺失的信息将是总字节数(仅表示消息创建之前的传输数据量)和总时间(不考虑连接剩余的生命周期或传输时间)。对于 HTTP,捕获 Content-Length 响应标头是一个好习惯,这样日志至少可以显示预期的传输字节数。
listen http_proxy 0.0.0.0:80 mode http option httplog option logasap log 192.168.2.200 local3 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 9/10/7/14/+30 200 +243 - - ---- 3/1/1/1/0 1/0 \ "GET /image.iso HTTP/1.0"
使用 MySQL 健康检查进行服务器测试
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<username> 这是连接到 MySQL 服务器时将使用的用户名。 post-41 发送与 v4.1 后版本客户端兼容的检查
如果您指定了用户名,则检查包括发送两个 MySQL 数据包,一个客户端身份验证数据包和一个 QUIT 数据包,以正确关闭 MySQL 会话。然后,我们解析 MySQL Handshake Initialization 数据包和/或 Error 数据包。这是一个基本但有用的测试,它不会在服务器上产生错误或中止连接。但是,它需要一个未锁定的授权用户,没有密码。要创建具有可选资源限制的基本有限用户,请使用:CREATE USER '<username>'@'<ip_of_haproxy|network_of_haproxy/netmask>' /*!50701 WITH MAX_QUERIES_PER_HOUR 1 MAX_UPDATES_PER_HOUR 0 */ /*M!100201 MAX_STATEMENT_TIME 0.0001 */; 如果您未指定用户名(已弃用且不推荐),则检查仅包括解析 MySQL Handshake Initialization 数据包或 Error 数据包,我们在此模式下不发送任何内容。据报告,如果检查过于频繁和/或流量不足,它可能会导致锁定。实际上,在这种情况下,您需要检查 MySQL 的“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 一起使用。仅支持 IPv4 地址。“http-request add-header”或“http-request set-header”规则可用于解决此限制。此选项可以在前端或后端指定。如果至少有一个使用它,则会添加标头。请注意,如果前端和后端都定义了标头,则后端的标头子参数设置将优先于前端的设置。
# 原始目标地址 frontend www mode http option originalto except 127.0.0.1 # 这些服务器希望在 X-Client-Dst 中获取 IP 地址 backend www mode http option originalto header X-Client-Dst
启用或禁用对故障服务器的强制持久性
可在以下部分中使用
| 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”将允许代理打破 cookie 或一致性哈希的持久性,并将它们重新分发到正常工作的服务器。它还允许在多次连接失败的情况下重试连接到另一台服务器。当然,这需要将“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”全局禁用。由于拼接使用管道,使用它需要有足够的备用管道。重要提示:基于内核的 TCP 拼接是一项仅限 Linux 的功能,首次出现在内核 2.6.25 中。它提供基于内核的加速,可在套接字之间传输数据,而无需将这些数据复制到用户空间,从而提供显著的性能提升和 CPU 周期节省。由于许多早期实现都存在错误、损坏数据和/或效率低下,因此默认不启用此功能,应格外谨慎使用。虽然无法检测实现的正确性,但 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 |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
此健康检查方法旨在与“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”指令,后跟一个字符串。此字符串将在调试模式下的日志和 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 无关。使用选项“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”。在后端部分,无法确定监听器,并且 <proxy_address> 和 <proxy_port> 都将是字符串值“NOT_USED”。一些值也通过环境变量提供。环境变量:HAPROXY_PROXY_ADDR 第一个绑定地址(如果可用,如果不可用则为空,例如在“backend”部分)。HAPROXY_PROXY_ID 后端 ID。HAPROXY_PROXY_NAME 后端名称。HAPROXY_PROXY_PORT 第一个绑定端口(如果可用,如果不可用则为空,例如在“backend”部分或 UNIX 套接字)。HAPROXY_SERVER_ADDR 服务器地址。HAPROXY_SERVER_CURCONN 服务器上的当前连接数。HAPROXY_SERVER_ID 服务器 ID。HAPROXY_SERVER_MAXCONN 服务器最大连接数。HAPROXY_SERVER_NAME 服务器名称。HAPROXY_SERVER_PORT 服务器端口(如果可用,如果是 UNIX 套接字则为空)。PATH 在执行命令时使用的 PATH 环境变量可以通过“external-check path”进行设置。另请参阅“2.3. 环境变量”以了解其他变量。如果执行的命令以零状态退出,则认为检查已通过,否则认为检查失败。
external-check command /bin/true
运行外部检查时使用的 PATH 环境变量的值
可在以下部分中使用
| 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 包含在已知服务器列表中找到服务器所需的所有信息。因此,当在后端中设置此选项时,将分析请求,如果找到 RDP cookie,则会对其进行解码。如果它与仍然 UP 的已知服务器匹配(或者如果设置了 "option persist"),则连接将被转发到此服务器。请注意,这仅在 TCP 后端中有意义,但要使其工作,前端必须等待足够长的时间以确保 RDP cookie 存在于请求缓冲区中。这与 "rdp-cookie" 负载均衡方法的要求相同。因此,强烈建议将所有语句放在一个 "listen" 部分中。此外,重要的是要理解,终端服务器只有在配置为 "令牌重定向模式" 时才会发出此 RDP cookie,这意味着 "IP 地址重定向" 选项被禁用。
listen tse-farm bind :3389 # 在请求中等待 RDP cookie 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # 应用 RDP cookie 持久性 persist rdp-cookie # 如果服务器未知,让我们在相同的 cookie 上进行负载均衡。 # 或者,"balance leastconn" 也可能有用。 balance rdp-cookie server srv1 1.1.1.1:3389 server srv2 1.1.1.2:3389
设置前端每秒接受的新会话数限制
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 是![]() | 是![]() | 否![]() |
<rate> <rate> 参数是一个整数,指定前端每秒接受的最大新会话数。
当前端达到每秒新的会话数达到指定值时,它会停止接受新连接,直到速率再次降至限制以下。在此期间,待处理的会话将保留在套接字的积压(在系统缓冲区中),haproxy 甚至不会知道会话正在等待。当对负载很高的服务设置非常低的限制时,使用“backlog”关键字来增加套接字的积压是有意义的。此功能在阻止连接建立型攻击或对脆弱服务器的服务滥用方面特别有效。由于会话速率每毫秒测量一次,因此非常准确。此外,该限制会立即应用,无需任何延迟即可检测到阈值。将 SMTP 的连接速率限制为最大每秒 10 个listen smtp mode tcp bind :25 rate-limit sessions 10 server smtp1 127.0.0.1:1025
注意:当达到最大速率时,前端的状态不会改变,但如果启用了 "socket-stats" 选项,其套接字在统计信息中将显示为 "WAITING"。
如果/除非条件匹配,则返回 HTTP 重定向
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
如果/除非条件匹配,HTTP 请求将导致重定向响应。如果未指定条件,则重定向无条件适用。
<loc> 使用“redirect location”时,<loc> 中的确切值将被放入 HTTP“Location”标头。当在“http-request”规则中使用时,<loc> 值遵循 log-format 规则,并且可以包含一些动态值(请参阅第 8.2.4 节中的自定义日志格式)。<pfx> 使用“redirect prefix”时,“Location”标头将由 <pfx> 和完整的 URI 路径(包括查询字符串)的连接构建,除非指定了“drop-query”选项(见下文)。作为特殊情况,如果 <pfx> 等于“/”,则在原始 URI 前面不会插入任何内容。它允许重定向到同一个 URL(例如,用于插入 cookie)。当在“http-request”规则中使用时,<pfx> 值遵循 log-format 规则,并且可以包含一些动态值(请参阅第 8.2.4 节中的自定义日志格式)。<sch> 使用“redirect scheme”时,“Location”标头将通过连接 <sch>、“://”然后“Host”标头的第一个出现,然后是 URI 路径(包括查询字符串,除非指定了“drop-query”选项(见下文))来构建。如果没有找到路径或路径是“*”,则改用“/”。如果没有找到“Host”标头,则将返回一个空的 host 组件,大多数现代浏览器会将其解释为重定向到同一个 host。此指令主要用于将 HTTP 重定向到 HTTPS。当在“http-request”规则中使用时,<sch> 值遵循 log-format 规则,并且可以包含一些动态值(请参阅第 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> 是在服务器失败后,请求或连接尝试应重试的次数。
默认情况下,重试仅适用于新连接尝试。但是,当使用“retry-on”指令时,其他条件可能会触发重试(例如,空响应、不期望的状态码),并且其中每个条件都会计数一次尝试,当总尝试次数达到此处指定的值时,将返回错误。为避免立即重新连接到正在重启的服务器,在同台服务器上重试之前,会应用一个周转计时器,该计时器为 min(“timeout connect”,一秒)。当设置了“option redispatch”时,即使 cookie 引用了不同的服务器,也可能会在另一台服务器上执行某些重试。默认情况下,这只会是最后一次重试,除非为“option redispatch”传递了参数。
指定何时尝试自动重试失败的请求
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<keywords> 是关键字或 HTTP 状态码的列表,每个关键字或状态码代表一个失败事件类型,当发生该类型事件时,希望尝试重试请求。请阅读底部的注释,然后再更改此设置。支持以下关键字:none 从不重试 conn-failure 当连接或 SSL 握手失败且请求未能发送时重试。这是默认值。empty-response 当服务器在发送部分请求后关闭连接,并且未从服务器接收到任何内容时重试。此类型的失败可能由服务器端的请求超时、糟糕的网络状况或服务器在处理请求期间崩溃或重启引起。junk-response 当服务器返回的内容看起来不像完整的 HTTP 响应时重试。这包括部分响应头以及非 HTTP 内容。通常不应该重试这些事件,这些事件可能由配置问题(错误的服务器端口)或请求对服务器有害(例如缓冲区溢出攻击)引起。response-timeout 服务器在等待服务器响应请求时发生超时。这可能是由糟糕的网络状况、重用已在路径上过期的空闲连接,或者请求的处理成本极高引起的。对于处理繁重数据库处理(如全扫描等)的服务器,通常不应重试这些事件,因为这可能会放大拒绝服务攻击。0rtt-rejected 重试通过早期数据发送但被服务器拒绝的请求。这些请求通常被认为是安全的,可以重试。<status> 任何 HTTP 状态码,例如“404”(未找到)、“408”(请求超时)、“425”(太早)、“500”(服务器错误)、“501”(未实现)、“502”(网关错误)、“503”(服务不可用)、“504”(网关超时)。all-retryable-errors 重试所有被认为是可重试的错误的请求。这目前激活了“conn-failure”、“empty-response”、“junk-response”、“response-timeout”、“0rtt-rejected”、“500”、“502”、“503”和“504”。
使用此指令会用新设置替换任何先前的设置;它不是累加的。请注意,使用“none”和“conn-failure”以外的任何选项都需要分配缓冲区并将整个请求复制到其中,因此会影响内存和性能。不适合单个缓冲区的请求将永远不会被重试(请参阅全局 tune.bufsize 设置)。您必须确保应用程序内置了重放保护机制,例如在请求中传递的唯一事务 ID,或者重放相同的请求没有后果,否则使用除“conn-failure”和“none”之外的任何 retry-on 值将非常危险。静态文件服务器和缓存通常被认为是安全的,可以抵御任何类型的重试。使用状态码可以快速离开出现异常行为(内存不足、文件系统问题等)的服务器,但在这种情况下,立即将连接重新分派到另一台服务器可能是一个好主意(请参阅“option redispatch”)。最后,重要的是要理解,大多数失败的原因是请求本身,重试导致服务器行为异常的请求通常会使该服务器的情况变得更糟,或者在重新分派的情况下使整个服务的状况变得更糟。除非您确切地知道应用程序如何处理重放的请求,否则不应使用此指令。默认值是“conn-failure”。
在 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)- 'sockpair@' -> 地址是已连接的 Unix 套接字或套接字对的 FD。在连接期间,后端会创建一个连接的套接字对,并将其中一个传递给 FD。绑定部分将使用接收到的套接字作为客户端 FD。应谨慎使用。您可能希望在地址参数中引用某些环境变量,有关环境变量,请参阅第 2.3 节。“init-addr”设置可用于修改启动时 IP 地址的解析方式。<port> 是可选的端口规范。如果设置,所有连接都将发送到此端口。如果未设置,将使用客户端连接到的同一端口。端口前面也可以加上“+”或“-”。在这种情况下,服务器的端口将通过将此值添加到客户端端口来确定。<param*> 是此服务器的参数列表。“server”关键字接受大量选项,并有一个专门的部分用于描述它们。有关更多详细信息,请参阅第 5 节。
server first 10.1.1.1:1080 cookie first check inter 1000 server second 10.1.1.2:1080 cookie second check inter 1000 server transp ipv4@ server backup "${SRV_BACKUP}:1080" backup server www1_dc1 "${LAN_DC1}.101:80" server www1_dc2 "${LAN_DC2}.101:80"
注意:关于 Linux 的抽象命名空间套接字,HAProxy 使用整个 sun_path 长度作为地址长度。其他一些程序,如 socat,默认只使用字符串长度。在 socat 中对任何抽象套接字定义传递选项 ",unix-tightsocklen=0",以使其与 HAProxy 兼容。
设置要读取、加载并应用于此后端中可用服务器的服务器状态文件。
可在以下部分中使用
| 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
设置一个模板来初始化具有共享参数的服务器。这些服务器的名称由 <prefix> 和 <num | range> 参数构建。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 否![]() | 是![]() | 是![]() |
<prefix> 要构建的服务器名称的前缀。<num | range> 如果提供了 <num>,此模板将初始化 <num> 个服务器,其服务器名称后缀从 1 到 <num>。也可以使用数字范围 <num_low>-<num_high> 来使用 <num_low> 到 <num_high> 作为服务器名称后缀。<fqdn> 此模板初始化的所有服务器的 FQDN。<port> 与“server”<port> 参数(参见“server”关键字)具有相同的含义。<params*> 此模板初始化的服务器参数列表,包括所有“server”关键字支持的所有选项。
# 初始化 3 个服务器,名称分别为 srv1、srv2 和 srv3, # FQDN 为 google.com,并启用了健康检查。 server-template srv 1-3 google.com:80 check # 或 server-template srv 3 google.com:80 check # 将等同于: server srv1 google.com:80 check server srv2 google.com:80 check server srv3 google.com:80 check
设置出站连接的源地址
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<addr> 是 HAProxy 在连接到服务器之前将绑定的 IPv4 地址。此地址也用作运行状况检查的源。默认值 0.0.0.0 意味着系统将选择最合适的地址来达到其目标。可选地,可以在地址前使用地址族前缀来强制指定地址格式无关的地址族,这在指定没有斜杠 ('/') 的 Unix 套接字路径时可能很有用。当前支持的前缀是:- 'ipv4@' -> 地址始终是 IPv4- 'ipv6@' -> 地址始终是 IPv6- 'unix@' -> 地址是本地 Unix 套接字的路径。您可能希望在地址参数中引用某些环境变量,有关环境变量,请参阅第 2.3 节。<port> 是可选端口。通常不需要,但在某些非常特定的上下文中可能有用。默认值零意味着系统将选择一个空闲端口。请注意,后端不支持端口范围。如果您想强制端口范围,您必须在每个“server”行上指定它们。<addr2> 是在完全透明代理模式下转发连接时呈现给服务器的 IP 地址。这目前仅在某些补丁过的 Linux 内核上受支持。当指定此地址时,连接到服务器的客户端将看到此地址,而运行状况检查仍将使用地址 <addr>。<port2> 是在完全透明代理模式下转发连接时(参见上面的 <addr2>)呈现给服务器的可选端口。默认值零意味着系统将选择一个空闲端口。<hdr> 是一个 HTTP 标头的名称,从中获取要绑定的 IP。这是逗号分隔的标头列表的名称,其中可以包含多个 IP 地址。默认情况下,使用最后一个出现的值。此设计用于与 X-Forwarded-For 标头配合使用,并自动绑定到前一个代理看到的客户端 IP 地址,通常是 Stunnel。为了使用最后一个以外的其他出现的值,请参阅下面的 <occ> 参数。当找不到标头(或出现项)时,不会执行绑定,以便使用代理的默认 IP 地址。还请注意,标头名称不区分大小写,就像任何 HTTP 标头一样。<occ> 是用于多值标头中某个值的出现次数。这与“hdr_ip(<hdr>)”结合使用,以便指定要用于源 IP 地址的出现次数。正值表示从第一次出现开始的位置,1 是第一个。负值表示相对于最后一个的位置,-1 是最后一个。这对于 X-Forwarded-For 标头在基础设施入口点设置,并且必须在多个代理层之后使用的情况很有帮助。当未指定此值时,假定为 -1。传递零会禁用此功能。<name> 是要绑定传出流量的可选接口名称。在支持此功能的系统上(目前仅限 Linux),这允许将所有到服务器的流量绑定到此接口,即使该接口不是系统根据路由表选择的接口。这应该非常小心地使用。请注意,使用此选项需要 root 权限。
“source”关键字在特定地址只允许连接到服务器的复杂环境中很有用。例如,当需要通过公共网关使用私有地址时,并且已知系统无法自行确定合适的源地址,则可能需要它。可以通过可选关键字“usesrc”使用某些补丁过的 Linux 内核上的扩展。它使得可以使用不属于系统本身的 IP 地址连接到服务器。这被称为“完全透明代理模式”。为此,目标服务器必须通过运行 HAProxy 的机器将其流量路由回此地址,并且通常需要在此机器上启用 IP 转发。在此“完全透明代理”模式下,可以强制向服务器呈现特定的 IP 地址。实际上很少使用此功能。更常见的用途是告诉 HAProxy 呈现客户端的 IP 地址。为此,有两种方法:- 呈现客户端的 IP 和端口地址。这是最透明的模式,但当 IP 连接跟踪在机器上启用时,可能会导致问题,因为同一个连接可能会被看到两次,状态不同。然而,此解决方案的最大优点是不限制系统到 64k 个出站地址+端口对,因为可以使用所有客户端范围。- 仅呈现客户端的 IP 地址并选择一个备用端口。此解决方案仍然相当优雅,但透明度略低(下游防火墙日志将与上游的不匹配)。它还存在将并发连接数限制为通常的 64k 端口的缺点。但是,由于上游和下游端口不同,本地 IP 连接跟踪在机器上不会因重用同一个会话而受到影响。此选项设置后端所有服务器的默认源。它也可以在“defaults”部分指定。可以使用服务器级别的“source”服务器选项在服务器级别进行更精细的源地址指定。有关更多信息,请参阅第 5 节。“usesrc”需要 root 权限才能工作。
backend private # 使用我们的 192.168.1.200 源地址连接到服务器 source 192.168.1.200 backend transparent_ssl1 # 从客户端源地址连接到 SSL farm source 192.168.1.200 usesrc clientip backend transparent_ssl2 # 从客户端源地址和端口连接到 SSL farm # 如果本地机器上有 IP conntrack,不推荐。 source 192.168.1.200 usesrc client backend transparent_ssl3 # 从客户端源地址连接到 SSL farm。 # 它对 conntrack 更友好。 source 192.168.1.200 usesrc clientip backend transparent_smtp # 从客户端源地址/端口连接到 SMTP farm # 使用 Tproxy 版本 4。 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 |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
此语句在满足 if/unless 条件时启用统计管理员级别。管理员级别允许从 Web 界面启用/禁用服务器。默认情况下,统计页面出于安全原因仅为只读。注意:在多进程模式(nbproc > 1)下使用此功能时要小心,除非您知道自己在做什么:进程之间不共享内存,这可能导致随机行为。当前,POST 请求受限于缓冲区大小减去保留的缓冲区空间,这意味着如果服务器列表太长,请求将不会被处理。建议一次修改少量服务器。
# 仅对 localhost 启用统计信息管理级别 backend stats_localhost stats enable stats admin if LOCALHOST
# 由于身份验证,统计信息管理级别始终启用 backend stats_auth stats enable stats auth admin:AdMiN123 stats admin if TRUE
# 统计信息管理级别取决于经过身份验证的用户 userlist stats-auth group admin users admin user admin insecure-password AdMiN123 group readonly users haproxy user haproxy insecure-password haproxy backend stats_auth stats enable acl AUTH http_auth(stats-auth) acl AUTH_ADMIN http_auth_group(stats-auth) admin stats http-request auth unless AUTH stats admin if AUTH_ADMIN
启用带身份验证的统计信息,并为一个账户授予访问权限
可在以下部分中使用
| 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> 定义了条目自上次创建、使用 'track-sc' 刷新或使用 'stick match' 或 'stick on' 规则匹配以来的最长保留时间。过期延迟使用标准时间格式定义,与各种超时类似。最长保留时间略高于 24 天。有关更多信息,请参阅 第 2.4 节。如果未指定此延迟,则会话不会自动过期,但当表已满时,会删除旧条目。请务必不要在未指定过期延迟时使用 "nopurge" 参数。注意:'table_*' 转换器执行查找但不会更新 expire,因为它们不需要 'track-sc'。<data_type> 用于在 stick-table 中存储额外信息。ACL 可以使用它来控制与匹配 stick-table 的客户端活动相关的各种标准。对于此处指定的每个项目,每个条目的大小都会增加,以便额外的中可以容纳。多个数据类型可以与一个条目一起存储。多个数据类型可以在 "store" 关键字之后指定,作为逗号分隔的列表。或者,可以重复 "store" 关键字,后跟一个或多个数据类型。除了 "server_id" 类型(自动检测并启用)外,所有数据类型都必须显式声明才能存储。如果 ACL 引用了未存储的数据类型,则 ACL 将简单地不匹配。某些数据类型需要一个参数,该参数必须在括号内紧跟在类型之后传递。有关支持的数据类型及其参数,请参阅下文。
可以与条目一起存储的数据类型如下:- server_id:这是一个整数,保存请求分配到的服务器的数字 ID。它用于 "stick match"、"stick store" 和 "stick on" 规则。当引用时,它会自动启用。- gpc0:第一个通用计数器。它是一个正 32 位整数,可用于任何目的。大多数情况下,它将用于为某些条目添加特殊标记,例如,表示已检测到某种特定行为,并且必须为将来的匹配知道。- gpc0_rate(<period>):第一个通用计数器在一段时间内的递增速率。它是一个正 32 位整数,可用于任何目的。就像 <gpc0> 一样,它计算事件,但不是保持累积数量,而是维护计数器递增的速率。大多数情况下,它将用于衡量某些事件(例如,对特定 URL 的请求)的发生频率。- gpc1:第二个通用计数器。它是一个正 32 位整数,可用于任何目的。大多数情况下,它将用于为某些条目添加特殊标记,例如,表示已检测到某种特定行为,并且必须为将来的匹配知道。- gpc1_rate(<period>):第二个通用计数器在一段时间内的递增速率。它是一个正 32 位整数,可用于任何目的。就像 <gpc1> 一样,它计算事件,但不是保持累积数量,而是维护计数器递增的速率。大多数情况下,它将用于衡量某些事件(例如,对特定 URL 的请求)的发生频率。- gpt0:第一个通用标记。它是一个正 32 位整数,可用于任何目的。大多数情况下,它将用于为某些条目添加特殊标记,例如,表示已检测到某种特定行为,并且必须为将来的匹配知道。- conn_cnt:连接计数。它是一个正 32 位整数,用于计算来自匹配此条目的客户端的连接总数。它不表示连接已被接受,只表示它们已被接收。- conn_cur:当前连接数。它是一个正 32 位整数,用于存储条目的并发连接计数。当传入连接匹配该条目时,它会增加,当连接离开时,它会减少。这样,就可以随时知道条目的确切并发连接数。- conn_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示计算平均值的周期长度。它报告该周期内的平均传入连接速率,单位为每周期连接数。结果是一个整数,可以使用 ACL 进行匹配。- sess_cnt:会话计数。它是一个正 32 位整数,用于计算来自匹配此条目的客户端的会话总数。会话是由第 4 层规则接受的连接。- sess_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示计算平均值的周期长度。它报告该周期内的平均传入会话速率,单位为每周期会话数。结果是一个整数,可以使用 ACL 进行匹配。- http_req_cnt:HTTP 请求计数。它是一个正 32 位整数,用于计算来自匹配此条目的客户端的 HTTP 请求总数。无论它们是否是有效请求,都不重要。注意,这与使用 keep-alive 的客户端的会话不同。- http_req_rate(<period>):频率计数器(占用 12 字节)。它接受一个整数参数 <period>,该参数以毫秒为单位指示计算平均值的周期长度。它报告该周期内的平均 HTTP 请求速率,单位为每周期请求数(无论它们是否是有效请求)。注意,这与使用 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 服务器 hello 时存储 SSL 会话 ID。
某些协议或应用程序需要复杂的粘性规则,并且不能总是仅仅依赖于 cookie 或哈希。"stick store-response" 语句描述了一条规则,用于决定从响应中提取什么以及何时提取,以便将其存储到粘性表中,供后续请求使用 "stick match" 语句进行匹配。显然,提取的部分必须有意义,并且有机会在后续请求中匹配。存储响应头中的 ID 是有意义的。有关可能的模式和转换规则的完整列表,请参阅 第 7 节。表必须使用 "stick-table" 语句声明。它必须是与模式兼容的类型。默认情况下,它与同一后端中存在的表相同。可以通过使用 "table" 关键字引用来与其他后端共享表。如果引用了另一个表,则会使用后端中的服务器 ID。默认情况下,每个后端中的所有服务器 ID 都从 1 开始,因此服务器顺序就足够了。但如有疑问,强烈建议使用其 "id" 设置来强制设置服务器 ID。可以使用 "if" 或 "unless" 后跟一个条件来限制 "stick store-response" 语句适用的条件。此条件将在解析响应时进行评估,因此可以使用任何标准。有关基于 ACL 的条件,请参阅 第 7 节。"stick store-response" 语句的数量没有限制,但每个请求或响应最多只能同时存储 8 个。这使得可以存储最多 8 个标准,所有这些标准都从请求或响应中提取,无论规则的数量如何。只有前 8 个匹配的才能被保留。通过使用此功能,可以一次性填充多个表,以期增加在其他协议或访问方式上识别用户的机会。可以使用多个带有相同表的 store-response 规则,并通过按递减偏好顺序排列规则来找到最可依赖的标准。给定表只存储第一个提取的标准。所有后续引用相同表的 store-response 规则都将被跳过,并且它们的 ACL 也不会被评估。然而,即使 store-request 规则引用了一个表,store-response 规则也可以使用同一个表。这意味着每个表一次可以学习一个来自请求的元素和一个来自响应的元素。表将包含处理请求的实际服务器。
# 从请求和响应中学习 SSL 会话 ID 并创建亲和性。 backend https mode tcp balance roundrobin # 最大 SSL 会话 ID 长度为 32 字节。 stick-table type binary len 32 size 30k expire 30m acl clienthello req.ssl_hello_type 1 acl serverhello res.ssl_hello_type 2 # 使用 tcp content 接受来检测 ssl 客户端和服务器 hello。 tcp-request inspect-delay 5s tcp-request content accept if clienthello # 默认情况下,响应检查延迟没有超时。 tcp-response content accept if serverhello # SSL 会话 ID (SSLID) 可能存在于客户端或服务器 hello 中。 # 其长度在偏移量 43 处用 1 字节编码,其值从 # 偏移量 44 开始。 # 如果是客户端 hello,则在请求上匹配并学习。 stick on req.payload_lv(43,1) if clienthello # 如果是服务器 hello,则在响应上学习。 stick store-response resp.payload_lv(43,1) if serverhello server s1 192.168.1.1:443 server s2 192.168.1.1:443
打开一个新连接
可在以下部分中使用
| 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> 必须是字符串。<hexstring>:测试响应缓冲区中的精确字符串的十六进制形式匹配。如果响应的缓冲区包含此精确十六进制字符串,则健康检查响应将被视为有效。目的是在二进制协议上发送二进制数据以进行查询。
# 二进制 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 规则允许仅针对某些 IP 地址范围使用 ACL 来接受 PROXY 协议。这在流量来自公共主机并经过多层负载均衡器时非常方便。- expect-netscaler-cip layer4:配置客户端连接在从套接字读取任何字节之前接收 NetScaler 客户端 IP 插入协议标头。这相当于在“bind”行上具有“accept-netscaler-cip”关键字,除了使用 TCP 规则允许仅针对某些 IP 地址范围使用 ACL 来接受 PROXY 协议。这在流量来自公共主机并经过多层负载均衡器时非常方便。- capture <sample> len <length>:这仅适用于“tcp-request content”规则。它从请求缓冲区捕获样本表达式 <sample>,并将其转换为最多 <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-inc-gpc1(<sc-id>): “sc-inc-gpc1”操作根据由 <sc-id> 指定的粘性计数器增加 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估将继续。- 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 表达式,由一个样本提取后跟一些转换器组成。
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*”操作以及更改默认操作为拒绝可能很有用。
接受所有来自白名单主机的连接,拒绝过快的连接而不计数,并跟踪已接受的连接。这导致来自滥用来源的连接速率受到限制。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 keep-alive 的情况下,所有 tcp-request content 规则都会被重新评估,因此 haproxy 会记录由“tcp-request connection”与“tcp-request content”规则分配的粘性计数器,并在处理 HTTP 请求后刷新所有与内容相关的计数器,以便它们可以被下一个请求评估的规则重新评估。这在规则跟踪某些 L7 信息或由 L7 基于 ACL 条件时尤其重要,因为跟踪可能在请求之间发生变化。基于内容的规则按其声明的精确顺序进行评估。如果没有规则匹配或没有规则,则默认操作是接受内容。可以插入的规则数量没有特定限制。支持几种类型的操作:- accept:接受请求- do-resolve:执行 DNS 解析- reject:拒绝请求并关闭连接- capture:捕获指定的样本表达式- set-priority-class <expr> | set-priority-offset <expr>- { track-sc0 | track-sc1 | track-sc2 } <key> [table <table>]- sc-inc-gpc0(<sc-id>)- sc-inc-gpc1(<sc-id>)- sc-set-gpt0(<sc-id>) <int>- set-dst <expr>- set-dst-port <expr>- set-var(<var-name>) <expr>- unset-var(<var-name>)- silent-drop- send-spoe-group <engine-name> <group-name>- use-service <service-name>它们具有与“tcp-request connection”中的对应项相同的含义,因此请参阅该部分以获取完整描述。对于“do-resolve”操作,请检查“http-request do-resolve”配置部分。虽然没有强制性,但建议在“tcp-request connection”规则中使用 track-sc0,在前端的“tcp-request content”规则中使用 track-sc1,在后端的“tcp-request content”规则中使用 track-sc2,因为这使得配置更具可读性且更易于故障排除,但这只是一个指南,所有计数器都可以在任何地方使用。请注意,“if/unless”条件是可选的。如果操作没有设置条件,它将无条件执行。这对于“track-sc*”操作以及更改默认操作为拒绝可能很有用。通过“tcp-request content”规则匹配第 7 层内容是完全可能的,因为 HTTP 特定的 ACL 匹配能够初步解析缓冲区内容,然后再提取所需数据。如果缓冲的内容无法解析为有效的 HTTP 消息,则 ACL 不匹配。所涉及的解析器与所有其他 HTTP 处理的解析器完全相同,因此不存在以不同方式解析的风险。在从 HTTP 前端连接的 HTTP 后端中,保证在首次评估规则时,HTTP 内容始终是立即可用的。跟踪第 7 层信息也是可能的,前提是信息在处理规则时可用。规则处理引擎能够等待直到检查延迟到期,即使要跟踪的数据尚未可用。“set-dst”和“set-dst-port”分别用于设置目标 IP 和端口。有关如何使用它的更多信息,请参阅“http-request set-dst”。“set-var”用于设置变量的内容。变量是内联声明的。对于“tcp-request session”规则,只能使用会话级别的变量,没有任何第 7 层内容。<var-name> 变量的名称以其范围的指示开头。允许的范围是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。<expr> 是一个标准的 HAProxy 表达式,由样本获取后跟一些转换器组成。“unset-var”用于取消设置变量。有关 <var-name> 的详细信息,请参阅上文。“set-priority-class”用于设置当前请求的队列优先级类别。值必须是一个样本表达式,该表达式转换为 -2047..2047 范围内的整数。超出此范围的结果将被截断。优先级类别决定了队列中请求的处理顺序。值越低,优先级越高。“set-priority-offset”用于设置当前请求的队列优先级时间戳偏移量。值必须是一个样本表达式,该表达式转换为 -524287..524287 范围内的整数。超出此范围的结果将被截断。当请求入队时,它首先按优先级类别排序,然后按当前时间戳(根据给定的偏移量调整)排序(以毫秒为单位)。值越低,优先级越高。请注意,结果时间戳仅以足以表示 524,287 毫秒(8 分钟 44 秒 287 毫秒)的精度进行跟踪。如果请求排队时间过长,导致调整后的时间戳超出此值,它将被错误地识别为最高优先级。因此,重要的是将“timeout queue”设置为一个值,该值与偏移量结合后不会超出此限制。“send-spoe-group”用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。<engine-name> SPOE 引擎名称。<group-name> SPOE 组名称,如引擎配置中所指定。“use-service”用于执行一个 TCP 服务,该服务将回复请求并停止规则评估。此服务可以选择通过发送任何有效响应来回复,也可以在不发送任何内容的情况下立即关闭连接。除了原生服务之外,还可以用 Lua 编写自己的服务。不再评估其他“tcp-request”规则。
tcp-request content use-service lua.deny if { src -f /etc/haproxy/blacklist.lst }
tcp-request content set-var(sess.my_var) src tcp-request content unset-var(sess.my_var2)
# 接受包含 Host 头部为 "example.com" 的 HTTP 请求 # 并拒绝所有其他请求。 acl is_host_com hdr(Host) -i example.com tcp-request inspect-delay 30s tcp-request content accept if is_host_com tcp-request content reject
# 如果客户端先说话,则拒绝 SMTP 连接 tcp-request inspect-delay 30s acl content_present req.len gt 0 tcp-request content reject if content_present # 仅当客户端说话时才转发 HTTPS 连接 tcp-request inspect-delay 30s acl content_present req.len gt 0 tcp-request content accept if content_present tcp-request content reject
# 跟踪 X-Forwarded-For 中的最后一个 IP(粘滞表类型为 string) tcp-request inspect-delay 10s tcp-request content track-sc0 hdr(x-forwarded-for,-1) # 或者跟踪 X-Forwarded-For 中的最后一个 IP(粘滞表类型为 ip|ipv6) tcp-request content track-sc0 req.hdr_ip(x-forwarded-for,-1)
# 按“base”(Host+URL 的串联)跟踪请求计数 tcp-request inspect-delay 10s tcp-request content track-sc0 base table req-rate
跟踪每个前端和每个后端的计数器,当后端检测到滥用(并标记 gpc0)时,在前端阻止滥用者。frontend http # 在 SC0 中使用通用计数器 0 作为全局滥用计数器 # 保护我们所有的站点 stick-table type ip size 1m expire 5m store gpc0 tcp-request connection track-sc0 src tcp-request connection reject if { sc0_get_gpc0 gt 0 } ... use_backend http_dynamic if { path_end .php } backend http_dynamic # 如果某个来源对此动态站点发出的请求过快(由 # SC1 跟踪),则在前端全局阻止它。 stick-table type ip size 1m expire 5m store http_req_rate(10s) acl click_too_fast sc1_http_req_rate gt 10 acl mark_as_abuser sc0_inc_gpc0(http) gt 0 tcp-request content track-sc1 src tcp-request content reject if click_too_fast mark_as_abuser
有关 ACL 的用法,请参见第 7 节。
设置在内容检测期间等待数据的最大允许时间
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
否![]() | 是![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
主要用作 TCP 中继器使用 haproxy 的用户通常担心未经分析地将任何类型协议传递给服务器的风险。为了能够分析请求内容,我们必须首先保留数据,然后进行分析。此语句仅启用数据保留,最多保留指定的时间。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-inc-gpc1(<sc-id>): 此操作根据由 <sc-id> 指定的粘性计数器增加 GPC1 计数器。如果发生错误,此操作将静默失败,并且操作评估将继续。- sc-set-gpt0(<sc-id>) <int>:此操作根据由 <sc-id> 指定的粘性计数器和 <int> 的值设置 GPT0 标签。预期结果为布尔值。如果发生错误,此操作将静默失败,并且操作评估将继续。- "silent-drop":这会停止规则的评估,并以一种系统依赖的方式突然消失客户端连接,试图防止客户端收到通知。其效果是客户端仍然看到一个已建立的连接,而在 HAProxy 上没有任何连接。其目的是实现与“tarpit”类似的效果,但它根本不使用运行 HAProxy 的机器上的任何本地资源。它可以抵抗比“tarpit”高得多的负载,并减缓更强的攻击者。理解使用此机制的影响很重要。位于客户端和 HAProxy 之间的所有有状态设备(防火墙、代理、负载均衡器)也将长时间保持已建立的连接,并可能因此操作而受到影响。在具有足够权限的现代 Linux 系统上,TCP_REPAIR 套接字选项用于阻止 TCP 重置的发送。在其他系统上,套接字的 TTL 会减少到 1,这样 TCP 重置就不会通过第一个路由器,尽管它仍然会被传递到本地网络。除非您完全了解它的工作原理,否则请勿使用它。- send-spoe-group <engine-name> <group-name>:发送一组 SPOE 消息。请注意,“if/unless”条件是可选的。如果操作没有设置条件,它将无条件执行。这对于更改默认操作为拒绝可能很有用。通过“tcp-response content”规则匹配第 7 层内容是完全可能的,但重要的是要确保响应已完全缓冲,否则任何内容都不会匹配。为了实现这一点,最佳解决方案是在检查期间检测 HTTP 协议。“set-var”用于设置变量的内容。变量是内联声明的。<var-name> 变量的名称以其范围的指示开头。允许的范围是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享“req”:变量仅在请求处理期间共享“res”:变量仅在响应处理期间共享此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。<expr> 是一个标准的 HAProxy 表达式,由样本获取后跟一些转换器组成。“unset-var”用于取消设置变量。有关 <var-name> 的详细信息,请参阅上文。“send-spoe-group”用于触发发送一组 SPOE 消息。为此,必须定义用于发送消息的 SPOE 引擎,以及要发送的 SPOE 组。当然,SPOE 引擎必须引用一个现有的 SPOE 过滤器。如果 SPOE 过滤器行上未提供引擎名称,则必须使用 SPOE 代理名称。<engine-name> SPOE 引擎名称。<group-name> SPOE 组名称,如引擎配置中所指定。有关 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-inc-gpc1(<sc-id>)- sc-set-gpt0(<sc-id>) <int>- set-dst <expr>- set-dst-port <expr>- set-src <expr>- set-src-port <expr>- set-var(<var-name>) <expr>- unset-var(<var-name>)- silent-drop这些操作具有与它们在“tcp-request connection”和“tcp-request content”中的对应项相同的含义,因此请参阅这些部分以获取完整描述。请注意,“if/unless”条件是可选的。如果操作没有设置条件,它将无条件执行。这对于“track-sc*”操作以及更改默认操作为拒绝可能很有用。
默认跟踪原始源地址,或者对于来自本地代理的连接,跟踪 PROXY 协议头中通告的地址。第一个连接级别的规则为这些连接启用了 PROXY 协议的接收,第二个规则跟踪我们在可选解码后决定保留的任何地址。tcp-request connection expect-proxy layer4 if { src -f proxies.lst } tcp-request session track-sc0 src
接受所有来自白名单主机的会话,拒绝过快的会话而不对其进行计数,并跟踪已接受的会话。这导致来自滥用来源的会话速率受到限制。tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session reject if { src_sess_rate gt 10 } tcp-request session track-sc0 src
接受所有来自白名单主机的会话,对所有其他会话进行计数,并拒绝过快的会话。这导致滥用会话被阻止,直到它们减速为止。tcp-request session accept if { src -f /etc/haproxy/whitelist.lst } tcp-request session track-sc0 src tcp-request session reject if { sc0_sess_rate gt 10 }
有关 ACL 的用法,请参见第 7 节。
设置内容检测期间等待响应的最大允许时间
可在以下部分中使用
| 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”。它应用于空闲的 HTTP/2 连接,一旦发送了 GOAWAY 帧,这通常表示期望连接很快结束。此参数特定于前端,但可以在“defaults”部分一次性指定。默认情况下,它未设置,因此半关闭的连接将使用其他超时(timeout.client 或 timeout.tunnel)。
设置等待服务器连接尝试成功的最大时间。
可在以下部分中使用
| defaults | frontend | listen | backend |
|---|---|---|---|
是![]() | 否![]() | 是![]() | 是![]() |
<timeout> 是默认以毫秒为单位指定的超时值,但如果数字后缀有单位,则可以是任何其他单位,如本文档开头所述。
如果服务器与 haproxy 位于同一 LAN 上,连接应该是即时的(不到几毫秒)。无论如何,一个好的做法是设置略高于 3 秒倍数的超时时间(例如 4 或 5 秒),以覆盖一个或多个 TCP 数据包丢失。默认情况下,连接超时还会将队列和 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 内容规则),此超时就会被使用。在 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 中使用,可以通过无状态 ACL(例如源地址验证)不带内容使用,或与“tcp-request”规则结合使用以等待一些有效负载。可以根据需要设置任意数量的“use_backend”规则。所有这些规则都按声明顺序进行评估,第一个匹配的规则将分配后端。在第一种形式中,如果满足条件,则使用后端。在第二种形式中,如果条件不满足,则使用后端。如果没有条件有效,则使用“default_backend”定义的后端。如果没有定义默认后端,则使用同一节中的服务器(如果是“listen”节),或者,如果是前端,则不使用服务器并返回 503 服务不可用响应。请注意,可以从 TCP 前端切换到 HTTP 后端。在这种情况下,要么前端已经检查了协议是 HTTP,然后后端处理将立即进行,要么后端将等待完整的 HTTP 请求进入。当一个前端必须在唯一端口上解码多种协议时,其中一种是 HTTP,这个功能就很有用。当是一个简单名称时,它在配置时解析,如果指定的后端不存在,则报告错误。如果 是一个日志格式字符串,则在配置时可能不会进行检查,因此后端名称在运行时动态解析。如果生成的后端名称不对应任何有效后端,则不评估其他规则,而是应用 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 的协议(也请参阅“req.ssl_sni”)时,可以根据 TLS SNI 字段在服务器场中选择一个服务器。如果这些服务器的权重设置为零,则它们不会用于其他流量。
# 基于 SNI 字段拦截传入的 TLS 请求 use-server www if { req.ssl_sni -i www.example.com } server www 192.168.0.1:443 weight 0 use-server mail if { req.ssl_sni -i mail.example.com } server mail 192.168.0.1:465 weight 0 use-server imap if { req.ssl_sni -i imap.example.com } server imap 192.168.0.1:993 weight 0 # 所有其余请求都转发到此服务器 server default 192.168.0.2:443 check
“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" 以更精细地设置允许哪些客户端使用该协议。
允许在使用TLSv1.3时接收早期数据。由于安全考虑,此功能默认禁用。因为它容易受到重放攻击,您只应在对可以安全重放的请求(即幂等请求)允许此功能。对于任何使用早期数据不安全的请求,您可以使用"wait-for-handshake"操作。
此选项启用 TLS ALPN 扩展,并通告指定的协议列表作为 ALPN 支持的协议。协议列表是一个以逗号分隔的协议名称列表,例如:“http/1.1,http/1.0”(不含引号)。这要求 SSL 库在构建时启用了对 TLS 扩展的支持(请使用 haproxy -vv 进行检查)。ALPN 扩展取代了最初的 NPN 扩展。启用 HTTP/2 需要 ALPN。OpenSSL 1.0.2 之前的版本不支持 ALPN,只支持现已过时的 NPN 扩展。在撰写本文时,大多数浏览器仍然同时支持 ALPN 和 NPN 用于 HTTP/2,因此回退到 NPN 可能在一段时间内仍然有效。但应尽可能使用 ALPN。如果希望同时支持 HTTP/2 和 HTTP/1.1,可以按优先顺序通告这两个版本,如下所示: bind :443 ssl crt pub.pem alpn h2,http/1.1
将套接字的 backlog 设置为此值。如果未指定或为 0,则使用前端的 backlog,通常默认为 maxconn 值。
此设置仅在内置 OpenSSL 支持时可用。它设置描述在与 ECDHE 的 SSL/TLS 握手期间协商的椭圆曲线算法列表(“曲线套件”)的字符串。该字符串的格式是以冒号分隔的曲线名称列表。
此设置仅在内置 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 握手期间(最高到 TLSv1.2)协商的密码算法列表(“密码套件”)的字符串。该字符串的格式在 OpenSSL 手册页的“man 1 ciphers”中定义。有关背景信息和建议,请参阅(https://wiki.mozilla.org/Security/Server_Side_TLS)和(https://mozilla.github.io/server-side-tls/ssl-config-generator/)。有关 TLSv1.3 密码配置,请检查“ciphersuites”关键字。此设置仅在构建中支持 OpenSSL 并且使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。它设置了在 TLSv1.3 握手期间协商的密码算法(“密码套件”)的列表的字符串。字符串的格式在 OpenSSL man 页面的“man 1 ciphers”中“ciphersuites”部分下定义。有关 TLSv1.2 及更早版本的密码配置,请参阅“ciphers”关键字。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载验证客户端证书的证书吊销列表。
此设置仅在构建中支持 OpenSSL 时可用。它指定一个 PEM 文件,其中包含必需的证书和任何关联的私钥。此文件可以通过将多个 PEM 文件连接到一个文件中来构建(例如,cat cert.pem key.pem > combined.pem)。如果您的 CA 需要中间证书,也可以将其连接到此文件中。如果使用的 OpenSSL 支持 Diffie-Hellman,则会加载此文件中存在的参数。如果使用目录名而不是 PEM 文件,则该目录中的所有文件将按字母顺序加载,除非其名称以“.issuer”、“.ocsp”或“.sctl”(保留的扩展名)结尾。此指令可以指定多次,以从多个文件或目录加载证书。证书将呈现给提供有效的 TLS 服务器名称指示(SNI)字段匹配其 CN 或 alt subject 的客户端。通配符受支持,其中一个通配符字符 '*' 用于代替第一个主机名组件(例如,\*.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 文件中找不到颁发者的证书,它将从同一路径下以“.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 密码套件。使用 BoringSSL 和 Openssl >= 1.1.1 时,多证书是原生支持的,无需捆绑证书。如果客户端支持 ECDSA 证书,则会优先选择 ECDSA 证书。如果将目录名作为参数给出,haproxy 将自动搜索并加载该目录中的捆绑文件。OSCP 文件(.ocsp)和颁发者文件(.issuer)支持多证书捆绑。每个证书都可以有自己的 .ocsp 和 .issuer 文件。目前,sctl 不支持多证书捆绑。
此设置仅在内置 OpenSSL 支持时可用。设置一个逗号分隔的错误 ID 列表,在深度 == 0 的验证期间忽略这些错误。如果设置为 'all',则忽略所有错误。如果忽略了某个错误,SSL 握手不会中止。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件列表,其中包含可选的 SSL 配置和每个证书的 SNI 过滤器,每行的格式如下:<crtfile> [\[<sslbindconf> ...\]] [[!]<snifilter> ...] sslbindconf 支持 "allow-0rtt"、“alpn"、“ca-file"、“ciphers"、“ciphersuites"、“crl-file"、“curves"、“ecdhe"、“no-ca-names"、“npn"、“verify" 配置。使用 BoringSSL 和 OpenSSL >= 1.1.1 时,还支持“ssl-min-ver”和“ssl-max-ver”。它会覆盖绑定行中为证书设置的配置。通配符支持 SNI 过滤器。配置中可以指定负面过滤器,但它们仅用作提示,不起实际作用。(此行为在较新的 haproxy 版本中有所更改)如果您想从通配符中排除 SNI,请在另一行使用此正面 SNI。(如示例所示)。证书将呈现给提供有效 TLS 服务器名称指示字段且与 SNI 过滤器之一匹配的客户端。如果未指定 SNI 过滤器,则使用 CN 和 alt subject。此指令可以指定多次。有关更多信息,请参阅“crt”选项。默认证书仍需要满足 OpenSSL 的期望。如果未使用,则可以使用 `strict-sni` 选项。多证书捆绑(请参阅“crt”)受 `crt-list` 支持,只要 `crt-list` 中仅给出基本名称即可。SNI 过滤器将对所有捆绑的证书执行相同的工作。使用 BoringSSL 和 OpenSSL >= 1.1.1 时,多证书是原生支持的,请避免多证书捆绑。RSA 和 ECDSA 证书可以并排放置,并设置不同的 ssl 和过滤器参数。crt-list 文件示例:cert1.pem cert2.pem [alpn h2,http/1.1] certW.pem *.domain.tld !secure.domain.tld certS.pem [curves X25519:P-256 ciphers ECDHE-ECDSA-AES256-GCM-SHA384] secure.domain.tld
是一个可选关键字,仅在某些 Linux 内核上受支持。它规定只有在连接上有数据到达时,或者最坏情况下在第一次重传后,才会接受连接。这只应在客户端首先发言的协议(例如 HTTP)上使用。它可以通过确保在接受连接时大部分请求已经可用,从而略微提高性能。另一方面,它将无法检测到不发言的连接。重要的是要注意,此选项在所有 2.6.31 之前的内核中都是有问题的,因为在客户端发言之前连接永远不会被接受。这可能会导致前端防火墙出现问题,前端防火墙会看到一个已建立的连接,而代理只会看到它处于 SYN_RECV 状态。此选项仅在 TCPv4/TCPv6 套接字上受支持,其他套接字会忽略它。
此选项仅可用于 stats 套接字。它使您的 stats 套接字能够将监听器 FD 传递给另一个 HAProxy 进程。在 master-worker 模式下进行重载时,进程会自动重新执行,并添加 -x 和带有此选项的 stats 套接字之一。另请参见管理指南中的“-x”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 SSLv3。对于高连接速率,SSLv3 通常比 TLS 对应项的开销更低。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.0。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.1。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.2。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此选项强制从此侦听器实例化的 SSL 连接仅使用 TLSv1.3。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。它启用动态 SSL 证书生成。需要一个 CA 证书及其私钥(参见“ca-sign-file”)。当 HAProxy 配置为透明转发代理时,由于呈现给客户端的证书上的通用名称不匹配,SSL 请求会产生错误。启用此选项后,HAProxy 将尝试使用客户端指示的 SNI 主机名伪造一个证书。这仅在没有证书与 SNI 主机名匹配时才会发生(参见“crt-list”)。如果发生错误,则使用默认证书,否则设置“strict-sni”选项。当 HAProxy 配置为反向代理时,它也可以用于简化具有许多后端的架构的部署。创建 SSL 证书是一项昂贵的操作,因此使用 LRU 缓存来存储伪造的证书(参见“tune.ssl.ssl-ctx-cache-size”)。它增加了 HAProxy 的内存占用,以减少多次使用同一证书时的延迟。
将 UNIX 套接字的组设置为指定的系统 gid。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "group" 设置等效,不同之处在于它使用组 ID 而不是组名。此设置对非 UNIX 套接字无效。
将 UNIX 套接字的组设置为指定的系统组。也可以在全局部分的 "unix-bind" 语句中默认设置。请注意,某些平台会直接忽略此设置。此设置与 "gid" 设置等效,不同之处在于它使用组名而不是组 ID。此设置对非 UNIX 套接字无效。
固定套接字 ID。默认情况下,套接字 ID 是自动分配的,但有时为了方便监控而固定它们会更方便。此值必须是严格正数,并且在侦听器/前端内是唯一的。此选项只能在定义单个套接字时使用。
将套接字限制到特定接口。指定后,只有从该特定接口接收的数据包才会由套接字处理。目前仅在 Linux 上受支持。该接口必须是主系统接口,而不是别名接口。如果多个前端绑定到不同的接口,也可以将它们绑定到同一地址。请注意,绑定到网络接口需要 root 权限。此参数仅与 TCPv4/TCPv6 套接字兼容。指定后,返回流量将使用与入站流量相同的接口及其关联的路由表,即使配置了通过不同接口的显式路由也是如此。当同一客户端 IP 地址需要能够访问托管在不同接口上的前端时,这对于解决非对称路由问题非常有用。
此设置仅用于统计套接字,用于限制可以在套接字上发出的命令的性质。其他套接字会忽略它。<level> 可以是以下之一:- “user” 是权限最低的级别;只能读取非敏感统计信息,不允许进行任何更改。在难以限制套接字访问的系统上,这很有意义。- “operator” 是默认级别,适用于大多数常见用途。可以读取所有数据,只允许进行非敏感的更改(例如,清除最大计数器)。- “admin” 应谨慎使用,因为一切都被允许(例如,清除所有计数器)。此设置仅与 stats 套接字一起使用,用于配置附加到信息反馈消息前的严重性级别输出。消息的严重性级别范围可以在 0 到 7 之间,符合 syslog rfc5424。请求数据的有效且成功的套接字命令(例如“show map”、“get acl foo”等)绝不会附加严重性级别。其他套接字会忽略此设置。<format> 可以是以下之一:- “none”(默认)不向反馈消息前附加严重性级别。- “number” 严重性级别作为数字附加。- “string” 严重性级别作为遵循 rfc5424 约定的字符串附加。
将套接字限制为此数量的并发连接。多余的连接将保留在系统的 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 支持时可用。它在使用 `ca-file` 时,可防止在服务器 hello 消息中发送 CA 名称。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此侦听器实例化的任何套接字上的 SSLv3 支持。请注意,SSLv2 在代码中被强制禁用,并且无法使用任何配置选项进行启用。此选项在全局语句“ssl-default-bind-options”中也可用。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复在 CPU 使用方面成本更高。此选项在全局语句“ssl-default-bind-options”中也可用。TLS ticket 机制仅用于 TLS 1.2 及以下版本。除非定期轮换 ticket 密钥(通过 reload 或使用“tls-ticket-keys”),否则使用 TLS ticket 会损害前向保密性。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此侦听器实例化的任何套接字上的 TLSv1.0 支持。请注意,SSLv2 在代码中被强制禁用,并且无法使用任何配置选项进行启用。此选项在全局语句“ssl-default-bind-options”中也可用。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此侦听器实例化的任何套接字上的 TLSv1.1 支持。请注意,SSLv2 在代码中被强制禁用,并且无法使用任何配置选项进行启用。此选项在全局语句“ssl-default-bind-options”中也可用。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此侦听器实例化的任何套接字上的 TLSv1.2 支持。请注意,SSLv2 在代码中被强制禁用,并且无法使用任何配置选项进行启用。此选项在全局语句“ssl-default-bind-options”中也可用。请改用“ssl-min-ver”和“ssl-max-ver”。
此设置仅在内置 OpenSSL 支持时可用。当支持 SSL 时,它会禁用从此侦听器实例化的任何套接字上的 TLSv1.3 支持。请注意,SSLv2 在代码中被强制禁用,并且无法使用任何配置选项进行启用。此选项在全局语句“ssl-default-bind-options”中也可用。请改用“ssl-min-ver”和“ssl-max-ver”。
此功能启用 NPN TLS 扩展,并宣布指定的协议列表作为 NPN 之上的支持协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库已启用 TLS 扩展支持(通过 `haproxy -vv` 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(请参阅“alpn”关键字),尽管后者仅在 OpenSSL 1.0.2 及更高版本中可用。如果需要在较旧版本的 OpenSSL 中使用 HTTP/2,仍然可以使用 NPN,因为在撰写本文时,大多数客户端仍支持它。可以同时启用 NPN 和 ALPN,尽管这可能毫无意义,除非用于测试。在选择密码套件时使用客户端的偏好,默认情况下强制使用服务器的偏好。此选项也可在全局语句“ssl-default-bind-options”中使用。请注意,对于 OpenSSL >= 1.1.1,如果 ChaCha20-Poly1305 密码位于客户端密码列表的顶部,ChaCha20-Poly1305 无论如何都会被重新优先排序(无需设置此选项)。
此选项限制了此侦听器允许运行的进程或线程列表。它不强制执行任何进程,但会排除不匹配的进程。如果前端使用了 `bind-process` 设置,则会应用两者之间的交集。如果最终侦听器不允许在任何剩余进程上运行,则会发出警告,并且侦听器将运行在侦听器的第一个进程上(如果指定了单个进程),或者运行在其所有进程上(如果指定了多个进程)。如果指定了线程集,它将限制允许处理此侦听器的传入连接的线程,并针对进程集。如果配置了多个进程和线程,则会发出警告,因为这可能是配置错误或对这些模型的不理解所致。对于需要多个范围的不太可能的情况,可以重复使用此指令。<process-set> 和 <thread-set> 必须使用 `all | odd | even | number[-[number]]` 格式。范围可以部分定义。上限可以省略。在这种情况下,它将被替换为相应最大值。此指令的主要目的是与统计套接字一起使用,每个进程拥有一个不同的套接字。第二个目的是让多个绑定行共享相同的 IP:port 但不共享侦听器中的同一个进程,以便系统可以将传入连接分配到多个队列中,并允许更顺畅的进程间负载均衡。目前已知 Linux 3.9 及更高版本支持此功能。另请参阅“bind-process”和“nbproc”。
强制使用多路复用器协议处理传入连接。它必须与前端模式(TCP 或 HTTP)兼容。它也必须能在前端使用。可用协议列表在 `haproxy -vv` 中报告。此选项的目的是绕过为从该侦听套接字实例化的所有连接选择最佳的多路复用器协议。例如,可以通过在绑定行中指定“proto h2”来强制在纯 TCP 上使用 http/2。
此设置仅在内置 OpenSSL 支持时可用。它在此监听器实例化的连接上启用 SSL 解密。需要一个证书(参见上面的“crt”)。缓冲区中的所有内容都将以明文形式出现,因此 ACL 和 HTTP 处理只能访问解密后的内容。默认情况下禁用 SSLv3,使用“ssl-min-ver SSLv3”来启用它。此选项强制使用 <version> 或更低版本来处理从此侦听器实例化的 SSL 连接。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-min-ver”。
此选项强制使用 <version> 或更高版本来处理从此侦听器实例化的 SSL 连接。此选项在全局语句“ssl-default-bind-options”中也可用。另请参阅“ssl-max-ver”。
此设置仅在内置 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 票证密钥文件。根据使用 aes128 还是 aes256,密钥需要是 48 或 80 字节长,并使用 base64 编码,每行一个密钥(例如 openssl rand 80 | openssl base64 -A | xargs echo)。第一个密钥决定了后续密钥使用的密钥长度:您不能混合使用 aes128 和 aes256 密钥。密钥数量由 TLS_TICKETS_NO 构建选项指定(默认为 3),文件中至少需要存在同样数量的密钥。最后的 TLS_TICKETS_NO 个密钥将用于解密,倒数第二个密钥用于加密。这通过简单地将新密钥追加到文件并重新加载进程来实现轻松的密钥轮换。密钥必须定期轮换(例如每 12 小时),否则完美前向保密性会受到损害。将密钥远离任何永久性存储设备(如硬盘)也是一个好主意(提示:使用 tmpfs 并且不要交换这些文件)。生命周期提示可以使用 tune.ssl.timeout 进行更改。
是一个可选关键字,仅在某些 Linux 内核上受支持。它表示即使地址不属于本地机器,也会绑定这些地址,并且目标为这些地址的数据包将被截获,就好像这些地址是本地配置的一样。这通常需要启用 IP 转发。注意!不要将此与默认地址 '*' 一起使用,因为它会重定向指定端口的所有流量。此关键字仅在 HAProxy 使用 USE_LINUX_TPROXY=1 构建时可用。此参数仅与 TCPv4 和 TCPv6 套接字兼容,具体取决于内核版本。一些发行版的内核包含该功能的向后移植版本,因此请向您的供应商查询支持情况。
是一个可选关键字,仅在包括 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[:port] [settings ...]` `default-server [settings ...]` 请注意,所有这些设置都同时受“server”和“default-server”关键字支持,但“id”仅受“server”关键字支持。当前支持的设置如下。
使用“addr”参数,可以为发送健康检查或探测 agent-check 使用不同的 IP 地址。在某些服务器上,可能需要将一个 IP 地址专用于能够执行复杂测试的特定组件,这些测试比应用程序本身更适合进行健康检查。如果未设置“check”参数,则此参数将被忽略。另请参见“port”参数。
启用辅助代理检查,该检查独立于常规健康检查运行。代理健康检查是通过连接到 `agent-port` 参数设置的端口,并读取以第一个 '\r' 或 '\n' 结尾的 ASCII 字符串来执行的。该字符串由空格、制表符或逗号分隔的单词组成,顺序任意,每个单词包括:- 正整数百分比的 ASCII 表示形式,例如“75%”。此格式的值将设置权重,该权重与 haproxy 启动时配置的服务器的初始权重成比例。请注意,零权重在统计页面上报告为“DRAIN”,因为它对服务器的效果相同(它被移出了 LB 池)。- 字符串“maxconn:”,后跟一个整数(之间无空格)。此格式的值将设置服务器的最大连接数。报告的连接数上限需要乘以负载均衡器的数量和使用此健康检查的不同后端数量,才能获得服务器可能收到的总连接数。示例:maxconn:30- 单词“ready”。这将把服务器的管理员状态设置为 READY 模式,从而取消任何 DRAIN 或 MAINT 状态- 单词“drain”。这将把服务器的管理员状态设置为 DRAIN 模式,因此除了通过持久性接受的连接外,它将不接受任何新连接- 单词“maint”。这将把服务器的管理员状态设置为 MAINT 模式,因此它根本不接受任何新连接,并且健康检查将停止- 单词“down”、“fail”或“stopped”,可选地在井号 ('#') 后面跟一个描述字符串。所有这些都将服务器的操作状态标记为 DOWN,但由于单词本身会报告在统计页面上,因此差异允许管理员知道情况是否符合预期或不是:服务可能有意停止,可能看起来正常但未能通过某些有效性测试,或者可能被视为关闭(例如,缺少进程或端口无响应)。- 单词“up”将服务器的操作状态设置回 UP,前提是健康检查也报告服务可访问。未由代理通告的参数不会更改。例如,代理可能设计用于监控 CPU 使用率,并且仅报告相对权重,而从不与操作状态交互。同样,代理可能设计为用户界面,带有 3 个单选按钮,允许管理员仅更改管理员状态。但是,重要的是要考虑只有代理才能撤销其自己的操作,因此如果服务器通过代理设置为 DRAIN 模式或 DOWN 状态,代理必须实现其他等效操作才能使服务恢复正常运行。连接到代理的失败不被视为错误,因为连接性由常规健康检查测试,该检查由 `check` 参数启用。但是请注意,在代理报告“down”后停止代理不是一个好主意,因为只有报告“up”的代理才能再次将服务器启动。请注意,Unix 统计套接字上的 CLI 也可以强制执行代理结果,以解决错误的代理问题(如果需要)。需要设置 `agent-port` 参数。另请参阅 `agent-inter` 和 `no-agent-check` 参数。
如果指定了此选项,haproxy 将在连接时将给定的字符串(按原样)发送到代理服务器。例如,您可以将后端名称编码到此字符串中,这将使您的代理能够根据后端发送不同的响应。请确保包含 `\n`,如果您想以换行符终止您的请求。
“agent-inter”参数将两次 agent 检查之间的间隔设置为 <delay> 毫秒。如果未指定,延迟默认为 2000 毫秒。与所有其他基于时间的参数一样,它可以输入任何其他明确的单位,如 { us, ms, s, m, h, d }。“agent-inter”参数在未设置“timeout check”时也用作 agent 检查的超时。为了减少当多个服务器托管在同一硬件上时的“共振”效应,所有服务器的 agent 和健康检查都以一个小的时差启动。也可以使用全局“spread-checks”关键字在 agent 和健康检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这样做是有意义的。另请参见“agent-check”和“agent-port”参数。
`agent-addr` 参数设置代理检查的地址。您可以将代理检查卸载到另一个目标,这样您就可以在一个地方管理 haproxy 中定义的服务器的状态和权重,以防您无法创建自我意识和自我管理的 à 服务。您可以指定 IP 或主机名,它们都将被解析。
“agent-port”参数设置用于 agent 检查的 TCP 端口。另请参见“agent-check”和“agent-inter”参数。
在使用 TLS 1.3 时,允许向服务器发送早期数据。请注意,只有当客户端使用了早期数据,或者后端使用了带有“0rtt-rejected”关键字的“retry-on”时,才会发送早期数据。
此功能启用 TLS ALPN 扩展,并宣布指定的协议列表作为 ALPN 之上的支持协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不带引号)。这要求 SSL 库已启用 TLS 扩展支持(通过 `haproxy -vv` 检查)。ALPN 扩展取代了原始的 NPN 扩展。ALPN 是连接到 HTTP/2 服务器所必需的。OpenSSL 版本早于 1.0.2 不支持 ALPN,仅支持现已废弃的 NPN 扩展。如果预期同时支持 HTTP/2 和 HTTP/1.1,则可以按首选顺序声明这两个版本,如下所示:`server 127.0.0.1:443 ssl crt pub.pem alpn h2,http/1.1`
当 server 行上存在“backup”时,该服务器仅在所有其他非备份服务器都不可用时才用于负载均衡。但是,带有引用该服务器的持久性 cookie 的请求将始终被处理。默认情况下,只使用第一个可操作的备份服务器,除非在后端设置了“allbackups”选项。另请参见“no-backup”和“allbackups”选项。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,从中加载用于验证服务器证书的 CA 证书。
此选项启用服务器上的运行状况检查。默认情况下,服务器始终被视为可用。如果设置了“check”,当服务器接受定期 TCP 连接时,它就被认为是可用的,以确保它确实能够处理请求。用于发送测试的默认地址和端口是服务器本身的地址和端口,而默认源与后端中定义的源相同。可以使用“addr”参数更改地址,使用“port”参数更改端口,使用“source”地址更改源地址,并使用“inter”、“rise”和“fall”参数更改间隔和计时器。请求方法在后端使用“httpchk”、“smtpchk”、“mysql-check”、“pgsql-check”和“ssl-hello-chk”选项定义。有关更多信息,请参阅这些选项和参数。另请参阅“no-check”选项。
此选项强制在出站健康检查中发送 PROXY 协议行,无论服务器是否为正常流量使用 send-proxy。默认情况下,如果 PROXY 协议已为正常流量启用,并且不存在“port”或“addr”指令,则为健康检查启用 PROXY 协议。但是,如果存在此类指令,则需要使用“check-send-proxy”选项来强制使用该协议。有关更多信息,请参见“send-proxy”选项。
定义要通过 ALPN 通告的协议。协议列表由逗号分隔的协议名称组成,例如:“http/1.1,http/1.0”(不含引号)。如果未设置,将使用服务器的 ALPN。
此选项允许您指定在通过 SSL 进行健康检查时使用的 SNI。只能使用字符串来设置 <sni>。如果您想为代理的流量设置 SNI,请参见“sni”。
此选项强制使用 SSL 加密所有运行状况检查,无论服务器是否对正常流量使用 SSL。这通常在指定了显式“port”或“addr”指令且未继承 SSL 运行状况检查时使用。重要的是要理解,此选项在检查下方插入了一个 SSL 传输层,因此简单的 TCP 连接检查会变成 SSL 连接,从而取代了旧的 ssl-hello-chk。最常见的用法是结合“httpchk”和 SSL 检查来发送 HTTPS 检查。所有 SSL 设置对运行状况检查和流量都是通用的(例如,密码套件)。有关更多信息,请参阅“ssl”选项,使用“no-check-ssl”禁用此选项。
此选项启用使用上游 socks4 代理的传出运行状况检查。默认情况下,即使已为主流量启用 Socks 隧道,运行状况检查也不会通过 Socks 隧道。
此设置仅在内置 OpenSSL 支持时可用。此选项设置一个字符串,该字符串描述了在与服务器进行 SSL/TLS 握手期间协商的密码算法列表。字符串的格式定义在 OpenSSL man 页面的“man 1 ciphers”中。有关背景信息和建议,请参阅例如 (https://wiki.mozilla.org/Security/Server_Side_TLS) 和 (https://mozilla.github.io/server-side-tls/ssl-config-generator/)。对于 TLSv1.3 密码配置,请检查“ciphersuites”关键字。此设置仅在内置 OpenSSL 支持并使用 OpenSSL 1.1.1 或更高版本构建 HAProxy 时可用。此选项设置一个字符串,该字符串描述了在与服务器进行 TLS 1.3 握手期间协商的密码算法列表。字符串的格式定义在 OpenSSL man 页面的“man 1 ciphers”的“ciphersuites”部分中。对于 TLSv1.2 及更早版本的密码配置,请检查“ciphers”关键字。
“cookie”参数将分配给服务器的 cookie 值设置为 <value>。此值将在传入请求中进行检查,并且将选择拥有相同值的第一个可运行服务器。作为回报,在 cookie 插入或重写模式下,此值将分配给发送给客户端的 cookie。有几个服务器共享相同的 cookie 值并没有错,实际上,在正常服务器和备份服务器之间的情况相当普遍。另请参阅后端部分的“cookie”关键字。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载用于验证服务器证书的证书吊销列表。
此设置仅在内置 OpenSSL 支持时可用。它指定一个 PEM 文件,用于加载证书和关联的私钥。通过将这两个 PEM 文件连接到一个文件中,可以创建此文件。如果服务器发送客户端证书请求,则会发送此证书。
“disabled”关键字将服务器启动为“disabled”状态。这意味着它在维护模式下被标记为宕机,除了持久化模式允许的连接外,任何连接都不会到达它。它非常适合设置新服务器,因为正常流量永远不会到达它们,同时仍然可以通过使用强制持久化机制来测试服务。另请参阅“enabled”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“disabled”设置作为默认值。它也可作为“default-server”设置,以重置任何以前的“default-server”“disabled”设置。
如果启用了运行状况监视,“error-limit”参数指定触发“on-error”选项所选事件的连续错误次数。默认设置为 10 次连续错误。另请参阅“check”、“error-limit”和“on-error”。
“fall”参数表示服务器将在 <count> 次连续不成功的运行状况检查后被视为死亡。如果未指定,此值默认为 3。另请参阅“check”、“inter”和“rise”参数。
此选项强制仅使用 SSLv3,当 SSL 用于与服务器通信时。SSLv3 对于高连接速率通常比 TLS 对应项成本更低。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.0,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.1,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.2,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
此选项强制仅使用 TLSv1.3,当 SSL 用于与服务器通信时。此选项在全局语句“ssl-default-server-options”上也可使用。另请参阅“ssl-min-ver”和 ssl-max-ver”。
为服务器设置一个持久化 ID。此 ID 必须是正数且对代理是唯一的。如果未设置,将自动分配一个未使用的 ID。第一个分配的值将是 1。此 ID 目前仅在统计信息中返回。
指示启动时应以何种顺序解析服务器地址(如果它使用 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
“inter”参数将两次连续运行状况检查之间的间隔设置为 <delay> 毫秒。如果未指定,则延迟默认为 2000 毫秒。还可以使用“fastinter”和“downinter”来优化取决于服务器状态的检查之间的延迟。
| 服务器状态 | 使用的间隔 |
|---|---|
| UP 100% (非过渡状态) | “inter” |
| 过渡性 UP (正在变为 down "fall"), 过渡性 DOWN (正在变为 up "rise"), 或尚未检查。 | 如果设置了“fastinter”,则使用它, 否则使用“inter”。 |
| DOWN 100% (非过渡状态) | 如果设置了“downinter”,则使用它, 否则使用“inter”。 |
与所有其他基于时间的参数一样,它们可以以任何其他显式单位 {us, ms, s, m, h, d} 输入。“inter”参数在未设置“timeout check”时,也用作服务器运行状况检查的超时。为了减少托管在同一硬件上的多个服务器之间的“共振”效应,代理和所有服务器的运行状况检查都以它们之间一个小的时差开始。还可以使用全局“spread-checks”关键字在代理和运行状况检查间隔中添加一些随机噪声。例如,当许多后端使用相同的服务器时,这很有意义。“maxconn”参数指定将发送到此服务器的最大并发连接数。如果传入的并发连接数超过此值,它们将被排队,等待插槽被释放。此参数非常重要,因为它可以防止脆弱的服务器在极端负载下崩溃。如果指定了“minconn”参数,则限制将变为动态。默认值为“0”,表示无限制。另请参阅“minconn”和“maxqueue”参数,以及后端的“fullconn”关键字。在 HTTP 模式下,此参数限制的是并发请求数而不是连接数。多个请求可能被多路复用在到服务器的单个 TCP 连接上。例如,如果您指定 maxconn 为 50,您可能会看到 1 到 50 个实际的服务器连接,但并发请求不超过 50 个。
“maxqueue”参数指定此服务器队列中等待的最大连接数。如果达到此限制,后续请求将被重新分发到其他服务器,而不是无限期等待服务。这将破坏持久性,但可能允许用户在他们尝试连接的服务器即将崩溃时快速重新登录。默认值为“0”,表示队列无限制。另请参阅“maxconn”和“minconn”参数。
“max-reuse”参数指示 HTTP 连接处理器,它们不应将服务器连接重复使用超过此次数来发送新请求。允许的值为 -1(默认值),它禁用此限制,或任何正值。值为零将有效禁用 keep-alive。这仅用于解决某些服务器随时间推移而导致资源泄漏的 bug。由于可能存在技术限制使其无法强制执行,因此底层可能不会完全遵守此参数。至少 HTTP/2 连接到服务器会遵守它。
当设置“minconn”参数时,maxconn 限制将变为一个动态限制,根据后端的负载进行调整。服务器将始终接受至少 <minconn> 个连接,最多不超过 <maxconn> 个连接,当后端并发连接数少于 <fullconn> 时,限制将在两者之间进行调整。这使得在正常负载下限制服务器的负载成为可能,但在重要负载下可以将其进一步推高,而不会在异常负载下过载服务器。另请参阅“maxconn”和“maxqueue”参数,以及“fullconn”后端关键字。
在 Linux 上,可以指定套接字属于哪个网络命名空间。此指令使得可以明确地将服务器绑定到不同于默认命名空间的命名空间。有关网络命名空间的更多详细信息,请参阅您的操作系统文档。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“agent-check”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“agent-check”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“backup”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“backup”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“check”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“check”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“check-ssl”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“check-ssl”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“send-proxy”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“send-proxy”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“send-proxy-v2”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“send-proxy-v2”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“send-proxy-v2-ssl”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“send-proxy-v2-ssl”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“send-proxy-v2-ssl-cn”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“send-proxy-v2-ssl-cn”设置。
此选项可用作“server”设置,以重置从“default-server”指令继承的任何“ssl”设置作为默认值。它也可作为“default-server”设置,以重置任何先前的“default-server”的“ssl”设置。
此选项在 SSL 用于与服务器通信时禁用 SSL 会话重用。它将强制服务器为每个新连接执行完整的握手。这可能只对基准测试、故障排除和多疑用户有用。
此选项在 SSL 用于与服务器通信时禁用对 SSLv3 的支持。请注意,SSLv2 在代码中已禁用,无法通过任何配置选项启用。请改用“ssl-min-ver”和“ssl-max-ver”。默认服务器支持:否
此设置仅在构建时支持 OpenSSL 时可用。它禁用无状态会话恢复(RFC 5077 TLS Ticket 扩展)并强制使用有状态会话恢复。无状态会话恢复在服务器的 CPU 使用率方面成本更高。此选项也可用在全局语句 "ssl-default-server-options" 中。TLS Ticket 机制仅用于 TLS 1.2 及以下版本。前向保密会因 TLS Ticket 而受到损害,除非 Ticket 密钥被定期轮换(通过重载或使用 "tls-ticket-keys")。另请参阅 "tls-tickets"。
使用 SSL 与服务器通信时,此选项会禁用 TLSv1.0 支持。请注意,SSLv2 已在代码中禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用在全局语句 "ssl-default-server-options" 中。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
使用 SSL 与服务器通信时,此选项会禁用 TLSv1.1 支持。请注意,SSLv2 已在代码中禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用在全局语句 "ssl-default-server-options" 中。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
使用 SSL 与服务器通信时,此选项会禁用 TLSv1.2 支持。请注意,SSLv2 已在代码中禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用在全局语句 "ssl-default-server-options" 中。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
使用 SSL 与服务器通信时,此选项会禁用 TLSv1.3 支持。请注意,SSLv2 已在代码中禁用,无法通过任何配置选项启用。TLSv1 比 SSLv3 成本更高,因此在与本地服务器通信时禁用它通常是有意义的。此选项也可用在全局语句 "ssl-default-server-options" 中。请改用 "ssl-min-ver" 和 "ssl-max-ver"。在 default-server 中支持:否
此选项可用作 "server" 设置,以重置从 "default-server" 指令继承的任何 "verifyhost" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何之前的 "default-server" "verifyhost" 设置。
此选项可用作 "server" 设置,以重置从 "default-server" 指令继承的任何 "tfo" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何之前的 "default-server" "tfo" 设置。
永远不要将分配给此服务器的连接添加到 stick-table。这可以与 backup 结合使用,以确保为 backup 服务器禁用 stick-table 持久性。
这会启用 NPN TLS 扩展,并在 NPN 之上声明支持的协议列表。协议列表是一系列由逗号分隔的协议名称,例如:"http/1.1,http/1.0"(不带引号)。这要求 SSL 库在启用 TLS 扩展支持的情况下构建(通过 haproxy -vv 检查)。请注意,NPN 扩展已被 ALPN 扩展取代(请参阅 "alpn" 关键字),尽管后者仅在 OpenSSL 1.0.2 及以上版本可用。此选项启用基于观察与服务器通信的健康状况调整。默认情况下,此功能被禁用,启用它还需要启用健康检查。支持两种模式:"layer4" 和 "layer7"。在 layer4 模式下,只有成功的/不成功的 tcp 连接是重要的。在 layer7 模式下(仅允许用于 http 代理),会验证从服务器收到的响应,例如有效的/无效的 http 代码、无法解析的头信息、超时等。有效的状态码包括 100 到 499、501 和 505。另请参阅 "check"、"on-error" 和 "error-limit"。
选择在检测到足够多的连续错误时应执行的操作。目前提供四种模式:- fastinter:强制 fastinter - fail-check:模拟失败的检查,也强制 fastinter(默认) - sudden-death:模拟一个预致命的健康检查失败,再多一次失败的检查将导致服务器标记为宕机,强制 fastinter - mark-down:立即将服务器标记为宕机并强制 fastinter 另请参阅 "check"、"observe" 和 "error-limit"。
修改服务器被标记为宕机时发生的操作。目前提供一种操作:- shutdown-sessions:关闭会话。启用此设置后,当服务器宕机时,所有到该服务器的连接将立即终止。如果健康检查检测到的情况比简单的连接状态更复杂,并且长时间的超时会导致服务长时间无响应,则可能需要使用此选项。例如,健康检查可能检测到数据库卡死,并且没有机会重用现有连接。以此方式终止的连接将以 'D' 终止代码(表示 "Down")进行记录。默认情况下,操作是禁用的。
修改服务器被标记为正常时发生的操作。目前提供一种操作:- shutdown-backup-sessions:关闭所有备用服务器上的会话。这仅在服务器未处于备用状态且未被禁用(其有效权重必须 > 0)时执行。当处理长会话(例如 LDAP、SQL 等)时,这有时可用于强制活动服务器在恢复后重新承担所有流量。这样做可能会比试图解决的问题更多(例如,未完成的事务),因此请谨慎使用此功能。因服务器启动而终止的会话将以 'U' 终止代码(表示 "Up")进行记录。默认情况下,操作是禁用的。
设置服务器的空闲连接最大数量。-1 表示无限连接,0 表示无空闲连接。默认值为 -1。启用空闲连接后,不再属于任何客户端会话的孤立空闲连接将被移至专用池,以便未来的客户端可以使用它们。这仅适用于可以根据与 "http-reuse" 相同的原则共享的连接。
设置开始清除空闲连接的延迟。每隔 <delay> 时间间隔,一半的空闲连接将被关闭。0 表示不保留任何空闲连接。默认值为 5 秒。
使用 "port" 参数,可以为健康检查使用不同的端口。在某些服务器上,可能希望将一个端口专门用于能够执行复杂测试的特定组件,这些测试比应用程序更适合健康检查。例如,通常在 inetd 中运行一个简单的脚本。如果未设置 "check" 参数,则此参数将被忽略。另请参阅 "addr" 参数。
强制用于到此服务器的出站连接的多路复用器协议。它必须与后端的模式(TCP 或 HTTP)兼容。它也必须能在后端侧使用。可用协议列表在 haproxy -vv 中报告。此选项的目的是绕过为建立到此服务器的所有连接选择最佳多路复用器协议。
"redir" 参数为所有针对此服务器的 GET 和 HEAD 请求启用了重定向模式。这意味着 HAProxy 不会将请求转发到服务器,而是发送一个 "HTTP 302" 响应,其中 "Location" 头由此前缀组成,后跟请求的 URI,从路径组件的第一个 '/' 开始。这意味着 <prefix> 后面不应有尾随斜杠。所有无效请求将被拒绝,所有非 GET 或 HEAD 请求将正常由服务器提供服务。请注意,由于响应完全是伪造的,因此响应中不可能进行头信息篡改或 cookie 插入。但是,请求中的 cookie 仍会被分析,这使得该解决方案在本地发生灾难时,可完全用于将用户重定向到远程位置。主要用途是通过让客户端直接连接到静态服务器来增加其带宽。注意:切勿在此处使用相对位置,否则会导致客户端和 HAProxy 之间发生循环!
server srv1 192.168.1.1:80 redir http://image1.mydomain.com check
"rise" 参数指定服务器将在连续 <count> 次成功的健康检查后被视为可运行。如果未指定,此值默认为 2。另请参阅 "check"、"inter" 和 "fall" 参数。
逗号分隔的选项列表,应用于与此服务器关联的 DNS 解析。可用选项:* allow-dup-ip 默认情况下,HAProxy 在运行时 DNS 解析时会防止后端 IP 地址重复。尽管如此,在某些情况下,两个服务器(在同一后端,由相同的 FQDN 解析)具有相同的 IP 地址是有意义的。在这种情况下,只需启用此选项。这是 prevent-dup-ip 的反义词。* prevent-dup-ip 确保 HAProxy 的默认行为在服务器上得到执行:防止在同一后端且共享同一 FQDN 的服务器上重复使用已设置的 IP 地址。这是 allow-dup-ip 的反义词。
backend b_myapp default-server init-addr none resolvers dns server s1 myapp.example.com:80 check resolve-opts allow-dup-ip server s2 myapp.example.com:81 check resolve-opts allow-dup-ip
设置了 allow-dup-ip 选项后:* 如果域名服务器返回单个 IP 地址,则两个服务器都将使用它 * 如果域名服务器返回 2 个 IP 地址,则每个服务器将选择一个不同的地址 默认值:未设置
当为服务器启用 DNS 解析并且返回了来自不同族的多个 IP 地址时,HAProxy 将优先使用 "resolve-prefer" 参数中指定的族中的 IP 地址。可用族:"ipv4" 和 "ipv6" 默认值:ipv6
server s1 app1.domain.com:80 resolvers mydns resolve-prefer ipv6
此选项优先选择匹配网络的 IP 地址。这在云环境中很有用,可以优先选择本地 IP。在某些情况下,云高可用服务可以通过多个数据中心上的多个 IP 地址进行 anúnciate。数据中心之间的延迟不可忽略,因此此补丁允许优先选择本地数据中心。如果没有任何地址与配置的网络匹配,则会选择其他地址。
server s1 app1.domain.com:80 resolvers mydns resolve-net 10.0.0.0/8
指向一个现有的 "resolvers" 部分,以解析当前服务器的主机名。server s1 app1.domain.com:80 check resolvers mydns
另请参见 第 5.3 节
"send-proxy" 参数强制对建立到此服务器的任何连接使用 PROXY 协议。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它能够知道客户端地址或访问的公共地址,而不考虑上层协议。对于由 "accept-proxy" 或 "accept-netscaler-cip" 监听器接受的连接,将使用所 anúnciate 的地址。仅支持 TCPv4 和 TCPv6 地址族。其他族,如 Unix 套接字,将报告 UNKNOWN 族。使用此选项的服务器可以完全链接到另一个监听了 "accept-proxy" 设置的 haproxy 实例。如果服务器不了解该协议,则不应使用此设置。当向服务器发送健康检查时,如果设置了此选项,则会自动使用 PROXY 协议,除非有明确的 "port" 或 "addr" 指令指示应将检查发送到不同位置,在这种情况下,还需要一个明确的 "check-send-proxy" 指令来使用 PROXY 协议。另请参阅此部分的 "no-send-proxy" 选项以及 "bind" 关键字的 "accept-proxy" 和 "accept-netscaler-cip" 选项。
"send-proxy-v2" 参数强制对建立到此服务器的任何连接使用 PROXY 协议版本 2。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它能够知道客户端地址或访问的公共地址,而不考虑上层协议。如果协商了 alpn,它还会发送 ALPN 信息。如果服务器不了解该协议的此版本,则不应使用此设置。另请参阅此部分的 "no-send-proxy-v2" 选项以及 "bind" 关键字的 "send-proxy" 选项。
"proxy-v2-options" 参数在使用了 "send-proxy-v2" 时,会添加选项以发送到 PROXY 协议版本 2。可用选项包括:"ssl"(另请参阅 send-proxy-v2-ssl)、"cert-cn"(另请参阅 "send-proxy-v2-ssl-cn")、"ssl-cipher":使用的密码名称,"cert-sig":所用证书的签名算法,"cert-key":所用证书的密钥算法),"authority":客户端传递的主机名值(仅支持 TLS 连接的 sni),"crc32c":代理协议 v2 头的校验和。
"send-proxy-v2-ssl" 参数强制对建立到此服务器的任何连接使用 PROXY 协议版本 2。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它能够知道客户端地址或访问的公共地址,而不考虑上层协议。此外,还将 SSL 信息扩展添加到 PROXY 协议头中。如果服务器不了解该协议的此版本,则不应使用此设置。另请参阅此部分的 "no-send-proxy-v2-ssl" 选项以及 "bind" 关键字的 "send-proxy-v2" 选项。
"send-proxy-v2-ssl" 参数强制对建立到此服务器的任何连接使用 PROXY 协议版本 2。PROXY 协议会告知另一端传入连接的第 3/4 层地址,以便它能够知道客户端地址或访问的公共地址,而不考虑上层协议。此外,还将在 PROXY 协议头中添加 PROXY 协议的 SSL 信息扩展,以及客户端证书主体(如果存在)中的通用名称。如果服务器不了解该协议的此版本,则不应使用此设置。另请参阅此部分的 "no-send-proxy-v2-ssl-cn" 选项以及 "bind" 关键字的 "send-proxy-v2" 选项。
服务器的 "slowstart" 参数接受一个以毫秒为单位的值,表示刚刚恢复的服务器将在多长时间后以全速运行。与所有其他基于时间的参数一样,它可以输入任何其他显式单位 { us, ms, s, m, h, d }。速度在此期间从 0% 线性增长到 100%。限制适用于两个参数:- maxconn:服务器接受的连接数将从 1% 增长到 100% 的常规动态限制(由 minconn、maxconn、fullconn 定义)。- weight:当后端使用动态加权算法时,权重从 1% 线性增长到 100%。在这种情况下,权重会在每次健康检查时更新。因此,"inter" 参数小于 "slowstart" 很重要,以最大化步骤数量。慢启动在 haproxy 启动时从不适用,否则会给正在运行的服务器带来麻烦。它仅在服务器先前被视为失败时才适用。
"sni" 参数评估样本提取表达式,将其转换为字符串,并使用结果作为在 SNI TLS 扩展中发送到服务器的主机名。一个典型的用例是在桥接的 TCP/SSL 场景中发送从客户端接收到的 SNI,使用 "ssl_fc_sni" 样本提取作为表达式。THIS MUST NOT BE USED FOR HTTPS,在 HTTPS 中应改用 req.hdr(host),因为 HTTPS 的 SNI 必须始终与 Host 字段匹配,并且客户端允许在同一连接上使用不同的主机名)。如果设置了 "verify required"(这是推荐的设置),则结果名称还将与服务器证书的名称进行匹配。有关更多详细信息,请参阅 "verify" 指令。如果您想为健康检查设置 SNI,请参阅 "check-sni" 指令了解更多详细信息。
"source" 参数设置连接到服务器时将使用的源地址。它遵循与后端 "source" 关键字完全相同的参数和原则,但它仅适用于引用它的服务器。请参阅 "source" 关键字了解详细信息。此外,服务器行上的 "source" 语句允许通过指示由连字符('-')分隔的下限和上限来指定源端口范围。某些操作系统在指定源端口范围时可能需要有效的 IP 地址。允许多个服务器具有相同的 IP/范围。这样做可以绕过 64k 总并发连接的最大数量。然后,每个服务器的限制将达到 64k 个连接。自 Linux 4.2/libc 2.23 以来,IP_BIND_ADDRESS_NO_PORT 会被设置为指定源地址但不指定端口的连接。
此选项启用对服务器的出站连接进行 SSL 加密。使用 SSL 连接到服务器时,使用 "verify" 验证服务器证书至关重要,否则通信容易受到简单的中间人攻击,从而使 SSL 无效。当使用此选项时,健康检查也会自动通过 SSL 发送,除非有 "port" 或 "addr" 指令指示检查应发送到不同位置。请参阅 "no-ssl" 来禁用 "ssl" 选项,并参阅 "check-ssl" 选项来强制 SSL 健康检查。
使用 SSL 与服务器通信时,此选项强制使用 <version> 或更低版本。此选项也可用在全局语句 "ssl-default-server-options" 中。另请参阅 "ssl-min-ver"。
使用 SSL 与服务器通信时,此选项强制使用 <version> 或更高版本。此选项也可用在全局语句 "ssl-default-server-options" 中。另请参阅 "ssl-max-ver"。
此选项可用作 "server" 设置,以重置从 "default-server" 指令继承的任何 "no-ssl-reuse" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何之前的 "default-server" "no-ssl-reuse" 设置。
此选项可用作 "server" 设置,以重置从 "default-server" 指令继承的任何 "non-stick" 设置作为默认值。它也可用作 "default-server" 设置,以重置任何之前的 "default-server" "non-stick" 设置。
此选项为到服务器的出站连接启用上游 socks4 隧道。使用此选项默认不会强制健康检查通过 socks4。您需要使用关键字 "check-via-socks4" 来启用它。
设置到此服务器的所有出站连接的 TCP 用户超时。此选项自 Linux 2.6.37 版本起可用。它允许 haproxy 为包含在配置延迟内未收到确认的数据的套接字配置超时。这对于经历长时间空闲期的长连接特别有用,例如远程终端或数据库连接池,其中客户端和服务器超时必须保持较高以允许长时间空闲,但重要的是要检测到服务器已消失,以便释放与其连接(以及客户端会话)相关的所有资源。另一个典型用例是强制死服务器连接在健康检查太慢或在软重新加载期间(因为此时健康检查被禁用)终止。参数默认以毫秒为单位表示延迟。这仅适用于常规 TCP 连接,对于其他协议将被忽略。
此选项在支持它的系统(目前仅限 Linux 内核 >= 4.11)上启用连接到服务器时使用 TCP Fast Open。有关 TCP Fast Open 的更多信息,请参阅 "tfo" bind 选项。请注意,在使用 tfo 时,您还应该为 "retry-on" 使用 "conn-failure"、"empty-response" 和 "response-timeout" 关键字,否则 haproxy 将无法在失败时重试连接。另请参阅 "no-tfo"。
此选项通过跟踪另一个服务器来设置服务器的当前状态。可以跟踪一个本身跟踪另一个服务器的服务器,前提是链的末端有一个启用了健康检查的服务器。如果省略 <backend>,则使用当前服务器。如果使用了 disable-on-404,则必须在两个代理上都启用它。
此选项可用作 "server" 设置,以重置任何 "no-tls-tickets" 设置,该设置将从 "default-server" 指令继承为默认值。TLS 票证机制仅用于 TLS 1.2 及以下版本。前向保密性会因 TLS 票证而受到损害,除非定期轮换票证密钥(通过重新加载或使用 "tls-ticket-keys")。它还可以用作 "default-server" 设置,以重置任何先前的 "default-server" "no-tls-tickets" 设置。
此设置仅在内置 OpenSSL 支持时可用。如果设置为“none”,则不验证服务器证书。在其他情况下,服务器提供的证书将使用来自“ca-file”的 CA 和来自“crl-file”的可选 CRL 进行验证,前提是已检查证书主题和 subjectAlternateNames 属性中提供的名称是否与通过 "sni" 指令传递的名称匹配,或者在未提供时,与通过 "verifyhost" 指令传递的静态主机名匹配。当找不到名称时,将忽略证书中的名称。因此,在没有 SNI 的情况下,使用 "verifyhost" 非常重要。验证失败时,握手将被中止。在使用 SSL 连接到服务器时,验证服务器证书至关重要,否则通信容易受到轻微的中间人攻击,从而使 SSL 完全无效。除非“ssl_server_verify”出现在全局部分,否则 "verify" 默认为“required”。
此设置仅在内置 OpenSSL 支持时可用,并且仅在同时指定“verify required”时生效。此指令设置了一个默认的静态主机名,用于在未使用 SNI 连接到服务器时检查服务器证书。如果未使用 SNI,这是启用主机名验证的唯一方法。此静态主机名(设置后)也将用于健康检查(这些健康检查无法提供 SNI 值)。如果证书中的任何主机名与指定的主机名不匹配,握手将被中止。服务器提供的证书中的主机名可能包含通配符。另请参阅 "verify"、“sni”和“no-verifyhost”选项。
“weight”参数用于调整服务器相对于其他服务器的权重。所有服务器将根据其权重相对于所有权重总和的比例接收负载,因此权重越高,负载越高。默认权重为 1,最大值为 256。值为 0 表示服务器不参与负载均衡,但仍接受持久连接。如果使用此参数根据服务器容量分配负载,建议从可以增长和收缩的值开始,例如 10 到 100 之间,以便为以后调整留出足够的空间。
HAProxy 允许在服务器行中使用主机名通过名称服务器检索其 IP 地址。默认情况下,HAProxy 在解析配置文件时解析名称,并在启动时缓存结果,并在进程生命周期内缓存该结果。这在某些情况下不够用,例如在 Amazon 中,服务器的 IP 地址在重启后可能会发生变化,或者 ELB 虚拟 IP 地址会根据当前工作负载而变化。本章介绍 HAProxy 如何配置为在运行时处理服务器名称解析。无论是否启用了运行时服务器名称解析,HAProxy 在解析配置时都会继续进行第一次解析。
正如我们在引言中所见,HAProxy 中的名称解析发生在进程生命周期的两个不同阶段:1. 启动时,HAProxy 解析服务器行定义并匹配主机名。它使用 libc 函数来解析主机名。此解析依赖于 /etc/resolv.conf 文件。2. 运行时,HAProxy 会定期对需要 DNS 解析的服务器执行名称解析。其他一些事件也可能触发运行时名称解析:- 当服务器的健康检查最终导致连接超时时:这可能是因为服务器有了新的 IP 地址。因此,我们需要触发名称解析来获取这个新 IP。使用解析器时,服务器名称可以是主机名,也可以是 SRV 标签。HAProxy 将任何以“_”开头的视为 SRV 标签。如果指定了 SRV 标签,则将从 DNS 服务器检索相应的 SRV 记录,并使用提供的名称。SRV 标签将定期检查,如果添加或删除了任何服务器,haproxy 将自动执行相同的操作。需要注意的几点:- 所有名称服务器都会在中间被查询。HAProxy 将处理第一个有效响应。- 当所有服务器都返回错误时,解析将被视为无效(NX、超时、拒绝)。
本节专门介绍与 HAProxy 中名称解析相关的宿主信息。可以根据需要创建任意数量的 resolvers 部分。每个部分都可以包含多个名称服务器。当在 resolvers 部分中配置了多个名称服务器时,HAProxy 会使用第一个有效响应。在无效响应的情况下,只处理最后一个。目的是让慢速服务器在快速故障或过时的服务器之后有机会提供有效答案。当每个服务器返回不同的错误类型时,HAProxy 仅使用最后一个错误。应用以下处理来处理此错误:1. HAProxy 使用新的查询类型重试相同的 DNS 查询。A 查询切换到 AAAA 或反之亦然。SRV 查询不在此范围内。超时错误也排除在外。2. 当发生查询类型回退(或不适用)时,HAProxy 使用首选查询类型重试原始 DNS 查询。3. HAProxy 重试之前步骤 <resolve_retries> 次。如果在此之后仍未收到有效响应,它将停止 DNS 解析并报告错误。例如,在 resolvers 部分配置了 2 个名称服务器的情况下,可能出现以下情况:- 第一个响应有效并直接应用,第二个响应被忽略- 第一个响应无效,第二个有效,然后应用第二个响应- 第一个响应是 NX 域,第二个是截断响应,然后 HAProxy 使用新类型重试查询- 第一个响应是 NX 域,第二个是超时,然后 HAProxy 使用新类型重试查询- 两个名称服务器的查询都超时,然后 HAProxy 使用相同的查询类型重试查询由于 DNS 服务器可能无法在一个 DNS 请求中提供所有 IP 地址,haproxy 会保留之前答案的缓存,在 IP 地址返回后的 <hold obsolete> 秒后,答案将被视为过时。
创建一个新的名为 <resolvers id> 的域名服务器列表。resolvers 部分接受以下参数:
定义 HAProxy 接受的最大负载大小,并通告给此 resolvers 部分中配置的所有名称服务器。<nb> 以字节为单位。如果未设置,HAProxy 会通告 512。 (RFC 6891 定义的最小值) 注意:允许的最大值为 8192。
DNS 服务器描述: <id> :服务器的标签,应唯一 <ip> :服务器的 IP 地址 <port> :DNS 服务实际运行的端口
将 /etc/resolv.conf 中找到的所有域名服务器添加到此 resolvers 域名服务器列表中。顺序如同 /etc/resolv.conf 中的每个域名服务器被单独放置在此指令的位置。
定义最后一个名称解析应保留的 <period>,该保留期基于最后一个解析 <status> <status>:最后一个名称解析状态。可接受的值为“nx”、“other”、“refused”、“timeout”、“valid”、“obsolete”。<period>:当最后一个答案为 <status> 时的两次连续名称解析之间的间隔。它遵循 HAProxy 时间格式。默认情况下,<period> 以毫秒为单位。“valid”为 10 秒,“obsolete”为 0 秒,“other”为 30 秒。定义在放弃之前为解析服务器名称而发送的查询次数 <nb>。默认值:3。当名称服务器超时或完整的 DNS 查询类型故障转移序列结束并且我们需要从默认的 ANY 查询类型重新开始时,会发生重试。
定义与名称解析相关的超时。<event>:<time> 超时周期适用的事件。可用事件有: - resolve:当没有其他时间适用时,触发名称解析的默认时间。默认值:1s - retry:两次 DNS 查询之间的时间,当没有收到有效响应时。默认值:1s <time>:与事件相关的时间。它遵循 HAProxy 时间格式。<time> 以毫秒表示。
resolvers mydns nameserver dns1 10.0.0.1:53 nameserver dns2 10.0.0.2:53 parse-resolv-conf resolve_retries 3 timeout resolve 1s timeout retry 1s hold other 30s hold refused 30s hold nx 30s hold timeout 30s hold valid 10s hold obsolete 30s
在 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 语言一样写入 ASCII 十六进制码 XX<replace> 参数包含用于替换与 regex 匹配的最大文本部分。它可以利用上述特殊字符,并通过写入紧跟在数字 0 到 9 之间的反斜杠 ('\') 来引用 regex 中用括号分隔的子字符串,其中 0 表示整个行。此做法对于“sed”程序的 C 语言用户来说非常普遍。<string> 参数表示将系统性地添加到最后一个头行后的字符串。它也可以使用上述特殊字符序列。
- 这些关键字不总是方便地基于头内容进行允许/拒绝。强烈建议使用 ACL 和“block”关键字,这样可以获得更灵活和易于管理的规则。- 行始终被视为整体。无法仅引用头名称或值。这一点很重要,因为头部的编写方式(尤其是冒号后的空格数)。- 第一行始终被视为一个头,这使得重写或过滤 HTTP 请求 URI 或响应代码成为可能,但反过来又使得区分头部和请求行更加困难。regex 前缀 ^[^\ \t]*[\ \t] 匹配任何 HTTP 方法后跟一个空格,前缀 ^[^ \t:]*: 匹配任何头名称后跟一个冒号。- 出于性能原因,添加到请求或响应的字符数在构建时限制在 1 到 4 kB 之间。这对于大多数用法来说应该绰绰有余。如果在偶尔使用时太短,可以通过删除一些无用的头后再添加新的头来获得一些空间。- 以“reqi”和“rspi”开头的关键字与其不带 'i' 的对应项相同,但它们在匹配模式时会忽略大小写。- 当请求通过前端然后后端时,将评估前端的所有 req* 规则,然后评估后端的所有 req* 规则。响应应用相反的路径。- req* 语句在“block”语句之后应用,因此“block”始终是第一个,但在“use_backend”之前,以便在切换之前进行重写。
HAProxy 能够从请求或响应流、客户端或服务器信息、表、环境信息等中提取数据……提取此类数据的操作称为获取样本。一旦检索到,这些样本可用于各种目的,例如作为粘滞表的键,但最常见的用法是将其与称为模式的预定义常量数据进行匹配。
使用访问控制列表 (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 指向的文件加载为映射文件。-u:强制 ACL 的唯一 ID --:强制标志结束。当字符串看起来像一个标志时很有用。“-f”标志后跟一个文件名,该文件名中的所有行都将作为单独的值读取。如果模式要从多个文件中加载,甚至可以传递多个“-f”参数。空行和以“#”开头的行将被忽略。将删除所有前导空格和制表符。如果绝对有必要插入以“#”开头的有效模式,只需在其前面加上空格,使其不被视为注释。根据数据类型和匹配方法,haproxy 可能会将行加载到二叉树中,从而实现非常快速的查找。IPv4 和精确字符串匹配就是这种情况。在这种情况下,重复项将自动删除。“-M”标志允许 ACL 使用映射文件。如果设置了此标志,则该文件将作为两列文件解析。第一列包含 ACL 使用的模式,第二列包含样本。样本稍后可用于映射。在 ACL 仅用于在应用映射之前检查映射中模式存在性的某些罕见情况下,这可能很有用。“-u”标志强制 ACL 的唯一 ID。此唯一 ID 用于套接字接口以标识 ACL 并动态更改其值。请注意,即使设置了 ID,文件也始终由其名称标识。另外,请注意“-i”标志适用于后续条目,而不是加载自其之前文件的条目。例如:acl valid-ua hdr(user-agent) -f exact-ua.lst -i -f generic-ua.lst test在此示例中,“exact-ua.lst”的每一行都将与请求的“user-agent”头进行精确匹配。然后,“generic-ua”的每一行都将进行不区分大小写的匹配。然后,“test”一词也将被不区分大小写地匹配。“-m”标志用于选择输入样本上的特定模式匹配方法。所有 ACL 特定标准都隐含一个模式匹配方法,通常不需要此标志。但是,此标志对于通用样本提取方法很有用,用于描述它们将如何与模式匹配。对于返回没有明显匹配方法的(例如字符串或二进制)数据类型的样本提取方法,这是必需的。当指定“-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”:regex 匹配:将内容与一系列正则表达式进行匹配。可用于二进制或字符串样本。-“beg”:前缀匹配:检查内容是否以提供的字符串模式开头。可用于二进制或字符串样本。-“end”:后缀匹配:检查内容是否以提供的字符串模式结尾。可用于二进制或字符串样本。-“dir”:子目录匹配:检查斜杠分隔的内容部分是否与提供的字符串模式之一完全匹配。可用于二进制或字符串样本。-“dom”:域名匹配:检查点分隔的内容部分是否与提供的字符串模式之一完全匹配。可用于二进制或字符串样本。例如,要快速检测 HTTP 请求中是否存在 cookie“JSESSIONID”,可以执行:acl jsess_present req.cook(JSESSIONID) -m found为了在缓冲区的前 500 字节数据上应用正则表达式,将使用以下 ACL:acl script_tag req.payload(0,500) -m reg -i <script> 在 regex 库在使用“-i”时速度慢得多的系统上,可以先将样本转换为小写,然后进行匹配,如下所示:acl script_tag req.payload(0,500),lower -m reg <script> 所有 ACL 特定标准都隐含一个默认匹配方法。大多数情况下,这些标准由原始样本提取方法的名称和匹配方法的名称连接而成。例如,“hdr_beg”将“beg”匹配应用于使用“hdr”提取方法检索的样本。此匹配方法仅在使用关键字单独使用时才可用,无需转换器。如果之后应用了任何此类转换器,则 ACL 关键字的默认匹配方法将被忽略,因为起作用的是最后一个转换器的输出类型。由于所有 ACL 特定标准都依赖于样本提取方法,因此始终可以选择使用原始样本提取方法和显式匹配方法“-m”。如果在 ACL 特定标准上使用“-m”指定了备用匹配,则该匹配方法将简单地应用于底层样本提取方法。例如,以下所有 ACL 都等效:acl short_form hdr_beg(host) www. acl alternate1 hdr_beg(host) -m beg www. acl alternate2 hdr_dom(host) -m beg www. acl alternate3 hdr(host) -m beg www.下表总结了样本或转换器类型与要提取的模式类型之间的兼容性矩阵。它为每种兼容组合指示要使用的匹配方法名称,用尖括号“>”和“<”括起来,当方法是默认方法且在没有“-m”的情况下正常工作时。+-------------------------------------------------+ | 输入样本类型 | +----------------------+---------+---------+---------+---------+---------+ | 模式类型 | 布尔值 | 整数 | ip | string | binary | +----------------------+---------+---------+---------+---------+---------+ | 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 | +----------------------+---------+---------+---------+---------+---------+ | regex | 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:如果测试值等于至少一个值,则为 true ge:如果测试值大于或等于至少一个值,则为 true gt:如果测试值大于至少一个值,则为 true le:如果测试值小于或等于至少一个值,则为 true lt:如果测试值小于至少一个值,则为 true 例如,以下 ACL 匹配任何负 Content-Length 头:acl negative-length req.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就会匹配。因此,“/images/png/logo/32x32.png”字符串会匹配“/images”、“/images/png”、“images/png”、“/png/logo”、“logo/32x32.png”或“32x32.png”,但不会匹配“png”或“32x32”。- 域匹配(-m dom):在提取的字符串中的任何位置查找模式,这些模式由点(“.”)、冒号(“:”)、斜杠(“/”)、问号(“?”)、字符串的开头或结尾分隔。此选项用于URL。模式中的前导和尾随分隔符将被忽略。如果找到任何模式,ACL就会匹配。因此,在示例字符串“http://www1.dc-eu.example.com:80/blah”中,“http”、“www1”、“.www1”、“dc-eu”、“example”、“com”、“80”、“dc-eu.example”、“blah”、“:www1:”、“dc-eu.example:80”将匹配,但“eu”或“dc”不会匹配。通常不建议使用此选项来匹配域后缀进行过滤或路由,因为例如通过在另一个域前面添加匹配的前缀,路由很容易被欺骗。字符串匹配适用于按原样传递的字符串,但反斜杠(“\”)除外,它允许转义某些字符,例如空格。如果“-i”标志在第一个字符串之前传递,则将执行匹配,忽略大小写。为了匹配字符串“-i”,可以将其设置为第二个,或者在第一个字符串之前传递“--”标志。匹配字符串“--”也同样适用。请勿将字符串匹配用于可能包含null字节(0x00)的二进制获取,因为比较会在第一个null字节出现时停止。而是先使用十六进制转换器将二进制获取转换为十六进制字符串。
# 如果字符串 <tag> 存在于二进制样本中,则匹配 acl tag_found req.payload(0,0),hex -m sub 3C7461673E
与字符串匹配一样,正则表达式匹配也适用于按字面传递的字符串,但反斜杠("\")除外,它使得可以转义某些字符,如空格。如果在第一个正则表达式之前传递了“-i”标志,则匹配将忽略大小写。为了匹配字符串“-i”,要么将其放在第二个位置,要么在第一个正则表达式之前传递“--”标志。当然,匹配字符串“--”也适用相同的原则。
可以将一些提取的样本与一个可能无法安全地表示为字符串的二进制块进行匹配。为此,当匹配方法设置为二进制时,模式必须以偶数个十六进制数字的形式传递。每两个数字的序列将代表一个字节。十六进制数字可以使用大写或小写。
# 在输入流中匹配 "Hello\n" (\x48 \x65 \x6c \x6c \x6f \x0a) acl hello req.payload(0,6) -m bin 48656c6c6f0a
IPv4地址值可以指定为纯地址或附加了网络掩码,在这种情况下,只要IPv4地址在网络内,它就会匹配。纯地址也可以被可解析的主机名替换,但这种做法通常不被推荐,因为它会使配置更难阅读和调试。如果使用主机名,您至少应该确保它们存在于/etc/hosts中,这样配置就不会依赖于在解析配置时产生的任何随机DNS匹配。IPv4地址的点分表示法支持常规形式和省略所有0八位组的缩写形式:+------------------+------------------+------------------+ | 示例 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地址表示法不同,在该表示法中,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 { 或 [!]acl1 [!]acl2 ... [!]acln } ... 这些条件通常用在“if”或“unless”语句之后,指示何时条件将触发操作。例如,阻止对“*”URL的HTTP请求,方法不是“OPTIONS”,以及没有content-length的POST请求,以及content-length大于0的GET或HEAD请求,最后阻止所有不是GET/HEAD/POST/OPTIONS的请求! acl missing_cl req.hdr_cnt(Content-length) eq 0 http-request deny if HTTP_URL_STAR !METH_OPTIONS || METH_POST missing_cl http-request deny if METH_GET HTTP_CONTENT http-request deny unless METH_GET or METH_POST or METH_OPTIONS 要为“www”站点上的静态内容请求以及“img”、“video”、“download”和“ftp”主机上的所有请求选择不同的后端:acl url_static path_beg /static /images /img /css acl url_static path_end .gif .png .jpg .css .js acl host_www hdr_beg(host) -i www acl host_static hdr_beg(host) -i img. video. download. ftp. # 现在使用后端“static”处理所有纯静态主机,以及主机“www”的静态URL。# 使用后端“www”处理其余部分。use_backend static if host_static or host_www url_static use_backend www if host_www 也可以使用“匿名ACL”形成规则。这些是未命名的ACL表达式,它们是即时构建的,无需声明。它们必须用大括号括起来,大括号之间有一个空格(因为大括号必须被视为独立的单词)。示例:以下规则:acl missing_cl req.hdr_cnt(Content-length) eq 0 http-request deny if METH_POST missing_cl 也可以这样写:http-request deny if METH_POST { req.hdr_cnt(Content-length) eq 0 } 通常不推荐使用此构造,因为它更容易在配置中留下错误。但是,对于仅匹配一个源IP地址的非常简单的规则,使用它们比声明具有随机名称的ACL更有意义。另一个好的用途是:使用命名ACL:acl site_dead nbsrv(dynamic) lt 2 acl site_dead nbsrv(static) lt 2 monitor fail if site_dead 使用匿名ACL:monitor fail if { nbsrv(dynamic) lt 2 } || { nbsrv(static) lt 2 } 有关“http-request deny”和“use_backend”关键字的详细帮助,请参阅第4.2节。
历史上,样本获取方法仅用于检索数据以与ACL进行匹配。随着stick-tables的出现,创建了一类新的样本获取方法,大多数共享与其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”、“.”和“_”。
根据 <bits> 参数,使用 AES128-GCM、AES192-GCM 或 AES256-GCM 算法解密原始字节输入。所有其他参数都需要进行 base64 编码,返回的结果是原始字节格式。如果 <aead_tag> 验证失败,转换器不会返回任何数据。<nonce>、<key> 和 <aead_tag> 可以是字符串或变量。此转换器至少需要 OpenSSL 1.0.1。
http-response set-header X-Decrypted-Text %[var(txn.enc),\ aes_gcm_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]
对 <value> 与输入的有符号整数值执行按位“AND”操作,并将结果作为有符号整数返回。 <value> 可以是数值或变量名。变量名以其作用域的指示开头。允许的作用域有:"proc" : 变量与整个进程共享 "sess" : 变量与整个会话共享 "txn" : 变量与事务(请求和响应)共享 "req" : 变量仅在请求处理期间共享 "res" : 变量仅在响应处理期间共享 此前缀后跟一个名称。分隔符是“.”。名称只能包含字符 'a-z'、'A-Z'、'0-9'、'.' 和 '_'。
将base64编码的输入字符串转换为其二进制表示。它执行base64()的逆操作。
将二进制输入样本转换为base64字符串。它用于以可靠传输的方式(例如,SSL ID可以复制到标头中)记录或传输二进制内容。
如果类型为有符号整数的输入值非空,则返回布尔值 TRUE,否则返回 FALSE。与 and() 结合使用,可用于报告输入值的位测试的真/假(例如,验证标志的存在)。
从输入二进制样本中提取一些字节。结果是一个二进制样本,从原始样本的偏移量(以字节为单位)开始,并可选地在给定长度处截断。
将当前样本之后的最多3个字段连接起来,然后将当前样本转换为字符串。第一个字段<start>是一个常量字符串,它将紧随现有样本之后附加。如果未使用,则可以省略。第二个字段<var>是一个变量名。将查找该变量,将其内容转换为字符串,并将其紧随<first>部分之后附加。如果找不到该变量,则不附加任何内容。它也可以省略。第三个字段<end>是一个常量字符串,它将附加在变量之后。它也可以省略。总之,这些元素允许将变量与分隔符连接到现有的变量集。这可用于构建由其他变量连续组成的变量,例如冒号分隔的值。请注意,由于配置解析器,无法将逗号或右括号用作分隔符。
tcp-request session set-var(sess.src) src tcp-request session set-var(sess.dn) ssl_c_s_dn tcp-request session set-var(txn.sig) str(),concat(<ip=,sess.ip,>),concat(<dn=,sess.dn,>) http-request set-header x-hap-sig %[var(txn.sig)]
获取类型为有符号整数的输入值,应用取反(翻转所有位)并以有符号整数的形式返回结果。
使用 CRC32 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它旨在与其他需要对某些输入键计算 CRC32 的软件兼容,因此它遵循在以太网、Gzip、PNG 等中最常见的实现。它比其他算法慢,但可能提供更好或至少更不可预测的分布。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32c”和“hash-type”指令。
使用 CRC32C 哈希函数将二进制输入样本哈希成一个无符号 32 位量。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用完整的雪崩哈希函数。此转换器使用 RFC4960 附录 B [8] 中描述的相同函数。它旨在与其他需要对某些输入键计算 CRC32C 的软件兼容。它比其他算法慢,并且不得用于安全目的,因为 32 位哈希很容易被破解。另请参见“djb2”、“sdbm”、“wt6”、“crc32”和“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”、“crc32c”和“hash-type”指令。
如果类型为有符号整数的输入值为偶数,则返回布尔值 TRUE,否则返回 FALSE。它在功能上等同于 "not,and(1),bool"。
从输入字符串中,根据给定的分隔符,从开头(正索引)或结尾(负索引)提取给定索引处的子字符串。索引从 1 或 -1 开始,分隔符是格式化为字符串的字符列表。您可以选择指定要提取的字段数量 <count>(默认为 1)。值为 0 表示提取所有剩余字段。
str(f1_f2_f3__f5),field(4,_) # <空> str(f1_f2_f3__f5),field(5,_) # f5 str(f1_f2_f3__f5),field(2,_,0) # f2_f3__f5 str(f1_f2_f3__f5),field(2,_,2) # f2_f3 str(f1_f2_f3__f5),field(-2,_,3) # f2_f3_ str(f1_f2_f3__f5),field(-3,_,0) # f1_f2_f3
将二进制输入样本转换为十六进制字符串,其中每个输入字节对应两个十六进制数字。它用于以可靠的方式记录或传输某些二进制输入数据的十六进制转储(例如,可以将 SSL ID 复制到标头中)。
将每个输入字节包含两个十六进制数字的十六进制字符串转换为整数。如果输入值无法转换,则返回零。
将一个应包含自纪元以来日期的整数转换为表示该日期的字符串,格式适用于 HTTP 标头字段。如果指定了偏移值,则它是在转换操作之前添加到日期的秒数。这在发出 Date 标头字段、响应中的 Expires 值(当与正偏移结合时)或 Last-Modified 值(当偏移为负时)时特别有用。
使用输入样本的字符串表示在指定表中进行查找。如果在表中找不到键,则返回布尔值false。否则返回布尔值true。这可以用于验证表中是否存在某个键,该键跟踪某些元素(例如,是否已看到源IP地址或授权标头)。ipmask(<mask4>[,<mask6>])将掩码应用于IP地址,并将结果用于查找和存储。这可以用于使某个掩码内的所有主机共享相同的表条目,从而使用相同的服务器。mask4可以以点分形式(例如,255.255.255.0)或CIDR形式(例如,24)给出。mask6可以以四分体形式(例如,ffff:ffff::)或CIDR形式(例如,64)给出。如果未给出mask6,IPv6地址将因向后兼容性原因而无法转换。
转义输入字符串并生成一个ASCII输出字符串,该字符串可用于JSON字符串。转换器尝试根据<input-code>参数解码输入字符串。它可以是“ascii”、“utf8”、“utf8s”、“utf8p”或“utf8ps”。“ascii”解码器从不失败。“utf8”解码器检测3种错误:- 错误的UTF-8序列(单独的延续字节、错误的延续字节数,...)- 无效范围(解码值在UTF-8禁止范围内)- 码过长(值编码的字节数超过必要)。UTF-8 JSON编码可能产生“值过长”错误,当UTF-8字符大于0xffff时,因为JSON字符串转义规范仅允许4个十六进制数字用于值编码。UTF-8解码器存在4个变体,由两个后缀字母组合指定:“p”表示“容错”,“s”表示“静默忽略”。解码器的行为是:-“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'、'.' 和 '_'。
接受一个字符串类型的输入值,将其解释为后端名称,并返回该后端中可用服务器的数量。可用于需要从动态名称(如 map 查找的结果)查找后端的地方。
获取类型为有符号整数的输入值,计算其相反值,并以有符号整数的形式返回余数。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'、'.' 和 '_'。
这以原始模式提取输入二进制样本表示的协议缓冲区消息的协议缓冲区消息字段,其中<field_number>是字段号(点分表示法),如果<field_type>不存在,则以字段号表示,或者如果存在该字段,则以整数样本表示(另请参阅下面的“ungrpc”)。授权类型的列表如下:“int32”、“int64”、“uint32”、“uint64”、“sint32”、“sint64”、“bool”、“enum”,用于“varint”线型0“fixed64”、“sfixed64”、“double”,用于64位线型1,“fixed32”、“sfixed32”、“float”,用于线型5。请注意,“string”被视为长度分隔类型,因此不需要任何<field_type>参数即可提取。有关协议缓冲区消息字段类型的更多信息,请访问:https://developers.google.com/protocol-buffers/docs/encoding
对输入字符串应用基于正则表达式的替换。它的操作与著名的“sed”实用程序使用“s/<regex>/<subst>/”的操作相同。默认情况下,它将用替换字符串<subst>替换输入字符串中与正则表达式<regex>匹配的最大部分的第一个出现。可以通过在第三个参数<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来对输出应用完全雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此将提供完全相同的结果。它主要用于调试,但可以用作stick-table条目来收集粗略统计信息。不应将其用于安全目的,因为32位哈希很容易被破解。另请参阅“crc32”、“djb2”、“wt6”、“crc32c”和“hash-type”指令。set-var(<var name>)使用输入内容设置变量,并按原样返回内容。变量保留值和关联的输入类型。变量名以作用域指示开头。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
将二进制输入样本转换为SHA1摘要。结果是长度为20字节的二进制样本。
将<var>的内容与类型为字符串的输入值进行比较。返回与strcmp(3)兼容的有符号整数结果:如果两个字符串相同,则为0。如果左字符串在字典顺序上小于右字符串,或者如果左字符串较短,则小于0。否则大于0(右字符串大于左字符串,或右字符串较短)。
http-request set-var(txn.host) hdr(host) # 检查客户端是否正在尝试域前置(domain fronting)。 acl ssl_sni_http_host_match ssl_fc_sni,strcmp(txn.host) eq 0
从输入的有符号整数值中减去 <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 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的第二个通用目的计数器的当前值。另请参见 sc_get_gpc1 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 gpc1 计数器在表中配置的时间段内增量的频率。另请参见 sc_get_gpc1_rate 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 错误累积数量。另请参见 sc_http_err_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 错误的平均速率,以表中配置的时间段内的错误数量来衡量。另请参阅 sc_http_err_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的 HTTP 请求累积数量。另请参见 sc_http_req_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,返回与指定表中的输入样本关联的 HTTP 请求的平均速率,以表中配置的时间段内的请求数量来衡量。另请参阅 sc_http_req_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的客户端到服务器数据的累积数量,以千字节为单位。当前测试是在 32 位整数上进行的,这会将值限制在 4 TB。另请参见 sc_kbytes_in 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器到客户端数据的累积数量,以千字节为单位。当前测试是在 32 位整数上进行的,这会将值限制在 4 TB。另请参见 sc_kbytes_out 样本获取关键字。
使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的服务器 ID。当连接到服务器成功时,服务器 ID 通过“stick”规则进行关联。服务器 ID 零表示没有与此键关联的服务器。使用输入样本的字符串表示形式在指定表中进行查找。如果在表中找不到键,则返回整数值零。否则,转换器将返回指定表中与输入样本关联的传入会话的累积数量。请注意,此处会话是指由“tcp-request connection”规则集接受的传入连接。另请参见 sc_sess_cnt 样本获取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回与指定表中的输入样本关联的平均传入会话速率。请注意,此处的会话指的是被“tcp-request connection”规则集接受的传入连接。另请参阅 sc_sess_rate 样本提取关键字。
使用输入样本的字符串表示形式在指定表中执行查找。如果在表中找不到键,则返回整数值零。否则,转换器返回在指定表中跟踪与输入样本相同键的当前并发连接数。它与 table_conn_cur 的不同之处在于,它不依赖任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。另请参阅 sc_trackers 样本提取关键字。
将字符串样本转换为大写。这只能放在字符串样本提取函数之后或返回字符串类型的转换关键字之后。结果为字符串类型。
接受一个经过 URL 编码的字符串作为输入,并返回其解码后的版本作为输出。输入和输出的类型都是字符串。如果将 <in_form> 参数设置为非零整数值,则假定输入字符串是表单或查询字符串的一部分,并且“+”字符将被转换为空格(' ')。否则,只有在表示查询字符串的问号(“?”)之后才会发生这种情况。
这以原始模式提取输入二进制样本表示的gRPC消息的协议缓冲区消息字段,其中<field_number>是字段号(点分表示法),如果<field_type>不存在,则以字段号表示,或者如果存在该字段,则以整数样本表示。授权类型的列表如下:“int32”、“int64”、“uint32”、“uint64”、“sint32”、“sint64”、“bool”、“enum”,用于“varint”线型0“fixed64”、“sfixed64”、“double”,用于64位线型1,“fixed32”、“sfixed32”、“float”,用于线型5。请注意,“string”被视为长度分隔类型,因此不需要任何<field_type>参数即可提取。有关协议缓冲区消息字段类型的更多信息,请访问:https://developers.google.com/protocol-buffers/docs/encoding// 带有这样的协议缓冲区 .proto 文件内容,改编自 // https://github.com/grpc/grpc/blob/master/examples/protos/route_guide.proto message Point { int32 latitude = 1; int32 longitude = 2; } message PPoint { Point point = 59; } message Rectangle { // 矩形的一个角。PPoint lo = 48; // 矩形的另一个角。PPoint hi = 49; } 假设请求体由“Rectangle”对象值(两个PPoint协议缓冲区消息)组成,则可以使用以下“ungrpc”指令提取四个协议缓冲区字段:req.body,ungrpc(48.59.1,int32) # 第一个PPoint的“lo”的“latitude” req.body,ungrpc(48.59.2,int32) # 第一个PPoint的“lo”的“longitude” req.body,ungrpc(49.59.1,int32) # 第二个PPoint的“hi”的“latitude” req.body,ungrpc(49.59.2,int32) # 第二个PPoint的“hi”的“longitude” 我们也可以像这样提取中间的48.59字段作为二进制样本:req.body,ungrpc(48.59) 由于gRPC消息始终由gRPC标头后跟协议缓冲区消息组成,因此在前面的示例中,第一个PPoint的“lo”的“latitude”可以通过以下等效指令提取:req.body,ungrpc(48.59),protobuf(1,int32) req.body,ungrpc(48),protobuf(59.1,int32) req.body,ungrpc(48),protobuf(59),protobuf(1,int32) 请注意,第一个转换必须是“ungrpc”,其余的必须是“protobuf”,并且只有最后一个可以有一个或没有第二个参数来解释之前的二进制样本。
unset-var(<var name>) 如果输入内容已定义,则取消设置变量。变量名以作用域指示开头。允许的作用域是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
将一个假定包含自纪元以来日期的整数,使用 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 或 -1 开始,分隔符是格式化为字符串的字符列表。空单词会被跳过。这意味着输入字符串开头或结尾的分隔符会被忽略,输入字符串内的连续分隔符被视为单个分隔符。您可以选择性地指定要提取的单词数 <count>(默认为 1)。值为 0 表示提取所有剩余的单词。
str(f1_f2_f3__f5),word(4,_) # f5 str(f1_f2_f3__f5),word(5,_) # <未找到> str(f1_f2_f3__f5),word(2,_,0) # f2_f3__f5 str(f1_f2_f3__f5),word(3,_,2) # f3__f5 str(f1_f2_f3__f5),word(-2,_,3) # f1_f2_f3 str(f1_f2_f3__f5),word(-3,_,0) # f1_f2 str(/f1/f2/f3/f4),word(1,/) # f1 str(/f1////f2/f3/f4),word(1,/) # f2
使用 WT6 哈希函数将二进制输入样本哈希为一个无符号 32 位整数。可选地,如果可选的 <avalanche> 参数等于 1,则可以对输出应用全雪崩哈希函数。此转换器使用与各种基于哈希的负载均衡算法相同的函数,因此它将提供完全相同的结果。它主要用于调试,但可以用作粘滞表条目以收集粗略的统计数据。它不得用于安全目的,因为 32 位哈希很容易被破解。另请参阅“crc32”、“djb2”、“sdbm”、“crc32c”和“hash-type”指令。
对 <value> 和类型为有符号整数的输入值执行按位“XOR”(异或)操作,并将结果作为有符号整数返回。<value> 可以是数字值或变量名。变量名以指示其范围的指示符开头。允许的作用域是:“proc”:变量与整个进程共享;“sess”:变量与整个会话共享;“txn”:变量与事务(请求和响应)共享;“req”:变量仅在请求处理期间共享;“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
使用 XXHash 哈希函数的 32 位变体将二进制输入样本哈希为一个无符号 32 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
使用 XXHash 哈希函数的 64 位变体将二进制输入样本哈希为一个有符号 64 位整数。此哈希支持一个种子,默认为零,但可以通过 <seed> 参数传递不同的值。此哈希以其优异性能和极快速度而闻名,因此可用于哈希 URL 和/或 URL 参数,作为粘滞表键来收集具有低碰撞率的统计数据,但必须注意,该算法不被认为是密码学安全的。
第一组样本提取方法适用于甚至不涉及任何客户端信息的内部信息。这些方法有时与“monitor-fail”指令一起使用,向外部监视器报告内部状态。本节描述的样本提取方法可在任何地方使用。
始终返回布尔值“false”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
始终返回布尔值“true”。在调整配置时,它可以与 ACL 一起用作另一个 ACL 的临时替代品。
返回指定后端的排队连接总数除以活动服务器的数量。如果未指定后端,则使用当前后端。这与“queue”非常相似,只是考虑了服务器场的大小,以便更准确地衡量新连接可能需要多长时间才能处理。主要用途是与ACL一起向用户返回一个抱歉页面,当确定他们将获得降级服务时,或者将其作为标头传递给后端服务器,以便他们决定在降级模式下工作或禁用某些功能以稍微加快处理速度。请注意,如果没有活动服务器,则将考虑排队连接数的两倍作为测量值。这是一个公平的估计,因为我们预计会很快恢复一台服务器,但我们仍然更倾向于将新流量发送到形状更好的另一个后端。另请参阅“queue”、“be_conn”和“be_sess_rate”样本获取。
适用于后端上当前已建立的连接数,可能包括正在评估的连接。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“fe_conn”、“queue”、“be_conn_free”和“be_sess_rate”标准。
返回一个整数值,对应于后端中可用服务器上的可用连接数。不包括队列槽位。也不包括备份服务器,除非所有其他服务器都已关闭。如果未指定后端名称,则使用当前后端。但也可以检查另一个后端。当标称服务器组已满时,它可用于使用特定的服务器组。另请参见“be_conn”、“connslots”和“srv_conn_free”标准。其他注意事项和说明:如果任何服务器的 maxconn 或 maxqueue 为 0(表示无限制),则此提取显然没有意义,在这种情况下返回的值将为 -1。
返回一个整数值,对应于后端上的会话创建速率,以每秒新会话数表示。这与 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。
返回自处理流或当前请求的任务分配以来对其的调用次数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值通常应较低且稳定(对于典型的简单请求约为 2 次调用),但如果执行了某些处理(压缩、缓存或分析),则可能会变高。这纯粹是为了性能监控。
返回处理流或当前请求的每个任务调用的平均纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。注意:此值正好是 cpu_ns_tot 除以 cpu_calls。
返回处理流或当前请求的每个任务调用的总纳秒数。在 HTTP keep-alive 的情况下,每次新请求都会在同一连接上重置此数字。此值表示每次调用处理请求或连接的总体成本。没有好坏之分,但调用中花费的时间会自动导致其他处理的延迟(参见下面的 lat_ns_avg),导致机器上的 CPU 成本,并可能影响其他连接的表观响应时间。某些操作(如压缩、复杂正则表达式匹配或繁重的 Lua 操作)可能会直接影响此值,将其记录在日志中将更容易发现需要修复以恢复良好性能的错误处理。由于 cpu_calls 计数较高(例如,在处理许多 HTTP 块时),该值可能会人为地偏高,因此通常首选记录 cpu_ns_avg。
以纪元(自 1970 年 1 月 1 日以来的秒数)形式返回当前日期。如果指定了偏移值,则它是在返回值之前添加到当前日期的秒数。这对于计算相对日期特别有用,因为允许正负偏移。与 http_date 转换器结合使用很有用。
# 在每个响应中设置一个过期头为现在+1小时 http-response set-header Expires %[date(3600),http_date]
返回日期的微秒部分(“秒”部分由 date 样本返回)。此样本与 date 样本一致,因为它来自相同的 timeval 结构。
解析distcc消息并返回与标记<token>的出现次数#<occ>关联的正文。出现次数从1开始,如果未指定,则任何出现次数都可能匹配,尽管实际上目前只检查第一个。这可用于提取通过haproxy构建的文件中的文件名或参数。有关支持的令牌的完整列表,请参阅distcc的协议文档。
解析distcc消息并返回与标记<token>的出现次数#<occ>关联的参数。出现次数从1开始,如果未指定,则任何出现次数都可能匹配,尽管实际上目前只检查第一个。这可用于提取某些信息,例如协议版本、文件大小或通过haproxy构建的文件中的参数。另一个用例是等待预处理文件内容开始,然后再连接到服务器,以避免保持空闲连接。有关支持的令牌的完整列表,请参阅distcc的协议文档。
# 等待预处理文件上传最多 20 秒 tcp-request inspect-delay 20s tcp-request content accept if { distcc_param(DOTI) -m found } # 将大文件发送到大型服务器场 use_backend big_farm if { distcc_param(DOTI) gt 1000000 }
返回一个包含环境变量 <name> 值的字符串。提醒一下,环境变量是每个进程的,并在进程启动时采样。这对于将一些信息传递给下一跳服务器,或者与 ACL 结合使用以在进程以特定方式启动时采取特定操作很有用。
# 将 Via 头传递给下一跳,其中包含本地主机名 http-request add-header Via 1.1\ %[env(HOSTNAME)] # 当设置了 STOP 环境变量时,拒绝无 cookie 的请求 http-request deny if !{ req.cook(SESSIONID) -m found } { env(STOP) -m found }
返回前端上当前已建立的连接数,可能包括正在评估的连接。如果未指定前端名称,则使用当前前端。但也可以检查另一个前端。它可用于在硬阻塞之前返回一个“抱歉”页面,或者在服务器场被认为已满时使用特定的后端来处理新请求。这主要与 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 地址。
返回处理流的任务被唤醒和实际调用之间花费的纳秒数的平均值。在HTTP保持活动的情况下,此数字会在同一连接上的每个新请求重置。此值指示所有其他并行处理的请求对当前请求造成的总体延迟,并且是由于嘈杂邻居造成的感知性能的直接指标。为了保持该值较低,可以通过“tune.runqueue-depth”减小调度程序的运行队列深度,通过“tune.maxpollevents”减小一次处理的并发事件数,通过“bind”行或前端上的“nice”选项来降低流的nice值,或在日志中查找其他重度请求(那些显示“cpu_ns_avg”值的请求),这些请求的处理需要进行调整或修复。大缓冲区的压缩可能是一个原因,例如重度正则表达式或长正则表达式列表。注意:此值精确等于lat_ns_tot除以cpu_calls。
返回处理流的任务被唤醒和实际调用之间花费的总纳秒数。在HTTP保持活动的情况下,此数字会在同一连接上的每个新请求重置。此值指示所有其他并行处理的请求对当前请求造成的总体延迟,并且是由于嘈杂邻居造成的感知性能的直接指标。为了保持该值较低,可以通过“tune.runqueue-depth”减小调度程序的运行队列深度,通过“tune.maxpollevents”减小一次处理的并发事件数,通过“bind”行或前端上的“nice”选项来降低流的nice值,或在日志中查找其他重度请求(那些显示“cpu_ns_avg”值的请求),这些请求的处理需要进行调整或修复。大缓冲区的压缩可能是一个原因,例如重度正则表达式或长正则表达式列表。注意:虽然直观上可能认为总延迟会加到传输时间上,但这几乎从未发生,因为当任务等待CPU时,网络缓冲区会继续填充,下一次调用将一次处理更多内容。由于高cpu_calls计数,该值可能会人为地偏高,例如在处理多个HTTP块时,因此通常最好记录lat_ns_avg,这是一个更相关的性能指标。
返回一个方法。
返回一个整数值,对应于已启动的进程数(它等于全局“nbproc”设置)。这对于日志记录和调试目的很有用。返回一个整数值,对应于当前后端或指定后端的可用服务器数量。这主要与 ACL 一起使用,但在添加到日志中时也很有用。这通常用于在服务器数量过低而无法处理某些负载时切换到备用后端。当与“monitor fail”结合使用时,报告故障很有用。
返回http模式下当前会话或tcp模式下连接的优先级类别。该值将是最后一次调用“http-request set-priority-class”或“tcp-request content set-priority-class”时设置的值。
返回http模式下当前会话或tcp模式下连接的优先级偏移量。该值将是最后一次调用“http-request set-priority-offset”或“tcp-request content set-priority-offset”时设置的值。
返回一个整数值,对应于调用该函数的进程的位置,介于 1 和 global.nbproc 之间。这对于日志记录和调试目的很有用。
返回指定后端的排队连接总数,包括服务器队列中的所有连接。如果未指定后端名称,则使用当前后端,但也可以检查另一个后端。这对于 ACL 或将统计信息传递给后端服务器很有用。这可用于在排队超过已知水平时采取行动,这通常表示流量激增或服务器大规模减速。一个可能的操作是拒绝新用户但仍然接受老用户。另请参阅“avg_queue”、“be_conn”和“be_sess_rate”提取。
返回一个在 <range> 个可能值范围内的随机整数值,从零开始。如果未指定范围,则默认为 2^32,即数字介于 0 和 4294967295 之间。例如,传递一些需要用于做出某些路由决策的值可能很有用,或者仅仅用于调试目的。此随机数不得用于安全目的。
返回遵循RFC4122标准的UUID。如果未指定版本,则返回UUID版本4(完全随机)。目前,仅支持版本4。
返回一个整数值,对应于指定服务器上当前已建立的连接数,可能包括正在评估的连接。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“fe_conn”、“be_conn”、“queue”和“srv_conn_free”提取方法。
返回一个整数值,对应于指定服务器上的可用连接数,可能包括正在评估的连接。该值不包括队列槽位。如果省略 <backend>,则在当前后端中查找服务器。当一台服务器已满时,它可用于使用特定的服务器组,或告知服务器我们对其活动连接数的看法。另请参见“be_conn_free”和“srv_conn”提取方法。其他注意事项和说明:如果服务器的 maxconn 为 0,则此提取显然没有意义,在这种情况下返回的值将为 -1。
当指定服务器处于 UP 状态时返回 true,当其处于 DOWN 或维护模式时返回 false。如果省略 <backend>,则在当前后端中查找服务器。它主要用于根据通过健康检查报告的外部状态采取行动(例如,地理站点的可用性)。另一种可能的用途,更像是一种技巧,是使用虚拟服务器作为布尔变量,可以从 CLI 启用或禁用,以便可以实时调整依赖于这些 ACL 的规则。
返回一个整数值,对应于当前在指定服务器队列中等待的连接数。如果省略 <backend>,则在当前后端中查找服务器。有时可以与“use-server”指令一起使用,以在已知更快的服务器负载不大时强制使用它。另请参见“srv_conn”、“avg_queue”和“queue”样本提取方法。
返回一个对应于指定服务器上的会话创建速率的整数,以每秒新会话数表示。如果省略 <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。
返回一个整数值,对应于调用该函数的线程的位置,介于 0 和 (global.nbthread-1) 之间。这对于日志记录和调试目的很有用。
返回带有存储类型变量。如果变量未设置,则采样获取失败。变量名以其范围的指示开始。允许的范围是:“proc”:变量与整个进程共享“sess”:变量与整个会话共享“txn”:变量与事务(请求和响应)共享,“req”:变量仅在请求处理期间共享,“res”:变量仅在响应处理期间共享。此前缀后跟一个名称。分隔符是“.”。名称只能包含字符“a-z”、“A-Z”、“0-9”、“.”和“_”。
第 4 层通常只描述传输层,在 haproxy 中,传输层最接近连接,此时还没有内容可用。此处描述的获取方法可以在“tcp-request connection”规则集(除非需要未来信息)的低层使用。这些通常包括 TCP/IP 地址和端口,以及与传入连接相关的 stick-table 中的元素。要从粘性计数器中检索值,可以使用预定义的“sc0_”、“sc1_”或“sc2_”前缀显式设置计数器号 0、1 或 2。这三个预定义前缀仅在 MAX_SESS_STKCTR 值不超过 3 时才可使用,否则在使用“sc_”前缀时,计数器号可以作为第一个整数参数指定。从“sc_0”到“sc_N”,其中 N 是 (MAX_SESS_STKCTR-1)。可以使用“sc*”形式指定一个可选表,在这种情况下,将查找当前跟踪的键,而不是在当前跟踪的表中,而是在此备用表中查找。
返回后端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
返回一个包含当前后端 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 头将目标端口信息传递给服务器时使用。
返回内核为客户端连接测量的 fack 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
报告前端连接的 HTTP 主版本编码,可以是 1(用于 HTTP/0.9 到 HTTP/1.1)或 2(用于 HTTP/2)。请注意,这基于线上传输的编码,而不是请求标头中存在的版本。
返回内核为客户端连接测量的丢失计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
如果客户端使用 PROXY 协议头启动连接,则返回 true。
返回内核为客户端连接测量的重排序计数器。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的重传计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的往返时间(RTT)。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的往返时间(RTT)方差。<unit> 是可选的,默认单位是毫秒。<unit> 可以设置为“ms”表示毫秒,或“us”表示微秒。如果服务器连接未建立,连接不是 TCP,或者操作系统不支持 TCP_INFO(例如 Linux 内核 2.4 之前的版本),则样本获取失败。
返回内核为客户端连接测量的 sacked 计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回内核为客户端连接测量的未确认计数器。如果服务器连接未建立,如果连接不是 TCP,或者如果操作系统不支持 TCP_INFO(例如,2.4 版本之前的 Linux 内核),则样本提取失败。
返回前端的默认后端名称的字符串。它可以在前端用于检查哪个后端将默认处理请求。
返回一个包含当前前端 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
清除与当前跟踪计数器关联的第二个通用计数器,并返回其先前的值。在第一次调用之前,存储的值为零,因此第一次调用将始终返回零。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
返回当前跟踪的计数器所统计的传入连接的总数。另请参阅 src_conn_cnt。
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。另请参阅 src_conn_cur。
返回当前跟踪的计数器中的平均连接速率,以表中配置的时间段内的连接数量来衡量。另请参阅 src_conn_rate。
返回与当前跟踪的计数器关联的第一个通用计数器的值。另请参阅 src_get_gpc0 和 sc/sc0/sc1/sc2_inc_gpc0。
返回与当前跟踪的计数器关联的第二个通用目的计数器的值。另请参阅 src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。
返回与当前跟踪的计数器关联的第一个通用标签(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”仅保存事件计数。
返回与当前跟踪计数器关联的第二个通用计数器的平均增量速率。它报告了在配置的时间段内 gpc1 计数器被增量的频率。另请参阅 src_gpcA_rate、sc/sc0/sc1/sc2_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。请注意,“gpc1_rate”计数器必须存储在粘滞表中才能返回一个值,因为“gpc1”只保存事件计数。
返回当前跟踪计数器中的 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
递增与当前跟踪计数器关联的第二个通用计数器,并返回其新值。在第一次调用之前,存储的值为零,因此第一次调用会将其增加到 1 并返回 1。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 被验证后标记连接。
返回当前跟踪的计数器中客户端到服务器的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_in。
返回当前跟踪的计数器中服务器到客户端的总数据量,以千字节为单位。该测试目前在 32 位整数上执行,这将值限制为 4 TB。另请参阅 src_kbytes_out。
返回从当前跟踪计数器中转换为会话的传入连接总数,这意味着它们被“tcp-request connection”规则接受。后端可能会计算比连接更多的会话,因为每个连接都可能导致许多后端会话,如果通过与客户端的连接执行了某些 HTTP keep-alive。另请参阅 src_sess_cnt。
返回当前跟踪的计数器中的平均会话速率,以表中配置的时间段内的会话数量来衡量。会话是通过早期“tcp-request connection”规则的连接。一个后端可能会计算比连接更多的会话,因为如果通过与客户端的连接执行了 HTTP 保持连接(keep-alive),每个连接可能会导致多个后端会话。另请参阅 src_sess_rate。
如果指定的会话计数器当前正被当前会话跟踪,则返回 true。这在决定是否要在传递给服务器的头中设置某些值时很有用。
返回跟踪相同跟踪计数器的当前并发连接数。此数字在跟踪开始时自动递增,在跟踪停止时自动递减。它与 sc0_conn_cur 的不同之处在于,它不依赖于任何存储的信息,而是依赖于表的引用计数(即在 CLI 上通过“show table”返回的“use”值)。这有时可能更适合于第 7 层跟踪。例如,它可以用来告诉服务器来自给定地址的并发连接数。
返回一个包含当前监听套接字 ID 的整数。在涉及多个“bind”行但需要在前端中使用的监听套接字 ID 非常有用,或者将通过同一套接字传入的所有用户绑定到同一服务器。返回一个包含当前监听套接字名称的字符串,该名称在“bind”行中通过 name 定义。它的用途与 so_id 相同,但使用字符串而不是整数。这是会话客户端的源 IPv4 地址。它属于 IP 类型,并且适用于 IPv4 和 IPv6 表。在 IPv6 表中,IPv4 地址根据 RFC 4291 映射到其 IPv6 等效地址。请注意,使用的是 TCP 级别的源地址,而不是代理后面的客户端地址。但是,如果使用了“accept-proxy”或“accept-netscaler-cip”bind 指令,那么对于除了“tcp-request connection”(它会看到真实地址)之外的所有规则集,它可以是另一个 PROXY-protocol 兼容组件后面的客户端地址。当传入连接经过地址转换或涉及连接跟踪的重定向时,将报告重定向之前的原始目标地址。在 Linux 系统上,如果设置了 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。
清除当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第一个通用计数器,并返回其先前的值。如果未找到该地址,则会创建一个条目并返回 0。这通常用作表达式中的第二个 ACL,以便在第一个 ACL 得到验证时标记一个连接。
# 如果连续 5 个请求的速率持续高于每秒 10 个会话,则阻止, # 并在流量减慢时立即重置计数器。 acl abuse src_http_req_rate gt 10 acl kill src_inc_gpc0 gt 5 acl save src_clr_gpc0 ge 0 tcp-request connection accept if !abuse save tcp-request connection reject if abuse kill
清除当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器,并返回其先前的值。如果未找到该地址,则会创建一个条目并返回 0。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的已建立连接的总数。如果未找到该地址,则返回零。另请参阅 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。
返回当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器的值。如果未找到该地址,则返回零。另请参阅 sc/sc0/sc1/sc2_get_gpc1 和 src_inc_gpc1。
返回与当前代理的粘性表或指定粘性表中传入连接的源地址关联的第一个通用标签的值。如果找不到地址,则返回零。另请参阅 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 中与传入连接的源地址关联的第二个通用计数器的平均增量率。它报告 gpc1 计数器在配置周期内的增量频率。另请参阅 sc/sc0/sc1/sc2_gpc1_rate、src_get_gpc1 和 sc/sc0/sc1/sc2_inc_gpc1。请注意,“gpc1_rate”计数器必须存储在 stick-table 中才能返回值,因为“gpc1”只包含事件计数。
返回当前代理的 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
递增当前代理的 stick-table 或指定 stick-table 中与传入连接的源地址关联的第二个通用计数器,并返回其新值。如果未找到该地址,则会创建一个条目并返回 1。另请参阅 sc0/sc2/sc2_inc_gpc1。这通常用作表达式中的第二个 ACL,以便在验证第一个 ACL 时标记连接。
如果入站连接的源地址是本地的,则返回 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 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
这会从通过 TLS 传输层建立的传出连接中提取应用程序层协议协商字段。结果是包含与服务器协商的协议名称的字符串。SSL 库必须已构建为支持 TLS 扩展(请参阅 haproxy -vv)。请注意,除非“alpn”关键字在“server”行上指定了协议列表。此外,没有什么会强迫服务器从该列表中选择一个协议,它可能会请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅“ssl_bc_npn”。
当传出连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
当传入连接是通过 SSL/TLS 传输层建立时,返回后端连接的客户端随机数。这对于解密使用临时密码发送的流量很有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当后端连接是通过 SSL/TLS 传输层建立,并且新创建的 SSL 会话是通过缓存会话或 TLS 票据恢复的时,返回 true。
这会从通过 TLS 传输层建立的传出连接中提取下一协议协商字段。结果是包含与服务器协商的协议名称的字符串。SSL 库必须已构建为支持 TLS 扩展(请参阅 haproxy -vv)。请注意,除非“npn”关键字在“server”行上指定了协议列表。此外,没有什么会强迫服务器从该列表中选择一个协议,它可能会使用任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。
当传出连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当传出连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。该唯一 ID 可以使用转换器 "ssl_bc_unique_id,base64" 编码为 base64。
当传入连接是通过 SSL/TLS 传输层建立时,返回后端连接的服务器随机数。这对于解密使用临时密码发送的流量很有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传出连接通过 SSL/TLS 传输层建立时,返回后端连接的 SSL ID。如果我们想知道会话是否被重用,记录此信息会很有用。
当传出连接是通过 SSL/TLS 传输层建立时,返回后端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量很有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传出连接通过 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。这意味着它匹配了一个使用“bind”行声明的套接字,该套接字具有“ssl”选项。
# 当客户端通过 SSL 连接时,向服务器传递 "X-Proto: https" listen http-https bind :80 bind :443 ssl crt /etc/haproxy.pem http-request add-header X-Proto https if { ssl_fc }
当传入连接通过 SSL/TLS 传输层建立时,返回支持的对称加密密钥大小(以位为单位)。
这会从通过 TLS 传输层建立的传入连接中提取应用程序层协议协商字段,该连接由 haproxy 本地解密。结果是包含客户端通告的协议名称的字符串。SSL 库必须已构建为支持 TLS 扩展(请参阅 haproxy -vv)。请注意,除非“alpn”关键字在“bind”行上指定了协议列表。此外,没有什么会强迫客户端从该列表中选择一个协议,它可能会请求任何其他协议。TLS ALPN 扩展旨在取代 TLS NPN 扩展。另请参阅“ssl_fc_npn”。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的加密套件的名称。
返回客户端 hello 密码列表的二进制形式。返回值的最大长度与“tune.ssl.capture-cipherlist-size”的值一致。
返回编码为十六进制的客户端 hello 密码列表的二进制形式。返回值的最大长度与“tune.ssl.capture-cipherlist-size”的值一致。
返回已解码的客户端 hello 密码列表的文本形式。返回的密码最大数量与“tune.ssl.capture-cipherlist-size”的值一致。请注意,此采样获取仅在 OpenSSL >= 1.0.2 时可用。如果未启用该函数,则此采样获取将返回类似“ssl_fc_cipherlist_xxh”的哈希值。
返回密码列表的 xxh64 哈希值。只有当“tune.ssl.capture-cipherlist-size”的值设置为大于 0 时才能返回此哈希值,但是哈希值会考虑密码列表的所有数据。
当入站连接通过 SSL/TLS 传输层建立时,返回前端连接的客户端随机数(client random)。它对于解密使用临时密码(ephemeral ciphers)发送的流量很有用。这需要 OpenSSL >= 1.1.0,或 BoringSSL。
如果传入的 SSL/TLS 传输层连接中存在客户端证书,则返回 true。在 'verify' 语句设置为 'optional' 时很有用。注意:在使用会话 ID 或 TLS 票据进行 SSL 会话恢复时,当前连接中不存在客户端证书,但可以从缓存或票据中检索。因此,如果您想检查当前 SSL 会话是否使用了客户端证书,请优先使用 "ssl_c_used"。
如果发送了早期数据,并且握手尚未发生,则返回 true。由于它具有安全隐患,因此能够拒绝这些数据或等到握手发生后再处理它们非常有用。
这会检查入站连接是否通过 SSL/TLS 传输层建立,以及是否包含服务器名称指示(Server Name Indication, SNI)TLS 扩展。当入站连接提供 TLS SNI 字段时,返回 true。这需要 SSL 库已构建为支持 TLS 扩展(请检查 haproxy -vv)。
如果通过 SSL/TLS 传输层传入的连接上,SSL/TLS 会话已通过使用 SSL 会话缓存或 TLS 票据得到恢复,则返回 true。
这会从通过 TLS 传输层建立的传入连接中提取下一协议协商字段,该连接由 haproxy 本地解密。结果是包含客户端通告的协议名称的字符串。SSL 库必须已构建为支持 TLS 扩展(请参阅 haproxy -vv)。请注意,除非“npn”关键字在“bind”行上指定了协议列表。此外,没有什么会强迫客户端从该列表中选择一个协议,它可能会请求任何其他协议。请注意,TLS NPN 扩展已被 ALPN 取代。
当传入连接通过 SSL/TLS 传输层建立时,返回所使用的协议的名称。
当连接通过 SSL/TLS 传输层建立时,返回 RFC5929 第 3 节中定义的 TLS 唯一 ID。可以使用转换器 "ssl_fc_unique_id,base64" 将唯一 ID 编码为 base64。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的服务器随机数。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
当传入连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL ID。这对于将给定客户端粘滞到某个服务器很有用。需要注意的是,某些浏览器每隔几分钟就会刷新其会话 ID。
在连接通过 SSL/TLS 传输层建立时,返回前端连接的 SSL 会话主密钥。这对于解密使用临时密码发送的流量非常有用。这需要 OpenSSL >= 1.1.0 或 BoringSSL。
这会从通过 SSL/TLS 传输层建立的传入连接中提取服务器名称指示 TLS 扩展 (SNI) 字段,该连接由 haproxy 本地解密。结果(如果存在)通常是与 HTTPS 主机名匹配的字符串(最多 253 个字符)。SSL 库必须已构建为支持 TLS 扩展(请参阅 haproxy -vv)。此获取与上面的“req.ssl_sni”不同,因为它应用于 haproxy 正在解密的连接,而不是盲目转发的 SSL 内容。另请参阅下面的“ssl_fc_sni_end”和“ssl_fc_sni_reg”。这要求 SSL 库已构建为支持 TLS 扩展(请参阅 haproxy -vv)。注意!除非在非常特定的条件下,否则通常不应将此字段用作 HTTP“Host”标头字段的替代。例如,当将 HTTPS 连接转发到服务器时,SNI 字段必须使用“req.hdr(host)”从 HTTP Host 标头字段设置,而不是从前端 SNI 值设置。原因是 SNI 仅用于选择服务器端将呈现的证书,并且客户端随后可以发送具有不同 Host 值的请求,只要它们与证书中的名称匹配即可。因此,除非后端在 TCP 模式下运行,否则通常不应将“ssl_fc_sni”用作“sni”服务器关键字的参数。ACL 派生:ssl_fc_sni_end:后缀匹配 ssl_fc_sni_reg:正则表达式匹配
当传入连接通过 SSL/TLS 传输层建立时,返回实际使用的对称加密密钥大小(以位为单位)。
从缓冲区内容获取样本与上述的样本获取方法有些不同,因为采样的数据是短暂的。这些数据只有在可用时才能使用,并且在转发后会丢失。因此,例如,在请求期间从缓冲区内容获取的样本不能在响应中使用。即使在获取数据时,它们也可能发生变化。有时需要设置一些延迟或组合多种样本获取方法,以确保预期的数据是完整和可用的,例如通过 TCP 请求内容检查。有关该主题的更多详细信息,请参阅 "tcp-request content" 关键字。
这是 "req.payload" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload" 的别名。
这是 "req.payload_lv" 在请求上下文(例如,“stick on”、“stick match”)中的别名,在响应上下文(例如“stick store response”)中是 "res.payload_lv" 的别名。
返回一个整数值,对应于请求缓冲区中存在的字节数。这主要用于 ACL。重要的是要理解,只要缓冲区在变化,此测试就不会返回 false。这意味着在会话开始时,等于零的检查几乎总是会立即匹配,而检查更多数据的测试将等待数据进入,并且仅当 haproxy 确定不会有更多数据进入时才会返回 false。此测试旨在与 TCP 请求内容检查一起使用。
这会从请求缓冲区中提取 <length> 字节的二进制块,从字节 <offset> 开始。作为特殊情况,如果 <length> 参数为零,则提取从 <offset> 到末尾的整个缓冲区。这可以与 ACL 一起使用,以检查缓冲区中任何位置是否存在某些内容。ACL 派生:req.payload(<offset>,<length>):十六进制二进制匹配
这会提取一个二进制块,其大小由 <offset1> 指定 <length> 字节,如果指定了 <offset2>,则从该位置开始,否则紧跟在请求缓冲区中的长度之后。<offset2> 参数如果以 '+' 或 '-' 符号开头,也支持相对偏移。ACL 派生:req.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 协议时,提取 RDP cookie <name>,或者在未指定时提取任何 cookie。解析器仅检查第一个 cookie,如 RDP 协议规范所示。cookie 名称不区分大小写。通常使用 "MSTS" cookie 名称,因为它可能包含连接到服务器的客户端用户名(如果客户端配置正确)。"MSTSHASH" cookie 也经常用于会话粘性到服务器。这与 "balance rdp-cookie" 不同,因为可以使用任何平衡算法,因此客户端到后端服务器的分布与 RDP cookie 的哈希值无关。设想使用 "balance roundrobin" 或 "balance leastconn" 等平衡算法将导致客户端到后端服务器的分布比 "balance rdp-cookie" 的哈希值更均匀。ACL 派生:req.rdp_cookie([<name>]):精确字符串匹配
listen tse-farm bind 0.0.0.0:3389 # 在请求中等待 RDP cookie 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if RDP_COOKIE # 应用 RDP cookie 持久性 persist rdp-cookie # 基于 mstshash cookie 进行持久化 # 仅在不使用 balance rdp-cookie 时 # 才有意义 stick-table type string size 204800 stick on req.rdp_cookie(mstshash) server srv1 1.1.1.1:3389 server srv1 1.1.1.2:3389
尝试将请求缓冲区解析为 RDP 协议,然后返回一个整数,表示找到的 RDP cookie 的数量。如果提供了可选的 cookie 名称,则只考虑匹配该名称的 cookie。这主要用于 ACL。ACL 派生:req.rdp_cookie_cnt([<name>]):整数匹配
返回一个字符串,其中包含客户端在 SSL ClientHello 消息中发送的应用程序层协议协商 (ALPN) TLS 扩展 (RFC7301) 的值。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此对于具有“bind”选项的“ssl”行无效。这在 ACL 中非常有用,可以根据 TLS 客户端的 ALPN 偏好做出路由决策,如下面的示例所示。另请参阅“ssl_fc_alpn”。
# 等待客户端 hello 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } use_backend bk_acme if { req.ssl_alpn acme-tls/1 } default_backend bk_default
返回一个布尔值,指示客户端是否在 SSL ClientHello 消息中发送了 RFC4492 第 5.1 节定义的受支持椭圆曲线扩展。这可用于向 ECC 兼容客户端呈现 EC 证书,并为所有其他客户端使用 RSA,而在同一 IP 地址上。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此对于具有“bind”选项的“ssl”行无效。
如果缓冲区包含可解析为完整 SSL(v3 或更高版本)客户端 hello 消息的数据,则返回请求缓冲区中 SSL hello 消息类型的整数值。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此对于具有“bind”选项的“ssl”行无效。这主要用于 ACL 中,以检测 SSL hello 消息的存在,该消息应该包含可用于粘性的 SSL 会话 ID。
如果缓冲区包含可解析为完整 SSL(v3 或更高版本)客户端 hello 消息的数据,则返回客户端在 TLS 流的请求缓冲区中发送的服务器名称 TLS 扩展的值的字符串。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此对于具有“bind”选项的“ssl”行无效。这仅适用于实际的隐式 TLS 协议(如 HTTPS (443)、IMAPS (993)、SMTPS (465)),但对于显式 TLS 协议(如 SMTP (25/587) 或 IMAP (143))则无效。SNI 通常包含客户端尝试连接的主机名(对于较新的浏览器)。SNI 可用于允许或拒绝访问某些主机(当客户端使用 SSL/TLS 时)。此测试旨在与 TCP 请求内容检查一起使用。如果需要内容切换,建议首先等待完整的客户端 hello(类型 1),如下面的示例所示。另请参阅“ssl_fc_sni”。ACL 派生:req.ssl_sni:精确字符串匹配
# 等待客户端 hello 最多 5 秒 tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } use_backend bk_allow if { req.ssl_sni -f allowed_sites } default_backend bk_sorry_page
如果客户端未发送会话票证 TLS 扩展 (RFC5077),则返回 0。如果客户端发送了会话票证 TLS 扩展,则返回 1。如果客户端还发送了非零长度的 TLS 会话票证,则返回 2。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此对于具有“bind”选项的“ssl”行无效。这可以用于例如检测客户端是否发送了会话票证,并相应地粘住它,如果没有会话票证,则粘住会话 ID 或不粘住,因为当使用会话票证时没有服务器端状态。
返回一个整数值,其中包含请求缓冲区中存在的流的 SSL/TLS 协议版本。SSLv2 hello 消息和 SSLv3 消息都支持。TLSv1 被宣布为 SSL 版本 3.1。该值由主版本乘以 65536,加上次版本组成。请注意,这仅适用于请求缓冲区中的原始内容,而不适用于通过 SSL 数据层解密的内容,因此对于具有“bind”选项的“ssl”行无效。ACL 版本测试匹配十进制表示法 MAJOR.MINOR(例如 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 数据层解密的内容,因此对于具有“server”选项的“ssl”行无效。这主要用于 ACL 中,以检测 SSL hello 消息的存在,该消息应该包含可用于粘性的 SSL 会话 ID。
此获取在检查周期结束时返回 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”头行中提取Cookie名称<name>的最后一个出现项,并将其值作为字符串返回。如果未指定名称,则返回第一个cookie值。当与ACL一起使用时,会评估所有匹配的cookie。根据Cookie头规范(RFC6265)的要求,忽略名称和值周围的空格。Cookie名称区分大小写。空Cookie是有效的,因此如果存在,空Cookie可能会返回空值。使用“found”匹配来检测存在。使用res.cook()变体来处理服务器发送的响应Cookie。ACL派生:req.cook([<name>]):精确字符串匹配req.cook_beg([<name>]):前缀匹配req.cook_dir([<name>]):子目录匹配req.cook_dom([<name>]):域匹配req.cook_end([<name>]):后缀匹配req.cook_len([<name>]):长度匹配req.cook_reg([<name>]):正则表达式匹配req.cook_sub([<name>]):子字符串匹配
返回一个整数值,表示名为 <name> 的 cookie 在请求中出现的次数;如果未指定 <name>,则表示所有 cookie 的数量。
此函数从请求的 "Cookie" 头部行中提取名为 <name> 的 cookie 的最后一次出现,并将其值转换为整数返回。如果未指定名称,则返回第一个 cookie 的值。在 ACL 中使用时,将遍历所有匹配的名称,直到找到一个匹配的值。
从请求的“Cookie”标头行中提取 cookie 名称 <name> 的最后一次出现,或从响应的“Set-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 请求中标题的最后一次出现。当从 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 头部一起使用。
以字符串形式返回当前请求标头,包括分隔标头和请求正文的最后空行。最后空行可用于检测截断的标头块。此样本获取对于某些 SPOE 标头分析器和高级日志记录非常有用。
以预解析的二进制形式返回当前请求标头。这对于使用 SPOE 进行部分处理非常有用。每个字符串由长度后面跟着长度指示的字节数描述。长度使用 SPOE 文档中详细的可变整数编码表示。列表的末尾由一对空标头名称和值(长度均为 0)标记。*(<str:header-name><str:header-value>)<empty string><empty string> int:参考 SPOE 文档的编码 str:<int:length><bytes>
返回一个布尔值,指示从客户端收到的身份验证数据是否与指定用户列表中存储的用户名和密码匹配。此获取函数在 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”获取方法。请注意,URI 中的任何片段引用(路径后的 '#')都严格违反 HTTP 标准,并将被拒绝。但是,如果接收请求的前端具有“option accept-invalid-http-request”,则将接受此片段部分,并且它也会出现在路径中。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 名称的最后一次出现,并将其值作为字符串返回。如果未指定名称,则返回第一个 cookie 值。ACL 派生:res.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 响应中标题的最后一次出现,或者如果未指定 ,则提取最后一个标题。还可以选择指定一个特定的出现作为位置号。正值表示从第一次出现开始的位置,1 是第一次出现。负值表示相对于最后一次出现的位置,-1 是最后一次出现。这对于将某些数据学习到 stick-table 中可能很有用。该函数将任何逗号视为分隔符,以区分不同的值。如果不需要这样做,则应使用 res.fhdr() 获取方法。ACL 派生:res.hdr([<name>[,<occ>]]):精确字符串匹配 res.hdr_beg([<name>[,<occ>]]):前缀匹配 res.hdr_dir([<name>[,<occ>]]):子目录匹配 res.hdr_dom([<name>[,<occ>]]):域名匹配 res.hdr_end([<name>[,<occ>]]):后缀匹配 res.hdr_len([<name>[,<occ>]]):长度匹配 res.hdr_reg([<name>[,<occ>]]):正则表达式匹配 res.hdr_sub([<name>[,<occ>]]):子字符串匹配
返回一个整数值,表示响应标头字段名 <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"。请注意,HTTP标准严格禁止URI中的任何片段引用(路径后的'#')并将被拒绝。但是,如果接收请求的前端具有"option accept-invalid-http-request"选项,则将接受此片段部分,并且它也将出现在url中。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中应用某些检查。请注意,此fetch的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格式相同。-自定义日志格式,允许您创建自己的日志行。下一节将详细介绍每种格式。格式规范将基于"字段"进行。除非另有说明,字段是任意数量的空格分隔的文本片段。由于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
字段格式从上面的示例中提取1 process_name '[' pid ']:' haproxy[14387]: 2 client_ip ':' client_port 10.0.1.2:33313 3 '[' accept_date ']' [06/Feb/2009:12:12:51.443] 4 frontend_name fnt 5 backend_name '/' server_name bck/srv1 6 Tw '/' Tc '/' Tt* 0/0/5007 7 bytes_read* 212 8 termination_state -- 9 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 0/0/0/0/3 10 srv_queue '/' backend_queue 0/0详细字段说明:- "client_ip"是发起TCP连接到haproxy的客户端的IP地址。如果连接是在UNIX套接字上接受的,IP地址将被"unix"一词替换。请注意,当连接在配置了"accept-proxy"并正确使用PROXY协议的套接字上接受,或配置了"accept-netscaler-cip"并正确使用NetScaler客户端IP插入协议的套接字上接受时,日志将反映转发连接的信息。- "client_port"是发起连接的客户端的TCP端口。如果连接是在UNIX套接字上接受的,端口将被替换为接受套接字的ID,该ID也在统计信息界面中报告。- "accept_date"是haproxy接收连接的确切日期(如果系统后台存在一些排队,则可能与网络上观察到的日期略有不同)。这通常是任何上游防火墙日志中可能出现的同一日期。在HTTP模式下使用时,accept_date字段将被重置为连接准备好接收新请求的第一个时刻(HTTP/1的上一响应结束,HTTP/2的上一请求之后立即)。- "frontend_name"是接收和处理连接的前端(或监听器)的名称。- "backend_name"是选择用于管理与服务器连接的后端(或监听器)的名称。如果没有应用切换规则,这将与前端相同,这对于TCP应用程序很常见。- "server_name"是发送连接到的最后一个服务器的名称,如果发生连接错误并进行了重新分发,则可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果连接在到达服务器之前被中止,则显示"<NOSRV>"而不是服务器名称。- "Tw"是以毫秒为单位在各种队列中等待的总时间。如果连接在到达队列之前被中止,则可能为"-1"。有关更多详细信息,请参阅下面的"计时器"。- "Tc"是以毫秒为单位等待连接到最终服务器(包括重试)的总时间。如果连接在能够建立连接之前被中止,则可能为"-1"。有关更多详细信息,请参阅下面的"计时器"。- "Tt"是以毫秒为单位从接受到最后关闭所经过的总时间。它涵盖了所有可能的处理。有一个例外,如果指定了"option logasap",则计时将在发出日志时停止。在这种情况下,值前面会加上"+"号,表示最终值将更大。有关更多详细信息,请参阅下面的"计时器"。- "bytes_read"是发出日志时从服务器传输到客户端的总字节数。如果指定了"option logasap",此值将带有"+"号前缀,表示最终值可能更大。请注意,此值是64位计数器,因此日志分析工具必须能够处理它而不溢出。- "termination_state"是会话结束时的会话状态。这表示会话状态,是哪一方导致会话结束,以及原因(超时、错误等)。正常标志应为"--",表示会话由任一端关闭,缓冲区中没有剩余数据。有关更多详细信息,请参阅下面的"断开连接时的会话状态"。- "actconn"是记录会话时进程上的并发连接总数。这对于检测何时达到某些每进程系统限制非常有用。例如,如果actconn接近512时发生多个连接错误,那么很可能是系统将进程限制为最多使用1024个文件描述符,并且所有这些都已被使用。请参阅第3节"全局参数",了解如何调整系统。- "feconn"是记录会话时前端上的并发连接总数。这对于估算维持高负载所需的资源量以及检测前端的"maxconn"已被达到非常有用。大多数时候,当此值大幅增加时,是因为后端服务器存在拥塞,但有时也可能是拒绝服务攻击。- "beconn"是记录会话时后端处理的并发连接总数。它包括服务器上的并发连接总数以及队列中等待的连接数。这对于估算给定应用程序所需支持高负载的额外服务器数量非常有用。大多数时候,当此值大幅增加时,是因为后端服务器存在拥塞,但有时也可能是拒绝服务攻击。- "srv_conn"是记录会话时服务器上仍处于活动状态的并发连接总数。它永远不会超过服务器配置的"maxconn"参数。如果此值经常接近或等于服务器的"maxconn",则表示流量调节涉及很多,意味着服务器的maxconn值太低,或者没有足够的服务器来以最佳响应时间处理负载。当只有一个服务器的"srv_conn"很高时,通常意味着该服务器存在一些问题,导致连接的处理时间比其他服务器长。- "retries"是此会话在尝试连接到服务器时遇到的连接重试次数。它通常应该是零,除非在尝试连接的同一时间有服务器正在停止。频繁重试通常表示haproxy和服务器之间的网络问题,或服务器上的系统后台配置不当,阻止新连接排队。此字段可能选择性地以"+"号作为前缀,表示会话在初始服务器达到最大重试次数后经历了重新分发。在这种情况下,日志中显示的服务器名称是连接被重新分发到的服务器,而不是第一个服务器,尽管两者有时可能相同(例如,在哈希的情况下)。因此,总的来说,当重试计数前有一个"+"号时,此计数不应归因于已记录的服务器。- "srv_queue"是服务器队列中此请求之前的已处理请求总数。当请求未经过服务器队列时,它为零。通过将队列中花费的时间除以队列中的请求数,可以估算近似服务器响应时间。值得注意的是,如果会话经历了重新分发并通过两个服务器队列,则它们的位置将是累积的。除非发生重新分发,否则请求不应同时通过服务器队列和后端队列。- "backend_queue"是后端全局队列中此请求之前的已处理请求总数。当请求未经过全局队列时,它为零。通过将服务器的"maxconn"参数除以平均队列长度,可以估算平均队列长度,这很容易转化为服务器数量不足。值得注意的是,如果会话经历了重新分发,它可能会两次通过后端队列,然后两个位置都将是累积的。除非发生重新分发,否则请求不应同时通过服务器队列和后端队列。
HTTP格式是最完整的,最适合HTTP代理。当在前端指定"option httplog"时,它将被启用。它提供与TCP格式相同的信息级别,并具有HTTP协议特有的附加功能。与TCP格式一样,日志通常在会话结束时发出,除非指定了"option logasap",这通常只对下载站点有意义。匹配"monitor"规则的会话永远不会被记录。通过在前端指定"option dontlognull",还可以不记录客户端未发送任何数据的会话的日志。如果前端指定了"option dontlog-normal",则不会记录成功连接的日志。大多数字段与TCP日志共享,有些则不同。一些字段可能因某些配置选项而略有不同。这些字段在下面的字段名称后用星号('*')标记。
frontend http-in mode http option httplog log global default_backend bck backend static server srv1 127.0.0.1:8000 >>> Feb 6 12:14:14 localhost \ haproxy[14389]: 10.0.1.2:33317 [06/Feb/2009:12:14:14.655] http-in \ static/srv1 10/0/30/69/109 200 2750 - - ---- 1/1/1/1/0 0/0 {1wt.eu} \ {} "GET /index.html HTTP/1.1"
字段格式 示例中的字段提取 1 process_name '[' pid ']:' haproxy[14389]: 2 client_ip ':' client_port 10.0.1.2:33317 3 '[' request_date ']' [06/Feb/2009:12:14:14.655] 4 frontend_name http-in 5 backend_name '/' server_name static/srv1 6 TR '/' Tw '/' Tc '/' Tr '/' Ta* 10/0/30/69/109 7 status_code 200 8 bytes_read* 2750 9 captured_request_cookie - 10 captured_response_cookie - 11 termination_state ---- 12 actconn '/' feconn '/' beconn '/' srv_conn '/' retries* 1/1/1/1/0 13 srv_queue '/' backend_queue 0/0 14 '{' captured_request_headers* '}' {haproxy.1wt.eu} 15 '{' captured_response_headers* '}' {} 16 '"' http_request '"' "GET /index.html HTTP/1.1" 详细字段描述: - "client_ip" 是发起 TCP 连接到 haproxy 的客户端的 IP 地址。如果连接在 UNIX 套接字上接受,IP 地址将被“unix”一词替换。请注意,当连接在配置了 "accept-proxy" 的套接字上接受并且 PROXY 协议使用正确,或者配置了 "accept-netscaler-cip" 并且 NetScaler 客户端 IP 插入协议使用正确,日志将反映转发连接的信息。 - "client_port" 是发起连接的客户端的 TCP 端口。如果连接在 UNIX 套接字上接受,端口将被接受套接字的 ID 替换,该 ID 也在统计界面中报告。 - "request_date" 是 haproxy 收到 HTTP 请求的第一个字节的确切日期(日志字段 %tr)。 - "frontend_name" 是接收和处理连接的前端(或监听器)的名称。 - "backend_name" 是被选定用于管理服务器连接的后端(或监听器)的名称。如果没有应用切换规则,这将与前端相同。 - "server_name" 是连接被发送到的最后一个服务器的名称,如果发生连接错误并出现重新分派,它可能与第一个服务器不同。请注意,此服务器属于处理请求的后端。如果请求在到达服务器之前被中止,则指示 "<<NOSRV>>" 而不是服务器名称。如果请求被统计子系统拦截,则指示 "<<STATS>>" 而不是服务器名称。 - "TR" 是在收到第一个字节后,等待客户端完整 HTTP 请求(不包括正文)所花费的总时间(毫秒)。如果在收到完整请求之前连接被中止,或者收到了错误请求,则可能为“-1”。它通常应该非常小,因为请求通常适合一个数据包。这里的大时间通常表示客户端和 haproxy 之间的网络问题或手动输入请求。有关更多详细信息,请参阅 第 8.4 节“计时事件”。 - "Tw" 是在各种队列中等待所花费的总时间(毫秒)。如果在到达队列之前连接被中止,则可能为“-1”。有关更多详细信息,请参阅 第 8.4 节“计时事件”。 - "Tc" 是等待连接建立到最终服务器所花费的总时间(毫秒),包括重试。如果在建立连接之前请求被中止,则可能为“-1”。有关更多详细信息,请参阅第 8.4 节“计时事件”。 - "Tr" 是等待服务器发送完整的 HTTP 响应(不包括数据)所花费的总时间(毫秒)。如果在收到完整响应之前请求被中止,则可能为“-1”。它通常与服务器处理请求的时间匹配,但可能会因客户端发送到服务器的数据量而改变。对于“GET”请求,这里的大时间通常表示服务器过载。有关更多详细信息,请参阅 第 8.4 节“计时事件”。 - "Ta" 是请求在 haproxy 中保持活动的时间,即从收到请求的第一个字节到发送响应的最后一个字节所经过的总时间(毫秒)。它涵盖了除握手(参见 Th)和空闲时间(参见 Ti)之外的所有可能处理。有一个例外,如果指定了 "option logasap",则计时将在发出日志时停止。在这种情况下,值前面会加上一个“+”号,表示最终值会更大。有关更多详细信息,请参阅 第 8.4 节“计时事件”。 - "status_code" 是返回给客户端的 HTTP 状态码。此状态通常由服务器设置,但也可能由 haproxy 设置,因为服务器无法访问或其响应被 haproxy 阻止。 - "bytes_read" 是在发出日志时传输到客户端的总字节数。这包括 HTTP 标头。如果指定了 "option logasap",此值将以“+”号为前缀,表示最终值可能更大。请注意,此值为 64 位计数器,因此日志分析工具必须能够处理它而不会溢出。 - "captured_request_cookie" 是一个可选的“name=value”条目,表示客户端在请求中具有此 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。如果未设置选项,该字段为单个破折号('-')。只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "captured_response_cookie" 是一个可选的“name=value”条目,表示服务器已在其响应中返回 cookie。cookie 名称及其最大长度由前端配置中的 "capture cookie" 语句定义。如果未设置选项,该字段为单个破折号('-')。只能捕获一个 cookie,它通常用于跟踪客户端和服务器之间的会话 ID 交换,以检测由于应用程序错误导致的客户端之间的会话交叉。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "termination_state" 是会话结束时会话所处的状态。这表示会话状态,是哪个端导致会话结束,原因是什么(超时、错误等),就像 TCP 日志一样,以及关于 cookie 在最后两个字符中的持久化操作的信息。正常标志应以“--”开头,表示会话已关闭,且缓冲区中没有剩余数据。有关更多详细信息,请参阅下面的“断开连接时的会话状态”。 - "actconn" 是记录会话时进程上的并发连接总数。它有助于检测何时达到了某些每个进程的系统限制。例如,如果 actconn 接近 512 或 1024 并且发生多个连接错误,则很有可能系统将进程限制为最多使用 1024 个文件描述符,并且它们都已用完。有关如何调整系统的详细信息,请参阅 第 3 节“全局参数”。 - "feconn" 是记录会话时前端上的并发连接总数。它有助于估计维持高负载所需的资源量,并检测何时已达到前端的 "maxconn"。当此值大幅增加时,通常是因为后端服务器拥塞,但有时也可能是拒绝服务攻击造成的。 - "beconn" 是记录会话时后端处理的并发连接总数。它包括服务器上活动的并发连接总数以及队列中待处理的连接数。它有助于估计支持给定应用程序高负载所需的额外服务器数量。当此值大幅增加时,通常是因为后端服务器拥塞,但有时也可能是拒绝服务攻击造成的。 - "srv_conn" 是记录会话时服务器上仍处于活动状态的并发连接总数。它永远不会超过服务器配置的 "maxconn" 参数。如果此值非常接近或等于服务器的 "maxconn",则表示流量调节涉及很多,这意味着服务器的 maxconn 值太低,或者没有足够的服务器来以最佳响应时间处理负载。当只有服务器的 "srv_conn" 之一很高时,通常意味着该服务器存在某些问题,导致请求的处理时间比其他服务器长。 - "retries" 是在尝试连接到服务器时,此会话经历的连接重试次数。它通常应为零,除非在尝试连接的同一时刻服务器正在停止。频繁重试通常表示 haproxy 和服务器之间的网络问题,或者服务器上配置错误的系统积压导致无法排队新连接。此字段可以选择性地以“+”号为前缀,表示会话在达到初始服务器的最大重试次数后经历了重新分派。在这种情况下,日志中出现的服务器名称是连接被重新分派到的服务器,而不是第一个服务器,尽管两者有时可能相同,例如在哈希时。因此,作为一般经验法则,当重试计数前面有“+”时,此计数不应归因于已记录的服务器。 - "srv_queue" 是此请求在服务器队列中之前处理的请求总数。当请求未经过服务器队列时,该值为零。通过将队列中花费的时间除以队列中的请求数量,可以估计服务器的近似响应时间。值得注意的是,如果一个会话经历了重新分派并经过两个服务器队列,则它们的位置将是累积的。除非发生重新分派,否则请求不应同时经过服务器队列和后端队列。 - "backend_queue" 是此请求在后端全局队列中之前处理的请求总数。当请求未经过全局队列时,该值为零。通过将服务器的 "maxconn" 参数除以平均队列长度,可以估计平均队列长度,这很容易转化为丢失的服务器数量。值得注意的是,如果一个会话经历了重新分派,它可能会两次通过后端队列,然后两个位置都将是累积的。除非发生重新分派,否则请求不应同时经过服务器队列和后端队列。 - "captured_request_headers" 是由于前端中存在 "capture request header" 语句而在请求中捕获的标头的列表。可以捕获多个标头,它们将由竖线('|')分隔。启用无捕获时,花括号不会出现,导致其余字段移位。重要的是要注意,此字段可能包含空格,并且使用它需要比不使用时更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "captured_response_headers" 是由于前端中存在 "capture response header" 语句而在响应中捕获的标头的列表。可以捕获多个标头,它们将由竖线('|')分隔。启用无捕获时,花括号不会出现,导致其余字段移位。重要的是要注意,此字段可能包含空格,并且使用它需要比不使用时更智能的日志解析器。有关更多详细信息,请参阅下面的“捕获 HTTP 标头和 cookie”部分。 - "http_request" 是完整的 HTTP 请求行,包括方法、请求和 HTTP 版本字符串。不可打印字符将被编码(参见下面的“不可打印字符”部分)。这始终是最后一个字段,并且始终用引号分隔,并且是唯一可以包含引号的字段。如果向日志格式添加了新字段,它们将在此字段之前添加。如果请求非常大,不适合标准 syslog 缓冲区(1024 个字符),则此字段可能会被截断。这就是为什么此字段必须始终保持最后的原因。log-format 指令允许您自定义 http 模式和 tcp 模式下的日志。它接受一个字符串作为参数。HAProxy 识别一些日志格式变量。% 前缀是日志格式变量。变量可以使用花括号 ('{}') 获取参数,并且多个参数在花括号内用逗号分隔。标志可以通过在前面加上 '+' 或 '-' 号来添加或删除。特殊变量 "%o" 可用于将其标志传播到同一格式字符串上的所有其他变量。这对于带引号("Q")和转义("E")的字符串格式特别有用。如果一个变量用方括号 ('[' .. ']') 命名,那么它被用作采样表达式规则(参见 第 7.3 节)。这对于添加一些不太常见的信息很有用,例如客户端的 SSL 证书的 DN,或者记录用于将条目存储到粘滞表中的密钥。注意:空格必须转义。空格被视为分隔符。为了发出一个字面的 '%',它必须由另一个 '%' 前缀,结果是 '%%'。HAProxy 将自动合并连续的分隔符。注意:使用 RFC5424 syslog 消息格式时,PARAM-VALUE 中的字符 '"'、'\' 和 ']' 应使用 '\' 作为前缀进行转义(有关更多详细信息,请参阅 https://tools.ietf.org/html/rfc5424#section-6.3.3)。在这种情况下,应考虑使用标志 "E"。标志是: * Q:引用字符串 * X:十六进制表示(IP、端口、%Ts、%rt、%pid) * E:用 '\' 作为前缀转义字符串中的字符 '"'、'\' 和 ']'(预期目的是用于 RFC5424 结构化数据日志格式)log-format %T\ %t\ Some\ Text log-format %{+Q}o\ %t\ %s\ %{-Q}r log-format-sd %{+Q,+E}o\ [exampleSDID@1234\ header=%[capture.req.hdr(0)]]
目前,默认的 HTTP 格式定义如下: log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC \ %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r" 默认的 CLF 格式定义如下: log-format "%{+Q}o %{-Q}ci - - [%trg] %r %ST %B \"\" \"\" %cp \ %ms %ft %b %s %TR %Tw %Tc %Tr %Ta %tsc %ac %fc \ %bc %sc %rc %sq %bq %CC %CS %hrl %hsl" 默认的 TCP 格式定义如下: log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts \ %ac/%fc/%bc/%sc/%rc %sq/%bq" 请参考下表了解当前定义的变量: +---+------+-----------------------------------------------+-------------+ | R | var | 字段名(8.2.2 和 8.2.3 描述) | 类型 | +---+------+-----------------------------------------------+-------------+ | | %o | 特殊变量,将标志应用于所有后续变量 | | +---+------+-----------------------------------------------+-------------+ | | %B | bytes_read(从服务器到客户端) | 数值 | | H | %CC | captured_request_cookie | 字符串 | | H | %CS | captured_response_cookie | 字符串 | | | %H | 主机名 | 字符串 | | | %HM | HTTP 方法(例如:POST) | 字符串 | | H | %HP | HTTP 请求 URI(不带查询字符串,路径) | 字符串 | | H | %HQ | HTTP 请求 URI 查询字符串(例如:?bar=baz) | 字符串 | | H | %HU | HTTP 请求 URI(例如:/foo?bar=baz) | 字符串 | | H | %HV | HTTP 版本(例如:HTTP/1.0) | 字符串 | | | %ID | unique-id | 字符串 | | | %ST | status_code | 数值 | | | %T | GMT 日期时间 | 日期 | | H | %Ta | 请求的活动时间(从 TR 到结束) | 数值 | | | %Tc | Tc | 数值 | | | %Td | Td = Tt - (Tq + Tw + Tc + Tr) | 数值 | | | %Tl | 本地日期时间 | 日期 | | | %Th | 连接握手时间(SSL, PROXY proto) | 数值 | | H | %Ti | HTTP 请求前的空闲时间 | 数值 | | H | %Tq | Th + Ti + TR | 数值 | | H | %TR | 接收完整请求的第一个字节到接收完成的时间 | 数值 | | H | %Tr | Tr(响应时间) | 数值 | | | %Ts | 时间戳 | 数值 | | | %Tt | Tt | 数值 | | | %Tw | Tw | 数值 | | | %U | bytes_uploaded(从客户端到服务器) | 数值 | | | %ac | actconn | 数值 | | | %b | backend_name | 字符串 | | | %bc | beconn(后端并发连接数) | 数值 | | | %bi | backend_source_ip(连接地址) | IP | | | %bp | backend_source_port(连接地址) | 数值 | | | %bq | backend_queue | 数值 | | | %ci | client_ip(接受地址) | IP | | | %cp | client_port(接受地址) | 数值 | | | %f | frontend_name | 字符串 | | | %fc | feconn(前端并发连接数) | 数值 | | | %fi | frontend_ip(接受地址) | IP | | | %fp | frontend_port(接受地址) | 数值 | | | %ft | frontend_name_transport('~' 后缀表示 SSL) | 字符串 | | | %lc | frontend_log_counter | 数值 | | | %hr | captured_request_headers 默认样式 | 字符串 | | | %hrl | captured_request_headers CLF 样式 | 字符串列表 | | | %hs | captured_response_headers 默认样式 | 字符串 | | | %hsl | captured_response_headers CLF 样式 | 字符串列表 | | | %ms | accept date milliseconds(左填充 0) | 数值 | | | %pid | PID | 数值 | | H | %r | http_request | 字符串 | | | %rc | retries | 数值 | | | %rt | request_counter(HTTP 请求或 TCP 会话) | 数值 | | | %s | server_name | 字符串 | | | %sc | srv_conn(服务器并发连接数) | 数值 | | | %si | server_IP(目标地址) | IP | | | %sp | server_port(目标地址) | 数值 | | | %sq | srv_queue | 数值 | | S | %sslc| ssl_ciphers(例如:AES-SHA) | 字符串 | | S | %sslv| ssl_version(例如:TLSv1) | 字符串 | | | %t | date_time(带毫秒精度) | 日期 | | H | %tr | HTTP 请求的 date_time | 日期 | | H | %trg | HTTP 请求开始的 GMT 日期时间 | 日期 | | H | %trl | HTTP 请求开始的本地日期时间 | 日期 | | | %ts | termination_state | 字符串 | | H | %tsc | termination_state 带 cookie 状态 | 字符串 | +---+------+-----------------------------------------------+-------------+ R = 限制:H = 仅限 http 模式;S = 仅限 SSL当传入连接因 SSL 握手或无效的 PROXY 协议头而失败时,haproxy 将使用较短的固定行格式记录该事件。默认情况下,日志在 LOG_INFO 级别发出,除非在后端设置了 "option log-separate-errors" 选项,在这种情况下将使用 LOG_ERR 级别。如果没有进行数据交换的连接(例如,探测)如果设置了 "option 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 模式下的第二个请求时,它从前一个响应的传输结束开始计数。当使用 HTTP/2 等多路复用协议时,它在上一请求之后立即开始计数。一些浏览器会预先建立到服务器的连接,以减少未来请求的延迟,并将其保持挂起状态,直到它们需要为止。此延迟将报告为空闲时间。值为 -1 表示在连接上未收到任何内容。 - TR: 获取客户端请求的总时间(仅限 HTTP 模式)。它是从收到的第一个字节到代理收到标记 HTTP 标头结束的空行之间经过的时间。“-1”值表示从未看到标头结束。这发生在客户端过早关闭或超时时。此时间通常非常短,因为大多数请求都适合单个数据包。长时间可能表明在测试期间手动输入了请求。 - Tq: 从接受日期或自上一个响应的最后一个字节发送以来获取客户端请求的总时间(仅限 HTTP 模式)。它恰好等于 Th + Ti + TR,除非其中任何一个为 -1,在这种情况下,它也将返回 -1。此计时器在 HTTP keep-alive 和浏览器预连接功能出现之前非常有用。如今,建议将其替换为 TR,因为空闲时间会给报告带来很多噪音。 - Tw: 花费在队列中等待连接槽的总时间。它包括后端队列以及服务器队列,并且取决于队列大小以及服务器完成先前请求所需的时间。“-1”值表示请求在到达队列之前被终止,这通常是无效或被拒绝请求的情况。 - Tc: 与服务器建立 TCP 连接的总时间。它是从代理发送连接请求到服务器确认之间经过的时间,或者在 TCP SYN 数据包和匹配的 SYN/ACK 数据包之间返回的时间。“-1”值表示连接从未建立。 - Tr: 服务器响应时间(仅限 HTTP 模式)。它是从与服务器建立 TCP 连接到服务器发送其完整响应标头之间经过的时间。它仅显示其请求处理时间,而不包括数据传输的网络开销。值得注意的是,当客户端有数据发送到服务器时(例如,在 POST 请求期间),时间已经开始运行,这可能会扭曲表观响应时间。因此,通常明智的做法是不要过度依赖此字段来处理来自不受信任网络后客户端发起的 POST 请求。“-1”值表示从未看到最后一个响应标头(空行),最可能是因为服务器在服务器成功处理请求之前超时了。 - Td: 这是响应有效载荷传输到发送给客户端的最后一个字节的总传输时间。在 HTTP 中,它在最后一个响应标头(Tr 之后)之后开始。发送的数据不保证被客户端接收,它们可能卡在内核或网络中。 - Ta: HTTP 请求的总活动时间,介于代理收到请求标头的第一个字节和发送响应正文的最后一个字节之间。除非指定了“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 和 HTTP 日志在活动连接数之前提供了会话终止指示符,位于“termination_state”字段中。在 TCP 模式下,它是 2 个字符长,在 HTTP 模式下扩展到 4 个字符,每个字符都有特殊含义: - 第一个字符,一个报告导致会话终止的第一个事件的代码: C:TCP 会话被客户端意外中止。 S:TCP 会话被服务器意外中止,或被服务器明确拒绝。 P:会话被代理过早中止,因为连接限制被强制执行,因为匹配了 DENY 过滤器,因为安全检查检测并阻止了服务器响应中可能导致信息泄露的危险错误(例如,可缓存的 cookie)。 L:会话由 haproxy 本地处理,未传递给服务器。统计信息和重定向就是这样发生的。 R:代理上的资源已耗尽(内存、套接字、源端口,...)。通常,这发生在连接阶段,并且系统日志应包含精确错误的副本。如果发生这种情况,必须将其视为非常严重的异常,应尽快以任何方式修复。 I:代理在自行检查期间识别出内部错误。这绝不应该发生,并且鼓励您报告任何包含此内容的日志,因为这几乎肯定是一个错误。如果发生这种情况,最好预防性地重启进程,以防其是由内存损坏引起的。 D:由于检测到服务器已宕机并配置为在宕机时终止所有连接,因此会话被 haproxy 终止。 U:由于检测到活动服务器已上线并配置为在上线时终止备份连接,因此会话被 haproxy 在此备份服务器上终止。 K:会话被操作 haproxy 的管理员主动终止。 c:客户端超时,在等待客户端发送或接收数据时过期。 s:服务器超时,在等待服务器发送或接收数据时过期。 -:正常会话完成,客户端和服务器都已关闭,缓冲区中没有剩余内容。 - 第二个字符,TCP 或 HTTP 会话关闭时的状态: R:代理正在等待来自客户端的完整、有效的请求(仅限 HTTP 模式)。没有将任何内容发送到任何服务器。 Q:代理正在队列中等待连接槽。这仅在服务器设置了“maxconn”参数时发生。它也可能发生在重定向到正在死的服务器的失败尝试之后的全局队列中。如果没有报告重定向,则没有进行任何服务器连接尝试。 C:代理正在等待与服务器的连接建立。服务器最多可能已注意到连接尝试。 H:代理正在等待服务器的完整、有效的响应头(仅限 HTTP)。 D:会话处于数据传输阶段。 L:在服务器已完成数据传输时,代理仍在向客户端传输最后数据。这种情况非常罕见,因为它只发生在客户端在接收最后几个数据包时死亡。 T:请求被 tarpit 了。它与客户端保持打开状态,直到“timeout tarpit”持续时间或直到客户端关闭,这两者都将在“Tw”计时器中报告。 -:数据传输结束后的正常会话完成。 - 第三个字符指示客户端是否提供了持久性 cookie(仅限 HTTP 模式): N:客户端未提供 cookie。这通常是新访问者的情况,因此计算此标志在日志中的出现次数通常表明了网站访问量的有效趋势。 I:客户端提供了一个无效的 cookie,未匹配任何已知服务器。这可能由最近的配置更改、HTTP/HTTPS 站点之间的混合 cookie、条件性忽略的持久性或攻击引起。 D:客户端提供了一个指定了宕机的服务器的 cookie,因此使用了“option persist”并将客户端发送到该服务器,或者未设置,并且客户端被重定向到另一台服务器。 V:客户端提供了一个有效的 cookie,并被发送到关联的服务器。 E:客户端提供了一个有效 cookie,但最后一个日期比“maxidle” cookie 参数允许的要旧,因此 cookie 被视为过期并被忽略。请求将被重定向,就像没有 cookie 一样。 O:客户端提供了一个有效的 cookie,但第一个日期比“maxlife” cookie 参数允许的要旧,因此 cookie 被视为太旧并被忽略。请求将被重定向,就像没有 cookie 一样。 U:存在 cookie,但未使用它来选择服务器,因为使用了其他服务器选择机制(通常是“use-server”规则)。 -:不适用(配置中未设置 cookie)。 - 最后一个字符报告了对服务器提供的持久性 cookie 执行了哪些操作(仅限 HTTP 模式): N:服务器未提供 cookie,也未插入任何 cookie。 I:服务器未提供 cookie,并且代理插入了一个。请注意,在“cookie insert”模式下,如果服务器提供了 cookie,它仍将被覆盖并在此处报告为“I”。 U:代理更新了客户端提供的 cookie 中的最后一个日期。这只能在“maxidle”的 insert 模式下发生。每次在与 cookie 中指示的日期不同的日期发生活动时都会发生。如果发生任何其他更改(例如重定向),则 cookie 将被标记为已插入。 P:服务器提供了 cookie 并按原样传输。 R:服务器提供的 cookie 被代理重写,这发生在“cookie rewrite”或“cookie prefix”模式下。 D:服务器提供的 cookie 被代理删除。 -:不适用(配置中未设置 cookie)。前两个标志的组合提供了关于会话终止时发生了什么以及为什么终止的大量信息。它有助于检测服务器饱和、网络问题、本地系统资源耗尽、攻击等。最常见的终止标志组合如下所示。它们按字母顺序排序,小写字母紧跟在大写字母之后,以便于查找和理解。标志 原因 -- 正常终止。 CC 在服务器连接建立之前,客户端中止了。这可能发生在 haproxy 尝试连接到最近已宕机(或未检查)的服务器时,并且在 haproxy 等待服务器响应或“timeout connect”过期时,客户端中止了。 CD 在数据传输过程中,客户端意外中止。这可能由浏览器崩溃、客户端和 haproxy 之间的中间设备决定主动中断连接、客户端和 haproxy 之间的网络路由问题,或服务器和客户端之间的 keep-alive 会话首先由客户端终止引起。 cD 客户端在“timeout client”延迟期间未发送或确认任何数据。这通常是由客户端网络故障引起的,或者客户端只是不干净地离开网络。 CH 客户端在等待服务器开始响应时中止了。可能是服务器响应时间过长,或者客户端点击了“停止”按钮太快。 cH 客户端数据在等待客户端数据时,“timeout client”超时。这有时是由 PPPoE 网络上过大的 TCP MSS 值引起的,这些网络无法传输全尺寸数据包。当客户端超时小于服务器超时且服务器响应时间过长时,也可能发生这种情况。 CQ 客户端在其会话排队等待服务器有足够空槽接受它时中止了。可能是所有服务器都已饱和,或者分配的服务器响应时间过长。 CR 客户端在发送完整的 HTTP 请求之前中止了。最有可能的是,请求是通过 telnet 客户端手动输入的,并且过早中止。 HTTP 状态码很可能是 400。有时,这也可能由 IDS 终止 haproxy 和客户端之间的连接引起。“option http-ignore-probes”可用于忽略没有数据传输的连接。 cR 客户端在发送完整的 HTTP 请求之前,“timeout http-request”超时。这有时是由 PPPoE 网络上客户端过大的 TCP MSS 值引起的,这些网络无法传输全尺寸数据包,或者由手动发送请求但输入速度不够快或忘记在请求末尾输入空行导致。 HTTP 状态码很可能是 408。注意:最近,一些浏览器开始实现“预连接”功能,即推测性地连接到最近访问过的网站,以防用户将来访问它们。这导致连接到网站的数量很多,如果先发生超时,则导致 408 请求超时,或者如果浏览器首先决定关闭它们,则导致 400 Bad Request。这些会污染日志并馈送错误计数器。据报道,一些浏览器版本甚至显示了错误代码。通过在前端添加“option http-ignore-probes”可以解决此行为的不良影响,导致零数据传输的连接被完全忽略。但这肯定会掩盖那些遇到连接问题的用户的错误。 CT 客户端在其会话被 tarpit 时中止了。检查这是否发生在有效请求上很重要,以确保没有错误的 tarpit 规则被编写。如果发生了很多这种情况,则可能需要将“timeout tarpit”值降低到更接近平均报告的“Tw”计时器的值,以避免为少数攻击者消耗资源。 LR 请求被 haproxy 拦截并本地处理。通常这意味着它是重定向或统计请求。 SC 服务器或其与 haproxy 之间的设备明确拒绝了 TCP 连接(代理收到了 TCP RST 或 ICMP 消息作为响应)。在某些情况下,也可能是网络堆栈告知代理服务器不可达(例如,本地网络上没有路由或没有 ARP 响应)。在 HTTP 模式下发生这种情况时,状态码很可能是 502 或 503。 sC 在服务器连接完成之前,“timeout connect”超时。在 HTTP 模式下发生这种情况时,状态码很可能是 503 或 504。 SD 数据传输过程中,与服务器的连接因错误而中断。这通常意味着 haproxy 在与服务器交换数据时从服务器收到了 RST 或来自中间设备的 ICMP 消息。这可能由服务器崩溃或中间设备的网络问题引起。 sD 在数据阶段,服务器在“timeout server”设置允许的时间内未发送或确认任何数据。这通常是由服务器之前的 L4 设备(防火墙、负载均衡器等)的超时设置过短,以及客户端和服务器之间的 keep-alive 会话首先在 haproxy 上过期引起的。 SH 服务器在发送完整的 HTTP 响应头之前中止,或者在处理请求时崩溃。由于此时服务器中止非常罕见,因此检查其日志以控制它是否崩溃以及原因是有益的。记录的请求可能表明一组小的错误请求,证明了应用程序中的错误。有时,这也可能由 IDS 终止 haproxy 和服务器之间的连接引起。 sH 在服务器返回响应头之前,“timeout server”超时。这是最常见的异常,表明事务时间过长,可能由服务器或数据库饱和引起。立即的解决方法是增加“timeout server”设置,但请牢记,用户体验将因这些长时间响应而受到影响。唯一的长期解决方案是修复应用程序。 sQ 会话在队列中花费了太多时间并已过期。请参阅“timeout queue”和“timeout connect”设置,以了解如何解决此问题(如果经常发生)。如果经常在短时间内大量发生,则可能表明受影响服务器的 I/O 或数据库拥塞存在总体问题,或由外部攻击引起。 PC 代理拒绝建立与服务器的连接,因为在尝试连接时进程的套接字限制已达到。可以增加配置中的全局 maxconn 参数,以防止其再次发生。此状态非常罕见,并且可能在全局“ulimit-n”参数被手动强制执行时发生。 PD 代理阻止了请求或响应中格式不正确的分块编码消息,在服务器发出其标头之后。在大多数情况下,这表明服务器发来的消息无效。HAProxy 支持的最大块大小为 2GB - 1(2147483647 字节)。任何更大的尺寸将被视为错误。 PH 代理阻止了服务器的响应,因为它无效、不完整、危险(缓存控制)或匹配了安全过滤器。在任何情况下,都会向客户端发送 HTTP 502 错误。此错误的一个可能原因是 HTTP 标头名称中的语法无效,其中包含未经授权的字符。在服务器响应之前,代理因无效语法而阻止客户端的分块编码请求也是可能的,但很少见。在这种情况下,会向客户端发送 HTTP 400 错误并在日志中报告。 PR 代理阻止了客户端的 HTTP 请求,原因可能是 HTTP 语法无效,在这种情况下它向客户端返回 HTTP 400 错误,或者因为匹配了拒绝过滤器,在这种情况下它返回 HTTP 403 错误。 PT 代理阻止了客户端的请求,并在返回 500 服务器错误之前对其连接进行了 tarpit。没有将任何内容发送到服务器。连接保持打开状态的时间由“Tw”计时器字段报告。 RC 代理上的本地资源耗尽(内存、套接字、源端口),阻止了与服务器的连接建立。错误日志会准确说明缺少什么。这非常罕见,只能通过适当的系统调优来解决。最后两个标志的组合提供了关于客户端、服务器和 haproxy 如何处理持久性的信息。这对于排查断线问题(用户抱怨需要重新认证)非常重要。通常遇到的标志是:-- 持久性 cookie 未启用。 NN 客户端未提供 cookie,响应中也未插入任何 cookie。例如,这可能是“postonly”设置在 GET 请求上的 insert 模式。 II 客户端提供的 cookie 指定了一个无效的服务器,响应中插入了一个有效的 cookie。当服务器条目从配置中删除时,通常会发生这种情况,因为客户端可能会提供其 cookie 值,而没有其他服务器知道它。 NI 客户端未提供 cookie,响应中插入了一个。这通常发生在“insert”模式下每个用户的首次请求,这是一种计算真实用户数量的简便方法。 VN 客户端提供了 cookie,响应中未插入任何 cookie。对于客户端已有 cookie 的大多数响应,都会发生这种情况。 VU 客户端提供了 cookie,其最后一个访问日期不是最新的,因此响应中提供了更新的 cookie。这也可能发生,因为根本没有日期,或者有日期但未设置“maxidle”参数,因此 cookie 可以切换到无限时间。 EI 客户端提供的 cookie,其最后一个访问日期对于“maxidle”参数来说太旧了,因此 cookie 被忽略,并在响应中插入了一个新 cookie。 OI 客户端提供的 cookie,其第一个访问日期对于“maxlife”参数来说太旧了,因此 cookie 被忽略,并在响应中插入了一个新 cookie。 DI cookie 指定的服务器已宕机,选择了一个新服务器并在响应中发出了一个新 cookie。 VI cookie 指定的服务器未被标记为宕机但无法访问。发生了重定向,并选择了另一个服务器,然后该服务器在响应中被广告。
为了在查阅日志时避免给日志分析工具或终端带来麻烦,不可打印的字符不会按原样发送到日志文件中,而是会转换为其 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
Header captures are useful to track unique request identifiers set by an upper proxy, virtual host names, user-agents, POST content-length, referrers, etc. In the response, one can search for information about the response length, how the server asked the cache to behave, or an object location during a redirection. Header captures are performed using the "capture request header" and "capture response header" statements in the frontend. Please consult their definition in section 4.2 for more details. It is possible to include both request headers and response headers at the same time. Non-existent headers are logged as empty strings, and if one header appears more than once, only its last occurrence will be logged. Request headers are grouped within braces '{' and '}' in the same order as they were declared, and delimited with a vertical bar '|' without any space. Response headers follow the same representation, but are displayed after a space following the request headers block. These blocks are displayed just before the HTTP request in the logs. As a special case, it is possible to specify an HTTP header capture in a TCP frontend. The purpose is to enable logging of headers which will be parsed in an HTTP backend if the request is then switched to this HTTP backend.
# This instance chains to the outgoing proxy listen proxy-out mode http option httplog option logasap log global server cache1 192.168.1.1:3128 # log the name of the virtual server capture request header Host len 20 # log the amount of data uploaded during a POST capture request header Content-Length len 10 # log the beginning of the referrer capture request header Referer len 20 # server name (useful for outgoing proxies only) capture response header Server len 20 # logging the content-length is useful with "option logasap" capture response header Content-Length len 10 # log the expected cache behavior on the response capture response header Cache-Control len 8 # the Via header will report the next proxy's name capture response header Via len 20 # log the URL location during a redirection capture response header Location len 20 >>> Aug 9 20:26:09 localhost \ haproxy[2022]: 127.0.0.1:34014 [09/Aug/2004:20:26:09] proxy-out \ proxy-out/cache1 0/0/0/162/+162 200 +350 - - ---- 0/0/0/0/0 0/0 \ {fr.adserver.yahoo.co||http://fr.f416.mail.} {|864|private||} \ "GET http://fr.adserver.yahoo.com/" >>> Aug 9 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34020 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/0/182/+182 200 +279 - - ---- 0/0/0/0/0 0/0 \ {w.ods.org||} {Formilux/0.1.8|3495|||} \ "GET http://trafic.1wt.eu/ HTTP/1.1" >>> Aug 9 20:30:46 localhost \ haproxy[2022]: 127.0.0.1:34028 [09/Aug/2004:20:30:46] proxy-out \ proxy-out/cache1 0/0/2/126/+128 301 +223 - - ---- 0/0/0/0/0 0/0 \ {www.sytadin.equipement.gouv.fr||http://trafic.1wt.eu/} \ {Apache|230|||http://www.sytadin.} \ "GET http://www.sytadin.equipement.gouv.fr/ HTTP/1.1"
These are real-world examples of logs accompanied with an explanation. Some of them have been made up by hand. The syslog part has been removed for better reading. Their sole purpose is to explain how to decipher them. >>> haproxy[674]: 127.0.0.1:33318 [15/Oct/2003:08:31:57.130] px-http \ px-http/srv1 6559/0/7/147/6723 200 243 - - ---- 5/3/3/1/0 0/0 \ "HEAD / HTTP/1.0" => long request (6.5s) entered by hand through 'telnet'. The server replied in 147 ms, and the session ended normally ('----') >>> haproxy[674]: 127.0.0.1:33319 [15/Oct/2003:08:31:57.149] px-http \ px-http/srv1 6559/1230/7/147/6870 200 243 - - ---- 324/239/239/99/0 \ 0/9 "HEAD / HTTP/1.0" => Idem, but the request was queued in the global queue behind 9 other requests, and waited there for 1230 ms. >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.654] px-http \ px-http/srv1 9/0/7/14/+30 200 +243 - - ---- 3/3/3/1/0 0/0 \ "GET /image.iso HTTP/1.0" => request for a long data transfer. The "logasap" option was specified, so the log was produced just before transferring data. The server replied in 14 ms, 243 bytes of headers were sent to the client, and total time from accept to first data byte is 30 ms. >>> haproxy[674]: 127.0.0.1:33320 [15/Oct/2003:08:32:17.925] px-http \ px-http/srv1 9/0/7/14/30 502 243 - - PH-- 3/2/2/0/0 0/0 \ "GET /cgi-bin/bug.cgi? HTTP/1.0" => the proxy blocked a server response either because of an "rspdeny" or "rspideny" filter, or because the response was improperly formatted and not HTTP-compliant, or because it blocked sensitive information which risked being cached. In this case, the response is replaced with a "502 bad gateway". The flags ("PH--") tell us that it was haproxy who decided to return the 502 and not the server. >>> haproxy[18113]: 127.0.0.1:34548 [15/Oct/2003:15:18:55.798] px-http \ px-http/<NOSRV> -1/-1/-1/-1/8490 -1 0 - - CR-- 2/2/2/0/0 0/0 "" => the client never completed its request and aborted itself ("C---") after 8.5s, while the proxy was waiting for the request headers ("-R--"). Nothing was sent to any server. >>> haproxy[18113]: 127.0.0.1:34549 [15/Oct/2003:15:19:06.103] px-http \ px-http/<NOSRV> -1/-1/-1/-1/50001 408 0 - - cR-- 2/2/2/0/0 0/0 "" => The client never completed its request, which was aborted by the time-out ("c---") after 50s, while the proxy was waiting for the request headers ("-R--"). Nothing was sent to any server, but the proxy could send a 408 return code to the client. >>> haproxy[18989]: 127.0.0.1:34550 [15/Oct/2003:15:24:28.312] px-tcp \ px-tcp/srv1 0/0/5007 0 cD 0/0/0/0/0 0/0 => This log was produced with "option tcplog". The client timed out after 5 seconds ("c----"). >>> haproxy[18989]: 10.0.0.1:34552 [15/Oct/2003:15:26:31.462] px-http \ px-http/srv1 3183/-1/-1/-1/11215 503 0 - - SC-- 205/202/202/115/3 \ 0/0 "HEAD / HTTP/1.0" => The request took 3s to complete (probably a network problem), and the connection to the server failed ('SC--') after 4 attempts of 2 seconds (config says 'retries 3'), and no redispatch (otherwise we would have seen "/+3"). Status code 503 was returned to the client. There were 115 connections on this server, 202 connections on this proxy, and 205 on the global process. It is possible that the server refused the connection because of too many already established.此处列出了官方支持的过滤器及其接受的参数。根据编译选项,其中一些过滤器可能不可用。可用过滤器的列表将在 haproxy -vv 中报告。
<name> is an arbitrary name that will be reported in messages. If no name is provided, "TRACE" is used. <random-parsing> enables the random parsing of data exchanged between the client and the server. By default, this filter parses all available data. With this parameter, it only parses a random amount of the available data. <random-forwarding> enables the random forwarding of parsed data. By default, this filter forwards all previously parsed data. With this parameter, it only forwards a random amount of the parsed data. <hexdump> dumps all forwarded data to the server and the client.
此过滤器可用作开发新过滤器的基础。它定义了所有回调,并在标准错误流(stderr)上打印一条包含所有回调有用信息的消息。调试其他过滤器活动或 HAProxy 本身活动时可能很有用。使用 <;random-parsing> 和/或 <;random-forwarding> 参数是通过在处理中增加延迟来测试解析客户端和服务器之间交换数据的过滤器行为的好方法。
The HTTP compression has been moved in a filter in HAProxy 1.7. "compression" keyword must still be used to enable and configure the HTTP compression. And when no other filter is used, it is enough. When used with the cache enabled, it is also enough. In this case, the compression is always done after the response is stored in the cache. But it is mandatory to explicitly use a filter line to enable the HTTP compression when at least one filter other than the cache is used for the same listener/frontend/backend. This is important to know the filters evaluation order.
<name> is the engine name that will be used to find the right scope in the configuration file. If not provided, all the file will be parsed. <file> is the path of the engine configuration file. This file can contain configuration of several engines. In this case, each part must be placed in its own scope.
The Stream Processing Offload Engine (SPOE) is a filter communicating with external components. It allows the offload of some specifics processing on the streams in tiered applications. These external components and information exchanged with them are configured in dedicated files, for the main part. It also requires dedicated backends, defined in HAProxy configuration. SPOE communicates with external components using an in-house binary protocol, the Stream Processing Offload Protocol (SPOP). For all information about the SPOE configuration and the SPOP specification, see "doc/SPOE.txt". Important note: The SPOE filter is highly experimental for now and was not heavily tested. It is really not production ready. So use it carefully.
<name> is name of the cache section this filter will use.
The cache uses a filter to store cacheable responses. The HTTP rules "cache-store" and "cache-use" must be used to define how and when to use a cache. By default the corresponding filter is implicitly defined. And when no other filters than cache or compression are used, it is enough. In such case, the compression filter is always evaluated after the cache filter. But it is mandatory to explicitly use a filter line to use a cache when at least one filter other than the compression is used for the same listener/frontend/backend. This is important to know the filters evaluation order.
HAProxy provides a cache, which was designed to perform cache on small objects (favicon, css...). This is a minimalist low-maintenance cache which runs in RAM. The cache is based on a memory which is shared between processes and threads, this memory is split in blocks of 1k. If an object is not used anymore, it can be deleted to store a new object independently of its expiration date. The oldest objects are deleted first when we try to allocate a new one. The cache uses a hash of the host header and the URI as the key. It's possible to view the status of a cache using the Unix socket command "show cache" consult section 9.3 "Unix Socket commands" of Management Guide for more details. When an object is delivered from the cache, the server name in the log is replaced by "<CACHE>".
The cache won't store and won't deliver objects in these cases: - If the response is not a 200 - If the response contains a Vary header - If the Content-Length + the headers size is greater than "max-object-size" - If the response is not cacheable - If the request is not a GET - If the HTTP version of the request is smaller than 1.1 - If the request contains an Authorization header Caution!: For HAProxy version prior to 1.9, due to the limitation of the filters, it is not recommended to use the cache with other filters. Using them can cause undefined behavior if they modify the response (compression for example). For HAProxy 1.9 and greater, it is safe, for HTX proxies only (see "option http-use-htx" for details).
To setup a cache, you must define a cache section and use it in a proxy with the corresponding http-request and response actions.
声明一个缓存部分,分配一个名为 <name> 的共享缓存内存,缓存大小是强制性的。
以兆字节为单位定义缓存的 RAM 大小。此大小被分成 1kB 的块,供缓存条目使用。其最大值为 4095。
定义要缓存的对象最大大小。不得大于 “total-max-size” 的一半。如果未设置,则等于缓存大小的 256 分之一。所有大小大于 “max-object-size” 的对象将不会被缓存。
Define the maximum expiration duration. The expiration is set has the lowest value between the s-maxage or max-age (in this order) directive in the Cache-Control response header and this value. The default value is 60 seconds, which means that you can't cache an object more than 60 seconds by default.
Try to deliver a cached object from the cache <name>. This directive is also mandatory to store the cache as it calculates the cache hash. If you want to use a condition for both storage and delivering that's a good idea to put it after this one.
Store an http-response within the cache. The storage of the response headers is done at this step, which means you can use others http-response actions to modify headers before or after the storage of the response. This action is responsible for the setup of the cache storage filter.
backend bck1 mode http http-request cache-use foobar http-response cache-store foobar server srv1 127.0.0.1:80 cache foobar total-max-size 4 max-age 240