☰
打造‘cloudflare-os‘:Cloudflare边缘安全与Linux系统的融合实践
2026/10/28 3:59:57 网站建设 项目流程

很多人第一次听到“cloudflare-os”,第一反应是:Cloudflare 什么时候出操作系统了?其实并没有官方叫这个名字的系统,但社区里确实有这么一股风潮——把 Cloudflare 那套免费、强大的边缘安全能力,和开源的 Linux 底座组合在一起,打磨成一个面向自托管场景的“操作系统级”方案。我最初搭这套东西,是因为家里一台 NAS 和办公室一台开发机都需要安全地暴露到公网,但又不想为了一个临时服务去折腾公网 IP、路由器端口映射和安全组规则。后来我意识到,真正值得沉淀的不是某个单一工具,而是“Cloudflare 全家桶 + 操作系统内核配置”这套组合拳。

整件事的核心思路可以概括为一句话:不把自己的机器直接暴露在公网上,而是让 Cloudflare 的边缘节点替你做访问入口、身份认证、流量清洗和内容过滤。你在自己的服务器上运行一个轻量客户端,主动“拨号”连接到 Cloudflare 的全球网络,然后所有访客访问的都是 Cloudflare 的 IP ,你的真实服务器 IP 可以完全隐藏。这套体系用好了,确实有“把一个裸奔的 Linux 变成一台企业级安全网关”的效果。这篇文章我会从设计思路、组件拆解、实操步骤到问题排查,完整记录一遍我自己的搭建过程和踩坑实录,希望能帮到同样在折腾自托管、零信任网络或者远程访问的朋友。

1. 整体设计思路:为什么要把 Cloudflare 当“操作系统”用

1.1 从“暴露端口”到“主动出站”的架构转变

传统方式下,你想让外面的人访问你家里那台服务器上的网站,通常要这样:搞一个公网 IP,再去路由器上做端口映射,然后祈祷运营商别封 80/443,还要自己维护防火墙规则。这套方案的痛点很明显:端口暴露就是攻击面,扫描器几分钟就能扫到你的 SSH 端口,而你根本不知道攻击者什么时候在试探。

cloudflare-os 这套思路的关键一步,是改变网络流量的方向。我们不再是“把端口暴露出去等人来连”,而是让服务器上的 cloudflared 隧道客户端主动向外发起一条经过认证的长连接,连接到 Cloudflare 的边缘网络。外部的所有请求先到 Cloudflare,再由 Cloudflare 通过这条现成的隧道转发到你的服务器。换句话说,你家里那台机器在公网面前是“隐身”的,没有开放任何入站端口,攻击者连扫描都没有对象。这个思路和我给别人讲安全时常用的一句大白话一样:别把敌人往家门口引,让保安替你在小区门口先把人都验一遍。

从操作系统层面看,这意味着你的防火墙策略可以激进很多。因为我用的是 Ubuntu Server,系统自带的ufw可以直接把入站全部拒绝,只留本地局域网访问和必要的出站连接。反正入站流量都是走隧道,服务器本身不需要监听公网端口。这样哪怕隧道客户端本身出现漏洞,攻击者也只是拿到一个内网通道,想横向移动还得突破系统本地防火墙,纵深防御的效果立刻出来了。

1.2 为什么选 Cloudflare 这套全家桶而不是单一工具

市面上可以做内网穿透和反向代理的工具不少,frp、ngrok、Tailscale 我都用过。但 cloudflare-os 这个组合最吸引我的地方在于:它不只是“打通一条通路”,而是把一整层安全能力全部前置。举个例子,cloudflared 隧道本身只解决了“能不能连上”的问题,真正有价值的是 Cloudflare Access 这层身份网关。你可以做到没有邮箱验证码、没有硬件密钥的人连登录页面都看不到。注意,是“看不到”,不是“登不进去”,因为 Access 规则写在任何应用逻辑之前,请求在到达你的 Nginx 之前就被拦截了。

