当前位置:首页 > Yixn Like > 正文内容

Cdn该怎么套?我来教你

yixn1个月前 (09-13)Yixn Like32
自建 CDN 完整配置指南 · 域名解析 · SSL 证书 · 刷新预热

自建 CDN 完整配置指南

自建 CDN 系统 域名解析 SSL 证书 刷新预热

💡 核心结论:自建 CDN 套域名并启用 HTTPS,完整链路是——添加站点 → 配置 CNAME 解析 → 申请 SSL 证书 → 部署证书 → 配置强制跳转 → 按需开启 HSTS → 建立刷新预热机制。自建 CDN 和商用 CDN 最大的区别在于:证书要自己申请、缓存要自己管、回源要自己配,没有一键托管。

📋前置准备

自建 CDN 的系统构成

自建 CDN 通常由三部分组成:边缘节点(运行 Nginx / OpenResty / Varnish + 缓存模块)、调度系统(DNS 智能解析或 Anycast)、源站(你的博客服务器)。你需要自己维护边缘节点的缓存策略、证书和回源配置。

域名与备案

使用国外边缘节点不需要 ICP 备案。DNS 解析托管到 Cloudflare、DNSPod 或自建 DNS 都可以。如果是国内节点,加速域名必须完成 ICP 备案。

证书来源选择

方案 免费额度 有效期 泛域名 管理方式
Let's Encrypt 推荐 无限制 90 天 ✅ 支持 命令行(acme.sh)
ZeroSSL 每账号 3 张 90 天 ❌ 免费版不支持 图形界面 + API
Buypass 免费 180 天 不支持 命令行 / API
商业证书 付费 1 年 取决于类型 控制台

📌 自建 CDN 推荐方案:用 Let's Encrypt + acme.sh 申请泛域名证书,配合 --install-cert 钩子自动部署到所有边缘节点。免费、自动续期、支持泛域名,是自建 CDN 的最优解。

1添加站点 / 加速域名

在自建 CDN 的管理面板中添加站点。不同面板(如 Nginx Proxy Manager、宝塔 CDN 插件、自研面板)叫法不同,核心是配置加速域名和源站地址。

加速域名填什么

建议单独分配一个二级域名承载 CDN 加速,如 cdn.yourdomain.com 或 static.yourdomain.com,主域名留给业务入口。好处是隔离风险,CDN 出问题时不会波及主站。

源站配置

源站是单台服务器填 IP,负载均衡架构填域名更灵活。回源协议初期可选 HTTP,后续改为 HTTPS 实现全链路加密。

📌 配置完成后你会拿到一个 CNAME 地址

格式类似 cdn.yourdomain.com.edge-node-01.yourcdn.com。如果是自建 DNS 调度,可能直接是一个 A 记录指向边缘节点 IP。这是下一步解析的关键。

2申请 SSL 证书

Let's Encrypt(acme.sh 方案)自建 CDN 首选

安装 acme.sh 一条命令:

curl https://get.acme.sh | sh -s email=你的邮箱@example.com

用 DNS 验证方式签发泛域名证书(以 Cloudflare DNS 为例):

export CF_Token="你的Cloudflare_API_Token"
export CF_Account_ID="你的Cloudflare_Account_ID"
acme.sh --issue --dns dns_cf -d yourdomain.com -d *.yourdomain.com

📌 为什么自建 CDN 推荐 DNS 验证?DNS 验证不需要边缘节点开放 80 端口,证书签发在本地完成后再分发到各节点。对于多节点自建 CDN,这是唯一可行的方式。

证书文件位置:申请成功后,证书在 ~/.acme.sh/yourdomain.com/ 目录下。部署到边缘节点时需要的是:

  • fullchain.cer——包含服务器证书和中间证书的完整链
  • yourdomain.com.key——私钥文件

自动部署到边缘节点

用 acme.sh 的 --install-cert 钩子,证书续期后自动复制到 Nginx 目录并重载:

acme.sh --install-cert -d yourdomain.com \
  --key-file       /etc/nginx/ssl/yourdomain.com.key \
  --fullchain-file /etc/nginx/ssl/yourdomain.com.fullchain.cer \
  --reloadcmd      "nginx -s reload"

如果有多个边缘节点,可以配合 Ansible / rsync 批量分发证书文件。

ZeroSSL

访问 zerossl.com,输入域名,注册账号后按引导完成验证。支持文件验证、DNS 验证、邮箱验证三种方式。

⚠️ ZeroSSL 免费版限制:每个账号限 3 张免费证书,且不包含泛域名。自建 CDN 通常需要泛域名证书来覆盖多个子域名,所以更推荐 Let's Encrypt。

3配置 CNAME 解析

进入 DNS 解析控制台(Cloudflare、DNSPod 或自建 DNS),添加一条 CNAME 记录:

  • 主机记录:加速 cdn.yourdomain.com 就填 cdn;加速主域名填 @
  • 记录类型:选择 CNAME
  • 记录值:粘贴 CDN 分配的 CNAME 地址
  • TTL:保持默认

🚫 关键注意:CNAME 记录不能与 A 记录共存。如果之前给该主机记录配置过 A 记录指向服务器 IP,必须先删除 A 记录,否则解析冲突,CDN 不生效。这是自建 CDN 新手最常踩的坑。

验证是否生效:

dig cdn.yourdomain.com CNAME +short

4部署 SSL 证书到边缘节点

自建 CDN 没有「一键上传证书」的按钮,你需要手动把证书文件放到每个边缘节点,并在 Nginx / OpenResty 配置中引用。

Nginx 配置示例

server {
    listen 443 ssl http2;
    server_name cdn.yourdomain.com;

    ssl_certificate     /etc/nginx/ssl/yourdomain.com.fullchain.cer;
    ssl_certificate_key /etc/nginx/ssl/yourdomain.com.key;

    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://源站IP:端口;
        proxy_set_header Host $host;
        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;
    }
}

最容易踩的坑:证书链不完整

很多「HTTPS 配置看起来成功了,浏览器却报不安全」的问题,根源都在这里。

SSL 证书通常包含服务器证书、中间证书、根证书组成的证书链。如果只配置了服务器证书,浏览器可能无法验证证书来源,Chrome 会直接阻断访问。

✅ 正确做法

Nginx 的 ssl_certificate 指令指向的文件必须包含服务器证书和中间证书。用 acme.sh 时,fullchain.cer 就是完整链版本,直接用。不要用 cert.pem(只有服务器证书)。

验证证书链是否完整:

openssl s_client -connect cdn.yourdomain.com:443 -servername cdn.yourdomain.com

如果输出中 Verify return code 为 0 (ok),说明链完整。如果是 21 (unable to verify the first certificate),说明缺中间证书。

5强制跳转 HTTPS

这是最容易忽视但必须配置的一步。

配置 SSL 证书只是让 Nginx 具备处理 HTTPS 请求的能力,不会改变 HTTP 请求的处理方式。HTTP 到 HTTPS 的跳转需要单独配置。

Nginx 配置示例

server {
    listen 80;
    server_name cdn.yourdomain.com;
    return 301 https://$host$request_uri;
}

🚫 重定向死循环:最容易踩的坑。如果开启强制跳转后访问报 ERR_TOO_MANY_REDIRECTS,通常是因为:源站也配置了 HTTP 到 HTTPS 跳转,但 CDN 以 HTTP 协议回源。此时 CDN 收到 HTTP 请求 → 跳转到 HTTPS → 回源时仍用 HTTP → 源站又要求跳转到 HTTPS → 循环。

解决方案(二选一)

  • 方案一:关闭源站的 HTTP 强制跳转功能,统一由 CDN 处理跳转
  • 方案二:修改 CDN 回源协议为 HTTPS 或 跟随请求协议,避免触发源站跳转

