HAProxy:SSL 終止,特定域萬用字元 SSL 證書請求例外
我是 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 request) | wildcard server | O | | === *.wildcard.com ===> | | -|- ==> | mode | +-----------------+ / \ | tcp | (local socket) +-------------+ | | === others ===> | | +------+ | https front | | ssl-offload | | | +-------------+ | | (plain http request) | v +---------------+ | | | other servers | | | +---------------+
以下片段具有前端 TCP 代理和本地 ssl-offload 前端。請注意,這將消耗兩倍的連接數,相應地調整全域 maxconn。
defaults timeout server 1s timeout client 1s timeout connect 1s listen public mode tcp bind :443,:::443 tcp-request inspect-delay 5s tcp-request content accept if { req.ssl_hello_type 1 } acl wildcard req.ssl_sni wildcard.local acl wildcard req.ssl_sni -m end .wildcard.local use_backend passthrough if wildcard server local_offload unix@/var/run/local.sock send-proxy-v2 backend passthrough mode tcp server ssl 10.0.0.10:443 listen local_offload mode http bind unix@/var/run/local.sock ssl crt /var/haproxy/crt.pem accept-proxy server plain0 10.0.0.10:80 server plain1 10.0.0.11:80