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)
  • 你的实验截图与命令输出(已整合到上文示例)
相关推荐
Leinwin2 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
2401_865382502 小时前
信息化项目运维与运营的区别
运维·运营·信息化项目·政务信息化
漠北的哈士奇3 小时前
VMware Workstation导入ova文件时出现闪退但是没有报错信息
运维·vmware·虚拟机·闪退·ova
如意.7593 小时前
【Linux开发工具实战】Git、GDB与CGDB从入门到精通
linux·运维·git
运维小欣3 小时前
智能体选型实战指南
运维·人工智能
yy55273 小时前
Nginx 性能优化与监控
运维·nginx·性能优化
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ4 小时前
Linux 查询某进程文件所在路径 命令
linux·运维·服务器
05大叔6 小时前
网络基础知识 域名,JSON格式,AI基础
运维·服务器·网络
安当加密6 小时前
无需改 PAM!轻量级 RADIUS + ASP身份认证系统 实现 Linux 登录双因子认证
linux·运维·服务器
dashizhi20156 小时前
服务器共享禁止保存到本地磁盘、共享文件禁止另存为本地磁盘、移动硬盘等
运维·网络·stm32·安全·电脑