Ssl

如何在 HAProxy 負載平衡後水平擴展 SSL 終止?

  • April 5, 2013

我一直在環顧四周,似乎沒有人試圖以我的方式擴展 SSL 終止,我很好奇為什麼我的方法似乎如此不常見。

這是我想做的事情,然後是為什麼:

 10.0.1.1  10.0.1.2 - 10.0.1.5
-----+--------+----+----+----+
    |        |    |    |    |
 +--+--+   +-+-++-+-++-+-++-+-+
 | LB1 |   | A || B || C || D |
 +-----+   +---++---++---++---+
haproxy 1.5 haproxy 1.5 + tomcat
tcp mode    http mode

為什麼會有這種瘋狂的設置Internet -> HAProxy (tcp mode) -> HAProxy (http mode) -> Tomcat?簡而言之:安全性和可擴展性

通過將 SSL 終止解除安裝到執行 HAProxy 1.5 和 Tomcat 僅在環回介面上偵聽的 Web 後端 (AD),我可以保證從客戶端到伺服器的所有流量都已加密,不可能從網路本地以外的任何內容中嗅探後端。

此外,隨著 SSL 需求的增加,我可以簡單地在負載均衡器後面啟動新的(便宜的)後端伺服器。

最後,它消除了將證書保存在面向外部的 LB 上的要求,並通過這樣做增加了額外的安全性,因為受感染的 LB 上不會有任何 pem 或證書。

我的情況似乎與這個非常相似:為什麼沒有水平可擴展軟體負載平衡器平衡 ssl 的範例?但我沒有使用基於文件的會話,如果可能的話,我想避免通過 IP 進行平衡,因為客戶端可能來自 NAT 後面。

