Bri*_*onS 6 ssl scaling load-balancing haproxy
我一直在环顾四周,似乎没有人像我一样尝试扩展 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
Run Code Online (Sandbox Code Playgroud)
为什么这个疯狂的设置Internet -> HAProxy (tcp mode) -> HAProxy (http mode) -> Tomcat
?两个词:安全性和可扩展性
通过将 SSL 终端卸载到运行 HAProxy 1.5 的 Web 后端 (AD) 和仅在环回接口上侦听的 Tomcat,我可以保证从客户端到服务器的所有流量都经过加密,不可能从任何非本地网络嗅探到网络后端。
此外,随着 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
Run Code Online (Sandbox Code Playgroud)
我的 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
Run Code Online (Sandbox Code Playgroud)
在此配置中,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 工作负载。
我也不确定你关于安全的推理。除了网络服务器已经运行了更多可能被利用的服务这一事实之外,如果负载均衡器中存在任何漏洞,那么您也将它们引入了您的网络服务器!
归档时间: |
|
查看次数: |
9325 次 |
最近记录: |