基于cookie的会话保持

在 HAProxy 中,可以通过使用 cookie 配置来实现基于 Cookie 的会话保持。cookie 配置用于配置与会话保持相关的选项,允许您定义要在HTTP响应中插入或重写的Cookie以及其他与Cookie会话保持相关的参数。 以下是一些常用的 cookie 配置选项: cookie <cookie-name> <type> [prefix|postfix] [indirect] [nocache]: <cookie-name>: 要使用的Cookie名称。 <type>: 定义Cookie的类型,可以是insert, rewrite, 或者 insert indirect。insert 表示在响应中插入新的Cookie,rewrite 表示重写已有的Cookie,insert indirect 表示在响应中插入新的Cookie,并将值保存到一个间接的Cookie中。 prefix|postfix: 用于定义插入的Cookie值是作为前缀还是后缀添加到Cookie中,默认为前缀。 indirect: 与insert indirect 配合使用,将Cookie值保存到一个间接的Cookie中。 nocache: 表示HAProxy不会在响应中添加"Cache-Control"和"Expires"头部,防止缓存Cookie。 cookie <cookie-name> insert indirect nocache: 这是一个常用的基于Cookie的会话保持配置选项。它在响应中插入一个新的Cookie,并将值保存到一个间接的Cookie中。同时禁用缓存,确保会话保持的Cookie不会被缓存。 cookie <cookie-name> rewrite: 这个选项用于重写已有的Cookie的值。如果请求中已经包含指定名称的Cookie,HAProxy会根据会话保持策略更新Cookie的值。 image.png image.png

HAProxy状态页

HAProxy提供了一个状态页面,也称为HAProxy统计页面(HAProxy Stats Page),它是一个Web界面,用于查看和监控HAProxy的实时状态信息。通过访问这个状态页面,您可以获取HAProxy的运行状态、负载均衡信息、后端服务器的状态等,帮助您了解HAProxy的性能和连接情况。

stats enable #基于默认的参数启用stats page
stats hide-version #隐藏版本
stats refresh <delay> #设定自动刷新时间间隔
stats uri <prefix> #自定义stats page uri,默认值:/haproxy?stats
stats realm <realm> #账户认证时的提示信息,示例:stats realm : HAProxy\ Statistics
stats auth <user>:<passwd> #认证时的账号和密码,可使用多次,默认:no authentication
stats admin { if | unless } <cond> #启用stats page中的管理功能

image.png image.png

报文修改

在 HAProxy 中,可以通过使用报文修改(Message Modification)来修改请求和响应报文的内容。报文修改允许您在 HAProxy 转发请求和响应之前,对报文进行自定义的编辑、增加、删除或替换操作。这样您可以实现一些高级功能,例如重写请求URL、修改请求头部、处理响应内容等。 HAProxy 提供了两种报文修改的方式: HTTP 请求和响应报文修改: 通过使用 http-request 和 http-response 配置项,您可以在 HTTP 请求和响应处理阶段修改报文。 TCP 请求和响应报文修改: 通过使用 tcp-request 和 tcp-response 配置项,您可以在 TCP 请求和响应处理阶段修改报文。

在请求报文尾部添加指定首部
reqadd <string> [{if | unless} <cond>]
从请求报文中删除匹配正则表达式的首部
reqdel <search> [{if | unless} <cond>]
reqidel <search> [{if | unless} <cond>]
在响应报文尾部添加指定首部
rspadd <string> [{if | unless} <cond>]
示例:
rspadd X-Via:\ HAPorxy
从响应报文中删除匹配正则表达式的首部
rspdel <search> [{if | unless} <cond>]
rspidel <search> [{if | unless} <cond>]
示例:
rspidel server.* #从响应报文删除server信息
rspidel X-Powered-By:.* #从响应报文删除X-Powered-By信息

image.png image.pngimage.png

HAProxy日志配置

在 HAProxy 中,您可以通过配置日志来记录关于请求、响应和HAProxy运行状态的信息。通过日志记录,您可以监控流量、故障排查、性能优化以及分析用户行为。HAProxy 支持将日志输出到不同的目标,例如文件、远程服务器、syslog 等。

global
    log /dev/log local0
    log /dev/log local1 notice

defaults
    log global
    mode http
    option httplog
    option dontlognull
    timeout connect 5000
    timeout client 50000
    timeout server 50000

frontend http_front
    bind *:80
    default_backend http_back