另外,Cloudflare 的免费套餐对个人用户极其慷慨,无限流量的 CDN 加速、基础 DDoS 防护、全球 Anycast 网络,这些能力如果自己搭,哪怕只做到入门水平,成本也是按月计算的。但通过 cloudflare-os 这套体系,我一个月的额外支出基本为零,顶多买一个自定义域名,然后用 Cloudflare 管理 DNS。

对比下来,我有一个很实际的结论:如果你只是临时传个文件、偶尔连一下家里电脑,Tailscale 这类组网工具确实更方便,装完就能用;但如果你要对外提供持续的 Web 服务、还要给不同的人分配不同权限、希望有统一访问审计,那 Cloudflare 这套网关体系的上限高得多。本质上它不是一个穿透工具,而是一套安全接入编排系统。

1.3 这套方案解决的核心痛点

总结一下,cloudflare-os 真正帮我解决掉的问题就这么几个:

  1. 没有公网 IPv4 也能跑 Web 服务。现在不少宽带给的还是大内网 IP,别人根本访问不进来。隧道出站方式天然不受 NAT 类型限制。
  2. 零信任访问控制。每一条访问通道都有身份认证,不用再为一个小后台单独做一套用户密码体系。
  3. 隐藏真实服务器 IP,降低被定向攻击的风险。
  4. 域名、DNS、证书、CDN 集中管理,不用再单独维护 Let's Encrypt 的续期脚本,Cloudflare 边缘自动处理 HTTPS 证书。
  5. 全链路流量策略可编程。从防火墙规则到 WAF 规则,再到 Access 策略,全都可以在同一个控制台配置,变更即时生效。

2. 核心组件拆解:一个 cloudflare-os 由哪些零件组成

2.1 底层系统底座:选 Debian 系还是 Alpine 系

很多人一上来就纠结底层系统选什么。我的建议是,除非你对容器镜像体积有极端洁癖,否则老老实实用 Debian 或者 Ubuntu Server LTS。原因很简单:这套方案里的很多组件(cloudflared、WARP 客户端、fail2ban、审计工具)对主流发行版的支持最好,文档最多,遇到问题能搜到的解决方案也最多。

我自己测试过两种底座。第一次用的是 Alpine Linux,理由是系统干净、内存占用低,在 1GB 的小鸡上跑起来很轻。但后面加组件时发现,很多第三方软件源对 Alpine 的 musl libc 兼容性不一定好,编译安装又费时间,折腾成本远高于省下的那几十 MB 内存。后来换了 Ubuntu Server 22.04 LTS,所有组件直接 apt 装或者官方源装,顺畅很多。

实用角度讲,系统分区建议这样安排:/目录 20GB 以上,/var单独分出来给日志和缓存,/opt给服务端程序。服务器内存 1GB 起步,2GB 更舒服,因为 cloudflared 本身占用很小,但如果你在同一台机器上跑了 Nginx、Docker、WARP 客户端,内存规划还是要稍微留富余。

2.2 核心入口:cloudflared 隧道客户端

整个 cloudflare-os 体系里,最核心的组件就是 cloudflared。它是 Cloudflare 官方开源的隧道客户端,支持两种接入模式:一种是命名隧道,提前在控制台注册好隧道,然后生成证书和 Tunnel Token;另一种是快速隧道,一行命令跑起来,Cloudflare 随机给你分配一个trycloudflare.com的临时域名。

我为自己的服务做的是命名隧道。因为临时域名每次都会变,没法固定给用户使用。命名隧道的好处是:隧道 ID 固定,控制台里可以复用同一个隧道创建多条公开路由(比如a.example.com指向本机 8080 端口,b.example.com指向本机 3000 端口),而且 Tunnel Token 可以反复使用,相当于一张长期有效的“通行证”。

cloudflared 的配置逻辑也不难理解。安装好二进制之后,先cloudflared tunnel login做全局身份认证,然后cloudflared tunnel create <隧道名>会生成一段 Tunnel ID 和对应密钥。之后你可以直接在命令行指定--url启动,更便于管理的方式是写一个config.yml,把多条 ingress 规则放在里面,一条隧道管理员堆多个服务,这个做法非常像 Nginx 里配置多个 server 块,逻辑一脉相承。

2.3 身份认证层:Cloudflare Access 与零信任策略

