山山兔

给静态站套一层 CloudFront 免费套餐

· 约 961 字

这个站先是直接指向 GitHub Pages,之后改成前面套一层 CloudFront。记下做法和卡过的地方。

为什么

CloudFront 的 flat-rate 免费套餐把分发、WAF、DDoS 防护和 Route 53 托管区的费用打包在一起,超出额度时降速,不额外收费(见 AWS 文档)。托管区要在套餐里“挂上”才算在内,我们的区已经挂在这个分发的套餐下。

做法

  1. 源站设成 <用户名>.github.io,只走 HTTPS。
  2. 源站请求策略用托管的 AllViewer,让访客的 Host 头原样传给 GitHub。
  3. 证书用 ACM 里已有的 bunnishan.com 加通配符证书,区域必须是 us-east-1。
  4. Route 53 里根域和 www 都改成指向分发的别名记录(A 和 AAAA)。
  5. www 跳转到根域,用一个 CloudFront Function 在 viewer-request 阶段返回 301。

四个会卡住的地方

不转发 Host 就是 404。 GitHub Pages 靠 Host 头判断是哪个站。直接请求 <用户名>.github.io 返回 404,带上 Host: bunnishan.com 才是 200。所以源站请求策略不能用默认的,要把 Host 转发过去。

别名记录和 CNAME 不能共存。 www 原来是 CNAME,要换成别名记录时,必须在同一个变更批次里先删 CNAME 再建别名;单独建别名会被拒绝。

换源站后先清缓存。 分发之前指向别的源站,缓存里还留着旧内容,换完要对 /* 做一次清除,不然还是旧页面。以后每次发文章,等 GitHub 部署完成再清缓存,部署之前清没有用。

CAA 记录要把 Amazon 的签发方也放进去。 我们区里有 CAA,原来只允许 letsencrypt.org。ACM 证书续期需要 amazon.com、amazontrust.com、awstrust.com、amazonaws.com,缺了会签不出来。

验证

直接对 CloudFront 的边缘 IP 用 --resolve 请求每个页面,就不受本地 DNS 缓存影响。另外要看:证书主体是 bunnishan.com、http:// 会 301 到 https://、www 会跳到根域、不存在的路径返回 404。