> 技术文档 > HAPROXY-访问控制列表ACL

HAPROXY-访问控制列表ACL

本篇文章主要讲解haproxy中的acl如何灵活运用,实现一些在工作中很常用的功能。

ACL介绍

ACL是一种访问控制列表,用于控制资源访问的机制,广泛的被用于计算机系统,网络工程和安全等地方。本身是一组规则,用于定义哪些流量或者用户能够访问特定的资源,以及能执行的操作。

在Haproxy中ACL是一种基于规则的过滤机制,能够根据预设的条件对接收到的数据包进行精确匹配与过滤。它通过分析数据包的头部信息,包括但不限于源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等关键字段,判断数据包是否符合预设的访问规则。根据匹配结果,ACL可以执行相应的操作,例如允许数据包通过或直接丢弃,从而实现对网络流量的精细化管理和控制。这种机制广泛应用于网络安全设备(如防火墙、路由器)以及服务器端的流量管理场景中,有效保障了网络的安全性和稳定性。

我们在生产环境中常常将ACL与Haproxy结合实现下面的功能:

1.基于源地址的访问控制

2. 基于请求路径的动静分离

3. 基于正则表达式的访问控制

4. 基于文件后缀名的访问控制

5. 基于请求方法的访问控

6.灰度发布

配置和作用

Haproxy的配置文件为/etc/haproxy/haproxy.conf或者/etc/haproxy/conf.d/这个目录下面的conf结尾的文件。

ACL格式:acl                        [flags]        [operator]        []

其中criterion常用的有:

hdr string,提取在一个HTTP请求报文的首部

hdr:完全匹配字符串,header的指定信息, 表示在多值中使用的值的出 现次数

hdr_beg:前缀匹配,header中指定匹配内容的

hdr_end:后缀匹配,header中指定匹配内容

hdr_dom:域匹配,header中的domain

hdr_dir:路径匹配,header的uri路径

hdr_len:长度匹配,header的长度匹配

hdr_reg:正则表达式匹配,自定义表达式(regex)模糊匹配

hdr_sub:子串匹配,header中的uri模糊匹配 模糊匹配c 报文中a/b/c也会匹 配

也有path,path_beg,path_end,path_dir等都是提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分)

也有针对IP的匹配比如dst,dst_port,src,src_port

基于源地址的访问控制

顾名思义,主要是用来限制对敏感服务或内部资源的访问,只允许特定的 IP 地址或 IP 范围内的客户端访问,防止未经授权的外部访问。比如限制只有公司内部的IP地址在访问管理后台,防止外部网络的恶意攻击等

配置代码

frontend webcluster bind *:80 mode http acl allowed_ip src 192.168.1.0/24 http-request deny if !allowed_ip default_backend web_backend

由于acl是基于7层工作,所以mode这一行不能写tcp

配置格式:

acl src

http-request deny if #这里如果要禁止多个acl直接空一格接着写

基于请求路径的动静分离

动静分离,主要用于 优化Web的性能和资源管理,通过分析HTTP请求的路径URL,将静态资源(图片,CSS,JS等)和动态资源(比如PHP)分别转发到不同的后端服务器。

作用:通过将静态资源分离到高性能的静态文件服务器,可以减少对动态资源服务器的计算资源需求,降低运营成本。静态资源通常存储在低成本的存储设备上,而动态资源存储在高性能的服务器上,合理分配存储资源,提高资源利用效率。

配置示例:

frontend webcluster bind *:80 mode http # 定义ACL规则,匹配静态资源路径 acl is_static path_end -i .jpg .png .css .js .html .ico # 定义ACL规则,匹配动态资源路径 acl is_dynamic path_end -i .php .asp .jsp # 根据ACL规则转发请求 use_backend static_servers if is_static use_backend dynamic_servers if is_dynamic # 默认后端服务器(如果没有匹配上就走这个) default_backend dynamic_serversbackend static_servers balance roundrobin server static1 192.168.1.10:80 check server static2 192.168.1.11:80 checkbackend dynamic_servers balance roundrobin server dynamic1 192.168.1.20:80 check server dynamic2 192.168.1.21:80 check

