HaProxy--ACL规则
访问控制列表(ACL,Access Control Lists)是一种基于包过滤的访问控制技术,它可以根据设定的条件对经过服务器传输的数据包进行过滤(条件匹配),即对接收到的报文进行匹配和过滤,
基于请求报文头部中的源地址、源端口、目标地址、目标端口、请求方法、URL、文件后缀等信息内容进行匹配并执行进一步操作,比如允许其通过或丢弃。
1) 通过设置的ACL 规则检查客户端请求是否合法。如果符合ACL 规则要求,那么就将放行,反正,如果不符合规则,则直接中断请求。
2) 符合ACL 规则要求的请求将被提交到后端的backend 服务器集群,进而实现基于ACL 规则的负载均衡。
HAProxy 中的ACL 规则经常使用在frontend 段中
1 | 一、ACL配置选项 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | acl <aclname> <criterion> [flags] [ operator ] [<value>] acl 名称 匹配规范 匹配模式 具体操作符 操作对象类型 ------------------------------------------------ ACL-Name 调用名称 acl Acl_Name hdr_dom(host) -i img.magedu.com #ACL名称,可以使用大字母A-Z、小写字母a-z、数字0-9、冒号:、点.、中横线和下划线,并且严格区分大小写,比如Image_site和image_site就是两个完全不同的acl ------------------------------------------------ ACL-criterion 定义ACL匹配规范,即:判断条件 hdr string ,提取在一个HTTP请求报文的首部 hdr([<name> [,<occ>]]) :完全匹配字符串,header的指定信息,<occ> 表示在多值中使用的值的出现次数 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模糊匹配 #示例: hdr(< string >) 用于测试请求头部首部指定内容 hdr_dom(host) 请求的host名称,如 www.magedu.com hdr_beg(host) 请求的host开头,如 www. img. video. download. ftp. hdr_end(host) 请求的host结尾,如 .com .net .cn #示例: acl bad_agent hdr_sub(User-Agent) -i curl wget block if bad_agent #有些功能是类似的,比如以下几个都是匹配用户请求报文中host的开头是不是www: 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. base : string #返回第一个主机头和请求的路径部分的连接,该请求从第一个斜杠开始,并在问号之前结束,对虚拟主机有用 <scheme>: //<user>:<password>@#<host>:<port>/<path>;<params>#?<query>#<frag> base : exact string match精确字符串匹配 base_beg : prefix match base_dir : subdir match base_dom : domain match base_end : suffix match base_len : length match base_reg : regex match base_sub : substring match path : string #提取请求的URL路径,该路径从第一个斜杠开始,并在问号之前结束(无主机部分) <scheme>: //<user>:<password>@<host>:<port>#/<path>;<params>#?<query>#<frag> path : exact string match精确字符串匹配 path_beg : prefix match #请求的URL开头,如/ static 、/images、/img、/css path_end : suffix match #请求的URL中资源的结尾,如 .gif .png .css .js .jpg .jpeg path_dom : domain match path_dir : subdir match path_len : length match path_reg : regex match path_sub : substring match #示例: path_beg -i /haproxy-status/ path_end .jpg .jpeg .png .gif path_reg ^/images.*\.jpeg$ path_sub image path_dir jpegs path_dom magedu url : string #提取请求中的URL。一个典型的应用是具有预取能力的缓存,以及需要从数据库聚合多个信息并将它们保存在缓存中的网页门户入口,推荐使用path url :表示提取请求的整个URL路径 url_beg : prefix match url_dir : subdir match url_dom : domain match url_end : suffix match url_len : length match url_reg : regex match url_sub : substring match #地址和端口 dst #目标IP dst_port #目标PORT src #源IP src_port #源PORT #示例: acl invalid_src src 10.0.0.100 192.168.1.0/24 acl invalid_port src_port 0:1023 #七层协议 acl valid_method method GET HEAD http-request deny if ! valid_method #其它 status: integer # 返回在响应报文中的状态码,根据返回的状态码进行匹配 ------------------------------------------------ ACL-flags ACL匹配模式 -i 不区分大小写 -m 使用指定的pattern匹配方法 -n 不做DNS解析 -u 禁止acl重名,否则多个同名ACL匹配或关系 ------------------------------------------------ ACL- operator ACL 操作符 1.整数比较:eq、ge、gt、le、lt 3.字符比较: - 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进行匹配 ------------------------------------------------ ACL-value value的类型 - Boolean #布尔值 - integer or integer range #整数或整数范围,比如用于匹配端口范围 - IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24 - string --> www.magedu.com exact–精确比较 substring—子串 suffix-后缀比较 prefix-前缀比较 subdir-路径, /wp-includes/js/jquery/jquery.js domain-域名,www.magedu.com - regular expression #正则表达式 - hex block #16进制 |
1 | 实例: |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 实例: [root@centos7 ~]#cat /etc/haproxy/conf.d/test.cfg frontend magedu_http_port bind 10.0.0.7:80 mode http balance roundrobin log global option httplog acl pc_domain hdr_dom(host) -i www.magedu.org acl mobile_domain hdr_dom(host) -i mobile.magedu.org use_backend pc_hosts if pc_domain use_backend mobile_hosts if mobile_domain default_backend pc_hosts backend mobile_hosts mode http server web1 10.0.0.17 check inter 2000 fall 3 rise 5 backend pc_hosts mode http server web2 10.0.0.27:80 check inter 2000 fall 3 rise 5 例子一:实现ssh的调度 先在ssh的配置文件更改ssh监听的ip的ip为非22端口,然后haproxy配置如下 listen ssh bind 172.18.50.63:22 balance leastconn acl invalid_src src 172.18.50. tcp-request connection reject if invalid_src mode tcp server sshsrv1 172.18.50.65:22 check server sshsrv2 172.18.50.75:22 check backup 测试 在172.18.50.61上测试,每次测试完成后,都要把172.18.50.63下/root/.ssh/known_hosts下的172.18.50.63的记录清理掉然后在重新ssh连接,否则调度中,有一台会因为mac不一致导致安全问题,调度成功了,但是连接不上。 ssh 172.18.50.63 例子二:实现mysql调度 实现只有主机172.18.50.61能够通过172.18.50.73这台机器调度到后端的mysql,其他的机器都不能通过172.18.50.73调度连接 listenmysql mode tcp bind 172.18.50.73:3306 balance roundrobin acl valid_src src 172.18.50.61 tcp-request connection reject unless valid_src server mysqlsrv1 172.18.50.65:3306 check server mysqlsrv2172.18.50.75:3306 check 登陆数据库 mysql -uwpadmin -pPass123456 -h 172.18.50.73 登陆数据库后,如果用system可以调用本机的linux命令,但是查看的是本机的相关信息,如system hostname 查看的是本机的计算机名,通过查看变量名在mysql里查看远程的连接计算机名 show variables like 'hostname' ; 例子三:基于ACL 实现wordpress动静分离 注意,因为应用wordpress在调用php脚本时,需要用到其他资源,所以default_backend要设置在处理wordpress 里php文件的服务器组中,如以下的dynamicblog专门用来处理php文件,所以将default_backend设置为dynamicblog这一组服务器。 frontend http bind *:80 acl url_dyn path_end -i.php acl url_stac path_end-i .jpg .gif .png .css .js .html .txt default_backenddynamicblog if url_dyn use_backend staticblog if url_stac reqadd sunny-x-via:\ haproxy7c rspdel Server rspadd Server:\ Sunny-proxy7c option forwardfor header sunny-x-client backend staticblog balance roundrobin cookie WEBSRV insertnocache server web6e 172.18.50.65:80 check weight 1 inter 3000 rise 2 fall 2 cookie cksrv1 backend dynamicblog balance roundrobin cookie WEBSRV insertnocache server web6e 172.18.50.75:80 check weight 1 inter 3000 rise 2 fall 2 cookie cksrv2 listen stats bind :9091 stats enable stats auth admin:admin stats admin if TRUE 其它实例总结 域名匹配: acl web_host hdr_dom(host) www.magedu.net use_backend magedu_host if web_host ACL示例-基于源IP或子网调度访问 acl ip_range_test src 172.18.0.0/16 192.168.7.103 use_backend magedu_host if ip_range_test ACL示例-拒绝指定IP或者IP范围访问 acl block_test src 192.168.7.103 192.168.0.0/24 block if block_test #拒绝 ACL示例-匹配客户端浏览器,将不同类型的浏览器调动至不同的服务器组 acl redirect_test hdr(User-Agent) -m sub -i "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko" redirect prefix http: //192.168.7.103 if redirect_test #重写向到新地址上 acl acl_user_agent hdr_sub(User-Agent) -i curl wget #请求方法 redirect prefix http: //10.0.0.8 if acl_user_agent #301临时重定向至新URL acl acl_user_agent_ab hdr_sub(User-Agent) -i ApacheBench http-request deny if acl_user_agent_ab #请求拒绝 ACL示例-基于文件后缀名实现动静分离 acl php_server path_end -i .php use_backend php_server_host if php_server acl image_server path_end -i .jpg .png .jpeg .gif use_backend image_server_host if image_server ACL示例-匹配访问路径实现动静分离: acl static_path path_beg -i / static /images /javascript use_backend static_path_host if static_path ACL示例-基于ACL的HTTP访问控制 acl static_path path_beg -i / static /images /javascript use_backend static_path_host if static_path ACL示例- http-request deny if METH_TRACE HTTP_1.1 #引用预定义的ACL,与关系 命令测试:curl -I -XTRACE 10.0.0.7/ static /test.html 命令测试:curl -I -0 -XTRACE 10.0.0.7/ static /test.html ACL示例-四层访问控制 acl invalid_src src 192.168.1.0/24 10.0.0.8 tcp-request connection reject if invalid_src #四层ACL控制 #七层协议 acl valid_method method GET HEAD http-request deny if ! valid_method #非 GET HEAD拒绝请求。 |
1 | 二、ACL调用方式: |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | - 与:隐式(默认)使用 - 或:使用“or” 或 “||”表示 - 否定:使用“!“ 表示 示例: if valid_src valid_port #与关系,A和B都要满足为 true if invalid_src || invalid_port #或,A或者B满足一个为 true if ! invalid_src #非,取反,A和B哪个也不满足为 true use_backend配置调用 use_backend <backend>[{ if | unless} <condition>] #当 if /unless一个基于ACL的条件匹配时切换指定backend。 以下例子实现动静分离,当访问php文件的时候,就往dynhost这组backend调度,其他资源默认都发到websrv这组backend。 acl dynhost path_end .php acl p_w_picpathhost hdr(host) www.sunny.com use_backend p_w_picpath if dynhost default_backend websrv block { if | unless }<condition> #阻止7层请求 if /unless一个条件匹配 acl invalid_src src172.16.200.2 block if invalid_src http-request配置 #对7层请求的访问控制,主要指http-request http-request {allow | deny |add-header <name> <fmt> | set -header <name><fmt> } [ { if | unless } <condition>] #根据第4层条件对传入连接执行操作 tcp-request connection {accept|reject} [{ if | unless} <condition>] 注意协议和模式的匹配,默认为HTTP协议,haproxy一般用来调度http,如果非http协议就用mode来单独定义,如mode tcp,不过生产中,mysql一般用专业调度数据库的工具来调度 |
三、系统预定义的ACL,可以直接使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | ACL名称: ACL等价配置; ACL用法说明 TRUE: always_true; 总是匹配 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; 匹配已存在内容长度 HTTP_URL_ABS: url_reg ^[^/:]*: //; 匹配URL绝对路径 HTTP_URL_SLASH:url_beg /; 匹配URL相对路径 HTTP_URL_STAR: url *; 匹配URL 等于 "*" LOCALHOST: src 127.0.0.1/8; 匹配从localhost来的连接 METH_CONNECT: method CONNECT; 匹配HTTP CONNECT方法 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_TRACE: method TRACE; 匹配 HTTP TRACE方法 RDP_COOKIE: req_rdp_cookie_cntgt 0; 匹配RDPcookie的存在 REQ_CONTENT: req_len gt 0; 匹配请求缓冲区中的数据 WAIT_END: wait_end; 等待内容分析的结束 ----------------------------------- 例子: [root@centos6 ~]#curl -I -XTRACE 10.0.0.7/ static /test.html HTTP/1.1 200 OK date: Sat, 04 Apr 2020 02:04:01 GMT server: Apache/2.4.6 (CentOS) PHP/5.4.16 transfer-encoding: chunked content-type: message/http [root@centos7 ~]#cat /etc/haproxy/conf.d/test.cfg frontend magedu_http_port bind 10.0.0.7:80 mode http balance roundrobin log global option httplog ###################### acl setting ############################### acl acl_static_path path_beg -i / static /images /javascript ###################### acl hosts ################################# use_backend static_path_hosts http-request deny if METH_TRACE HTTP_1.1 #引用预定义的ACL,与关系 default_backend pc_hosts ################### backend hosts ################################ backend static_path_hosts mode http server web1 10.0.0.17 check inter 2000 fall 3 rise 5 backend mobile_hosts mode http server web1 10.0.0.17 check inter 2000 fall 3 rise 5 backend pc_hosts mode http server web2 10.0.0.27:80 check inter 2000 fall 3 rise 5 [root@centos6 ~]#curl -I -XTRACE 10.0.0.7/ static /test.html HTTP/1.1 403 Forbidden content-length: 93 cache-control: no-cache content-type: text/html connection: close [root@centos6 ~]#curl -I -0 -XTRACE 10.0.0.7/ static /test.html HTTP/1.1 200 OK date: Sat, 04 Apr 2020 02:10:13 GMT server: Apache/2.4.6 (CentOS) PHP/5.4.16 content-type: message/http connection: close #查看日志,观察协议版本 [root@centos17 ~]#tail / var /log/httpd/access_log 10.0.0.7 - - [04/Apr/2020:10:11:41 +0800] "TRACE /static/test.html HTTP/1.0" 200 230 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.27.1 zlib/1.2.3 libidn/1.18 libssh2/1.4.2" [root@centos6 ~]#curl -i 10.0.0.7/ static /test.html HTTP/1.1 200 OK date: Sat, 04 Apr 2020 02:07:58 GMT server: Apache/2.4.6 (CentOS) PHP/5.4.16 last-modified: Sat, 04 Apr 2020 01:27:45 GMT etag: "a-5a26cf0ed4913" accept-ranges: bytes content-length: 10 content-type: text/html; charset=UTF-8 10.0.0.17 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)