Haproxy ACL实战:精准分流与访问控制

Haproxy ACL 访问控制

本文整理 Haproxy 常见的 ACL(访问控制列表)示例与测试步骤,包含按域名、Host 前缀、URL 路径、IP 黑/白名单等场景的配置与测试方法。

目录

  • 简介
  • 实验环境准备(hosts)
  • 基础 HAProxy 配置
  • ACL 示例
    • 按域名后缀分流(.com)
    • 按 Host 前缀分流(bbs.)
    • 按路径分流(/lee)
    • 按源 IP 黑名单(deny)
    • 按源 IP 白名单(allow-only)
  • 测试命令与预期输出
  • 常见 ACL 表达式速查
  • 注意事项

简介

ACL(Access Control List)是 HAProxy 中非常常用的功能,用于基于请求的不同特征(Host、Header、Path、Source IP 等)做分流、拒绝或其它条件判断。通过 acl 定义条件,通过 use_backendhttp-request denyhttp-request redirect 等指令执行动作。


实验环境准备(在浏览器或 curl 的主机上做本地域名解析)

  • Windows:编辑 C:\Windows\System32\drivers\etc\hosts(文中有 gif 示例,示意本机做解析)
  • Linux:编辑 /etc/hosts

示例(Linux):

bash 复制代码
# 在 /etc/hosts 中添加测试域名解析
172.25.254.100  www.timinglee.org bbs.timinglee.org news.timinglee.org login.timinglee.org www.lee.org www.lee.com

测试:

bash 复制代码
ping bbs.timinglee.org

基础 HAProxy 配置

最小的前端 + 两个后端示例:

bash 复制代码
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
    bind *:80
    mode http
    # 默认将请求路由到 webserver-80-web1(下方会根据 ACL 修改)
    use_backend webserver-80-web1

backend webserver-80-web1
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

重载服务:

bash 复制代码
systemctl restart haproxy.service

ACL 示例

下面的示例都在 frontend webcluster 中定义 acl,并根据条件 use_backendhttp-request deny

1) 按域名后缀分流(以 .com 结尾走 web1,其他走 web2)

解释:hdr_end(host) 检查 Host 头是否以指定字符串结尾(忽略端口号)。

haproxy 复制代码
#在访问的网址中,所有以.com  结尾的访问10,其他访问20
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
    bind            *:80
    mode            http
    
    acl test hdr_end(host) -i .com			#acl列表
    
    use_backend  webserver-80-web1 if test	#acl列表访问匹配
    default_backend webserver-80-web2		#acl列表访问不匹配

backend webserver-80-web1
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

测试(客户端):

bash 复制代码
curl http://www.lee.com        # 期望返回 webserver1 (192.168.0.10)
curl http://www.lee.org        # 期望返回 webserver2 (192.168.0.20)

2) 按 Host 前缀分流(Host 以 bbs. 开头)

haproxy 复制代码
acl head hdr_beg(host) -i bbs.
    use_backend  webserver-80-web1 if head
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
    bind            *:80
    mode            http
    
    acl test hdr_end(host) -i .com			#acl列表
    
    acl head hdr_beg(host) -i bbs.
    use_backend  webserver-80-web1 if head
    default_backend webserver-80-web2

backend webserver-80-web1
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5

说明:hdr_beg(host) 检查 Host 头是否以某字符串开头。


3) 按路径分流(URL 路径以 /lee 开头)

说明:常用表达式有 path_beg(路径以开头匹配)、path(完整路径匹配)、path_reg(正则匹配)。示例使用 path_beg

haproxy 复制代码
frontend webcluster
    bind *:80
    mode http

    acl path_lee path_beg -i /lee
    use_backend webserver-80-web1 if path_lee
    default_backend webserver-80-web2

示例在后端 webserver 上准备页面:

bash 复制代码
# 在 web1 和 web2 上创建内容以便区分
mkdir -p /var/www/html/lee/test/
echo "lee - 192.168.0.10" > /var/www/html/lee/index.html    # web1
echo "lee/test - 192.168.0.10" > /var/www/html/lee/test/index.html
# web2 类似,内容写入 web2 的相应目录

测试:

bash 复制代码
curl http://172.25.254.100/lee/        # 期望 webserver1 的内容
curl http://172.25.254.100/lee/test/   # 期望 webserver1 的内容
curl http://172.25.254.100/index.html  # 期望 webserver2 的内容(没有 /lee 前缀)

4) 源 IP 黑名单(deny)

把特定源 IP 拒绝访问(返回 403):

haproxy 复制代码
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
    bind            *:80
    mode            http
    
    acl pathdir base_dir -i /lee
    use_backend  webserver-80-web1 if pathdir
    default_backend webserver-80-web2		#acl列表访问不匹配

backend webserver-80-web1
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5
    [root@webserver1+2 ~]# mkdir -p /var/www/html/lee/
[root@webserver1+2 ~]#  mkdir -p /var/www/html/lee/test/


[root@webserver1 ~]# echo lee - 192.168.0.10  > /var/www/html/lee/index.html
[root@webserver1 ~]# echo lee/test - 192.168.0.10 > /var/www/html/lee/test/index.html
[root@webserver2 ~]# echo lee - 192.168.0.20  > /var/www/html/lee/index.html
[root@webserver2 ~]# echo lee/test - 192.168.0.10 > /var/www/html/lee/test/index.html

