ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

把网站装进边缘:用Cloudflare免费服务搭一台能打的云操作系统

把网站装进边缘:用Cloudflare免费服务搭一台能打的云操作系统

我最早听说“cloudflare-os”这个叫法时,以为又是哪个社区老哥在玩梗造了个发行版。后来自己在Cloudflare上把域名托管、CDN加速、边缘脚本、网页应用、KV存储、静态站点全部串起来之后,才意识到这称呼其实挺贴切的:Cloudflare这套免费服务,覆盖了传统服务器要自己搞的DNS、证书、缓存、防火墙、网关、甚至后端逻辑,凑在一起,确实就是一台松散但能打的“云操作系统”。

这篇文章,我打算把这套“Cloudflare OS”的组装过程完整写一遍。不带纯理论,而是基于我实际动手搭站点、跑API、怼WAF规则的经历,把每一步怎么选、怎么配、为什么这么配,以及免费套餐下有哪些容易被忽略的坑,一次讲清楚。不管你是只想把博客跑得稳一点的个人站长,还是想用边缘服务替代部分后端逻辑的开发者,这套方案都值得抄作业。

1. 内容整体设计与思路拆解

1.1 所谓“Cloudflare OS”到底是什么

你可以把传统的服务器想象成一台个人电脑:上面要装系统、装Web服务、装数据库,还要手动配置防火墙、处理证书过期、扛流量波动。而Cloudflare提供的整套服务,相当于把电脑拆散了丢到离用户最近的机房里,每一层都被抽出来做成一个独立模块,用控制台就能编排。

我这次搭的项目不算复杂:一个个人站点,挂着静态页面,带一个简单的API网关,后端没有独立服务器,全部逻辑跑在边缘节点上。DNS交给Cloudflare托管,HTTPS证书由Cloudflare自动签发,静态资源走Pages,动态请求走Workers,数据存到KV,再套一层WAF和缓存规则。总花费为零,整套东西跑起来后的响应速度和抗打击能力,比我之前用那台小破VPS强太多。

这个方案的核心设计原则只有一条:能交给边缘做的,绝不回源。静态文件根本不需要打到源站;API逻辑能在离用户最近的节点直接出结果,就绝不绕远路;哪怕要回源,也最好让Cloudflare把能挡的流量先挡掉。按这个思路搭出来的架构,天然比“裸服务器+Nginx”要省心。

1.2 组件怎么分工,对应传统服务器的哪些角色

为了让你更好理解,我整理了一张对照表。左边是传统服务器上你要自己搞的东西,右边是Cloudflare里对应的免费模块。

传统服务器角色Cloudflare对应功能实际作用
DNS解析服务Cloudflare DNS接管域名解析,自带DNSSEC
Nginx/ApacheCloudflare CDN + 橙色云朵缓存静态资源、隐藏源站IP
HTTPS证书边缘证书自动签发和续期,无需手动处理
WAF防火墙WAF自定义规则 + 安全级别拦截恶意请求、CC攻击
后端业务逻辑Cloudflare Workers无服务器函数,跑在边缘
数据库/缓存Workers KV / D1轻量键值存储和SQL数据库
Web服务器托管Cloudflare Pages托管静态站点,支持构建
日志/监控Web Analytics + 实时日志流量统计、错误排查

你看完这个表应该就有感觉了:以前要单独买服务器、装环境、写Nginx配置、配Let‘s Encrypt,现在这些全部被一个个独立服务取代,而且都在同一个控制台里管理。免费套餐的量对个人项目和中小站点完全够用,后面我会提到具体限额。

按这个思路搭出来的“操作系统”,没有传统意义上的操作系统内核,也没有SSH登录界面,但你平时关心的事——可用性、攻击防护、性能、域名安全——它都替你兜住了。

2. 域名接管与全局路由设置

2.1 把域名交给Cloudflare,这一步不能省

搭建这套体系的第一步就是把域名全部托管到Cloudflare。为什么必须这么做?因为后续的CDN加速、边缘脚本、缓存规则,全部建立在一个前提上:Cloudflare能够代理你的域名流量。DNS托管就是整个体系的入口,如果这一步不彻底,后面很多功能都会受限。

操作流程其实很短:注册Cloudflare账号,添加域名,它会自动扫描你原来的DNS记录,然后给你两个Nameserver地址。你回到域名注册商的控制台,把原来的Nameserver替换成Cloudflare的,然后等待生效。生效时间取决于域名的注册局和之前的TTL设置,慢的可能会拖上一整天,但常规情况下几分钟到几小时就搞定了。

