当你使用AWS的S3存储桶,而你的用户分布在国内乃至全球时,直连下载的等待足以劝退大量访客。我们通过一次配置,将文件下载速度从6秒优化到1秒,第二次访问甚至能快7倍。本文不堆砌概念,只记录从创建CloudFront分配、配置OAC、解决SSL证书坑、到最终在Cloudflare上正确设置DNS的全过程。如果你也正被跨国访问速度困扰,这篇文章或许能帮你少走几步弯路。
📋 完整配置流程总结
🚀 阶段一:创建 CloudFront 分配(AWS 控制台)
- 进入 CloudFront → 点击"创建分配"
- 选择套餐:选择「免费」套餐(无月租,按量付费)
- 配置分配名称Distribution name :如
s3-cdn,Domain输入自定义域名:如s3.example.com - 配置源站(Origin) :
- 源域名S3 origin(AWS的S3域名):
xxx.s3.us-east-1.amazonaws.com - 创建 OAC(源站访问控制),并记录 OAC ID
- 源域名S3 origin(AWS的S3域名):
- 配置备用域名和证书(可先跳过,稍后配置)
- 点击创建 ,记录分配的 CloudFront 域名(如
xxx.cloudfront.net)
🔐 阶段二:申请 SSL 证书(AWS ACM)
- 切换到需要使用的区域
- 进入 Certificate Manager (ACM) → 请求公有证书
- 添加自定义域名
- 选择 DNS 验证,生成验证用的 CNAME 记录
- 暂不颁发,等待 Cloudflare DNS 配置完成后自动验证
🌐 阶段三:配置 DNS(Cloudflare)
- 登录 Cloudflare,进入自己的
example.com域名 - 添加两条 CNAME 记录 (代理状态必须为 灰色云朵 ,即"仅 DNS"):
SSL验证在AWS Certificate Manager上,类型CNAME,名称和值按照上面提供的填写
流量指向在CloudFront上,类型CNAME,名称填s3,内容填xxx.cloudfront.net - 等待 1-2 分钟 ,回到 ACM 刷新,证书状态变为 "已颁发"
🔗 阶段四:关联域名与证书(CloudFront)
-
进入 CloudFront 分配详情页 → Add domain
-
备用域名 :添加
s3.example.com -
自定义 SSL 证书:选择 ACM 中已颁发的证书
-
保存,等待分配状态变为 "已部署"(约 2-5 分钟)
🛡️ 阶段五:配置 S3 存储桶策略
- 进入 S3 控制台,找到使用的存储桶
- 权限 → 存储桶策略 → 编辑,添加以下策略(替换分配 ID 和账号 ID):
json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::桶名/*",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:cloudfront::[你的账号ID]:distribution/[你的分配ID]"
}
}
}
]
}
注意 :如果你需要保留公共匿名访问,可以额外添加
"Principal": "*"的语句,但生产环境建议只保留 OAC 策略。
✅ 阶段六:验证与配置生效
-
验证 SSL:
bashcurl -v https://s3.example.com/test.txt预期返回
SSL certificate verify ok. -
验证访问:
bashcurl -o /dev/null -s -w "Time_total: %{time_total}s\n" \ https://s3.example.com/你的文件路径预期返回
200 OK,且第二次请求(缓存命中)速度大幅提升。 -
速度对比:
bash
curl -o /dev/null -s -w "Time_total: %{time_total}s\nSpeed: %{speed_download} B/s\n" \
https://s3地址/文件路径
curl -o /dev/null -s -w "Time_total: %{time_total}s\nSpeed: %{speed_download} B/s\n" \
https://自定义加速地址/文件路径
🧭 整体架构流程图
#mermaid-svg-FJwxyIkihX30w44f{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FJwxyIkihX30w44f .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FJwxyIkihX30w44f .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FJwxyIkihX30w44f .error-icon{fill:#552222;}#mermaid-svg-FJwxyIkihX30w44f .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FJwxyIkihX30w44f .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FJwxyIkihX30w44f .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FJwxyIkihX30w44f .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FJwxyIkihX30w44f .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FJwxyIkihX30w44f .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FJwxyIkihX30w44f .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FJwxyIkihX30w44f .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FJwxyIkihX30w44f .marker.cross{stroke:#333333;}#mermaid-svg-FJwxyIkihX30w44f svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FJwxyIkihX30w44f p{margin:0;}#mermaid-svg-FJwxyIkihX30w44f .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FJwxyIkihX30w44f .cluster-label text{fill:#333;}#mermaid-svg-FJwxyIkihX30w44f .cluster-label span{color:#333;}#mermaid-svg-FJwxyIkihX30w44f .cluster-label span p{background-color:transparent;}#mermaid-svg-FJwxyIkihX30w44f .label text,#mermaid-svg-FJwxyIkihX30w44f span{fill:#333;color:#333;}#mermaid-svg-FJwxyIkihX30w44f .node rect,#mermaid-svg-FJwxyIkihX30w44f .node circle,#mermaid-svg-FJwxyIkihX30w44f .node ellipse,#mermaid-svg-FJwxyIkihX30w44f .node polygon,#mermaid-svg-FJwxyIkihX30w44f .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FJwxyIkihX30w44f .rough-node .label text,#mermaid-svg-FJwxyIkihX30w44f .node .label text,#mermaid-svg-FJwxyIkihX30w44f .image-shape .label,#mermaid-svg-FJwxyIkihX30w44f .icon-shape .label{text-anchor:middle;}#mermaid-svg-FJwxyIkihX30w44f .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FJwxyIkihX30w44f .rough-node .label,#mermaid-svg-FJwxyIkihX30w44f .node .label,#mermaid-svg-FJwxyIkihX30w44f .image-shape .label,#mermaid-svg-FJwxyIkihX30w44f .icon-shape .label{text-align:center;}#mermaid-svg-FJwxyIkihX30w44f .node.clickable{cursor:pointer;}#mermaid-svg-FJwxyIkihX30w44f .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FJwxyIkihX30w44f .arrowheadPath{fill:#333333;}#mermaid-svg-FJwxyIkihX30w44f .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FJwxyIkihX30w44f .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FJwxyIkihX30w44f .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FJwxyIkihX30w44f .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FJwxyIkihX30w44f .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FJwxyIkihX30w44f .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FJwxyIkihX30w44f .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FJwxyIkihX30w44f .cluster text{fill:#333;}#mermaid-svg-FJwxyIkihX30w44f .cluster span{color:#333;}#mermaid-svg-FJwxyIkihX30w44f div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FJwxyIkihX30w44f .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FJwxyIkihX30w44f rect.text{fill:none;stroke-width:0;}#mermaid-svg-FJwxyIkihX30w44f .icon-shape,#mermaid-svg-FJwxyIkihX30w44f .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FJwxyIkihX30w44f .icon-shape p,#mermaid-svg-FJwxyIkihX30w44f .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FJwxyIkihX30w44f .icon-shape .label rect,#mermaid-svg-FJwxyIkihX30w44f .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FJwxyIkihX30w44f .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FJwxyIkihX30w44f .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FJwxyIkihX30w44f :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是
否
用户请求
Cloudflare DNS
CloudFront 边缘节点
缓存命中?
直接返回缓存
通过 OAC 回源
S3 存储桶
返回文件并缓存到边缘节点
📌 关键注意事项
| 要点 | 说明 |
|---|---|
| Cloudflare 代理必须关闭 | 使用灰色云朵(仅 DNS),否则 SSL 证书验证会失败 |
| ACM 证书 | CloudFront 证书 |
| S3 存储桶策略 | 必须允许 CloudFront 的 OAC 服务访问,否则会返回 403 |
| 缓存 TTL | 默认 5 分钟,可根据文件类型调整 |
🎯 最终效果
- 国内用户 访问速度从 ~6 秒 降低到 ~1.3 秒(提升约 78%)
- 缓存命中后 ,速度可达首次的 2-7 倍
- 全球用户都能从就近的边缘节点获取文件,体验显著提升
整个流程的核心就是:用 CloudFront 作为 S3 的"全球缓存层",通过 OAC 安全访问私有桶,再配合自定义域名和 SSL 证书,最终实现安全、快速的静态资源分发。