Route53 + CloudFront 301 重定向方案
方案概述
使用 CloudFront Function 在边缘节点直接返回 301 重定向,无需源站。适用于任何域名重定向场景,包括:
- 根域名 → www 子域名(如
example.com→www.example.com) - 子域名 → 子域名(如
old.example.com→new.example.com) - 跨域名重定向(如
old-domain.com→new-domain.com)
关键要点
- 无需源站: CloudFront Function 在边缘直接返回 301,流量不会到达源站
- 成本低: 只有 CloudFront Function 调用费用($0.10/百万次请求)
- 延迟低: 在全球边缘节点执行,响应速度快
- SSL 必需: 自定义域名必须配置 ACM 证书(us-east-1 区域)
- 根域名支持: 完全支持根域名(apex domain)重定向
- SEO 友好: 301 永久重定向,搜索引擎会更新索引
架构流程
用户访问源域名
↓
Route53 解析到 CloudFront
↓
CloudFront Function 拦截请求(viewer-request)
↓
返回 301 重定向到目标域名
实施步骤
1. 创建 CloudFront Function
文件: redirect-function.js
function handler(event) {
return {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: 'https://<TARGET_DOMAIN>' } // 替换为目标域名
}
};
}
创建并发布:
# 创建 Function
aws cloudfront create-function \
--name <FUNCTION_NAME> \
--function-config '{"Comment": "Redirect <SOURCE_DOMAIN> to <TARGET_DOMAIN>", "Runtime": "cloudfront-js-2.0"}' \
--function-code fileb://redirect-function.js \
--region us-east-1 \
--profile <AWS_PROFILE>
# 发布 Function(使用返回的 ETag)
aws cloudfront publish-function \
--name <FUNCTION_NAME> \
--if-match <ETAG_FROM_CREATE> \
--region us-east-1 \
--profile <AWS_PROFILE>
2. 申请 SSL 证书
申请证书:
aws acm request-certificate \
--domain-name "<SOURCE_DOMAIN>" \
--validation-method DNS \
--subject-alternative-names "*.<SOURCE_DOMAIN>" \
--region us-east-1 \
--profile <AWS_PROFILE>
注意事项:
- CloudFront 的 ACM 证书必须在 us-east-1 区域
- 根域名重定向:申请
example.com+*.example.com - 子域名重定向:申请
*.example.com或单独的子域名证书
DNS 验证:
# 获取验证记录
aws acm describe-certificate \
--certificate-arn <CERTIFICATE_ARN> \
--region us-east-1 \
--profile <AWS_PROFILE> \
--query 'Certificate.DomainValidationOptions[0].ResourceRecord'
# 添加 CNAME 记录到 Route53
aws route53 change-resource-record-sets \
--hosted-zone-id <HOSTED_ZONE_ID> \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "<VALIDATION_NAME>",
"Type": "CNAME",
"TTL": 300,
"ResourceRecords": [{"Value": "<VALIDATION_VALUE>"}]
}
}]
}' \
--profile <AWS_PROFILE>
3. 创建 CloudFront 分配
配置文件: cloudfront-config.json
{
"CallerReference": "<UNIQUE_REFERENCE>",
"Aliases": {
"Quantity": 1,
"Items": ["<SOURCE_DOMAIN>"]
},
"Origins": {
"Quantity": 1,
"Items": [{
"Id": "dummy-origin",
"DomainName": "example.com",
"CustomOriginConfig": {
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginProtocolPolicy": "https-only"
}
}]
},
"DefaultCacheBehavior": {
"TargetOriginId": "dummy-origin",
"ViewerProtocolPolicy": "allow-all",
"AllowedMethods": {
"Quantity": 2,
"Items": ["GET", "HEAD"],
"CachedMethods": {
"Quantity": 2,
"Items": ["GET", "HEAD"]
}
},
"Compress": true,
"ForwardedValues": {
"QueryString": false,
"Cookies": {"Forward": "none"}
},
"MinTTL": 0,
"FunctionAssociations": {
"Quantity": 1,
"Items": [{
"FunctionARN": "<FUNCTION_ARN>",
"EventType": "viewer-request"
}]
}
},
"Comment": "Redirect <SOURCE_DOMAIN> to <TARGET_DOMAIN>",
"Enabled": true,
"ViewerCertificate": {
"ACMCertificateArn": "<CERTIFICATE_ARN>",
"SSLSupportMethod": "sni-only",
"MinimumProtocolVersion": "TLSv1.2_2021"
}
}
创建分配:
aws cloudfront create-distribution \
--distribution-config file://cloudfront-config.json \
--region us-east-1 \
--profile <AWS_PROFILE>
4. 配置 Route53 记录
aws route53 change-resource-record-sets \
--hosted-zone-id <HOSTED_ZONE_ID> \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "<SOURCE_DOMAIN>",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": "<CLOUDFRONT_DOMAIN>",
"EvaluateTargetHealth": false
}
}
}]
}' \
--region us-east-1 \
--profile <AWS_PROFILE>
注意: Z2FDTNDATAQYW2 是 CloudFront 的固定托管区域 ID(全球通用)
验证测试
检查 CloudFront 部署状态
aws cloudfront get-distribution \
--id <DISTRIBUTION_ID> \
--profile <AWS_PROFILE> \
--region us-east-1 \
--query 'Distribution.Status' \
--output text
测试重定向
# 测试 HTTP 请求
curl -I http://<SOURCE_DOMAIN>
# 测试 HTTPS 请求
curl -I https://<SOURCE_DOMAIN>
# 预期输出
HTTP/1.1 301 Moved Permanently
Location: https://<TARGET_DOMAIN>
X-Cache: FunctionGeneratedResponse from cloudfront
常见应用场景
场景 1: 根域名重定向到 www(推荐)
// example.com → www.example.com
function handler(event) {
return {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: 'https://www.example.com' }
}
};
}
配置要点:
- 证书:
example.com+*.example.com - CloudFront Alias:
example.com - Route53 A 记录:
example.com→ CloudFront
场景 2: 旧域名迁移到新域名
// old-site.com → new-site.com
function handler(event) {
return {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: 'https://new-site.com' }
}
};
}
场景 3: 保留路径的重定向
// old.example.com/path → new.example.com/path
function handler(event) {
var request = event.request;
var uri = request.uri;
var querystring = request.querystring;
var newUrl = 'https://new.example.com' + uri;
if (Object.keys(querystring).length > 0) {
newUrl += '?' + new URLSearchParams(querystring).toString();
}
return {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: newUrl }
}
};
}
成本估算
基于 AWS 官方定价(2025年):
费用构成
| 项目 | 费用 | 说明 |
|---|---|---|
| CloudFront Functions 调用 | $0.10/百万次 | 每次重定向触发一次调用 |
| CloudFront HTTPS 请求 | $1.00/百万次 | 美国区域定价 |
| CloudFront HTTP 请求 | $0.75/百万次 | 如果只用 HTTP |
| Route53 查询 | $0.40/百万次 | DNS 解析费用 |
| CloudFront 数据传输 | ~$0.00 | 301 响应几乎无数据传输 |
| ACM 证书 | 免费 | 包含在服务中 |
免费额度(Always Free Tier)
- CloudFront Functions: 前 2,000,000 次调用/月
- CloudFront 请求: 前 10,000,000 次 HTTP/HTTPS 请求/月
- CloudFront 数据传输: 前 1 TB/月
- ACM 证书: 完全免费
实际成本示例
小流量场景(< 200万次/月):
- 完全免费(在免费额度内)
中等流量(100万次 HTTPS 重定向/月,超出免费额度):
- CloudFront Functions: $0.10
- CloudFront HTTPS 请求: $1.00
- Route53 查询: $0.40
- 总计: $1.50/百万次
大流量(1000万次 HTTPS 重定向/月):
- CloudFront Functions: $1.00(10M × $0.10)
- CloudFront HTTPS 请求: $10.00(10M × $1.00)
- Route53 查询: $4.00(10M × $0.40)
- 总计: $15.00/月
参考: CloudFront 官方定价
故障排查
问题 1: 证书验证失败
- 检查 Route53 中是否存在验证 CNAME 记录
- 等待 DNS 传播(最多 30 分钟)
- 确认证书在 us-east-1 区域
问题 2: CloudFront 返回 502/503
- 检查 Function 是否已发布(Status: LIVE)
- 检查 Function 是否正确关联到 viewer-request
- 验证 Function 代码语法正确
问题 3: 重定向不生效
- 确认 CloudFront 状态为 Deployed(需要 5-15 分钟)
- 清除浏览器缓存
- 使用 curl 测试避免浏览器缓存
- 检查 DNS 是否已传播:
dig <SOURCE_DOMAIN>
问题 4: HTTPS 证书错误
- 确认 CloudFront Alias 与证书域名匹配
- 检查证书是否包含源域名(通配符或精确匹配)
- 验证证书状态为 ISSUED