这里有个建议:切换Nameserver前,先去原DNS服务商把TTL调成尽量短,比如300秒,这样切完之后系统能更快拿到新记录。如果你图省事直接切,原记录TTL是86400秒的话,那DNS生效硬要等满24小时,期间可能出现打不开站点的情况,这对线上业务来讲是纯粹给自己找麻烦。

2.2 橙色云朵和灰色云朵,选错等于白搭

添加完DNS记录后,每条记录旁边会有一个云朵图标。灰色云朵表示DNS只解析、不代理,流量直接打到你的源站IP;橙色云朵表示Cloudflare开启代理,所有请求先经过Cloudflare再回源。你要用Cloudflare的缓存、WAF、Workers、自动证书,必须开橙色。

我在刚接触时犯过一个小错误:把主力域名的A记录设成灰色,结果后面配的缓存和WAF规则全部不生效,查了好半天才发现是这个云朵没点亮。所以这里建议养成习惯:非特殊用途的记录一律点亮橙色。这里有一个例外,就是邮件服务的MX记录,这种记录不支持代理,只能保持灰色,因为它走的是邮件协议,不是HTTP,Cloudflare代理不了。

如果你有多条域名记录,比如api.你的域名.com这种子域名,也建议单独建一条记录并点亮橙色。这样可以用不同的Workers路由或缓存规则来区分入口,比全部挂到根域名再在代码里做判断要清晰很多。

2.3 SSL/TLS加密模式和证书状态管理

域名接管完毕后会看到一个证书状态区域。Cloudflare给每个域名自动签发边缘证书,但“自动”不代表立刻生效,给这个域名从DNS切换完到证书签发成功,中间需要等一会儿,有时会看到证书状态一直停在“等待签发”,不要慌,过一段时间刷新就会变成正常。

真正需要你手动选的是SSL/TLS加密模式。控制台里一般有这几个选项:Off、Flexible、Full、Full (strict)。我直接说我的推荐结论:源站只要能支持HTTPS,就一律选Full (strict);如果源站还没配HTTPS,起码选Full,甚至暂时用Flexible,但你心里要有数——Flexible模式下,用户到Cloudflare这一段是加密的,Cloudflare回源站那一段是明文HTTP。这意味着源站和Cloudflare之间的传输可能在中间链路被观察到,安全隐患是实际存在的。

Flexible模式还有一个容易踩的坑:如果你的源站本身已经配置了HTTPS证书,但证书链不完整,Flexible模式下Cloudflare反而会因为“回源握手失败”而报错。这种情况下要么修源站证书,要么暂时降级到Full,等源站修好了再切回strict。用这个顺序去排查能少走弯路。

3. 边缘逻辑实现:把后端代码搬到Workers

3.1 Workers到底是什么,为什么这么重要

Cloudflare Workers是这套“操作系统”里的计算核心。它允许你写一段JavaScript(也支持TypeScript),部署到Cloudflare边缘节点,当请求打到某个域名或路由时,这段代码直接在那个节点上执行,然后把响应返回给用户。你不用关心服务器在哪里、怎么扩容、进程挂了怎么拉起,这些全部被平台消化了。

我给你的比喻是这样:传统后端像是你去银行柜台办事,每个请求都要到中央总行排队;Workers像是遍布街头的自动柜员机,同一个业务逻辑被复制到全球节点上,用户就近取钱就行。延迟天然低一个数量级,而且没有单点故障,一个节点挂了其他节点顶上来。

在我这个项目里,Workers承担了两个核心职责:一是做API网关,对外提供一个带访问统计的接口;二是做路由分发,根据路径把请求转到不同后端或直接返回结果。这两件事如果放在传统服务器上,需要Nginx配置加后端语言,还要考虑进程驻留,在Workers里几十行代码就能搞定,且跑得更快。

3.2 实操举例:带访问计数和鉴权的API网关

下面我贴一段当时写的Workers代码,功能不复杂,但很适合拿来理解Workers的工作方式。它做两件事:访问指定路径时返回访客数量;访问信息接口时要求带一个简单的令牌。

export default { async fetch(request, env, ctx) { const url = new URL(request.url); const path = url.pathname; if (path === '/api/visits') { const count = (await env.COUNTER.get('visits')) || '0'; return new Response(JSON.stringify({ code: 0, visits: parseInt(count) }), { headers: { 'Content-Type': 'application/json; charset=utf-8' } }); } if (path === '/api/info') { const token = request.headers.get('X-Auth-Token'); if (token !== env.API_TOKEN) { return new Response(JSON.stringify({ code: 401, msg: 'unauthorized' }), { status: 401, headers: { 'Content-Type': 'application/json; charset=utf-8' } }); } return new Response(JSON.stringify({ code: 0, data: { runtime: 'edge', mode: 'cloudflare-os' } }), { headers: { 'Content-Type': 'application/json; charset=utf-8' } }); } return new Response('Not Found', { status: 404 }); } };