基于正则表达式的访问控制

这个主要用于通过正则表达式匹配特定的 URL 路径,限制对敏感接口或管理后台的访问。也可以用来识别并拒绝包含恶意模式的请求,例如 SQL 注入、XSS 攻击等。

配置示例:

frontend webcluster bind *:80 mode http #域名后面/admin/以后任意的字符 acl is_admin_path path_reg ^/admin/.* #定义ACL规则,匹配恶意 SQL 注入模式 acl is_malicious_request hdr_reg(User-Agent) -i SELECT\\ \\*\\ FROM #拒绝恶意请求 http-request deny if is_malicious_request #拒绝非授权访问管理后台 http-request deny if is_admin_path !{ src 192.168.1.100 } default_backend web_backend#略。。

acl is_malicious_request hdr_reg(User-Agent) -i SELECT\\ \\*\\ FROM这一句中的-i表示不区分大小写,\\ \\*\\ 这里对空格和*进行转义,所以意思是对User-Agent字段进行匹配。

基于文件后缀名的访问控制

这个和上面的静态分离的原理一样,也可以用于基于文件后缀名的访问控制完全可以用于资源下载的分离,比如将 .iso,.zip,.7z 这些等需要下载的资源请求分离到专门的下载服务器或后端服务。这种分离方式可以优化资源管理,提高下载速度,并减轻主应用服务器的负载。

配置示例:

frontend webcluster bind *:80 mode http #匹配下载资源文件后缀名 acl is_download path_end -i .iso .zip .7z .rar .tar.gz #根据 ACL 规则转发请求 use_backend download_servers if is_downloadbackend download_servers mode http balance roundrobin server download1 192.168.1.30:80 check server download2 192.168.1.31:80 check

基于请求方法的访问控制

这种可以用来限制一些敏感的操作,比如限制一些方法的使用方舟子未经授权的操作,某些攻击可能通过特定的HTTP方法发起,通过限制这些方法增强安全性

frontend webcluster bind *:80 mode http acl is_delete method DELETE # 拒绝所有 DELETE 请求 http-request deny if is_delete

匹配浏览器类型

匹配客户端浏览器,将不同类型的浏览器调动至不同的服务器组

示例(拒绝curl和wget访问)

 frontend testacl bind :80 mode http acl user_agent_block hdr_sub(User-Agent) -i curl wget acl user_agent_redirect hdr_sub(User-Agent) -i Mozilla/5.0 http-request deny if user_agent_block is_post #这里表示如果是用Mozilla访问则将后缀给到百度 redirect prefix https://www.baidu.com if user_agent_redirect default_backend default_webserver backend ip_test-host mode http server web1 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5 backend default_webserver mode http server web1 172.25.254.10:80 check weight 1 inter 3s fall 3 rise 5

 上面针对于访问的curl和wget进行了拒绝,User-Agent 是 HTTP 请求头中的一个字段,用于标识客户端(如浏览器、爬虫、命令行工具等)的类型和版本。curlwget 在发起请求时会设置自己的 User-Agent,因此可以通过匹配 User-Agent 来识别这些工具发起的请求。

灰度发布

一种逐步将新版本应用程序发布给用户的方法,确保在完全发布前解决潜在问题。通过灰度发布,可以将流量分配到不同的服务器或服务实例,以实现负载均衡、故障隔离等。

配置示例:

frontend http-in bind *:80 mode http # 定义 ACL 规则,按比例分配流量 http-request set-var(txn.rand) rand(10) http-request use-backend gray_backend if { var(txn.rand) eq 1 } default_backend stable_backendbackend stable_backend mode http balance roundrobin server stable1 192.168.1.10:80 check server stable2 192.168.1.11:80 checkbackend gray_backend mode http balance roundrobin server gray1 192.168.1.20:80 check server gray2 192.168.1.21:80 check

