我是 HAProxy 的新手,大部分部件都按预期工作。当前设置是:如果我将新站点添加到其中一个平衡(在 LB 之后)服务器,则证书由负载均衡器颁发和提供。所以 SSL Termination 可以正常使用常规 Let's Encrypt 证书,但是我正在使用的服务在此设置中存在限制:
如果我将新站点添加到平衡服务器并希望使用通配符*.wilddomain.com
证书,则它不是由负载平衡器颁发,而是由平衡服务器 (10.0.0.10) 颁发。由于 LE 验证是通过 DNS 完成的,因此通配符证书现在有效并且可以在平衡服务器上使用。
因此,现在我有一个负载均衡器,其中包含几个正确使用的“常规”LE 证书,以及一个保存通配符证书的服务器。
我的问题是:如何将 HAProxy 设置为仅针对特定域 (wilddomain.com) 传递通配符证书,同时通过 SSL 终止直接从 LB 提供所有其他证书。
我目前的配置是这样的:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
# An alternative list with additional directives can be obtained from
# https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
ssl-default-bind-ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE->
ssl-default-bind-options no-sslv3
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
# Default Let's Encrypt backend server used for renewals and requesting certificates
backend letsencrypt-backend
server letsencrypt 127.0.0.1:8888
# Load balancer settings
frontend load-balancer
bind *:80
bind *:443 ssl crt /etc/ssl/domain1.com/domain1.com.pem crt /etc/ssl/domain2.com/domain1.com.pem
redirect scheme https code 301 if !{ ssl_fc }
# See if its an letsencrypt request
acl letsencrypt-acl path_beg /.well-known/acme-challenge/
use_backend letsencrypt-backend if letsencrypt-acl
mode http
default_backend webservers
# Backend webservers (the attached servers to the load balancer)
backend webservers
balance roundrobin
option forwardfor
cookie SRVNAME insert
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
# Server www1
server www1 10.0.0.10:80 weight 1 check
# Server www2
server www2 10.0.0.11:80 weight 1 check
编辑我
通过将以下内容添加到上述配置中,我更进一步,但这会在 HAProxy 日志中产生“负载平衡器/2:SSL 握手失败”。
frontend wildcard_tcp
bind *:443
option tcplog
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl is_wilddomain req_ssl_sni -m end wilddomain.com
use_backend wildcard_server_tcp if is_wilddomain
backend wildcard_server_tcp
mode tcp
server ssl-wildcard-server 10.0.0.10:443
这是一个合适且正确的解决方案吗?还是有更好/性能更好的?是否有可能拥有一个仅负责 ssl-offload 的非常基本的后端服务器?那么仅用于颁发、更新和提供证书吗?
非常感谢!
tl;dr 这可以通过配置 TCP 代理侦听所有请求并使用SNI 扩展来完成:1) 调用 TCP 后端,将 ssl-offload 留给服务器,或 2) 调用 HAProxy 的 HTTP 前端来执行 ssl -卸载。
HAProxy 可以配置为在同一 IP/端口中的不同域使用不同的证书,因此在
bind
执行 TLS 握手时在同一行中。可以使用绑定行中的crt-list关键字微调此配置。但是,此类配置没有将 ssl-offload 传递到后端服务器的选项。HAProxy 前端应配置为执行 ssl-offload,或者应配置为
mode tcp
并将 ssl-offload 留给后端。为了在同一 IP/端口中实现混合本地和远程 ssl-offload,对于不同的域,应在 HAProxy 配置中添加另一个代理:
以下片段具有前端 TCP 代理和本地 ssl-offload 前端。请注意,这将消耗两倍的连接数,相应地调整全局 maxconn。