📌 自建 CDN 推荐方案二。回源协议设为 HTTPS,源站也配好证书,实现「用户到 CDN」和「CDN 到源站」全程加密。同时源站可以保留强制跳转作为兜底。

6HSTS 安全访问(进阶,慎开)

HSTS 是什么

HSTS(HTTP Strict Transport Security)是一种安全策略,开启后浏览器会缓存一个响应头,在缓存有效期内自动将所有 HTTP 请求转为 HTTPS,不再经过 HTTP 跳转这一步。

HSTS 与强制跳转的区别

强制跳转是服务端处理:浏览器发 HTTP → 服务器返回 301 → 浏览器再发 HTTPS。第一次 HTTP 请求仍然在网络上传输,有被劫持的风险。

HSTS是浏览器侧处理:浏览器发现请求是 HTTP → 浏览器直接转为 HTTPS 发出。HTTP 请求根本没有出现在网络上,彻底消除降级攻击风险。

Nginx 配置示例

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

🚫 HSTS 的致命风险(开之前必读):HSTS 配置后无法快速回退。HSTS 策略作用在客户端(浏览器),关闭 HSTS 后无法立即生效,需要用户手动刷新浏览器缓存。这意味着:如果开启 HSTS 后证书出了问题(过期、被吊销、配置错误),所有已经缓存过 HSTS 响应的用户将完全无法访问你的网站,浏览器会直接阻止连接,连“继续访问”的选项都不给。

必须遵守的规则

  • 开启 HSTS 前,确保证书配置稳定且自动续期正常工作
  • 不要为了测试而随便开启 HSTS
  • 如果开启 HSTS 后关闭了 HTTPS 证书,必须同时关闭 HSTS 配置
  • 过期时间不要设太长,初期建议 max-age=86400(1 天),确认稳定后再逐步延长到 31536000(1 年)
  • 强制跳转类型不能设为 HTTP,否则与 HSTS 冲突,会导致域名无法访问

⚠️ 自建 CDN 特别提醒:HSTS 头由边缘节点返回。如果你有多个边缘节点,必须确保所有节点都配置了相同的 HSTS 策略,否则用户在不同节点间切换时会遇到不一致的行为。

7缓存刷新与预热

核心概念

刷新(Refresh/Purge):向 CDN 节点下发缓存失效指令,将已缓存的资源标记为过期。用户再次请求时,CDN 回源获取最新资源并重新缓存。刷新会降低缓存命中率。

预热(Preload/Warm-up):CDN 节点主动从源站拉取资源并缓存。用户首次请求时可直接从 CDN 获取,无需回源。预热会提高缓存命中率。

什么时候用哪个

场景 操作
博客更新了文章,想让读者立即看到新内容 刷新对应文章 URL
删除了违规/错误内容 刷新对应 URL
首次接入 CDN,想加速热门文章 预热热门文章 URL
发布大型资源(视频、安装包) 预热,降低源站压力
更换了主题/静态资源 先刷新,再预热

自建 CDN 如何实现刷新预热

Nginx 缓存刷新

如果边缘节点用 Nginx 的 proxy_cache,刷新就是删除对应的缓存文件:

# 查找缓存文件
find /var/cache/nginx -type f -name "*yourdomain.com*"

# 删除指定缓存(按 URL 匹配)
grep -rl "cdn.yourdomain.com/article/123" /var/cache/nginx | xargs rm -f

# 重载 Nginx
nginx -s reload

OpenResty / Lua 缓存刷新

如果边缘节点用 OpenResty + lua-resty-cache,可以通过 ngx.shared.DICT 或 Redis 管理缓存键,提供 HTTP API 触发刷新:

# 通过 API 刷新单个 URL
curl -X POST "http://edge-node-01:8080/purge" \
  -d "url=https://cdn.yourdomain.com/article/123"

预热实现