backend http_back
    server web1 192.168.1.101:80 check
    server web2 192.168.1.102:80 check
在上述示例中,我们配置了两个日志输出目标,一个是 /dev/log,使用 local0 设施(facility),另一个是 /dev/log,使用 local1 设施。设施是 syslog 的一部分,用于将日志分配到不同的系统设施中。
日志配置项解释:
log /dev/log local0: 将日志输出到 /dev/log,使用 local0 设施。这是系统日志默认使用的设施,您可以在 syslog 配置中指定将该设施的日志输出到特定文件或远程服务器。
log /dev/log local1 notice: 将日志输出到 /dev/log,使用 local1 设施,并指定日志级别为 notice。notice 级别意味着只记录比 notice 级别更高的日志消息,例如 warning、err、alert 和 emerg 等。
log global: 在默认配置部分使用 log global,表示将使用全局配置的日志设置。
option httplog: 启用 HTTP 日志记录,这将记录关于 HTTP 请求和响应的信息,包括客户端IP、请求方法、请求URL、HTTP状态码等。
option dontlognull: 防止记录空连接的日志

Rsyslog配置

vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
local3.* /var/log/haproxy.log
# systemctl restart rsyslog

自定义日志格式

在 HAProxy 中,除了使用预定义的占位符来定义自定义日志格式外,还可以使用 capture 来自定义捕获特定请求或响应的信息,并将其包含在日志中。 capture 是一个强大的选项,允许您从请求和响应中提取关键信息,并将其记录在日志中。您可以在 http-request 和 http-response 配置中使用 capture 来捕获所需的信息。

capture cookie <name> len <length> #捕获请求和响应报文中的 cookie并记录日志
capture request header <name> len <length> #捕获请求报文中指定的首部内容和长度并记录日志
capture response header <name> len <length> #捕获响应报文中指定的内容和长度首部并记录日志
示例:
capture request header Host len 256
capture request header User-Agent len 512
capture request header Referer len 15
global
    log /dev/log local0
    log /dev/log local1 notice

defaults
    log global
    log-format "%ci:%cp [%t] %ft %b/%s %hrl %hs %[capture.req.hdr(0)] %[capture.res.hdr(0)]"

    mode http
    option httplog
    option dontlognull
    timeout connect 5000
    timeout client 50000
    timeout server 50000

frontend http_front
    bind *:80
    http-request capture req.hdr(Host) len 64
    default_backend http_back

backend http_back
    server web1 192.168.1.101:80 check
    server web2 192.168.1.102:80 check

在上述示例中,我们使用 %[capture] 来显示捕获的请求头部的值,并且使用了 %[capture.req.hdr(0)],表示从请求头部中捕获了第一个头部的值(在本例中,我们捕获了 "Host" 头部的值)。同样的,如果您需要显示捕获的响应头部的值,可以使用 %[capture.res.hdr(0)]。

压缩功能

对响应给客户端的报文进行压缩,以节省网络带宽,但是会占用部分CPU性能。在 HAProxy 中,可以通过配置压缩功能来对传输的内容进行压缩,从而减少数据传输的大小,提高网络性能,以及减少带宽消耗。压缩功能通常用于减轻网络负载和加快页面加载速度,特别是对于文本内容(例如 HTML、CSS、JavaScript)来说效果明显 HAProxy 提供了两种压缩方式:Gzip 压缩和Brotli 压缩。您可以根据需求选择适合您场景的压缩算法。

以下是如何在 HAProxy 中配置压缩功能的示例

global
    # 其他全局配置

defaults
    # 其他默认配置

frontend http_front
    bind *:80
    mode http
    default_backend http_back

backend http_back
    mode http
    compression algo gzip
    compression type text/html text/plain text/css application/javascript
    server web1 192.168.1.101:80 check
    server web2 192.168.1.102:80 check
global
    # 其他全局配置

defaults
    # 其他默认配置

frontend http_front
    bind *:80
    mode http
    default_backend http_back

backend http_back
    mode http
    compression algo br
    compression type text/html text/plain text/css application/javascript
    server web1 192.168.1.101:80 check
    server web2 192.168.1.102:80 check
#通过设置 compression algo gzip 来指定压缩算法为 Gzip。然后,使用 compression type

image.png

web服务器状态监测