如果只做“隧道打通”,那 cloudflare-os 和普通内网穿透工具就没有本质区别了。让这套系统真正有“OS 级安全”质感的,是 Cloudflare Access 这一层的加入。

Access 的原理可以理解成:请求先打到 Cloudflare 边缘,边缘会检查你的登录状态。如果未登录,直接重定向到身份提供商(身份提供商可以用 Cloudflare 自带的邮箱 OTP,或接 Google Workspace、GitHub 登录);登录成功之后,Cloudflare 会下发一个短时有效的会话 Cookie,后续每次请求边缘都会验证这个 Cookie 的签名的有效性,再把请求转发给源站。源站服务器本身不需要关心会话状态,不需要维护 JWT、Session ID 这些东西——因为身份验证已经完全前移到边缘了。

这样做的安全收益非常强。比如我部署在服务器上的很多个人运维工具,比如数据库管理面板、容器管理界面,这些东西自身有登录密码,但安全记录上出过不少漏洞。有了 Access 之后,我可以在边缘层面加一层“仅允许我的邮箱账号登录”,并且禁用所有未登录用户的源站访问尝试。攻击者哪怕拿到了程序本身的漏洞,连第一道门都进不来,因为他根本没有有效的边缘会话。

2.4 流量过滤层:DNS、防火墙与边缘规则

操作系统当然不能只有“入口认证”,还得有“内容检查”。cloudflare-os 的第三层能力是流量过滤。

这一层我用了两个维度。一是 DNS 过滤:把服务器的系统 DNS 设置为 Cloudflare 的 1.1.1.1,再配合 Cloudflare Gateway 的策略,可以在 DNS 解析阶段就拦截恶意域名。二是边缘防火墙:Cloudflare 免费版支持 5 条防火墙规则,配合 WAF 托管规则集,可以拦截常见的恶意爬虫、SQL 注入尝试、跨站脚本攻击。对于个人项目完全够用。

比较关键的一点是,边缘规则和源站防火墙各干各的,不冲突。边缘层挡掉大流量攻击和明显恶意请求,源站ufw只管本机端口开放范围。两层规则加起来就是纵深防御。我的服务器上实际效果是:外部扫描器看到的只是一台“没有开放任何公网端口”的主机,而边缘日志里每天帮我拦截掉几百次注入尝试。

2.5 原理解读:这条链路里的每个请求到底发生了什么

顺手串一下整条链路,方便大家有画面感。用户浏览器输入https://app.example.com:

  1. DNS 解析阶段,域名指向 Cloudflare 的 Anycast IP,就近接入边缘节点。
  2. Cloudflare 边缘检查该域名关联的 Access 策略,发现用户未认证,返回一个 302 重定向到登录页。
  3. 用户完成邮箱验证码认证,Cloudflare 生成会话 Cookie,重新发起原请求。
  4. 边缘节点放行请求,通过已经建立的隧道连接,把请求转发给源服务器的 cloudflared。
  5. cloudflared 根据config.yml里的 ingress 规则,把请求转发给本机对应端口(比如127.0.0.1:8080)。
  6. Nginx 或应用服务器正常响应,响应体原路返回,边缘节点负责开启 HTTPS 连接,用户全程无感知。

这整个过程里,用户连接的是 Cloudflare 的 IP,服务器只和 Cloudflare 边缘保持一条出站连接,源站这边不需要担心证书配置、端口暴露、DDOS 流量直击源站。这就是“操作系统级”安全的第一层含义:安全边界完全由边缘接管。

3. 实操搭建:从零开始部署一个可用的 cloudflare-os 环境

3.1 前置准备:域名与 Cloudflare 账号配置

动手之前你需要准备一个域名,并且把域名的 DNS 托管到 Cloudflare。域名在哪里注册的不重要,关键是把域名的 NS 记录改成 Cloudflare 分配的地址,这一步是后续所有配置的基础。

我建议先不要急着配置任何隧道规则,先把域名在控制台里“激活”。具体操作路径:Cloudflare 控制台 → 添加站点 → 输入域名 → 选择 Free 套餐 → 它会自动扫描你现有的 DNS 记录并导入,点击继续后你会拿到两个 NS 地址,去你的域名注册商处改 NS。改完后等几十分钟到几小时不等,域名状态从 Pending 变为 Active 就 OK 了。

