haproxy高级配置及案例
1、基于cookie的会话保持
cookie value :为当前 server 指定 cookie 值,实现基于 cookie 的会话黏性,相对于基于 source 地址 hash 调度算法对客户端的粒度更精准,但同时也加大了haproxy 负载,目前此模式使用较少, 已经被 session 共享服务器代替
cookie会话保持明显不支持 tcp mode ,使用 http mode
配置选项
cookie name [ rewrite | insert | prefix ][ indirect ] [ nocache ][ postonly ] [
preserve ][ httponly ] [ secure ][ domain ]* [ maxidle <idle> ][ maxlife ]
name : #cookie 的 key 名称,用于实现持久连接
insert : # 插入新的 cookie, 默认不插入 cookie
indirect : # 如果客户端已经有 cookie, 则不会再发送 cookie 信息
nocache: # 当 client 和 hapoxy 之间有缓存服务器(如: CDN )时,不允许中间缓存器缓存 cookie , #因为这会导致很多经过同一个 CDN 的请求都发送到同一台后端服务器
配置示例
haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
listen webserver_80
bind 172.25.254.100:80
option forwardfor
mode http
balance roundrobin
cookie WEBCOOKIE insert nocache indirect
server webserver1 192.168.0.10:80 cookie web1 weight 1 check inter 3s fall
3 rise 5
server webserver2 192.168.0.20:80 cookie web2 weight 1 check inter 3s fall
3 rise 5
.....
2、IP透传
P 透传(IP Transparency)指的是在代理服务器处理请求和响应的过程中,能够将客户端的真实 IP 地址传递到后端服务器,使得后端服务器能够获取到客户端的原始 IP 而不是代理服务器的 IP 地址。
在web服务器中需要记录客户端的真实IP地址,用于做访问统计、安全防护、行为分析、区域排行等场景。
IP透传分为四层和七层:tcp协议为四层,httpd协议为七层
2.1、四层代理
开启透传四层代理
[root@rs1 ~]# vim /etc/nginx/nginx.conf
。。。。。。
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request"'
' "$proxy_protocol_addr"'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
。。。内容省略。。。
server {
listen 80 proxy_protocol; #启用此项,将无法直接访问此网站,只能通过四层代理
访问
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
。。。。。。
}
}
修改haproxy
haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
listen webserver_80
bind 172.25.254.100:80
mode tcp
balance roundrobin
server webserver1 192.168.0.10:80 send-proxy weight 1 check inter 3s fall 3
rise 5
......
查看日志内容
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
192.168.0.10 - - [10/aug/2024:15:21:00 +0800] "GET / HTTP/1.1"200 18 "-"
"curl/7.29.0" "-"
192.168.0.10 - - [10/aug/2024:15:26:11 +0800] "GET / HTTP/1.1"200 18 "-"
"curl/7.29.0" "-"
192.168.0.10 - - [10/aug/2024:15:41:56 +0800] "GET / HTTP/1.1" "172.25.254.10"200
18 "-" "curl/7.29.0"
七层代理
修改haproxy
haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
listen webserver_80
option forwardfor
bind 172.25.254.100:80
mode http
balance roundrobin
server webserver1 192.168.0.10:80 send-proxy weight 1 check inter 3s fall 3
rise 5
server webserver1 192.168.0.20:80 weight 1 check inter 3s fall 3 rise 5
配置web服务日志格式
#nginx 日志格式:
$proxy_add_x_forwarded_for: #包括客户端IP和中间经过的所有代理的IP
$http_x_forwarded_For: #只有客户端IP
log_format main '"$proxy_add_x_forwarded_for" - $remote_user [$time_local]
"$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $http_x_forwarded_For';
查看日志
[root@rs1 ~]# tail -n 3 /var/log/nginx/access.log
"172.25.254.10, 192.168.0.10" 192.168.0.10 - - [10/aug/2024:16:15:00 +0800] "GET
/ HTTP/1.1"200 18 "-" "curl/7.29.0" "172.25.254.10"
[root@rs2 ~]# tail -n 3 /etc/httpd/logs/access_log
172.25.254.10 192.168.0.10 - - [11/aug/2024:00:15:00 +0800] "GET / HTTP/1.1" 200
27 "-" "curl/7.29.0"
HAProxy 中的 ACL(访问控制列表)详解
1. ACL 概述
1.1 基本概念
ACL(Access Control List)是 HAProxy 中用于实现基于请求报文的首部、响应报文的内容或其他环境状态信息来做出转发决策的一种机制。ACL 可以根据不同的条件来过滤流量,并据此执行特定的动作,如阻止请求、转发到特定的后端服务器等。
1.2 作用
- 智能路由:根据客户端请求的特性(如 IP 地址、请求方法、URL 等)将流量导向特定的后端服务器。
- 访问控制:限制或允许特定客户端的访问,提高系统的安全性。
- 负载均衡:根据服务器的负载情况和其他条件智能地分配请求。
- 故障恢复:在服务器出现故障时,可以自动将请求重新定向到健康的服务器。
2. ACL 配置
2.1 ACL 语法格式
ACL 的配置通常遵循以下格式:
acl <aclname> <criterion> [flags] [operator] <value>
- <calname>:定义 ACL 的名称,必须是唯一的,且只能包含字母、数字和连字符。
- [flags]:可选的标志位,例如
-i
表示忽略大小写。 - [operator]:可选的操作符,例如
eq
表示等于。 - <value>:定义测试条件的具体值。
2.2 ACL 示例
-
ACL-criterion 匹配规范
提取http报文首部
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中的dom(host) hdr_dir([<name> [,<occ>]]):路径匹配,header的uri路径 hdr_len([<name> [,<occ>]]):长度匹配,header的长度匹配 hdr_reg([<name> [,<occ>]]):正则表达式匹配,自定义表达式(regex)模糊匹配 hdr_sub([<name> [,<occ>]]):子串匹配,header中的uri模糊匹配 模糊匹配c 报文中a/b/c也会匹 配
首部指定内容
hdr(<string>) 用于测试请求头部首部指定内容 hdr_dom(host) 请求的host名称,如 www.zheng.org 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 http-request deny 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
ACL-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进行 匹配
ACL-value 操作对象
The ACL engine can match these types against patterns of the following types : - Boolean #布尔值 - integer or integer range #整数或整数范围,比如用于匹配端口范围 - IP address / network #IP地址或IP范围, 192.168.0.1 ,192.168.0.1/24 - string--> www.timinglee.org exact #精确比较 substring #子串 suffix #后缀比较 prefix #前缀比较 subdir #路径, /wp-includes/js/jquery/jquery.js domain #域名,www.timinglee.org - regular expression #正则表达式 - hex block #16进制
-
基于客户端 IP 地址:
acl ip100 src 192.168.1.100 acl ip100 src 192.168.1.100/24
-
基于请求的 URL:
acl api-uri path_beg /api acl api-uri path -i /api
-
基于 HTTP 方法:
acl get-method req.meth eq GET acl post-method req.meth eq POST
-
基于 HTTP 用户代理:
acl chrome-user-agent hdr(User-Agent) -i chrome
2.3 使用 ACL
一旦定义了 ACL,就可以在 HAProxy 的配置中使用它们来执行各种操作,例如:
-
转发到特定后端:
use_backend servers if api-uri
-
拒绝请求:
http-request deny if ip100
-
重定向:
http-request redirect code 302 if api-uri location /new-api-url
3. 实际应用场景
3.1 基于 IP 的访问控制
假设我们需要限制来自特定 IP 地址的访问,可以使用如下配置:
frontend http-in
bind *:80
mode http
default_backend servers
backend servers
balance roundrobin
server server1 192.168.0.10:80 check
server server2 192.168.0.20:80 check
acl block-ip src 192.168.0.100
http-request deny if block-ip
3.2 基于 URL 的路由
假设我们需要将所有以 /api/
开头的请求路由到一组专门处理 API 请求的后端服务器,可以使用如下配置:
frontend http-in
bind *:80
mode http
default_backend servers
backend servers
balance roundrobin
server server1 192.168.0.10:80 check
server server2 192.168.0.20:80 check
backend api-servers
balance roundrobin
server server3 192.168.0.11:80 check
server server4 192.168.0.21:80 check
acl api-uri path_beg /api
use_backend api-servers if api-uri
3.3 基于 HTTP 方法的重定向
假设我们需要将所有 POST 请求重定向到一个特定的 URL,可以使用如下配置:
frontend http-in
bind *:80
mode http
default_backend servers
backend servers
balance roundrobin
server server1 192.168.1.10:80 check
server server2 192.168.1.11:80 check
acl post-method req.meth eq POST
http-request redirect code 302 if post-method location /post-handler
3.4 匹配访问路径实现动静分离
假设我们需要将php与static静态界面的资源分别存放于指定的服务器,通过匹配访问路径访问动静态资源,可用以下配置:
frontend testacl
bind :80
mode http
########### ACL settings #######################
acl url_static path_end -i .jpg .png .css .js .html
acl url_static path_end -m sub /static /images /javascript
acl acl_app path_beg -m sub /api
########### host ###########################
use_backend static_host if url_static
use_backend api_host if acl_app
########### default server ###################
default_backend default_webserver
backend static_host
mode http
server web2 192.168.0.101:80 check weight 1 inter 3s fall 3 rise 5
backend api_host
mode http
server web1 192.168.0.102: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
创建相关文件
[root@rs1 ~]# mkdir /usr/share/nginx/html/static
[root@rs1 ~]# echo static 192.168.0.10 > /usr/share/nginx/html/static/index.html
[root@rs2 ~]# mkdir /var/www/html/php/
[root@rs2 ~]# vim /var/www/html/php/index.php
<?php
phpinfo();
?>
测试访问
自定义haproxy错误页面
配置示例
haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
defaults
mode http
......
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 1000000
errorfile 503 /haproxy/errorpages/503page.http
[root@haproxy ~]# mkdir /haproxy/errorpages/ -p
[root@haproxy ~]# cp /usr/share/haproxy/503.http /haproxy/errorpages/503page.http
[root@haproxy ~]# vim /haproxy/errorpages/503page.http
HTTP/1.0 503 Service Unavailable
Cache-Control: no-cache
Connection: close
Content-Type: text/html;charset=UTF-8
<html><body><h1>易如反掌易如反掌</h1>
</body></html
测试
haproxy四层负载
对于haproxy还存在除http外的tcp协议应用服务访问的应用场景,比如mysql
配置示例
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
listen mysql_port
bind :3306 #mysql服务使用的端口
mode tcp
balance leastconn
server mysql1 192.168.0.101:3306 check
server mysql2 192.168.0.102:3306 check #或者使用frontend和backend实现
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
......
frontend mysql_port
bind :3306
mode tcp
use_backend mysql_rs
backend mysql_rs
mode tcp
balance leastconn
server mysql1 192.168.0.101:3306 check
server mysql2 192.168.0.102:3306 check
[root@haproxy ~]# systemctl restart haproxy.service
在rs1,rs2安装mysql服务
yum install mariadb-server -y
vim /etc/my.cnf
[mysqld]
server-id=1