我有一个基于云(Amazon AWS、Rackspace 等)的多租户 SaaS 应用程序,我需要支持多个不相关的租户域的 HTTPS 通信。
举个例子,假设我们的 SaaS 可以在以下位置使用:
https://foo.com
租户可以通过以下方式访问其特定于租户的 UI 和服务端点:
https://tenantA.foo.com
https://tenantB.foo.com
...
如今,使用一个通配符 SSL 证书就可以轻松支持这一点。
然而,使用我们的 SaaS,我们的租户可能希望直接向他们自己的用户。
这会导致一个问题:假设 John Smith 是 的现有客户tenantA
(并且不了解foo.com
)。如果 John Smith 被引导到https://tenantA.foo.com
,他们很容易感到困惑(例如“foo.com 到底是谁?我为什么在这里?我被黑客入侵了吗?啊啊!”)。
为了避免这个问题,我们的租户会设置一个子域名,如下:
https://foo.tenantA.com
这避免了许多最终用户的困惑:tenantA
用户可以看到他们认识的 URL,并且tenantA
会更乐意使用该应用程序。 但tenantA
希望我们托管有关该应用程序的所有内容,这意味着foo.com
的基础设施需要提供 SSL 连接。
为此,我们希望支持以下几点:
- 租户向我们上传了 SSL 证书和密钥
foo.tenantA.com
。 - 我们采用该 SSL 证书并将其动态安装到高可用性负载平衡集群(2 个或更多 LB 节点)中,该集群将请求负载平衡到我们的 SaaS 应用程序 Web 端点。
- 租户更新他们的 DNS 以将
foo.tenantA.com
其 CNAME 重定向至tenantA.foo.com
。
这样,我们的负载均衡器池将服务/终止所有 HTTPS 通信,foo.tenantA.com
并且所有请求都将负载平衡到我们的 SaaS Web 服务器集群。
这意味着 SSL 证书应该能够在 LB 池中添加和删除在运行时. 更改不能中断服务现有或新的 HTTPS 请求的能力。
此外,由于我们将使用 Linux 在虚拟化硬件(例如 EC2)上部署,因此我们无法访问硬件/数据中心。这必须是可以在 Linux 中运行的基于软件的解决方案。它还必须具有高可用性(2 个或更多 LB“节点”)。
有人知道具体的解决方案吗?例如,可以设置 Nginx、HAProxy 或 Squid(或其他任何东西)来支持这一点吗?是否有记录在案且合适的“配方”或现有解决方案?
PS:亚马逊的 Elastic Load Balancer(在撰写本文时)无法切实满足这一需求——它需要 Amazon ELB 来实现每个租户域。由于每个 ELB 都需要“ping” Web 服务器,如果您有 500 个租户,那么您将有 500 个 ELB ping SaaS Web 服务端点 - 这对性能的影响不容忽视。
答案1
更新2017-09-13:SNI 现在在主流浏览器中已经足够流行,它可能被用来处理请求,并且这个答案应该被认为是过时的。
支持此功能的唯一方法是为每个客户端分配一个 IP。当您通过 https 连接时,连接是加密的立即地,浏览器没有机会说“我来这里是为了 foo.tenantA.com”。因此,服务器知道应该使用哪个 SSL 证书来加密连接的唯一方法是基于连接所用的 IP。
现在这仍然是可能的,但这意味着您将需要大量 IP。我们实际上在工作中执行了这种设置。我们有 2 个主动/主动负载平衡器,一半 IP 在一个平衡器上,另一半在另一个平衡器上(总共约 500 个 IP)。然后我们在后端有几个 Web 服务器来接收所有连接。任何 Web 服务器都可能发生故障,负载平衡器将停止向其发送连接。或者负载平衡器本身可能发生故障,另一个将接收其所有 IP。
执行此操作的负载平衡软件是起搏器和董事(两者都是主流项目,无论您运行哪个发行版,都应该在其存储库中包含它们)。Linux 内核本身才是真正执行负载平衡的内核,软件只负责处理故障转移。
注意:对于负载平衡,ldirectord 有很多替代方案,例如保持活跃和确实存活了下来。但对于实际的负载平衡器故障转移软件,您应该使用 pacemaker。
基本指南:
答案2
那建议你的客户自己给它包上一层薄包装怎么样?就像这样:
- 最终用户发送请求至
https://api.tenantA.com
api.tenantA.com
只需将请求转发给https://tenanta.foo.com
- 然后以同样的方式过滤响应。
我猜测,只要这只是一个极端情况,它就应该可以正常工作。