rand(10) 生成一个 0 到 9 的随机数,并将其存储在变量 txn.rand 中,然后通过 if { var(txn.rand) eq 1 } 来判断是否满足条件

也可以后续通过socat对访问后端的权重进行调整,在配置文件中写入新的后端然后systemctl reload haproxy

global stats socket /var/run/haproxy.sock mode 660 level admin

通过socat动态调整权重值:

echo \"set weight gray_backend/server gray1 3\" | socat stdio unix-connect:/var/run/haproxy.sock

算法补充

静态算法

所谓静态算法,按照事先定义好的规则轮询公平调度,不关心后端服务器的当前负载、连接数和响应速度 等,且无法实时修改权重(只能为0和1,不支持其它值),只能靠重启HAProxy生效。

static-rr:等价于LVS的WRR算法,不支持socat进行动态权重的调整,不支持慢启动;

backend test balancer static_rr...

注:慢启动是指在服务器刚刚启动上不会把他所应该承担的访问压力全部给它,而是先给一部分,当没问题后在给一部分

first:当第一台服务访问的连接数量到达上限之后,新的请求才会分给其他服务器,忽略权重设置,不支持socat,根据backend的列表位置,自上而下进行调度

backend test balancer first...

动态算法

可以在haproxy启动时进行动态调整,无需重启,新请求会调度到当前负载比较低的服务器

roundrobin:算法支持权重的概念。权重决定了每个服务器在轮询中的“份额”。可以通过 HAProxy 的运行时 API 动态调整权重。比如:

# 设置 server1 的权重为 3echo \"set weight my_backend/server1 3\" | socat stdio unix-connect:/var/run/haproxy.sock

 leastconn:将请求分配给当前连接数最少的后端服务器。这种算法特别适合处理长连接或处理时间差异较大的请求,因为它可以动态地根据服务器的当前负载情况分配流量。算法也支持权重的概念。权重决定了每个服务器在负载均衡中的“份额”。

backend my_backend mode http balance leastconn

其他的算法

这些算法没有和hash-type进行结合的时候实际上是静态算法,也就是意味着它们不会根据当前的负载情况动态调整请求的分配,而是根据固定的规则(如客户端 IP、请求 URI 或 HTTP 头)进行分配。

haproxy的负载均衡算法分为两个层面:输入层和算法层

其中输入层:balance指定拿什么做hash运算,

比如balance source指的就是针对客户端的IP,进行hash运算将请求分配到特定的后端服务器。适用于需要会话保持的场景,例如用户在同一个客户端 IP 下的多次请求总是被分配到同一个后端服务器。

比如balance uri根据请求的 URI 进行哈希计算,将请求分配到特定的后端服务器。适用于需要根据请求的路径进行负载均衡的场景,例如将不同路径的请求分配到不同的后端服务。

比如balance hdr(Host)根据 HTTP 请求头中的 Host 字段进行哈希计算,将请求分配到特定的后端服务器。适用于需要根据域名进行负载均衡的场景,例如将不同域名的请求分配到不同的后端服务。

算法层:

hash-type map-based:配合上面的计算出的HASH,进行对后端服务器数量进行取模,以保证客户端访问的连接都是同一台服务器。但是当后端权重发生变化时,所有都会发生调度结果都会发生变化

hash-type consistent:为了降低后端服务器变化造成的影响,先针对所有IP产生一个IP Hash环,对于后端服务器的IP落在哪些个地方,根据balance source/url/hdr(host)产生的HASH落到距离最近的服务器的点进行连接。这样即使权重变化也是影响局部的

以上就是简单的提及了一下haproxy的acl访问控制和算法部分,具体使用参考官方文档:HAProxy Documentation Converter