Haproxy --- 全站加密(HTTPS,HTTP→HTTPS 重定向)

摘要:
- 在 HAProxy 上启用全站 HTTPS(HTTP 重定向到 HTTPS)
- 使用自签证书或 CA 签发证书(示例使用 openssl 生成自签)
- 合并 crt 与 key 为 PEM,供 HAProxy 读取
- 推荐的 TLS 强化配置、测试与运维注意点
一、先决条件
- 已安装并运行 HAProxy
- 有 root 或可访问 /etc/haproxy 的权限
- 如启用防火墙,确保 80/443 端口可达
- (可选)SELinux:确保证书文件可被 haproxy 读取
二、制作证书(自签示例)
示例把私钥与证书生成并合并为一个 PEM 文件供 HAProxy 使用。
生成私钥与自签证书:
bash
[root@haproxy ~]# mkdir /etc/haproxy/certs/
openssl req -newkey rsa:2048 -nodes -sha256 \
-keyout /etc/haproxy/certs/example.com.key \
-x509 -days 365 \
-out /etc/haproxy/certs/example.com.crt
说明:
-nodes:不对私钥加密(如果加密,haproxy 启动时会要求输入密码)-x509:直接生成自签证书-days:有效期
合并为 PEM(HAProxy 要求私钥在证书之前或同一文件中):
bash
[root@haproxy ~]# cat /etc/haproxy/certs/timinglee.org.{key,crt} > /etc/haproxy/certs/timinglee.pem
设置权限(仅 root 可读):
bash
chmod 600 /etc/haproxy/certs/example.com.key
chmod 600 /etc/haproxy/certs/example.com.pem
chown root:haproxy /etc/haproxy/certs/example.com.* # 若 haproxy 进程属于 haproxy 组
注意:
- 自签证书在浏览器或 curl 中会报不受信任;生产建议使用受信任 CA(例如 Let's Encrypt)。
三、HAProxy 配置示例(HTTP 重定向 + HTTPS 反向代理)
下面给出较为标准且包含安全绑定选项的示例。将其放置于 /etc/haproxy/haproxy.cfg 的合适位置(或包含进主配置)。
示例配置:
text
# HTTP -> HTTPS 重定向
[root@haproxy ~]# 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 ~]# systemctl restart haproxy.service
说明与建议:
ssl-default-bind-options、ssl-default-bind-ciphers:示例中禁用了过时协议(SSLv3/TLS1.0/TLS1.1)并指定了较强的密码套件。根据 HAProxy 版本和合规要求(如 PCI)调整。- 如果需要支持多个域名/证书,可把多个
.pem文件放到/etc/haproxy/certs/并在 bind 中使用crt /etc/haproxy/certs/(HAProxy 会基于 SNI 选择证书)。 - 若后端使用 HTTPS,可在
server行加ssl与verify选项(例如server web1 10.0.0.1:443 ssl verify none)。
四、检查配置并重启 HAProxy
先校验配置语法:
bash
haproxy -c -f /etc/haproxy/haproxy.cfg
重启(或平滑重载):
bash
systemctl restart haproxy.service
# 或平滑 reload(视 HAProxy 包支持而定)
systemctl reload haproxy.service
五、测试方法
- 使用 curl 测试 HTTP 重定向与 HTTPS:
bash
# 测试 HTTP 重定向到 HTTPS(显示重定向)
curl -v -L http://<VIP或域名>
# 若使用自签证书,验证 HTTPS 时可能需要 -k (insecure) curl -v -k -L http://172.25.254.100
curl -v -k https://<VIP或域名>/
-
用浏览器访问域名,检查证书信息(CN/SAN、颁发机构、有效期)。
-
验证 TLS 协议与密码套件,例如使用
openssl s_client:
bash
openssl s_client -connect example.com:443 -servername example.com
注意事项:
- 如果你通过 IP 访问(如 https://172.25.254.100),证书的 CN/SAN 必须包含该 IP,否则会出现主机名不匹配。
- 自签证书会报"不受信任",仅用于测试或内部使用。
六、生产环境建议与进阶
- 使用 Let's Encrypt 自动化签发与续期(certbot):
- 推荐用 certbot 的
certonly模式并通过 webroot 或 dns 插件来完成验证,然后把生���的 cert+privkey 合并为 HAProxy 所需的 PEM。 - 续期脚本示例(renewal hook)将新的 cert 合并并 reload haproxy。
- 推荐用 certbot 的
- 开启 OCSP stapling(HAProxy 支持 OCSP stapling 配置,需具体版本与证书链支持)。
- 禁用弱加密、启用 HTTP/2(HAProxy 支持 h2 if compiled with OpenSSL & proper options)。
- 监控:监控 HAProxy 状态页 / stats,监控证书到期(避免过期中断服务)。
- 日志与审计:确保日志记录 TLS 相关事件(握手失败、客户端协议等),并根据需要进行告警。
七、常见问题(FAQ)
-
Q: 为什么 curl 报自签证书错误?
A: 因为证书不是由受信任 CA 签发。生产请使用受信任 CA。
-
Q: 访问 IP 时证书为何不匹配?
A: 证书必须包含访问的主机名或 IP(在 SAN 中)。最佳做法是使用域名访问。
-
Q: 后端是否也需要 HTTPS?
A: 不一定。很多架构在前端(HAProxy)终止 TLS,然后用 HTTP 与后端通信;如果要求端到端加密,后端也应启用 HTTPS。
A: 证书必须包含访问的主机名或 IP(在 SAN 中)。最佳做法是使用域名访问。
-
Q: 后端是否也需要 HTTPS?
A: 不一定。很多架构在前端(HAProxy)终止 TLS,然后用 HTTP 与后端通信;如果要求端到端加密,后端也应启用 HTTPS。