我已經嘗試按照配置文件中的 HAProxy 說明使用帶有 SSL ID 的棒表(http://cbonte.github.com/haproxy-dconv/configuration-1.5.html#4-stick%20store-response)但是這似乎沒有讓我的會話保持在一個後端伺服器上(重新載入顯示節點名稱在我所有後端伺服器之間反彈的 A/admin?stats 頁面)。

顯然,循環負載平衡正在工作,但粘性會話卻沒有。

這是我的 LB 配置的範例:

global
   log 127.0.0.1 local0 notice
   maxconn 200
   daemon
   user appserver
   group appserver
   stats socket /tmp/haproxy

defaults
   log     global
   mode    tcp
   timeout client  5000ms
   timeout connect 50000ms
   timeout server  50000ms

   option contstats

frontend frontend_http
   log global
   bind *:80
   default_backend backend_http_servers

frontend frontend_ssl
   log global
   bind *:443
   default_backend backend_servers

listen stats :8888
   mode http
   stats enable
   stats hide-version
   stats uri /

#################################################################################################
## NOTE: Anything below this section header will be generated by the bootstrapr process and may be 
##       re-generated at any time losing manual changes
#################################################################################################
##          BACKENDS
#################################################################################################
backend backend_http_servers
   mode tcp

   #option httpchk

   server webA:8081 webA:8081 check port 8081
   server webB:8081 webB:8081 check port 8081
   # This configuration is for HTTPS affinity from frontdoor to backend

   # Learn SSL session ID from both request and response and create affinity
   backend backend_servers
   mode tcp

   balance roundrobin
   option ssl-hello-chk
   #option httpchk

   # maximum SSL session ID length is 32 bytes
   stick-table type binary len 32 size 30k expire 30m

   acl clienthello req_ssl_hello_type 1
   acl serverhello rep_ssl_hello_type 2

   # use tcp content accepts to detects ssl client and server hello
   tcp-request inspect-delay 5s
   tcp-request content accept if clienthello

   # no timeout on response inspect delay by default
   tcp-response content accept if serverhello

   # SSL session ID (SSLID) may be present on a client or server hello
   # Its length is coded on 1 byte at offset 43 and its value starts
   # at offset 44
   # Match and learn on request if client hello
   stick on payload_lv(43,1) if clienthello

   # Learn on response if server hello
   stick store-response payload_lv(43,1) if serverhello

############################################
# HTTPS BACKENDS
############################################
   server webA:8443 webA:8443 check port 8443
   server webB:8443 webB:8443 check port 8443

我的 webA 後端配置範例如下所示:

global
   log 127.0.0.1 local0 info
   maxconn 200
   daemon

defaults
   log     global
   mode    http
   option  dontlognull
   option  forwardfor
   option  httplog
   option  httpchk # checks server using HTTP OPTIONS on / and marks down if not 2xx/3xx status
   retries 3
   option redispatch
   maxconn         200
   timeout client  5000
   timeout connect 50000
   timeout server  50000

frontend frontend_http
   log global

   # only allow connections if the backend server is alive
   monitor fail if { nbsrv(backend_application) eq 0 }

   reqadd X-Forwarded-Proto:\ http    # necessary for tomcat RemoteIPValve to report the correct client IP and port
   reqadd X-Forwarded-Protocol:\ http # necessary because who knows what's actually correct?
   reqadd X-Forwarded-Port:\ 80       # also here for safety
   bind *:8081
   default_backend backend_application

frontend frontend_ssl
   log global

   # only allow connections if the backend server is alive
   monitor fail if { nbsrv(backend_application) eq 0 }

   reqadd X-Forwarded-Proto:\ https    # necessary for tomcat RemoteIPValve to report the correct client IP and port
   reqadd X-Forwarded-Protocol:\ https # necessary because who knows what's actually correct?
   reqadd X-Forwarded-Port:\ 443       # also here for safety
   reqadd X-Forwarded-SSL:\ on         # also here for safety
   bind *:8443 ssl crt /path/to/default.pem crt /path/to/additional/certs crt /path/to/common/certs
   default_backend backend_application
#################################################################################################
#           Backends
#################################################################################################
backend backend_haproxy
   stats enable
   stats show-node
   stats uri    /haproxy
   acl acl_haproxy url_beg /haproxy
   redirect location /haproxy if !acl_haproxy

backend backend_application
   stats enable
   stats show-node
   stats uri  /haproxy
   option httpclose
   option forwardfor
   acl acl_haproxy url_beg /haproxy
   server 127.0.0.1:8080 127.0.0.1:8080 check port 8080

在此配置中,SSL(或非 SSL)連接以循環方式通過 LB 路由到後端之一。但是,當我重新載入頁面(發出新請求)時,很明顯我會移動到另一個後端,不管 SSL 與否。

我通過轉到https://LB/haproxy哪個是帶有節點名稱的後端統計頁面的 URL 來測試這一點(第一次顯示 webA,重新載入後顯示 webB,以此類推,每次後續重新載入)。將http://LB:8888顯示 LB 的統計數據並顯示我的後端一切正常。

當 SSL 在後端終止時,我需要更改哪些內容才能使會話堅持到一個後端?

編輯:問題:為什麼不跨後端伺服器反彈並將會話儲存在中央儲存(如 memcached)中?

*答:*因為遺留應用程序非常脆弱,並且在跨伺服器進行會話時會中斷。只要使用者停留在同一個後端,應用程序就會按預期工作。這最終會改變(重寫),但不會在短期內改變。

首先,這給您的網路伺服器增加了不必要的複雜性。

其次,在 LB 處終止 SSL 連接意味著您可以在客戶端使用 keepalive 進行連接,從而減少建立連接的複雜部分。此外,資源的最有效利用是將類似的工作負載分組。許多人將靜態和動態內容分開,LB 處的 SSL 意味著兩者可以通過同一連接來自不同的伺服器。

第三,SSL 通常以不同於您的 Web 應用程序所需的速率進行擴展。我認為缺少範例是由於單個 LB 對或循環 dns 對大多數人來說就足夠了。在我看來,您可能高估了 SSL 工作量。

另外,我不確定您對安全性的推理。除了網路伺服器已經在執行更多可能被利用的服務之外,如果 LB 中存在任何漏洞,那麼您也剛剛將它們引入您的網路伺服器!

引用自:https://serverfault.com/questions/496232