部署步骤:在Cloudflare控制台进入Workers,新建一个Service,把这段代码粘进去。上面的env.COUNTER需要在设置的“KV命名空间绑定”里,绑定一个名为COUNTER的KV命名空间;env.API_TOKEN需要在变量的“环境变量”里填,类型选“加密文本”。这样代码里就能安全引用到令牌,不会把密钥直接暴露在前端源码中。

跑通之后你会发现,这个接口在任何地区访问都很快,因为代码执行在当前边缘节点。数据一致性咱们后面讲KV的时候再说,这里先知道有这回事就行。

3.3 绑定KV存储:边缘函数怎么保存状态

Workers默认是无状态的,每次运行就像开了一个崭新的进程,什么都不会留下。但很多业务逻辑需要持久化数据,比如全局计数器、用户偏好、临时缓存。这时就要用Workers KV,一个全球复制的键值存储。

KV用起来很简单,核心就是get和put:

await env.COUNTER.put('visits', newCount); const count = await env.COUNTER.get('visits');

理解KV前先记住它的特性:全球边缘缓存一致性是“最终一致”的。你写入一个键值后,立刻读取,可能读到旧值,因为KV把数据先写入某个中心点,再异步同步到全球边缘节点。但对大部分统计类、配置类场景,这个短暂延迟完全可以容忍。如果你需要强一致性事务,那就得选D1数据库,它是Cloudflare提供的SQLite数据库,支持单区域强一致性。

我的建议是用KV存读多写少的数据,比如计数器、配置项、图片缓存结果;用D1存业务数据,比如订单、用户列表。免费套餐里KV每日有一万次写入、十万次读取的额度,大多数个人项目连零头都用不到。

4. 安全策略:免费WAF与访问规则到底怎么配

4.1 免费套餐的WAF能力清单

很多人的印象是WAF是付费产品,但Cloudflare免费套餐也同样给你几个安全武器:自定义WAF规则,可以写5条;Bot Fight Mode,可以拦截已知机器人;Security Level,可以控制应对威胁的严格程度;Under Attack Mode,一键开启“攻击模式”,所有访客要先通过一个验证页面才能访问。

这几个武器里最核心的是自定义WAF规则。你可以按IP、按路径、按User-Agent、按查询参数组合出过滤条件,命中后执行的动作有Block、Challenge、JS Challenge、Managed Challenge等。免费用户能配5条,这个额度对个人站点来说已经相当宽裕。

我按自己常用的规则给你列个参照表,你可以直接在控制台照着建:

规则名称匹配条件动作用途
封禁恶意UAUser Agent 包含python-requests且路径含/.envBlock阻止常见扫描器
保护后台路径路径含/admin且国家/地区不在白名单Managed Challenge后台增加一道验证关卡
拦截异常查询查询参数包含union select或sleep(Block防SQL注入试探
限制陌生地区登录路径含/wp-login.php且未知地区Block防止爆破
全站验证码请求频率高于设定速度JS Challenge防洪峰攻击

4.2 用自定义规则保护后台与敏感目录

站点一旦开放在公网上,扫描器很快就自动找上门了。最常见的是对着你后台路径连续请求,比如/admin、/wp-login.php、/server-status,想碰运气猜出弱密码或泄露信息。这事的解法就是写一条WAF规则,把后台路径的访问者过滤一遍。

这里有个细节必须注意:如果是你自己要更新后台内容,怎么保证不被自己的规则误伤?建议不要直接Block,最高也就是Managed Challenge。动作含义是“让请求先过一个交互式验证页面,确认是不是真人浏览器再说”,这是介于“直接拒绝”和“放行”之间的折中方案,对真实访问几乎无感,但会把没有浏览器环境的脚本全部拦下。

我自己站点里有一条路径是/debug,专门放调试信息,平时只有我访问。我在WAF规则里加了一条:路径等于/debug 且 IP不属于我的家庭宽带IP段就Block。IP段怎么填?去网上搜一个“查我公网IP”的页面,把得到的IP填进去即可;如果你的IP是动态的,那还是建议关联Cloudflare Access做进一步的身份验证,因为WAF按IP控制总归有误差。

4.3 安全级别与验证码,别把真实用户也拦了

Cloudflare的“安全级别”有五个档位:低、中、高、攻击模式、完全不安全。默认是“中”。安全级别越高,触发验证码的门槛就越低,恶意流量被拦得越狠,但真实用户也可能被频繁弹出的验证码烦到。所以大多数情况下保持默认“中”就够了,只在被攻击时临时拉高到“高”或“攻击模式”。

还有一个很多人不知道的事:Under Attack Mode开启后,所有访客哪怕访问你的静态博客,都要先经过一个“五秒盾”验证页面。这功能在遭受猛烈攻击时非常管用,但它同时会严重降低SEO爬虫的抓取效率。如果你是靠搜索流量吃饭的站点,这个模式只能当应急工具,不能长期开着。

我的经验是:日常就把Bot Fight Mode开启,自定义WAF规则把扫描器拦掉;真遇到异常流量波峰,先看Web Analytics里的请求分布,确认攻击类型后再决定要不要开攻击模式。大部分情况,免费套餐的这套组合已经能把站点保护得相当到位。

5. 缓存策略与静态资源优化

5.1 先搞懂Cloudflare默认缓存哪些文件

Cloudflare的CDN缓存不是所有请求都缓存的。它对图片(jpg、png、gif、webp)、CSS、JS、字体文件这类静态资源默认就会缓存;但对于HTML文档,默认情况下不缓存,因为HTML可能是动态生成的。很多新手以为把域名托管过来就自动全站加速了,结果发现浏览器每次刷新都要回源取HTML,误以为缓存没生效,其实是默认策略就是如此。

想要给HTML也做缓存,有两条路:一是用Pages托管整个静态站点,因为Pages本身就是给静态资源设计的,HTML自然会被加速;二是在Workers里给HTML响应加上自定义的Cache-Control头,手工把动态内容变成“可缓存”。我的建议是能走Pages就走Pages,这是最省心的路线。

5.2 缓存规则怎么配:静态文件和API分开管理

Cloudflare现在更推荐用“缓存规则(Cache Rules)”来替代老的页面规则,因为缓存规则的匹配条件更灵活,免费套餐也能建多条。我这里有两条核心规则,你可以参照:

规则名匹配条件缓存行为说明
静态资源长缓存URL路径包含/assets/浏览器缓存30天,边缘缓存30天图片、JS、CSS可以放心缓存
API不缓存URL路径包含/api/忽略边缘缓存防止把过期数据返回给用户

为什么API必须“不缓存”?因为你业务里带鉴权和计数,如果被CDN缓存住,所有用户拿到的都是同一个响应,等于计费、限流和个性化逻辑全部失效。对动态接口,宁愿牺牲一点延迟,也要保证数据实时。

这里也顺带提一下浏览器的区别。你以为在浏览器刷新页面就能绕开CDN缓存,并不一定。如果CDN返回的响应头里带着CF-Cache-Status: HIT,说明这个资源被边缘缓存直接命中了,跟你浏览器本地缓存没有关系。开发时想强制刷新真实回源,可以打开Cloudflare控制台,把对应记录临时“点灰”,强制直连源站,调试完再点亮。

5.3 缓存清理的正确时机和姿势

你更新了站点内容,但线上刷出来还是旧版,大概率是边缘缓存没失效。Cloudflare提供了三个等次的刷新方式:单条URL清除、按前缀清除、全站清除。个人建议用“单条URL清除”定位到具体资源,别动不动全站刷新,因为全站刷新会让大批资源重新回源,瞬间把源站流量打满。

还有一个自定义技巧:在文件名里加入版本号或内容哈希,比如把样式表命名为style.3f2a9.css,文件名一变,旧缓存自动被绕过,新版本自然加载。这在资源长期缓存的场景里比单纯调短TTL优雅得多。

6. 静态站点托管:用Pages替代传统Web服务器

6.1 从Git仓库到全球上线,只需要几分钟

Cloudflare Pages可以拉取你的Git仓库,自动构建静态站点并提供托管。构建框架方面,Hugo、VuePress、Astro、React、Vite全都能识别;构建命令和输出目录在项目设置里配好,之后每次推送代码,Pages自动拉新代码、安装依赖、执行构建、发布上线。

我实际操作过程中的配置长这样:构建命令填npm run build,输出目录填dist,安装命令填npm install。Pages拿到仓库后会在云端跑构建环境,构建完成后把产物发布到边缘节点,并自动分配一个*.pages.dev域名。如果你要绑定自己的域名,在Pages项目的“自定义域”里添加域名,Pages会引导你加一条CNAME记录,然后在Cloudflare侧开启橙色云朵,HTTPS证书自动签发。

整个过程确实比传统服务器省太多事。以前部署一个Hugo博客,要SSH到服务器、拉仓库、装Hugo、生成文件、再让Nginx指向目录;现在Git push一下,等待一两分钟,网站就在全球节点上发好了。构建失败时,Pages的日志里会有详细的报错信息,比如依赖没装、构建命令写错,照着改就行。

6.2 Pages Functions:静态网站也能有动态能力

Pages有一个很多人都低估了的能力:Pages Functions。它本质上是Workers,但和Pages项目深度集成。你只需要在项目根目录建一个functions文件夹,里面每个文件对应一个API路由,Pages会自动把这些函数部署到边缘节点。

举个例子,我在functions/api/hello.js里写了这么一段:

export function onRequest(context) { return new Response(JSON.stringify({ message: 'Hello from Pages Function' }), { headers: { 'Content-Type': 'application/json; charset=utf-8' } }); }

推送代码后,/api/hello这个路径立刻就能用。这意味着静态站和动态API可以在同一个项目里维护,不需要单独开一个Workers服务来转发。对独立开发者来说,这大大降低了运维复杂度。

6.3 Pages和Workers怎么分工,别选错了

Pages和Workers本质同一套底层基础设施,但使用场景有差异。我的判断标准很简单:以静态内容为主、偶尔有几条动态接口的站点,用Pages + Pages Functions;以API服务为主、对路由有非常细致的控制需求、或者要和KV/D1深度集成的服务,用Workers。

另外注意:Pages的Functions在免费套餐里有调用次数限制,但个人站点根本用不完。如果项目里既有复杂API又有大量静态资源,更合理的做法是站点主体走Pages,单独的API服务走Workers,再用一个自定义域名指向不同路径分开访问。这样每一部分都在它最顺手的环境下运行。

7. 常见问题与排查实录

7.1 部署和配置阶段的高频错误速查

搭建过程中我踩过不少坑,也帮朋友排查过同类问题,整理成了一张排查表,基本覆盖了新手最容易遇到的情况:

症状可能原因解决办法
DNS切换后站点长时间打不开原DNS记录TTL太长切换前先把TTL调低到300秒
证书一直处于等待状态域名的NS还没有完全生效检查Nameserver是否正确,等待解析生效
Workers返回1101错误代码语法错误或入口函数导出有问题控制台看实时日志,检查export default是否正确
API接口返回数据落后KV的最终一致性导致写入还没同步短暂等待后重试;业务需要强一致就换D1
页面修改后线上没变化CDN缓存把旧资源挡住了用单条URL清除或改名加版本号
WAF规则误伤自己规则匹配条件过宽调整为指定路径+指定动作,避免全局Block
Pages构建成功但页面没更新构建缓存残留在Pages设置里触发明晰缓存重建

7.2 几个容易被忽略的免费额度边界

Cloudflare的免费套餐够厚道,但也有硬上限,超过后被封控或者插件停用,解释权在平台。我自己的实践是:Workers每天十万次请求全免费,KV每天十万次读、一千次写,Pages每月五百次构建,D1数据库免费额度是5GB存储和每天五百万行读。这些额度看起来巨大,但如果你日志写得特别勤或者API被刷,还是有可能一天就撞线的。

合理用法是:把KV的读操作尽量合并缓存到边缘节点,减少每次都读KV的次数;Pages的构建周期设成只在有提交时触发,不要每天定时构建;Workers里写日志时增加采样比例,不要每条都落存储。这样你基本不可能触发任何限额。

7.3 我最后优化出来的常用配置组合

这里分享一套我最终跑稳定下来的配置组合,你可以当做一个“较优解”抄走:根域名做301跳转到www域名,全部点亮橙色云朵;SSL模式选Full (strict);安全级别保持中;开启Bot Fight Mode;自定义WAF规则保后台路径;缓存规则对/assets/长缓存、对/api/绕过;Pages托管站点主体;Workers单独跑API网关;API里所有状态写KV,但读取端做了5秒内存缓存。这套组合跑了一段时间,没有出现过一次被打穿的事件,访问速度体感也轻松。

在实际操作中我还有一个习惯值得留给你:每当遇到“为什么配置没生效”的疑问,第一件事永远去看DNS记录是不是点亮了橙色云朵。这个云朵状态决定了后面所有功能是否起效,排查顺序永远从它开始。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进