13.6.1 SSL终止原理与部署模式

在HAProxy中,SSL终止指由HAProxy承担TLS握手与解密,将明文HTTP转发到后端,从而集中证书管理、降低后端CPU消耗并统一安全策略。其核心在于边界层完成加解密与连接复用,后端仅处理业务流量。终止后的链路需结合信任边界进行风险评估,必要时通过内网加密或双向认证补强。

原理草图(边界与加密责任划分):

文章图片

常见部署模式:
- 前端SSL终止:客户端到HAProxy为TLS,HAProxy到后端为HTTP。适用于内网可信、追求性能与简化配置的场景。
- 端到端加密(TLS透传/再加密):客户端到HAProxy为TLS,HAProxy到后端仍为TLS,可在HAProxy进行SNI分发与ACL控制。适用于合规要求或跨不可信网络的场景。
- 混合模式:关键路径后端启用TLS,其余走HTTP,按服务敏感度分级。

典型流量路径与职责边界:
- 客户端:完成TLS握手、证书校验、SNI指示目标站点。
- HAProxy:终止SSL、选择后端、执行ACL与限速、记录日志与审计。
- 后端服务:处理业务请求,可选再次加密或双向认证。

示例:生成测试证书并部署SSL终止(单证书)

# 1) 生成自签证书(测试)
sudo mkdir -p /etc/haproxy/certs
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/haproxy/certs/site.key \
  -out /etc/haproxy/certs/site.crt \
  -subj "/C=CN/ST=Beijing/L=Beijing/O=Ops/OU=IT/CN=www.example.com"

# 2) 合并证书与私钥为HAProxy需要的PEM
sudo cat /etc/haproxy/certs/site.crt /etc/haproxy/certs/site.key \
  | sudo tee /etc/haproxy/certs/site.pem > /dev/null

# 3) 权限最小化
sudo chmod 600 /etc/haproxy/certs/site.pem

示例:HAProxy配置(SSL终止+HTTP后端)

# /etc/haproxy/haproxy.cfg
global
    log /dev/log local0
    maxconn 20000
    tune.ssl.default-dh-param 2048

defaults
    mode http
    timeout connect 5s
    timeout client  30s
    timeout server  30s
    option httplog

frontend fe_https
    bind *:443 ssl crt /etc/haproxy/certs/site.pem
    http-request set-header X-Forwarded-Proto https
    default_backend be_app

backend be_app
    balance roundrobin
    server app1 10.0.0.11:8080 check
    server app2 10.0.0.12:8080 check

配置说明(关键命令解释):
- bind *:443 ssl crt ...:在443端口启用TLS并加载证书。
- X-Forwarded-Proto:告知后端原始协议,便于重定向与日志。
- check:启用健康检查,避免转发到故障节点。

示例:端到端加密(HAProxy再加密到后端)

# /etc/haproxy/haproxy.cfg
frontend fe_https
    bind *:443 ssl crt /etc/haproxy/certs/site.pem
    default_backend be_tls

backend be_tls
    balance leastconn
    server app1 10.0.0.21:8443 ssl verify none check
    server app2 10.0.0.22:8443 ssl verify none check

说明:ssl verify none 仅用于测试。生产环境应启用CA校验(详见“证书管理与自动化更新”小节)。

安装与启停(以systemd为例)

# 安装(不同发行版包名可能略有差异)
sudo apt-get install -y haproxy     # Debian/Ubuntu
# sudo yum install -y haproxy       # RHEL/CentOS

# 启动与查看状态
sudo systemctl enable --now haproxy
sudo systemctl status haproxy

验证与测试

# 1) 验证配置语法
sudo haproxy -c -f /etc/haproxy/haproxy.cfg

# 2) 使用curl验证TLS终止与后端转发
curl -k https://www.example.com/

# 3) 查看前端是否监听
ss -lntp | grep ':443'

常见故障排查

# 1) 证书格式错误(PEM缺少私钥)
# 现象:HAProxy启动失败
# 检查证书是否包含私钥
openssl pkey -in /etc/haproxy/certs/site.pem -noout

# 2) 后端连接失败
# 现象:503/504
# 检查健康检查状态
sudo journalctl -u haproxy | tail -n 50
# 或在配置中启用 stats 查看后端健康

# 3) TLS版本不兼容
# 现象:客户端握手失败
# 检查客户端支持的协议与密码套件
openssl s_client -connect www.example.com:443 -tls1_2

练习
1. 为两个域名配置SNI证书分发,验证不同域名返回不同证书(使用openssl s_client -servername)。
2. 将后端HTTP改为HTTPS并启用verify required,完成CA校验。
3. 配置http-request redirect scheme https,实现80端口到443的强制跳转并测试效果。