实验简介

实验一:自定义 HAProxy 错误界面

核心目标

实现业务故障时的 “兜底容灾”:先通过备用服务器(sorryserver)承接流量,若备用服务器也故障,则返回自定义错误页面(或重定向到指定网站),提升用户体验。

实验步骤与核心操作
  1. 配置 sorryserver(备用兜底服务器)
    • 在 HAProxy 主机(或独立主机)部署 Apache,修改监听端口为 8080,编写兜底页面(如 “李哥在,没意外”);
    • 在 HAProxy 配置中添加backup标识的备用服务器(192.168.0.100:8080),仅当所有主服务器宕机时启用;
    • 测试:关闭所有主 Web 服务器后,访问 HAProxy 会返回备用服务器的兜底内容。
  2. 自定义错误页面
    • 当主服务器 + 备用服务器均宕机时,HAProxy 默认返回 503 页面,因此创建自定义 503 错误页面文件(自定义文案 “什么动物生气最安静 大猩猩!!”);
    • 在 HAProxy 的defaults块中通过errorfile 503指定自定义 503 页面路径,重启后验证访问返回自定义内容;
  3. 错误页面重定向到外部网站
    • 替换errorfileerrorloc 503,指定重定向目标(如百度),实现故障时跳转到外部网站。
关键价值

避免故障时返回默认生硬的错误页面,通过 “备用服务器 + 自定义错误页 / 重定向” 多层兜底,提升业务可用性和用户体验。

实验二:HAProxy ACL 访问控制

核心目标

基于 HAProxy 的 ACL(访问控制列表)功能,实现精细化的流量路由和访问权限管控。

实验步骤与核心操作
  1. 基础环境准备
    • 配置本地域名解析(如www.timinglee.orgbbs.timinglee.orgwww.lee.com等指向 HAProxy 服务器);
    • 配置 HAProxy 基础负载均衡,区分两个后端 Web 服务器(192.168.0.10/20)。
  2. ACL 精细化路由示例
    • 域名后缀匹配:匹配.com结尾的域名,路由到 web1;其他域名路由到 web2;
    • 域名前缀匹配:匹配bbs.开头的域名,路由到 web1;
    • 访问路径匹配:匹配/lee路径,路由到 web1;其他路径路由到 web2;
  3. ACL 访问权限管控
    • 黑名单:配置 ACL 匹配指定 IP(172.25.254.1),通过http-request deny拒绝该 IP 访问(返回 403);
    • 白名单:反向匹配 ACL,仅允许指定 IP 访问,拒绝其他所有 IP(注意语法:! invalid_src表示 “非该 IP”)。
关键价值

实现 “按域名 / 路径 / IP” 的精细化流量调度和访问控制,满足业务多维度的路由、权限管控需求(如多域名分流、IP 黑白名单、路径级路由)。

实验三:HAProxy 全站加密

核心目标

实现 HTTP 请求自动重定向到 HTTPS,完成全站 HTTPS 加密,保障数据传输安全。

实验步骤与核心操作
  1. 制作自签名 SSL 证书
    • 创建证书存储目录,通过openssl生成 RSA 2048 位的私钥和自签名证书,填写国家、省份、域名等信息(适配www.timinglee.org);
    • 将私钥和证书合并为 HAProxy 支持的 PEM 格式文件,便于配置加载。
  2. 配置 HAProxy 全站加密
    • 配置frontend监听 80 端口,通过redirect scheme https if ! { ssl_fc }将所有非 HTTPS 请求强制重定向到 HTTPS;
    • 配置listen块监听 443 端口,启用 SSL 并加载上述 PEM 证书,同时配置后端 Web 服务器(192.168.0.10/20)做负载均衡;
  3. 测试验证
    • 通过curl -v -k -L访问 80 端口,可观察到 302 重定向到 443 端口,且完成 TLS 握手、SSL 连接建立,最终返回后端 Web 服务器内容,验证全站加密生效。
关键价值

解决 HTTP 明文传输的安全风险,实现业务流量的全链路加密,同时保留 HAProxy 的负载均衡能力。

自定义HAProxy 错误界面

sorryserver的设定

#在新主机中安装apache(可以用haproxy主机代替)
[root@haproxy yxs]# dnf install httpd -y
[root@haproxy yxs]# vim /etc/httpd/conf/httpd.conf
47 Listen 8080
[root@haproxy yxs]# systemctl enable --now httpd
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service → /usr/lib/systemd/system/httpd.service.
[root@haproxy yxs]# echo "yxs" > /var/www/html/index.html

