13.6.2 证书管理与自动化更新

在HAProxy中进行SSL终止后,证书管理决定安全性与可维护性。本节提供证书生命周期管理的原理草图、目录组织、自动化更新脚本、无损加载流程、排错与练习。

原理与流程草图

文章图片

证书类型与适用场景
- 公有CA:公网服务必选,兼容性高。
- 内部CA:内网微服务通信,成本低且可控。
- 通配符/多域名:降低管理成本,但需控制使用权限。
- ECC/RSA:ECC性能好;兼容性优先可选择RSA。

证书目录与权限(示例)

# 创建证书目录并授权给haproxy用户
sudo mkdir -p /etc/haproxy/certs/example.com
sudo chown -R haproxy:haproxy /etc/haproxy/certs
sudo chmod 750 /etc/haproxy/certs

PEM合并与链完整性(可执行示例)

# 假设证书与私钥来源于ACME或CA
# server.crt: 服务器证书
# fullchain.crt: 服务器证书+中间证书链
# server.key: 私钥

cat /etc/ssl/example.com/server.crt \
    /etc/ssl/example.com/fullchain.crt \
    /etc/ssl/example.com/server.key \
    > /etc/haproxy/certs/example.com/example.com.pem

# 权限最小化,仅haproxy可读
sudo chown haproxy:haproxy /etc/haproxy/certs/example.com/example.com.pem
sudo chmod 640 /etc/haproxy/certs/example.com/example.com.pem

HAProxy引用证书(配置片段)

# /etc/haproxy/haproxy.cfg
frontend https_in
    bind *:443 ssl crt /etc/haproxy/certs/example.com/example.com.pem
    mode http
    default_backend web_pool

自动化更新与无损加载(示例脚本)

#!/usr/bin/env bash
# /usr/local/bin/renew_and_reload_haproxy.sh
set -euo pipefail

DOMAIN="example.com"
CERT_DIR="/etc/ssl/${DOMAIN}"
PEM_DST="/etc/haproxy/certs/${DOMAIN}/${DOMAIN}.pem"
TMP_PEM="/etc/haproxy/certs/${DOMAIN}/${DOMAIN}.pem.tmp"

# 1) 获取/更新证书(示例使用acme.sh,可替换为certbot)
# 假设acme.sh已安装并注册
/usr/local/bin/acme.sh --issue -d "${DOMAIN}" --standalone

# 2) 合并PEM并校验有效期
cat "${CERT_DIR}/server.crt" \
    "${CERT_DIR}/fullchain.crt" \
    "${CERT_DIR}/server.key" \
    > "${TMP_PEM}"

openssl x509 -in "${CERT_DIR}/server.crt" -noout -dates

# 3) 原子替换并设置权限
mv "${TMP_PEM}" "${PEM_DST}"
chown haproxy:haproxy "${PEM_DST}"
chmod 640 "${PEM_DST}"

# 4) 无损加载
systemctl reload haproxy

# 5) 验证证书生效
echo | openssl s_client -connect 127.0.0.1:443 -servername "${DOMAIN}" 2>/dev/null | openssl x509 -noout -subject -dates

命令解释
- acme.sh --issue:向CA申请/续期证书。
- openssl x509 -noout -dates:检查证书有效期,避免过期证书上线。
- mv:原子替换文件,降低并发读写风险。
- systemctl reload haproxy:无损加载配置与证书。
- openssl s_client:验证握手与证书链是否正确。

安装与依赖准备(示例)

# 安装openssl与acme.sh所需依赖
sudo yum -y install openssl curl
curl https://get.acme.sh | sh

# 安装haproxy(示例,按发行版调整)
sudo yum -y install haproxy

证书健康检查与监控(示例命令)

# 查看到期时间
openssl x509 -in /etc/ssl/example.com/server.crt -noout -enddate

# 提取剩余天数(可用于监控脚本)
END_DATE=$(openssl x509 -in /etc/ssl/example.com/server.crt -noout -enddate | cut -d= -f2)
echo "Cert expires at: $END_DATE"

常见问题排查(带命令)
1. 握手失败/证书链不完整

# 检查证书链输出是否包含中间证书
openssl s_client -connect example.com:443 -servername example.com -showcerts
  1. 更新未生效
# 确认reload成功及进程PID变化
systemctl status haproxy
ps -ef | grep haproxy
  1. 权限错误
# 确认haproxy用户可读
sudo -u haproxy cat /etc/haproxy/certs/example.com/example.com.pem >/dev/null

练习
1. 使用自签名证书生成并配置到HAProxy,完成本地HTTPS访问。
2. 编写脚本在证书到期前30天自动续期并reload。
3. 故意删掉中间证书后,使用openssl s_client观察错误并恢复。