给一个小提示:如果你手里没有域名,可以先去注册一个.xyz或.top之类便宜的后缀,一年也就几块钱,但如果是长期部署的项目,别用那种随时可能跑路的免费二级域名。这条链路里域名是身份的锚点,后面要接 TLS 证书、要绑 Access 策略、要配隧道路由,全需要域名支持。

3.2 安装与初始化 cloudflared

接下来是安装核心组件。以 Ubuntu 22.04 为例,官方提供 apt 仓库,配置起来很直接:

sudo mkdir -p --mode=0755 /usr/share/keyrings curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" | sudo tee /etc/apt/sources.list.d/cloudflared.list sudo apt-get update sudo apt-get install cloudflared

安装完之后,先验证一下版本:

cloudflared --version

如果输出正常,说明二进制已经就绪。接下来登录授权:

cloudflared tunnel login

这条命令会打印一个链接,你需要复制到浏览器打开,选择你托管在 Cloudflare 的域名,点击授权。授权完成后,cloudflared 会在本地~/.cloudflared/cert.pem写入一个证书文件,这个证书代表你有权限在这个账号下管理隧道。

然后创建隧道:

cloudflared tunnel create my-tunnel

创建成功后,控制台会出现一个 Tunnel ID,比如6d4a0c0e-82d7-4f0d-a800-123456789abc,同时本地~/.cloudflared/下会多出一个对应的凭据文件。这一步如果你忘了记 Tunnel ID,后面随时用cloudflared tunnel list查得到。

3.3 配置文件写法:用一条隧道管理多个服务

隧道创建好了,但不配置路由规则是没有意义的。我的做法是写一个config.yml,放在/etc/cloudflared/config.yml里,内容结构很简单:

tunnel: 6d4a0c0e-82d7-4f0d-a800-123456789abc credentials-file: /home/ubuntu/.cloudflared/6d4a0c0e-82d7-4f0d-a800-123456789abc.json ingress: - hostname: app.example.com service: http://localhost:8080 - hostname: status.example.com service: http://localhost:3000 - hostname: grafana.example.com service: http://localhost:9090 - service: http_status:404

注意最后一条规则写得有点特殊:service: http_status:404。这相当于一个兜底规则,任何没有匹配到前面 hostname 的流量,Cloudflare 会直接返回 404,不会转发到任何内网端口。我强烈建议你务必加上这个兜底,否则默认行为是拒绝连接还是转发到某个不存在的地址,行为不完全可控,加了兜底之后至少行为统一。

配置写完后先做一次语法检查:

cloudflared tunnel ingress validate

没有报错就可以启动服务:

sudo cloudflared service install sudo systemctl start cloudflared sudo systemctl status cloudflared

cloudflared service install这步会把 cloudflared 注册为系统服务,开机自启、崩溃自动重启这些全都由 systemd 替你管。相比之下,如果你只是nohup cloudflared ... &,重启机器后还得手动再拉起,完全谈不上“OS 级体验”。

启动服务之后,回到 Cloudflare 控制台,找到你的域名 → DNS → 添加两条记录。这里选 CNAME 类型,名称分别填app和status,目标统一填<隧道ID>.cfargotunnel.com。这个域名是 Cloudflare 为每条隧道自动分配的内部主机名,相当于告诉边缘:这个子域名的流量请走这条隧道。配好之后,等 DNS 传播生效,你访问https://app.example.com,应该就能看到隧道已经在正常工作了。

3.4 配置 Access 身份认证:给每个服务加一把锁

隧道通了之后,你的服务已经可以对外访问了。但这时候任何知道链接的人都能直接访问,所以下一步就要上 Access。

控制台操作路径:Zero Trust 面板 → Access → Applications → Add an application。类型选择 Self-hosted,域名填app.example.com。然后在 Policy 配置里,选择你允许登录的方式。如果是个人使用,最简单的方案是 Allow 指定邮箱后缀,比如@yourdomain.com,这样只有你自己的邮箱地址能过;如果你想给几个朋友开放,可以逐个添加邮箱地址,或者启用 Cloudflare 内置的 One-time PIN 登录,让他们填邮箱收验证码即可。

