我们的网络要求规定所有网络流量都必须加密。
网络配置如下:
------------
/-- https --> | server 1 |
/ ------------
|------------| |---------------|/ ------------
| Client | --- https --> | Load Balancer | ---- https --> | server 2 |
|------------| |---------------|\ ------------
\ ------------
\-- https --> | server 3 |
------------
并且必须通过客户端证书。
我有一个可以使用清晰的真实服务器进行负载平衡的配置:
<VirtualHost *:8666>
DocumentRoot "/usr/local/apache/ssl_html"
ServerName vmbigip1
ServerAdmin [email protected]
DirectoryIndex index.html
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
SSLEngine on
SSLProxyEngine On
SSLCertificateFile /usr/local/apache/conf/server.crt
SSLCertificateKeyFile /usr/local/apache/conf/server.key
<Proxy balancer://mycluster>
BalancerMember http://1.2.3.1:80
BalancerMember http://1.2.3.2:80
# technically we aren't blocking anyone, but could here
Order Deny,Allow
Deny from none
Allow from all
# Load Balancer Settings
# A simple Round Robin load balancer.
ProxySet lbmethod=byrequests
</Proxy>
# balancer-manager
# This tool is built into the mod_proxy_balancer module allows you
# to do simple mods to the balanced group via a gui web interface.
<Location /balancer-manager>
SetHandler balancer-manager
Order deny,allow
Allow from all
</Location>
ProxyRequests Off
ProxyPreserveHost On
# Point of Balance
# Allows you to explicitly name the location in the site to be
# balanced, here we will balance "/" or everything in the site.
ProxyPass /balancer-manager !
ProxyPass / balancer://mycluster/ stickysession=JSESSIONID
</VirtualHost>
我需要的是,我的负载均衡器中的服务器
BalancerMember https://1.2.3.1:443
BalancerMember https://1.2.3.2:443
但那不起作用。我收到 SSL 协商错误。
即使我确实让它工作了,我仍需要传递客户端证书。
任何帮助,将不胜感激。
答案1
你只需不能直接将客户端证书与将请求用户证书的后端节点一起使用,并且负载均衡器将“终止”来自最终用户的 SSL / TLS 连接。
使用客户端证书进行 SSL/TLS 握手需要客户端签署客户端和服务器之间交换的所有握手消息,这意味着客户端必须直接连接到实际请求客户端证书的 SSL/TLS 服务器。如果浏览器的 SSL/TLS 连接仅到达负载均衡器,则负载均衡器是后端节点的客户端。后端节点将看到不同的握手,这将失败。
有两种可能的方法可以解决这个问题:
使用基于 DNS 或 TCP 的负载均衡器(例如类似的东西
ipchains
):在这种情况下,来自浏览器的 SSL/TLS 连接将直接转到后端节点。可以直接进行客户端证书身份验证。让负载均衡器执行客户端证书身份验证,并将该信息简单地传达给后端节点。这要求后端节点信任负载均衡器已正确进行验证,但如果后端节点不能信任负载均衡器,则使用负载均衡器毫无意义。
mod_proxy_ajp
(或mod_jk
)可以将客户端证书作为 AJP 协议的一部分转发,但这主要用于 Java 容器,并且 AJP 流量未加密。如果您使用的是
mod_proxy_http
,则可以添加一个额外的标头,以便mod_header
通过 HTTP 标头传递证书,使用类似 的内容RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s
。我不记得确切的细节,但重要的是确保清除此标头,以便它永远不会来自客户端的浏览器(否则可能会伪造它)。无论您在后端节点上运行什么应用程序,都需要能够从该标头获取其身份验证信息(并相信它已经通过了负载平衡器的验证)。除了需要使用 来配置 Apache Httpd 上的常规客户端证书身份验证的
SSLVerifyClient
和指令之外,您还需要配置和将 Apache Httpd 配置为后端节点的 SSL/TLS 客户端(请参阅SSLCACertificateFile/Path
mod_ssl
SSLProxyCheckPeerCN on
SSLProxyCACertificateFile/Path
mod_proxy
文档,关于SSLProxy*
指令)。如果您希望后端服务器确保请求来自负载均衡器而不是其他客户端(可能建立直接连接),您可以让负载均衡器也使用客户端证书(使用
SSLProxyMachineCertificateFile
),以向后端服务器进行身份验证。请注意,这可能会使后端的身份验证系统变得不那么复杂:尽管他们获得的实际客户端证书身份验证是代理的身份验证(他们需要像往常一样进行验证),但就应用程序用户而言,这些服务器上的应用程序需要配置为使用基于标头的客户端证书。
答案2
您的 SSL 配置似乎不完整。对于需要客户端证书的情况,您需要添加
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile <your CA cert file>
看如何强制客户端使用证书进行身份验证了解详情。
不确定这是否是强制性的,但你还缺少SSL密码套件指令。如果这样做,你可以找出弱密码,并尽你所能对抗兽攻击:
SSLHonorCipherOrder On
SSLCipherSuite RC4-SHA:ALL:!ADH:!EXPORT:!LOW:!MD5:!SSLV2:!NULL
答案3
我想补充一下这个帖子,以防其他人遇到类似的问题。我遇到过这种设置问题,BigIP 前端 httpd 2.4 和 httpd ssl.conf 文件中的 SSLVerifyClient。
对我来说,它有时候有效,有时候无效,当我从 SoapUI 发出请求时,连接会间歇性终止,即使我的配置设置正确。
问题在于我们在 BigIP 中设置了基于 cookie 的会话持久性,这导致了此错误。一旦我们完全关闭会话持久性,它就会开始正常工作。
请注意,在我的例子中,BigIP 是路由第 4 层负载平衡,没有 TLS 卸载,只是标准循环负载平衡,并让 httpd 实例处理客户端证书验证。