在 HAProxy 中,可以使用健康检查来监测后端Web服务器的状态,以确保它们正常工作并提供服务。通过定期进行健康检查,HAProxy可以自动发现不可用的服务器,并将流量从故障服务器转移到其他健康的服务器,从而提高系统的可用性和稳定性。

option httpchk
option httpchk <uri>
option httpchk <method> <uri>
option httpchk <method> <uri> <version>
基于四层的传输端口做状态监测
基于指定URI 做状态监测
基于指定URI的request请求头部内容做状态监测

在 HAProxy 中,可以使用多种方式来进行后端服务器的健康检查。每种方式都适用于不同的应用场景和后端服务器类型。以下是一些常见的健康检查方式: TCP 健康检查: 使用TCP健康检查时,HAProxy会简单地尝试连接到后端服务器的指定端口。如果连接成功,则认为服务器是健康的,否则被视为不健康。TCP健康检查适用于不需要检查具体服务状态的场景,例如数据库服务器。

backend my_backend
    mode tcp
    server web1 192.168.1.101:3306 check
    server web2 192.168.1.102:3306 check

HTTP 健康检查: 使用HTTP健康检查时,HAProxy会发送HTTP请求到后端服务器的特定URL,并检查响应状态码是否符合预期。HTTP健康检查适用于Web服务器或应用服务器,可以检查具体的应用状态。

backend my_backend
    mode http
    option httpchk GET /healthcheck HTTP/1.1\r\nHost:\ www.example.com
    http-check expect status 200
    server web1 192.168.1.101:80 check
    server web2 192.168.1.102:80 check
#通过设置 option httpchk 来指定HTTP健康检查的请求,并使用 http-check expect status 200 来指定期望的响应状态码。

SMTP 健康检查: 使用SMTP健康检查时,HAProxy会尝试连接到后端服务器的SMTP端口,并检查服务器是否响应了有效的SMTP协议。

backend my_backend
    mode tcp
    option smtpchk
    server smtp1 192.168.1.101:25 check
    server smtp2 192.168.1.102:25 check

其他健康检查选项: HAProxy还支持其他健康检查选项,例如使用ssl-hello-chk进行SSL握手检查,使用ldap-check进行LDAP检查等。这些健康检查方式适用于特定的应用场景和协议。

ACL

在 HAProxy 中,acl(Access Control List)是用来定义访问控制规则的功能。ACL允许您根据特定条件对请求进行分类和匹配,然后根据匹配结果执行相应的操作。这使得您能够对请求进行高级的路由和过滤。

acl <aclname> <criterion> [flags] [operator] [<value>]
acl 名称 匹配规范 匹配模式 具体操作符 操作对象类型

<aclname>:ACL 的名称,用于标识 ACL 规则,可以自定义。
<criterion>:ACL 规则的匹配条件,可以是以下 ACL 配置选项之一,如 path_beg、hdr_dom、src 等。具体可以参考之前回答中提到的 ACL 配置选项。
[flags]:(可选)用于指定额外的标志,比如 i 表示大小写不敏感匹配,-i 表示大小写敏感匹配。
[operator]:(可选)用于指定匹配操作符,例如 eq 表示等于,ne 表示不等于,lt 表示小于,gt 表示大于,等。
[<value>]:(可选)用于指定要匹配的具体对象类型。
criterion
hdr([<name> [,<occ>]]):完全匹配字符串,header的指定信息
hdr_beg([<name> [,<occ>]]):前缀匹配,header中指定匹配内容的begin
hdr_end([<name> [,<occ>]]):后缀匹配,header中指定匹配内容end
hdr_dom([<name> [,<occ>]]):域匹配,header中的domain name
hdr_dir([<name> [,<occ>]]):路径匹配,header的uri路径
hdr_len([<name> [,<occ>]]):长度匹配,header的长度匹配
hdr_reg([<name> [,<occ>]]):正则表达式匹配,自定义表达式(regex)模糊匹配
hdr_sub([<name> [,<occ>]]):子串匹配,header中的uri模糊匹配
dst 目标IP
dst_port 目标PORT
src 源IP
src_port 源PORT
url_param():用于检查请求 URL 中的参数值
req_ 和 res_ 前缀**:用于检查请求和响应中的其他属性,例如 Cookies、HTTP 方法等。
ssl_fc:用于检查请求是否使用 SSL/TLS 加密。