比较容易被忽略的配置是Session Duration(会话时长)。默认可能会是 24 小时,对个人项目有点太长了。我一般设置为 8 小时,记得在 Access 策略里把“Session Duration”调短一点,很多人第一次配完发现第二天还能登录,就是这里没注意。

还有一个技巧:如果你只想保护某个路径而不是整个域名,比如/admin路径,可以在 Access 的 Application 配置里把路径设为app.example.com/admin,这样就只对这个路径启用登录校验。这个能力在某些场景下很实用,比如你的站点对普通访客完全公开,只有管理后台需要认证。

3.5 配置 Cloudflare 防火墙规则与 WAF

再往外一层,给边缘加几条免费流量过滤规则。控制台路径:Security → WAF → Custom rules。

个人项目我一般配三条:

规则一:如果国家属于某个特定区域 且 请求路径包含 /wp-login.php,则拦截 规则二:如果请求 User-Agent 为空或匹配明显爬虫特征,则执行托管质询 规则三:如果请求速率超过每分钟 100 次,则拦截 10 分钟

公式写法其实很简单,直接在规则编辑器里选字段、选运算符、填值就行,不需要写代码。值得强调的一点是:Cloudflare 免费版支持“托管质询”,它不是直接拦截,而是先弹一个验证页,让通过验证的真人继续访问。对正常用户来说几乎无感知,但能有效卡掉大批自动化脚本。

源站侧也不用完全放弃。ufw可以设置一条非常严格的默认规则:

sudo ufw default deny incoming sudo ufw allow from 127.0.0.1 sudo ufw allow from 192.168.1.0/24 sudo ufw enable

这样所有外部入站连接都被系统防火墙挡死,只有本机和局域网能直达端口。配合隧道转发,实际效果就是你的服务只能从隧道进入,等于给服务器套了两个门锁。

3.6 可选的 WARP 客户端:给源站出站流量加上加密通道

如果希望服务器访问外部 API 时也走 Cloudflare 网络,可以在同一台机器上装 WARP 客户端。WARP 是 Cloudflare 提供的免费客户端,装上之后所有出站流量会通过 Cloudflare 的网络加密转发,在公共 Wi-Fi 环境下非常有用。

Ubuntu 上安装:

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main" | sudo tee /etc/apt/sources.list.d/cloudflared.list sudo apt-get update sudo apt-get install cloudflare-warp

注册并连接:

warp-cli registration new warp-cli connect warp-cli status

这条链路的好处是服务器访问外部服务时,目标网站看到的 IP 是 Cloudflare 的 IP,源站的 IP 继续隐藏。对很多爬虫采集、API 调用场景来说,这个特性是额外红利。不过也有个需要注意的地方:启用 WARP 之后,如果你这台服务器本身还在跑需要固定 IP 白名单的服务,容易出问题,因为出站 IP 变成了 Cloudflare 的动态 IP。所以建议按需启用,不要无脑常开。

4. 常见问题与排查技巧实录

4.1 域名访问出现 1033 错误或 1034 错误

这个算是我在实操中碰到最多的问题之一。如果访问域名时,Cloudflare 直接返回一个错误页面,上面写着“1033 Argo Tunnel error”或者“1034”,大多数情况下是因为 DNS 记录里的目标地址不对,或者隧道没有正常运行。

第一次排查我会这样做:

cloudflared tunnel list cloudflared tunnel info <隧道名>

info会显示当前隧道是否有活跃连接。如果返回 0 个连接,说明客户端没起来;如果连接数大于 0,再检查 DNS 记录:

dig APP.example.com CNAME

正确结果应该是<Tunnel-ID>.cfargotunnel.com。如果 CNAME 指到了别的地方,去控制台修正 DNS 记录,等一两分钟再试就好。

4.2 登录认证成功但页面反复跳转

这个场景也很典型:你用 Access 登录,跳转了几个来回,但始终看不到真正的应用页面。我踩过这个坑后总结,绝大多数原因是Access 的 Cookie 域名和实际访问的域名不一致。