#配置sorryserver上线
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
listen webcluster
    bind        *:80
    mode        tcp
    balance     roundrobin
    server haha 192.168.0.10:80  check inter 3s fall 3 rise 5 weight 1
    server hehe 192.168.0.20:80  check inter 3s fall 3 rise 5 weight 1
    server wuwu 192.168.0.100:8080  backup					#sorryserver
[root@haproxy yxs]# systemctl restart haproxy.service

#测试
[root@test yxs]# curl 172.25.254.100 curl 172.25.254.100
webserver1 - 192.168.0.10
[root@test yxs]# curl 172.25.254.100 curl 172.25.254.100
webserver2 - 192.168.0.20

#关闭两台正常的业务主机
[root@webserver1 yxs]# systemctl stop httpd
[root@webserver2 yxs]# systemctl stop httpd
[root@test yxs]# curl 172.25.254.100 curl 172.25.254.100
yxs

自定义错误页面

#出现的错误页面
[root@webserver1 yxs]# systemctl stop httpd
[root@webserver2 yxs]# systemctl stop httpd
[root@haproxy yxs]# systemctl stop httpd

#所有后端web服务都宕机
[root@test yxs]# curl 172.25.254.100
<html><body><h1>503 Service Unavailable</h1>
No server is available to handle this request.
</body></html>
[root@haproxy yxs]# vim /errorpage/html/503.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>
[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    errorfile 503           /errorpage/html/503.http			#error 页面
[root@haproxy yxs]# systemctl restart haproxy.service

#测试
[root@test yxs]# curl 172.25.254.100
<html><body><h1>什么动物生气最安静</h1>
大猩猩!!
</body></html>

重定向错误到指定网站

[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    errorloc 503            http://www.baidu.com			#error 页面
[root@haproxy yxs]# systemctl restart haproxy.service

Haproxy ACL访问控制

实验环境

#在浏览器或者curl主机中设定本地解析
在windows中设定解析

#在Linux中设定解析
[root@test yxs]# vim /etc/hosts
172.25.254.100  www.timinglee.org     bbs.timinglee.org    news.timinglee.org   login.timinglee.org  www.lee.org   www.lee.com

#测试
[root@test yxs]# ping bbs.timinglee.org
PING www.timinglee.org (172.25.254.100) 56(84) 比特的数据。
64 比特,来自 www.timinglee.org (172.25.254.100): icmp_seq=1 ttl=64 时间=0.441 毫秒
64 比特,来自 www.timinglee.org (172.25.254.100): icmp_seq=2 ttl=64 时间=0.309 毫秒
^Z
[5]+  已停止               ping bbs.timinglee.org

设定基础的haproxy实验配置

[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
frontend webcluster
    bind            *:80
    mode            http
    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
[root@haproxy yxs]# systemctl restart haproxy.service

基础acl示例

#在访问的网址中,所有以.com结尾的访问10,其他访问20
[root@haproxy yxs]# 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
[root@haproxy yxs]# systemctl restart haproxy.service

#测试
[root@test yxs]# curl www.lee.com
webserver1 - 192.168.0.10
[root@test yxs]# curl www.lee.org
webserver1 - 192.168.0.20

#基于访问头部
[root@haproxy yxs]# 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
[root@haproxy yxs]# systemctl restart haproxy.service

#测试
[root@test yxs]# curl www.timinglee.org
webserver1 - 192.168.0.10
[root@test yxs]# curl bbs.timinglee.org
webserver1 - 192.168.0.20

#base参数acl
[root@haproxy yxs]# 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@haproxy yxs]# systemctl restart httpd.service 
[root@webserver1 yxs]# mkdir -p /var/www/html/lee/
[root@webserver1 yxs]# mkdir -p /var/www/html/lee/test/
[root@webserver1 yxs]# echo lee - 192.168.0.10  > /var/www/html/lee/index.html
[root@webserver1 yxs]# echo lee/test - 192.168.0.10 > /var/www/html/lee/test/index.html
[root@webserver2 yxs]# mkdir -p /var/www/html/lee/
[root@webserver2 yxs]# mkdir -p /var/www/html/lee/test/
[root@webserver2 yxs]# echo lee - 192.168.0.20  > /var/www/html/lee/index.html
[root@webserver2 yxs]# echo lee/test - 192.168.0.10 > /var/www/html/lee/test/index.html
[root@webserver1 yxs]# systemctl restart httpd
[root@webserver2 yxs]# systemctl restart httpd

#测试
[root@test yxs]# curl 172.25.254.100/lee/
lee - 192.168.0.10
[root@test yxs]# curl 172.25.254.100/lee/test/
lee/test - 192.168.0.10
[root@test yxs]# curl 172.25.254.100/index.html
webserver1 - 192.168.0.20

#acl禁止列表黑名单
[root@haproxy yxs]# 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
[root@haproxy yxs]# systemctl restart httpd.service 

#测试
[root@test yxs]# curl 172.25.254.100
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>

#禁止列表白名单
[root@haproxy yxs]# 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
[root@haproxy yxs]# systemctl restart httpd.service 

#测试
[root@test yxs]# curl 172.25.254.100
webserver1 - 192.168.0.20
[root@haproxy yxs]# curl 172.25.254.100
<html><body><h1>403 Forbidden</h1>
Request forbidden by administrative rules.
</body></html>

Haproxy全站加密

制作证书

[root@haproxy yxs]# mkdir /etc/haproxy/certs/
[root@haproxy yxs]# openssl req -newkey rsa:2048 -nodes -sha256  -keyout /etc/haproxy/certs/timinglee.org.key -x509 -days 365 -out /etc/haproxy/certs/timinglee.org.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Shanxi
Locality Name (eg, city) [Default City]:Xi'an
Organization Name (eg, company) [Default Company Ltd]:timinglee
Organizational Unit Name (eg, section) []:linux
Common Name (eg, your name or your server's hostname) []:www.timinglee.org
Email Address []:admin@timinglee.org
[root@haproxy yxs]# ls /etc/haproxy/certs/
timinglee.org.crt  timinglee.org.key
[root@haproxy yxs]# cat /etc/haproxy/certs/timinglee.org.{key,crt} > /etc/haproxy/certs/timinglee.pem

全站加密

[root@haproxy yxs]# vim /etc/haproxy/haproxy.cfg
frontend webcluster-http
    bind        *:80
    redirect scheme https if ! { ssl_fc }

listen webcluster-https
    bind        *:443 ssl  crt /etc/haproxy/certs/timinglee.pem
    mode        http
    balance     roundrobin
    server haha 192.168.0.10:80  check inter 3s fall 3 rise 5 weight 1
    server hehe 192.168.0.20:80  check inter 3s fall 3 rise 5 weight 1
[root@haproxy yxs]# systemctl restart httpd.service 

#测试
[Administrator.DESKTOP-VJ307M3] ➤ curl -v -k -L http://172.25.254.100
*   Trying 172.25.254.100:80...
* TCP_NODELAY set
* Connected to 172.25.254.100 (172.25.254.100) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.25.254.100
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< content-length: 0
< location: https://172.25.254.100/					#转换信息体现
< cache-control: no-cache
<
* Connection #0 to host 172.25.254.100 left intact
* Issue another request to this URL: 'https://172.25.254.100/'
*   Trying 172.25.254.100:443...
* TCP_NODELAY set
* Connected to 172.25.254.100 (172.25.254.100) port 443 (#1)
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: C=CN; ST=Shaanxi; L=Xi'an; O=timinglee; OU=linux; CN=www.timinglee.org; emailAddress=admin@timinglee.org
*  start date: Jan 26 08:38:57 2026 GMT
*  expire date: Jan 26 08:38:57 2027 GMT
*  issuer: C=CN; ST=Shaanxi; L=Xi'an; O=timinglee; OU=linux; CN=www.timinglee.org; emailAddress=admin@timinglee.org
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET / HTTP/1.1
> Host: 172.25.254.100
> User-Agent: curl/7.65.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< date: Mon, 26 Jan 2026 08:48:34 GMT
< server: Apache/2.4.62 (Red Hat Enterprise Linux)
< last-modified: Fri, 23 Jan 2026 03:52:02 GMT
< etag: "1a-64906147d3d6a"
< accept-ranges: bytes
< content-length: 26
< content-type: text/html; charset=UTF-8
<
webserver2 - 192.168.0.20
* Connection #1 to host 172.25.254.100 left intact

更多推荐