测试(来自被列入黑名单的主机):

bash 复制代码
curl http://172.25.254.100
# 返回:
# <html><body><h1>403 Forbidden</h1>Request forbidden by administrative rules.</body></html>

5) 源 IP 白名单(只允许某些源,其他拒绝)

常见写法是"除非来自白名单,否则拒绝":

bash 复制代码
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
    bind            *:80
    mode            http
    
    acl test hdr_end(host) -i .com			#acl列表
    
    use_backend  webserver-80-web1 if test	#acl列表访问匹配
    default_backend webserver-80-web2		#acl列表访问不匹配

	acl invalid_src src 172.25.254.1
    http-request deny if ! invalid_src

backend webserver-80-web1
    server web1 192.168.0.10:80 check inter 3s fall 3 rise 5

backend webserver-80-web2
    server web2 192.168.0.20:80 check inter 3s fall 3 rise 5
    

说明:!allowed_src 表示不在白名单中的请求会被拒绝,白名单中的源可以继续访问。


测试命令与示例输出(摘录)

示例命令(在测试主机上):

bash 复制代码
# 按域名测试
curl www.lee.com     # 期望: webserver1 - 192.168.0.10
curl www.lee.org     # 期望: webserver2 - 192.168.0.20

# 按路径测试
curl 172.25.254.100/lee/
curl 172.25.254.100/lee/test/
curl 172.25.254.100/index.html

# 源 IP 被拒绝的测试
curl 172.25.254.100  # 若客户端 IP 在黑名单 => 403 Forbidden

(你的原始示例中已有交互输出,已在上文保留预期说明。)


常见 ACL 表达式速查

  • hdr(host) / hdr_end(host) / hdr_beg(host) / hdr_sub(host) : 匹配 Host 头或 Host 的某部分
  • hdr() / hdr_end() / hdr_beg() : 匹配任意指定 Header 的值
  • path_beg : URL path 以 prefix 开头
  • path_end : URL path 以 suffix 结尾(视 HAProxy 版本)
  • path_reg : 使用正则表达式匹配路径
  • src <ip|network> : 请求源地址
  • method : 请求方法(GET/POST 等)

ACL 名称可以任意起(如 host_dot_compath_lee),后续通过 if <aclname>unless <aclname> 使用。


注意事项与建议

  • 编辑完 /etc/haproxy/haproxy.cfg 后,重启或平滑重载 HAProxy:
    • systemctl restart haproxy.service
    • 或者更安全的平滑重载:systemctl reload haproxy.service(视系统支持)
  • ACL 的判断顺序会影响结果,复杂规则建议通过注释和有意义的 ACL 名称来管理。
  • 使用 http-request deny 会返回 403;如果想返回 404 或重定向,可使用 http-request redirecthttp-request deny deny_status 404(具体语法请参考你所用 HAProxy 版本文档)。
  • 不同 HAProxy 版本对某些匹配关键字(例如 path_endpath_dir 等)的支持可能不同,请以你当前安装的 HAProxy 版本文档为准。常用且兼容度高的写法:path_begpathhdr_*src
  • 在生产环境请谨慎测试 ACL 规则,避免因规则错误导致不必要的访问中断。

参考

  • 官方文档(根据所用版本参考对应章节:ACL & sample fetches)
    equest deny deny_status 404`(具体语法请参考你所用 HAProxy 版本文档)。
  • 不同 HAProxy 版本对某些匹配关键字(例如 path_endpath_dir 等)的支持可能不同,请以你当前安装的 HAProxy 版本文档为准。常用且兼容度高的写法:path_begpathhdr_*src
  • 在生产环境请谨慎测试 ACL 规则,避免因规则错误导致不必要的访问中断。

参考

  • 官方文档(根据所用版本参考对应章节:ACL & sample fetches)
  • 你的实验截图与命令输出(已整合到上文示例)
相关推荐
RockHopper20252 小时前
解读数字化生产运行系统的裁决机制
运维·系统架构·智能制造·isa-95·isa-88
guizhoumen2 小时前
2026年建站系统推荐及选项指南
大数据·运维·人工智能
yingdonglan2 小时前
鸿蒙跨端Flutter学习——GridView高级功能
linux·运维·windows
遇见火星3 小时前
在Linux中使用journalctl命令进行日志分析和管理详细教程
linux·运维·服务器·journalctl
xuefuhe3 小时前
RHEL9 yum install etcd Error: Unable to find a match: etcd
linux·运维·centos
我送炭你添花3 小时前
树莓派部署 GenieACS 作为终端TR-069 ACS(自动配置服务器)的详细规划方案
运维·服务器·网络协议
华农第一蒟蒻3 小时前
一次服务器CPU飙升的排查与解决
java·运维·服务器·spring boot·arthas
NGINX开源社区3 小时前
借助 Okta 和 NGINX Ingress Controller 实现 K8s OpenID Connect 身份验证
运维·nginx·kubernetes
郝亚军4 小时前
如何在windows11和Ubuntu linux之间互传文件
linux·运维·ubuntu