Cloudflare 国内慢、还弹验证码?CDN 替代方案盘点与两台 VPS 自建私有 CDN 实战

Cloudflare 免费版国内慢、偶弹 CAPTCHA、部分 IP 被封锁。本文盘点 Bunny.net / Fastly / AWS CloudFront / 国内备案 CDN,并手把手用 Nginx 反代缓存 + GeoDNS + 健康检查,教你用两台便宜 VPS 自建双节点私有 CDN。

Cloudflare 几乎是每个个人站长的"默认答案":改个 NS、免费 SSL、自带 DDoS 防护、全球节点一大把。但一旦你的访客主要在国内,或者你折腾的是自部署的小服务,Cloudflare 的"真香"往往会变成"真慢"。这篇先说清 Cloudflare 在国内为什么拉胯、还有哪些坑,再把能平替的国内外 CDN 盘一遍,最后手把手教你用两台便宜 VPS 自建一个私有双节点 CDN。

延伸阅读

更多相关攻略推荐:泛域名 SSL 证书自动化避坑:Acme.sh + DNS API BGP 是互联网的"高德地图":打开网页时,数据是这样找路的【优化线路 02】BGP / AS4837 常规线路年付 10 美元高级玩家玩出花:如何在 VPS 上广播自己的 IP 地址?BYOIP计算机科学两大难题之一:缓存失效与 CDN 瞬时刷新奥秘

一、Cloudflare 真香,但国内是真慢

Cloudflare 的加速靠 Anycast:一个 IP 全球广播,用户自动连到"最近的"节点。问题就出在"最近"上——Cloudflare 在中国大陆几乎没有自己的节点。它的免费版和绝大多数付费版,国内用户请求都要绕到香港、日本、新加坡甚至欧美节点再回来,延迟动辄一两百毫秒,晚高峰更是能卡成幻灯片。

官方自己都承认这点:想用 Cloudflare 的国内节点,得走它和百度的合作(百度云加速 / Cloud Enterprise),而且那套要备案、要中文工单,和个人玩法基本不沾边。所以结论很现实:访客以国内为主、又不想备案,Cloudflare 免费版基本等于"减速带"

二、国内慢的根因:Anycast 没节点 + 政策

拆开看,慢有三层原因:

  • 节点缺位:国内没有 Cloudflare 的边缘节点,流量必须跨境,物理距离摆在那,RTT 下不来。
  • 国际出口拥堵:跨境链路本就拥挤,高峰丢包一上来,TCP 拥塞控制一砍窗,速度雪崩(参考上篇的 Mathis 公式)。
  • 政策与备案:没有 ICP 备案,正规 CDN 厂商没法把节点铺进国内,大家都只能绕着跑。这也是为什么国内 CDN(阿里云、腾讯云、网宿等)要求备案。

所以如果你主要服务国内用户,第一选择其实不是"调 Cloudflare",而是"换一个在国内有节点的方案"。

三、Cloudflare 的其他坑

  • 偶尔弹 CAPTCHA:某些访问模式(或你的 IP 段被标记)会触发五秒验证,对 API、爬虫、以及用客户端访问的场景极不友好。
  • 部分 IP 段被封锁:Cloudflare 的某些 Anycast IP 在大陆会被间歇性封锁,表现为"有时能开有时超时",排查起来很头疼。
  • 缓存/安全策略对自部署不友好:默认缓存规则偏保守,动态接口容易被误缓存或强制走它的 WAF;想精细控制常常要上付费套餐。
  • 免费版功能天花板:智能路由(Argo)、负载均衡、按地域解析这些进阶能力都要单独付费,小项目一算账就不划算。

四、替代方案盘点:Bunny.net(性价比之王)

Bunny.net 是这两年开发者圈口碑最好的 Cloudflare 平替之一。它的逻辑很简单:按量计费、用多少付多少,没有复杂的套餐套路,控制面板也清爽。亮点:

  • 亚洲节点(含新加坡香港东京等),对亚太用户比 Cloudflare 免费版明显友好。
  • 价格极低:流量计费几分钱 1GB 起,小站每月几块钱就能 cover。
  • 顺手还送了图片优化、边缘规则、以及把 DNS 做成免费(查询量不收费,但账号有每月 1 美元最低消费门槛)。

适合:日活几万的中小项目、图片/视频类站点、想花小钱办正事的人。缺点的话,节点规模仍拼不过 Cloudflare,企业级 SLA 也弱一些。另外它 2026 年把 DNS 免费化这步棋很漂亮——把延迟路由、健康检查、故障转移、地理路由这些原本要付费的进阶能力一并塞进了免费档,对中小开发者很有吸引力。

五、替代方案盘点:Fastly 与 AWS CloudFront

  • Fastly:企业级边缘,实时配置生效(VCL 可编程缓存逻辑),Twitter、GitHub 之类大厂用过。强在灵活性和边缘计算,但对个人来说偏贵、有门槛,适合有工程团队的项目。
  • AWS CloudFront:和 AWS 生态无缝,每月免费 1TB 出站流量,对已经在用 AWS 的人几乎是零成本起步。节点全球覆盖好(但国内同样没直连节点,需配合跨境优化)。配置略繁琐,胜在账单透明、和 S3/EC2 一键打通。

还有个思路:用 Cloudflare 管海外 + 国内 CDN 管国内,靠 DNS 按地域分流,谁也别勉强谁——这正是下一节自建玩法要解决的。

六、国内选手顺带提一句

