CloudFront白标化:添加多根域名作为备用域名的替代方案咨询
实现CloudFront分发的白标化自定义域名配置方案
场景描述
已有通过CloudFront+S3托管的React单页应用,配置了备用域名app.mycompany.com并绑定us-east-1区域的ACM证书,运行正常。需实现白标化功能,允许客户使用自有自定义域名(如app.clientdomain.com)指向同一CloudFront分发访问应用,但CloudFront限制同一分发无法添加不同根域名的域名,报错提示:
Domain must share the root domain mycompany.com
当前额外配置:
- DNS由第三方服务商管理(仅DNS解析,无代理功能)
- 客户使用不同DNS服务商的自有域名
可行解决方案
方案一:多域名ACM证书+CloudFront备用域名配置
适合客户数量不多的官方标准方案:
- 申请包含客户域名的ACM证书
- 要求客户在其DNS服务商处,为目标域名(如
app.clientdomain.com)添加CNAME记录,指向你的CloudFront分发域名(格式类似dxxxxxx.cloudfront.net),用于ACM的域名验证。 - 在us-east-1区域的ACM中申请包含
app.mycompany.com及所有客户自定义域名的证书,等待验证通过。
- 要求客户在其DNS服务商处,为目标域名(如
- 更新CloudFront分发
- 进入CloudFront分发的“备用域名(CNAMEs)”设置,添加客户的自定义域名
app.clientdomain.com。 - 确保分发关联的ACM证书已包含该域名,保存配置后等待CloudFront部署完成(约10-15分钟)。
- 进入CloudFront分发的“备用域名(CNAMEs)”设置,添加客户的自定义域名
- 客户侧DNS配置
- 客户将其
app.clientdomain.com设置为CNAME记录,指向你的CloudFront分发域名;若第三方DNS支持,也可设置A/AAAA记录(但不推荐A记录,因CloudFront IP会动态变更)。
- 客户将其
方案二:CloudFront Functions/Lambda@Edge实现域名路由验证
适合客户数量较多、不想频繁修改CloudFront备用域名的场景:
- 客户DNS配置
- 客户将其自定义域名设置为CNAME记录,指向你的CloudFront分发域名。
- 创建CloudFront函数处理请求
- 编写函数在Viewer Request阶段验证请求的
Host头是否属于允许的客户域名列表,同时处理单页应用的路由回退逻辑:function handler(event) { const request = event.request; const host = request.headers.host.value; // 维护允许的客户域名列表 const allowedDomains = ["app.clientdomain.com", "app.anotherclient.com"]; if (allowedDomains.includes(host)) { // 非静态资源请求跳转至index.html,适配React单页路由 if (!request.uri.match(/\.[a-zA-Z0-9]+$/)) { request.uri = "/index.html"; } return request; } // 非法域名返回403 return { statusCode: 403, statusDescription: "Forbidden" }; } - 将函数关联到CloudFront分发的Viewer Request事件。
- 编写函数在Viewer Request阶段验证请求的
- 证书配置
- 需申请包含所有允许的客户域名的ACM证书,若客户域名无统一后缀,需逐一添加;若有统一后缀(如
*.clientdomain.com),可使用通配符证书。
- 需申请包含所有允许的客户域名的ACM证书,若客户域名无统一后缀,需逐一添加;若有统一后缀(如
方案三:反向代理层中转(Nginx/容器)
适合无法通过CloudFront直接配置的场景,通过中间代理层绕过根域名限制:
- 部署反向代理服务器
- 使用EC2或容器服务部署Nginx,配置反向代理指向你的CloudFront分发域名。
- 配置SSL证书
- 在代理服务器上安装包含所有客户自定义域名的SSL证书(可使用Let's Encrypt免费多域名证书)。
- 客户DNS配置
- 客户将其自定义域名设置为A记录,指向代理服务器的公网IP。
- Nginx核心配置示例
server { listen 443 ssl; server_name app.clientdomain.com app.anotherclient.com; ssl_certificate /etc/letsencrypt/live/your-domain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your-domain/privkey.pem; location / { proxy_pass https://dxxxxxx.cloudfront.net; proxy_set_header Host dxxxxxx.cloudfront.net; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
内容的提问来源于stack exchange,提问作者Bharat Rana
相关产品推荐
相关产品推荐