预热本质是主动发起请求让 CDN 回源并缓存。可以用脚本批量发起:

# 批量预热热门文章
for url in $(cat hot-urls.txt); do
  curl -s -o /dev/null -w "%{http_code} %{url_effective}\n" "$url"
done

⚠️ 刷新预热的注意事项:

1. 大批量刷新会冲击源站。刷新后大量请求同时回源,源站带宽会突增。建议在流量低峰期操作。

2. 预热也是同理。大批量预热任务会让 CDN 节点同时回源拉取,源站带宽压力增大。根据源站带宽情况控制并发。

3. 刷新不是删除,是标记失效。CDN 不会实时删除缓存文件,只是标记为“过期”,用户下次请求时才回源获取新内容。

4. 如果缓存过期时间 < 5 分钟,不需要手动刷新。等它自然过期即可。

5. HTTP 和 HTTPS 共享缓存。只需要刷新或预热其中一种协议,不必两个都做。

自动化刷新预热

手动刷新适合低频场景。如果博客更新频繁,可以配置自动化:

  • Git Hook 触发:博客部署完成后,通过 webhook 调用刷新 API
  • CI/CD 集成:在 GitHub Actions / GitLab CI 中加入刷新步骤
  • 定时任务:用 cron 定期预热热门文章
  • 对象存储触发:文件上传到 OSS/COS 时自动触发刷新

8验证与排查

验证清单

  1. HTTPS 访问:用 https://cdn.yourdomain.com 访问,地址栏显示安全锁
  2. 证书信息:点击锁图标,确认 CA 为 Let's Encrypt、在有效期内、域名匹配
  3. HTTP 跳转:用 http://cdn.yourdomain.com 访问,应自动跳转到 HTTPS
  4. CNAME 生效:dig cdn.yourdomain.com CNAME +short 返回 CDN 地址
  5. 混合内容:浏览器控制台无 Mixed Content 警告
  6. 缓存验证:更新资源后,刷新 CDN,确认用户能获取最新内容

常见故障速查表

现象 大概率原因
浏览器标「不安全」但页面能打开 证书链不完整或未开强制跳转
ERR_TOO_MANY_REDIRECTS 源站也配了强制跳转 + CDN 以 HTTP 回源
页面图片/样式加载失败 混合内容被浏览器阻止
CNAME 配置后 CDN 不生效 A 记录与 CNAME 冲突,需删除 A 记录
回源报 502 CDN 回源协议设为 HTTPS 但源站不支持
裸域名证书报错 用了通配符证书但没单独配置裸域名
证书申请后 CDN 不识别 配置了不含中间证书的 cert.pem 而非 fullchain.pem
用户看到旧内容 缓存未过期且未刷新,或刷新未生效
HSTS 开启后网站打不开 证书问题,且浏览器已缓存 HSTS 无法回退

📝小结

完整流程:加域名 → 配 CNAME → 申请证书(Let's Encrypt / ZeroSSL)→ 部署 fullchain → 配强制跳转 → 按需开 HSTS(慎开)→ 建立刷新预热机制。

三个最关键的提醒:

  1. 强制跳转与回源协议必须匹配,否则重定向死循环
  2. HSTS 开之前确保证书稳定,开了就不好回头
  3. 刷新预热按需使用,大批量操作放在流量低峰期

📌 自建 CDN 的核心优势:完全掌控缓存策略、证书管理和回源逻辑。代价是需要自己维护边缘节点、自己处理证书续期、自己实现刷新预热。对于技术博客来说,这是一次性投入、长期受益的选择。

相关文章

我只喜欢一个人永远

她是?Luo Chenlu"I like Luo 'Chenluo forever, for a lifetime"🥰....

Yixn Html部署系统

https://h.3v4.top/ 这是我写的一个HTML部署系统,完全免费,是个匿名的但不能上传zip,为了安全嘛我怕里面藏什么炸弹或者是php的所以呢,只能上传html/htm静态文件我可能让你...