如果你的域名能备案,国内 CDN 在速度上碾压一切:阿里云 CDN、腾讯云 CDN、网宿、又拍云、七牛云、UCloud 等都有密集的国内节点,回源也快。又拍云/七牛对中小站还有免费额度,七牛的对象存储+CDN 组合适合图床类。备案是门槛,但一旦过了,体验完全不是一个维度。没备案又想服务国内用户,才需要后面的"野路子"自建。

七、自建 CDN 思路:两台便宜 VPS + Nginx 反代缓存

不想备案、又嫌公共 CDN 慢或不自由?可以自己搭。最小可用架构:两台不同线路的便宜 VPS 当边缘节点 + 一台源站 + 智能 DNS 调度

  • 节点 A:一台 CN2 GIA 之类回国优化线路(国内访问快,但贵一点),专门接国内访客。
  • 节点 B:一台普通国际 VPS(便宜大碗),接海外访客。
  • 两者都跑 Nginx,做反向代理 + 缓存,只有缓存未命中才回源。
  • 最前面用 GeoDNS:国内用户解析到节点 A,海外解析到节点 B。

成本:两台年付几十块的特价机就能撑起一个小站的静态资源加速。数据私有、规则你说了算,这是公共 CDN 给不了的自由。当然,自建的前提是你的内容可缓存(静态资源、图片、下载文件),纯动态接口加速意义不大。

八、Nginx 反代 + 缓存关键配置

在每个边缘节点上,核心就是 proxy_pass 指向源站,再用 proxy_cache 把响应缓存到本地磁盘。关键配置如下(放在 nginx.conf 的 http 段和对应的 server 段):

# 定义缓存区:路径、内存索引、磁盘上限、过期清理
proxy_cache_path /var/cache/nginx/edge levels=1:2
    keys_zone=edge:100m inactive=24h max_size=20g use_temp_path=off;

# 回源上游,带健康检查(连续失败3次、30s内不再发)
upstream origin_pool {
    server 203.0.113.10:443 max_fails=3 fail_timeout=30s;
    server 203.0.113.11:443 backup;
}

server {
    listen 443 ssl;
    server_name cdn.example.com;

    location / {
        proxy_pass https://origin_pool;
        proxy_cache edge;
        proxy_cache_valid 200 301 302 10m;
        proxy_cache_use_stale error timeout updating http_502 http_503;
        proxy_cache_lock on;
        proxy_cache_background_update on;
        add_header X-Cache-Status $upstream_cache_status;
        proxy_set_header Host origin.example.com;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

几个关键点:

  • proxy_cache_lock:同一份资源同时被很多人请求、又都没命中时,只回源一次,其余请求排队等结果,避免"惊群"把源站打爆。
  • proxy_cache_use_stale:源站短暂挂掉时,继续吐稍微过期的缓存,而不是直接 502,体验更稳。
  • X-Cache-Status 响应头:HIT 是命中、MISS 是回源,排障时一眼看清缓存有没有生效。

别忘了给缓存目录留够磁盘,并 nginx -t && systemctl reload nginx 生效。缓存目录记得放速度快的磁盘(SSD/NVMe),并设置合理的 inactivemax_size 防止撑爆。

九、GeoDNS:按访客地域解析到不同节点

调度层最简单经济的做法是用支持线路/地域解析的 DNS:DNSPod(腾讯云)、阿里云解析都支持"默认/国内/境外/按省份"分别指向不同 IP。配置好后:

  • 国内线路 → 节点 A(CN2 GIA)的 IP
  • 境外/默认线路 → 节点 B(国际 VPS)的 IP

进阶一点,可以在 Nginx 里用 geoip 模块按访客 IP 地域再做一次内部分发:

geo $backend {
    default    http://node_intl;
    CN         http://node_cn2;
}
server {
    location / {
        proxy_pass $backend;
    }
}

需要提醒:GeoDNS 的精确度依赖解析器位置和 EDNS Client Subnet,偶尔会有偏差,但对加速场景"够用";它和 Anycast 不同,切换靠 DNS 的 TTL,故障切换不是秒级而是 TTL 级(通常设 30-60 秒缩小窗口)。想要真·秒级切换得自己养 ASN + /24 做 Anycast,对个人来说通常杀鸡用牛刀。bigiron.cc 的那篇指南就直言:GeoDNS 用 5% 的 prerequisite 拿了 90% 的收益,是绝大多数自建 CDN 的正确取舍。

十、健康检查与 Failover 自动切换

自建最怕单点故障:节点挂了,那个区域的用户就全黑了。两道防线:

  • Nginx 上游健康检查:上面 upstream 里的 max_fails / fail_timeout 已经能在节点连续失败几次后自动摘掉,并把 backup 节点顶上。再讲究点可用 Nginx Plus 的 health_check 或开源的 nginx-upsync-module 做动态上下线。
  • 外部监控 + DNS 切换:用 Uptime Robot / 哪吒监控 / 自写脚本定时探活,一旦发现某节点连续超时,就调 DNSPod/阿里云 API 把对应线路解析切到备份节点。伪代码思路:
# 简单探活脚本(cron 每分钟跑一次)
if ! curl -fsS --max-time 5 https://cdn-node-a.example.com/health; then
    # 调用 DNS 服务商 API,把国内线路指向备用节点 IP
    cli-dns set --line cn --record cdn --value $BACKUP_IP
fi

这套组合拳下来:节点级故障由 Nginx 内部兜底,区域级/解析级故障由外部监控兜底,基本能做到"一个节点挂了用户无感"。记得把 DNS 的 TTL 设短(如 60 秒),切换才会够快;同时给源站也留一手,万一所有边缘全挂,还能让部分流量直连源站降级可用。

#VPS #CDN #Cloudflare #自建CDN #Nginx #反向代理 #GeoDNS #Bunny #Failover #Anycast