比如你把 Access 应用配置成了app.example.com,但实际上浏览器访问的是app.example.com:8080或者 IP 直连,Cookie 就无法匹配导致循环跳转。解决办法也很简单:访问一律用标准 443 端口,不要带自定义端口。另外,如果你中途改过域名,旧的 Cookies 还残留着,清理一下浏览器站点数据再试也很有效。

4.3 隧道连接不稳定,时不时 502 或超时

隧道跑起来之后偶尔出现 502,一般先看源站端口有没有正常监听:

ss -lntp | grep 8080

如果端口正常,再去看 cloudflared 日志:

journalctl -u cloudflared -f

我遇到过最隐蔽的一次问题是:配置文件里 hostname 指向的是http://localhost:8080,但 Nginx 只监听了 IPv6 的::1而不是 IPv4 的127.0.0.1,导致 cloudflared 转发请求时连接被拒。这类问题单纯看日志不一定明显,但当你用curl http://127.0.0.1:8080测试会立刻暴露。建议大家在写 ingress 规则时,统一用127.0.0.1而不是localhost,能减少一大部分 IPv6 解析差异引起的奇怪问题。

4.4 新增服务后隧道不生效

你添加了一个新的 ingress 规则,保存重启 cloudflared,但域名访问还是 404 或者 1033。这种情况先别急着怀疑配置不对,先确认新 hostname 是否添加了对应的 DNS CNAME 记录。很多人会漏掉这一步。隧道 ingress 只负责“流量来了之后转发到哪里”,至于“流量怎么来”,还需要 DNS 记录把域名指向隧道。

4.5 证书过期问题

这里说的证书不是源站证书,而是 cloudflared 的本地登录证书cert.pem。这个证书默认有效期是 10 年,日常基本不用管,但如果某一天你重新登录授权了另一个账号,旧隧道的证书会失效。处理方式很简单,重新执行cloudflared tunnel login,然后重启服务即可。

4.6 边缘规则误杀正常用户

防火墙规则最怕“宁可错杀一千”式的配置。我早期曾设置了一条规则:拦截所有非浏览器 UA 的请求。结果导致很多 API 客户端和 RSS 订阅器全部失效,好几个自动化任务直接停摆。

后来学乖了:边缘规则尽量用“质询”而不是“拦截”,给正常用户留一条活路;同时对 UA 尽量少做激进判断,因为 UA 本来就是客户端可以伪造的,它在防爬虫上的作用远不如速率限制有效。防火墙规则的核心目标应该是挡住端口扫描、注入攻击、异常速率,而不是去猜谁是真人。

5. 个人经验与最终建议

整套 cloudflare-os 方案我跑了半年多,从一个裸奔的 VPS 迁移到了“边缘安全网关”体系,最直观的感受是:很多事情确实被前置简化了。以前要自己维护 TLS 证书、配反向代理、写防火墙规则、绞尽脑汁隐藏真实端口,现在全部统一到 Cloudflare 边缘处理,控制台里点两下就能完成一次策略变更,访问日志、安全事件、身份认证状态全在一个面板里看得到。这种“统一控制面 + 分散数据面”的体验,确实有点像在用一个大厂定制好的安全操作系统,而不是一堆零散工具的堆叠。

如果你也想搭,我的建议是不要一上来就追求大而全。先把最基本的 cloudflared 隧道跑通,让一个服务能通过自己的域名安全访问,再逐步加上 Access 认证、WAF 规则、WARP 出站。每一步都等稳定运行一段时间再加,这样出了问题你能明确知道是哪一层新增策略引起的。整套体系的学习成本不算高,但胜在每一层都是在为“暴露面最小化”添砖加瓦。

最后再分享一个小技巧:所有系统级配置(cloudflared 的 config、systemd 的 service 文件、ufw 规则)都建议纳入版本管理,就算是自己一个人用也值得做一份简单的 git 仓库。因为这套体系的坑不在于某一个组件多难配置,而在于改来改去之后,你可能自己都忘了哪个规则是哪天为了什么原因加的。有版本历史兜底,回滚和排错都会从容得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询