示例
# 检查 User-Agent 请求头是否包含 "Mozilla"
acl is_mozilla hdr(User-Agent) -i Mozilla
# 检查 Host 请求头是否以 "example.com" 结束
acl is_example hdr_end(Host) -i example.com
# 检查请求是否使用 HTTPS 加密
acl is_https ssl_fc
# 检查请求的 HTTP 方法是否为 POST
acl is_post_method req.method POST
# 检查请求的来源 IP 地址是否在指定的 IP 段内
acl is_internal src 192.168.0.0/16
# 检查请求 URL 中的参数 "id" 是否等于 "123"
acl is_id_123 url_param(id) eq 123
# 检查请求的来源端口是否为 8080
acl is_src_port_8080 src_port 8080
# 检查请求的目标端口是否为 443
acl is_dst_port_443 dst_port 443
path_beg 请求的URL开头,如/static、/images、/img、/css
path_end 请求的URL中资源的结尾,如 .gif .png .css .js .jpg .jpe
flags
-i 不区分大小写
-m 使用指定的pattern匹配方法
-n 不做DNS解析
-u 禁止acl重名,否则多个同名ACL匹配或关系
-f:从文件中读取条件,比如黑名单或白名单
operator
整数比较:eq、ge、gt、le、lt
字符比较:
- exact match (-m str) :字符串必须完全匹配模式
- substring match (-m sub) :在提取的字符串中查找模式,如果其中任何一个被发现,ACL将匹配
- prefix match (-m beg) :在提取的字符串首部中查找模式,如果其中任何一个被发现,ACL将匹配
- suffix match (-m end) :将模式与提取字符串的尾部进行比较,如果其中任何一个匹配,则ACL进行匹配
- subdir match (-m dir) :查看提取出来的用斜线分隔(“/”)的字符串,如果其中任何一个匹配,则ACL进行
匹配
- domain match (-m dom) :查找提取的用点(“.”)分隔字符串,如果其中任何一个匹配,则ACL进行匹配
value
- Boolean #布尔值
- integer or integer range #整数或整数范围,比如用于匹配端口范围
- IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24
- string--> www.lgw.com
exact –精确比较
substring—子串
suffix-后缀比较
prefix-前缀比较
subdir-路径, /wp-includes/js/jquery/jquery.js
domain-域名,www.lgw.com
- regular expression #正则表达式
- hex block #16进制

ACL调用方式

在 HAProxy 中,可以通过以下方式来使用 ACL(Access Control List):

- 与:隐式(默认)使用
- 或:使用“or” 或 “||”表示
- 否定:使用“!“ 表示
示例:
if valid_src valid_port #与关系,A和B都要满足为true
if invalid_src || invalid_port #或,A或者B满足一个为true
if ! invalid_src #非,取反,A和B哪个也不满足为true

用于条件判断:将 ACL 用于条件判断,例如在 use_backend 或 use-server 语句中,根据请求的特征选择后端服务器或服务器组

# 定义 ACL 条件
acl is_example_com hdr(host) -i example.com
acl is_secure_req ssl_fc

# 根据 ACL 条件选择后端服务器
use_backend backend_secure if is_secure_req
use_backend backend_example if is_example_com

用于拒绝请求:在 http-request 或 http-response 中使用 ACL 条件,以便在特定情况下拒绝或重定向请求。

# 定义 ACL 条件
acl is_banned_ip src 192.168.0.100

# 拒绝来自被禁止 IP 的请求
http-request deny if is_banned_ip

自定义日志

# 定义 ACL 条件
acl is_api_request path_beg /api/

# 自定义日志格式,根据 ACL 条件输出不同的信息
log-format "%ci - [%t] %r %ST %B %ts %ac %HM %HV %hrl %hsl %hcl %{+Q}r \"%[capture.req.method] %[capture.req.uri]\""

image.png image.pngimage.pngimage.png

预定义ACL

image.pngimage.png

自定义错误页面

错误页面

image.png image.png

http重定向

image.png

ssl实现

配置HAProxy支持https协议:
支持ssl会话;
bind *:443 ssl crt /PATH/TO/SOME_PEM_FILE
crt 后证书文件为PEM格式,且同时包含证书和所有私钥
cat demo.crt demo.key > demo.pem
把80端口的请求重向定443
bind *:80
redirect scheme https if !{ ssl_fc }
向后端传递用户请求的协议和端口(frontend或backend)
http_request set-header X-Forwarded-Port %[dst_port]
http_request add-header X-Forwared-Proto https if { ssl_fc }