我喜欢dtorgo提供的答案,并且他提到了TLS终止,这是许多关于自定义域的在线教程都没有涉及到的。
我将详细介绍如何为您的SaaS实现自定义域功能,同时处理TLS / HTTPS。
如果您的客户只是将CNAME指向您的域名或创建指向您的IP的A记录,并且您不处理这些自定义域的TLS终止,则您的应用程序将不支持HTTPS,而没有HTTPS,您的应用程序将无法在这些自定义域上的现代浏览器中运行。
您需要在Web服务器前设置一个TLS终止反向代理。此代理可以在单独的机器上运行,但也可以在与Web服务器相同的机器上运行。
CNAME vs A记录
如果您的客户想要在其子域上使用您的应用程序,例如app.customer.com
,他们可以创建一个CNAME app.customer.com
指向您的代理。
如果他们想要在他们的根域名下使用你的应用,例如 customer.com
,那么他们必须在 customer.com
上创建一个指向你代理 IP 的 A 记录。确保这个 IP 永远不会改变!
如何处理 TLS 终止?
为了使 TLS 终止工作,你需要为这些自定义域名发放 TLS 证书。你可以使用 Let's Encrypt 来完成。你的代理将看到传入请求的 Host
头,例如 app.customer1.com
或 customer2.com
等等,然后通过检查 SNI 来决定使用哪个 TLS 证书。
代理可以设置自动为这些自定义域名发放和更新证书。对于来自新自定义域名的第一个请求,代理将发现它没有适当的证书。它将向 Let's Encrypt 请求一个新的证书。Let's Encrypt 将首先发出一个挑战来查看你是否管理该域名,由于客户已经创建了一个 CNAME 或 A 记录指向你的代理,这告诉 Let's Encrypt 你确实管理该域名,并允许你为其发放证书。
为了自动发放和更新证书,我建议使用 Caddyserver、greenlock.js、OpenResty(Nginx)。
tl;dr 对于这里发生的事情;
Caddyserver 监听 443 和 80 端口,自动接收、发放和更新证书,并将流量代理到您的后端。
如何在我的后端中处理它
您的代理正在终止 TLS 并将请求代理到您的后端。但是,您的后端不知道请求背后的原始客户是谁。所以您需要告诉您的代理在代理请求时包含附加的标头来识别客户。只需添加 X-Serve-For: app.customer.com
或 X-Serve-For: customer2.com
或任何原始请求的 Host
标头。
现在当您在后端接收代理请求时,可以读取此自定义标头,从而知道请求背后的客户是谁。您可以基于此实现逻辑,显示属于该客户的数据等。
更多内容
在代理服务器群集前面放置负载均衡器以提高可用性。您还必须使用分布式存储来存储证书和 Let's Encrypt 挑战。使用 AWS ECS 或 EBS 实现自动恢复,以防出现故障,否则您可能会在半夜被叫醒手动重启机器或代理。
如果您需要更多细节,可以在 Twitter 上私信我 @dragocrnjac