1. 先搞清楚 cloudflare-os 到底是什么
我第一次看到 cloudflare-os 这个名字,第一反应是去 GitHub 上搜仓库,结果发现这并非某个官方发布的操作系统发行版,而是社区里对“把 Cloudflare 开源工具链部署到自有 Linux 环境,形成一套具备边缘网络能力的系统底座”这种实践的统一称呼。我按这套思路在自己的服务器上完整跑了一遍,把家里的自建服务、团队内部的小工具全部收拢到一个统一的访问入口后面,体验相当不错。
这套实践的核心价值在于:你不必再为每一个自建服务单独处理公网暴露、IP 变更、证书申请、访问鉴权这些重复劳动,而是把 Cloudflare 的全球边缘网络当成一个“前置系统”,让流量先经过边缘清洗和身份校验,再进入你自己的服务器。这篇文章就是我对这套方案的完整复盘,重点讲组件选型逻辑、部署步骤、访问控制策略和问题排查,适合熟悉 Linux 基础操作、想给自建服务加一层安全入口的开发者和运维同学参考。
1.1 名称的由来与社区实践
“cloudflare-os”严格来说不是 Cloudflare 官方推出的操作系统,而是技术社区的一种约定俗成。随着 cloudflared、BoringTun、Pingora 等组件陆续开源,越来越多的人开始尝试在自有的 Linux 主机上把这些边缘能力组合起来,最终形成了一个“操作系统感”很强的体系:有网络层、有安全层、有控制面、有数据面,只不过这些都跑在你自己维护的机器上。
我在实际搭建时发现,社区的多数方案都遵循类似的分层思路:最底层是 DNS 解析与边缘代理,中间是隧道连接与证书管理,上层则是流量转发规则和访问控制策略。如果你把这些组件比作积木,cloudflared 负责打通“边缘到源站”的通道,Access 负责决定谁能进,而 DNS 记录则是整个体系的入口。理解了这个分层结构,后面所有配置都会变得顺理成章。
1.2 这套方案解决的核心问题
先说几个我真实遇到的场景,你应该也有共鸣。
第一个是“公网暴露焦虑”。以前我在服务器上跑一个 Web 服务,想从外面访问,要么直接把端口暴露到公网,要么去路由器上做端口映射。这两种做法都逃不开一个隐患:源站 IP 一旦泄露,后续的 DDoS 和端口扫描就全来了。cloudflared 隧道方案不开放任何入站端口,出站连接由你的服务器主动发起,源站 IP 落在 Cloudflare 后面,安全性高了一个量级。
第二个是“证书管理麻烦”。Let's Encrypt 的证书自动化已经很好用了,但每次续期失败、证书链配错、某个子域不生效,都会消耗不少时间。隧道方案可以直接用 Cloudflare 边缘证书,同一个证书体系覆盖所有子域,加上源站证书后链路完全加密,省掉了大量重复操作。
第三个是“多设备访问权限不一致”。以前团队内部工具只靠一个简单的登录密码保护,换成 Cloudflare Access 之后,权限策略集中在控制台里管理,按邮箱域名、按身份源限制访问范围,撤销某个人的权限只需要改一条规则,不用再去服务里删账号。单是这一点,我觉得就值回折腾成本了。
1.3 适用场景与不建议使用的场景
如果你有下面这些需求,这套方案非常适合你:
- 自建了 Nextcloud、Jellyfin、Grafana、Home Assistant 等服务,希望在不暴露端口的前提下安全访问;
- 维护了多个小型 Web 应用,域名不想一个个单独折腾证书;
- 有小团队协作平台,需要细粒度的访问控制与审计日志;
- 常年在 NAT 之后、没有固定公网 IP 的家庭网络里跑服务。
反过来,我也要说几句实话。如果你的业务对延迟极其敏感,请求完全走 Cloudflare 边缘节点会增加一跳网络开销,虽然体感通常不明显,但极端场景下还是要实测对比后再决定。另外,Cloudflare 免费计划的流量额度虽然在个人使用范围内一般够用,但如果要大规模分发视频或大文件,就得认真评估成本,不能无脑套用。
2. 整体架构设计与组件选型
在动手安装之前,先花点时间把架构理清楚。我习惯把这套系统分成四层来看:域名与 DNS 层、边缘控制层、隧道连接层、源站应用层。每一层的职责单一,排查问题时也容易定位。
2.1 为什么把 Linux 作为部署底座
我选择 Linux 作为部署底座,不是因为 Windwos 不好,而是这套生态里的绝大多数工具都优先支持 Linux,文档示例、systemd 服务单元、日志采集方案基本都是围绕 Linux 展开的。我自己用的是 Debian 系发行版,Ubuntu 22.04 LTS 和 Debian 12 都跑过,稳定性没有区别,选你熟悉的就行。
底层系统的要求其实很低:内存 512M 起步,单核 CPU 就足够跑一个中等负载的小型家庭网关。如果只是转发少数几个服务的流量,资源占用几乎可以忽略不计,常驻内存通常在 80M 到 150M 之间。把 cloudflared 安装在一台长期开机的低功耗设备上(比如旧笔记本、小主机),比跑在一台随时关机的家用电脑上可靠得多。
我做过一个小对比,不同安装方式对最终使用体验的影响:
| 安装方式 | 配置复杂度 | 适用场景 | 我的推荐度 |
|---|---|---|---|
| 官方二进制直接部署 | 低 | 单机快速上手 | 高 |
| 官方仓库包管理器安装 | 低 | 生产环境需要 systemd 托管 | 高 |
| Docker 容器部署 | 中 | 已有容器化体系、需要统一编排 | 中 |
不同方式没有绝对优劣,但我更倾向于用包管理器装官方仓库的版本,原因很简单:升级方便,systemd 服务文件会自动创建,日志收集也标准化,省得自己手写一堆维护脚本。
2.2 核心组件地图
这套体系里真正承担核心职责的组件并不多,但每一个都对应着一个不可替代的环节。
cloudflared 是最重要的组件,它在你的服务器与 Cloudflare 边缘之间建立一条双向的加密通道。它默认走 HTTPS 出站连接,所以你不需要在路由器上开放任何入站端口,也没有公网 IP 的硬性要求。创建隧道时会生成一个唯一 ID,边缘节点根据这个 ID 把匹配的域名流量路由到你的服务器。
Cloudflare DNS 负责把业务域名解析到 Cloudflare 的边缘节点。这里有一个关键点:要让 Cloudflare 代理生效,域名的解析必须使用 Cloudflare 的 nameserver,或者在 DNS 记录里把流量走代理通道(橙色云标志)。如果你只是把 DNS 当作普通解析用,边缘层的能力基本发挥不出来。
Cloudflare Access 是访问控制组件,基于 Zero Trust 模型工作。流量到达边缘时,Access 会先检查请求者是否满足你配置的策略,满足之后才允许其继续访问背后的服务。它的配置逻辑类似“前置门禁”,和源站应用自身的登录体系相互独立,可以有效防止应用漏洞暴露到公网。
2.3 数据流向与关键取舍
这套体系里,一次正常请求的完整链路是这样的:
用户访问 app.example.com,域名解析到 Cloudflare 边缘节点;边缘节点检查访问策略与 TLS 状态,通过后,流量经由 cloudflared 建立的隧道转发到你的服务器本地端口;应用处理完请求后原路返回响应。整个过程里,公网侧看到的只有 Cloudflare 的 IP,你的服务器 IP 对普通用户基本不可见。
这里有一个需要做出取舍的地方:应用服务应该直接绑定在本地端口上,还是外面再套一层 Nginx?我的建议是,如果服务本身已经占用了 80/443,或者你需要在转发前做额外的请求头改写、路径路由,那就保留 Nginx 或 Caddy 做前置;如果只是把简单服务暴露出去,直接用 cloudflared 的 ingress 规则把域名映射到端口即可,多一层代理就多一层故障点。
3. 部署准备与基础安装
架构清楚之后,实际操作就顺畅多了。这一节我会按照我踩过坑之后总结出的顺序来讲,第一步准备工作不要跳过。
3.1 域名、账号与服务器准备
你需要准备的东西不多:一个域名、一个 Cloudflare 账号、一台能长期开机的 Linux 服务器、一个自己想暴露的子域名。
域名方面,把域名的 DNS 托管到 Cloudflare 是这套方案的前提。如果你已经在用其他 DNS 服务商,迁到 Cloudflare 无非是把域名的 nameserver 换成 Cloudflare 分配给你的那两个,传播时间一般在几分钟到几小时不等。迁过来之后,先在 Dashboard 里确认域名的状态是 Active,再继续下一步。
服务器方面不需要做什么特殊配置,唯一要注意的是出站防火墙。有些云厂商的默认安全组策略比较严格,这通常不影响云主机主动访问外网,但如果你在本地路由器上加了出站过滤规则,要确认允许 7844、443 等端口出站。这里提一下,隧道默认使用 7844 端口做 QUIC 连接,失败会回退到 443 的 HTTP 连接,只要出站访问不受限,基本都能连通。
3.2 安装 cloudflared:三种方式的对比
官方二进制方式最直接。到 GitHub 的 cloudflared 发布页面下载对应架构的二进制,丢到 /usr/local/bin 下,加执行权限,再验证一下版本:
sudo wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -O /usr/local/bin/cloudflared sudo chmod +x /usr/local/bin/cloudflared cloudflared --version包管理器方式更适合生产环境。Debian/Ubuntu 用户可以用下面的命令添加官方仓库然后安装,装完会生成 cloudflared 用户和 systemd 服务模板:
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 $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list sudo apt-get update && sudo apt-get install cloudflaredDocker 方式适合已经全面容器化的环境。官方镜像 cloudflare/cloudflared 会定期更新,启动时把 token 或配置文件以环境变量或挂载方式传进去即可。不过我不太建议第一次尝试这套方案的人直接用容器,因为你还没弄清楚日志怎么找、配置怎么热加载,容器会多一个抽象层,排查问题时会多一些不便。
3.3 初始化隧道与 Token 获取
初始化方式有两条路线,我先说最简单的:在 Cloudflare Zero Trust Dashboard 里创建隧道。
登录 Cloudflare Dashboard,进入 Zero Trust => Networks => Tunnels,点击 Create a tunnel。命名随意,比如 home-gateway。创建完成后,页面会给你一条安装命令和对应的 Token,长这样:
cloudflared service install <token>在服务器上执行这条命令,cloudflared 会自动安装成系统服务并启动。这种方式的优点是无需在服务器上管理证书文件,Token 本身就绑定了隧道身份,换机器重新部署时直接把 Token 填进去就行。
另一种是命令行登录方式,适合想保留本地配置文件的用户。在服务器上执行cloudflared tunnel login,会生成一个登录链接,浏览器里打开并选择你的域名完成授权;然后cloudflared tunnel create tunnel-name,它会生成隧道 ID 和配套的凭据文件。这种方式的好处是配置文件完全可控,坏处是 cert.pem 如果丢了,重新登录生成后需要重新关联。
我个人的建议是:家庭用户或者只有一个节点的用户,直接走 Dashboard 的 Token 方式,省心;如果以后计划做多节点冗余、自己管理配置文件,那就一开始就习惯命令行方式。
4. 严格安全入口:Zero Trust 访问控制配置
隧道通了只是第一步,真正让这套方案比普通端口转发更安全的核心在于访问控制。Cloudflare Access 可以做到“未授权请求根本到不了你的源站”,这一点我非常看重。
4.1 创建 Access Application
在 Zero Trust 控制台里进入 Access => Applications,点击 Add an application,选择 Self-hosted。这里填的 Application domain 就是你要保护的子域名,例如 app.example.com。如果以后需要保护多个子域名,可以在同一个 Application 里配置多个域名,共用一套策略,管理效率高很多。
创建 Application 之后,进入 Policy 配置。默认情况下有一个名为 Allow 的初始策略,你可以立即修改它,改成“允许指定邮箱或指定域名下的所有账号”。比如团队内部工具,就可以限制为只有公司域名邮箱可以访问。策略会实时生效,不需要重启服务,这一点我实测过多次,配置保存后立刻就能感受到访问行为的变化。
4.2 策略规则与身份源配置
Access 的身份源默认支持邮箱验证加一次性验证码,但如果你不想让访问者每次都被要求输入邮箱验证码,可以提前接一个身份源。常见的选择有三种:
| 身份源 | 优点 | 缺点 |
|---|---|---|
| 邮箱 OTP | 无需额外账号体系 | 每次都输验证码,体验略繁琐 |
| GitHub / Google | 登录体验好 | 需要提前创建 OAuth 应用 |
| 本地 Username/Password | 完全自主可控 | 需要维护额外账号体系 |
我在实际使用中,个人服务器选了邮箱 OTP,因为个人使用频率不高,安全性和简单性兼顾;团队协作的小工具则接了企业的 OAuth 身份源,成员一次登录后可以用已有账号进入,体验顺畅很多。
策略本身支持 AND/OR 组合规则,可以按用户邮箱、IP 段、国家、设备姿态等多个维度来限制。比如我只允许自己家的出口 IP 直接放行,其余来源都必须走邮箱验证码,这样可以减少日常访问的验证环节,又不牺牲整体安全性。
4.3 二级验证与安全加固细节
Access 本身已经是一道很强的门禁,但还可以做得更细。
一个很实用的功能是 Access Service Token。它本质上是给机器用的身份凭证,不绑定具体用户。当你需要让另一台服务器(比如监控脚本、备份任务)通过 API 访问受保护服务时,Service Token 比在策略里硬编码 IP 更可靠,因为 IP 可能变化,Token 可以随时撤销。
另一个值得开启的是审计日志。Zero Trust 控制台的 Access => Logs 里能看到每一次请求的决策结果,包括允许或拒绝、命中哪条策略、用户是谁。出了问题回溯时,这几乎是唯一的权威信息来源。有一次我发现某个接口被频繁访问,最终就是从日志里定位到是服务间调用的健康检查,而不是安全事件,效率很高。
最后说一个细节:如果某个子域名没有配置 Access Application,那么默认情况下它是可以被公网直接访问的,前提是 DNS 记录走了代理模式。所以说,一定要养成习惯,每创建一个新子域名的隧道路由,就立刻同步去 Access 里新增一个 Application 或者加入已有 Application 的域名列表,这一步漏掉等于把门开着。
5. TLS 证书与反向代理联动配置
访问控制解决“谁能进”的问题,TLS 解决“通道是否加密、连接是否可信”的问题。这一节专门讲证书链路和源站侧的配置方式。
5.1 证书链路设计
整条链路上有两种证书角色。一种是边缘证书,由 Cloudflare 自动签发和管理,负责用户到边缘节点这一段;另一种是源站证书,负责边缘节点到你服务器这一段的加密。
在 Dashboard 的 SSL/TLS => Overview 里,加密模式建议直接选 Full (strict)。这个模式的含义是:不仅要求边缘到源站使用 HTTPS,还要求源站使用的证书由受信任的 CA 签发。如果你用的是 Cloudflare 自己生成的源站证书,它会自动被信任,无需在服务器里安装额外的根证书。
我在刚接触这套体系时犯过一个错:把加密模式设成 Flexible,结果边缘到源站是明文 HTTP。Flexible 模式下,数据虽然在用户和边缘之间加密了,但边缘到你本机的这一段是裸露的,隧道内传输的内容可以被本机网络上的其他程序看到,这完全违背了部署这套方案的安全初衷。
5.2 cloudflared 直连与 Nginx 前置两种模式对比
cloudflared 的 ingress 规则支持直接把域名映射到本地端口,比如 http://localhost:8080。这种情况下,隧道内部已经用源站证书做了加密,你不需要在本地服务上额外配置证书,因为 cloudflared 对边缘节点而言就是 HTTPS 源站。
但如果你已经有 Nginx 在跑反代,或者需要在一个端口上同时服务多个域名,那就让 Nginx 挂在 443,再让 cloudflared 把流量转发到 Nginx。这时候需要在 Nginx 的 server 块里配置源站证书的私钥和证书文件:
server { listen 443 ssl http2; server_name app.example.com; ssl_certificate /etc/ssl/cloudflare/origin-cert.pem; ssl_certificate_key /etc/ssl/cloudflare/origin-key.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }两种模式没有谁绝对更好。服务简单、域名少走直连省事;服务复杂、需要路径重写和请求头定制就上 Nginx,灵活更重要。
5.3 源站证书生成与配置
源站证书在 SSL/TLS => Origin Server 页面生成。操作时填两个信息:证书覆盖的域名列表和证书有效期,有效期官方允许最长 15 年,按照自己的安全策略选择即可,我一般选 10 年以上,省得隔几年就更换一次。
生成后会得到证书内容和私钥,保存到安全目录。证书内容建议保存为 /etc/ssl/cloudflare/origin-cert.pem,私钥保存为 /etc/ssl/cloudflare/origin-key.pem,权限设置为 600 并属主改为运行 Nginx 或 cloudflared 的用户。私钥文件权限太宽松是一个很容易被忽略的点,版务安全配置里最好也纳入例行检查。
如果你用的是纯 cloudflared 隧道模式,源站证书会在隧道与边缘建立连接时自动协商好,配置文件里 entry 后面写的 service 仍然是 http://localhost:8080 这种形式,不需要额外修改应用本身。
6. 稳定性、性能与常见问题排查
再稳的方案,实际运行中总会遇到奇怪的问题。我把这段时间遇到的典型问题和排查思路整理出来,希望你能少走一些弯路。
6.1 日志体系与常用诊断命令
把 cloudflared 当作 systemd 服务运行后,日志统一由 journald 管理,查看起来非常方便:
journalctl -u cloudflared -f日志里通常能看到网络连接建立、重连、请求转发的记录。如果某个服务出现 502,先看日志尾部有没有ERR error="Unable to reach the origin service"之类的报错,这能立刻定位到是源站端口没监听,还是防火墙拦截了本机连接。
还有一个内置的指标接口:cloudflared 默认监听 127.0.0.1:2000,访问 /metrics 可以看到连接数、请求数、TLS 证书过期时间等 Prometheus 指标。手动验证方法如下:
curl http://127.0.0.1:2000/metrics | grep -E "tunnel_cert_expiry|tunnel_requests_total" | head视图里看隧道是否在线,也可以在 Dashboard 的 Tunnels 页面查看 Connectors 数量。正常情况下会有 1 到 4 个连接,多条连接是并发的,出现若干连接断开又能自动重连的情况都不算异常。
6.2 典型问题速查表
| 现象 | 可能原因 | 处理方法 |
|---|---|---|
| 访问域名返回 502 | 源站端口没监听或 config 映射错误 | 检查 ingress 中的 service 地址,确认本地服务端口正常 |
| 返回 521 | 边缘无法连接源站,隧道未在线 | 执行 systemctl status cloudflared,查看日志 |
| 返回 526 | TLS 加密模式不匹配,源站证书无效 | 将 SSL 模式改为 Full (strict),重新生成源站证书 |
| 隧道在线但子域名解析失败 | DNS 记录没有指向隧道 | 在 DNS 面板把该子域名设为橙色云代理,或运行 tunnel route dns 命令 |
| 访问时反复要求验证 | Access 策略冲突或身份源异常 | 检查策略顺序,确认是否有两条策略互相覆盖 |
| 修改配置后不生效 | 忘记重启 cloudflared | 修改 /etc/cloudflared/config.yml 后执行 systemctl restart cloudflared |
另外有个容易被误判的坑:如果 config.yml 里的 ingress 规则写了多个域名,最后一条必须是一个 catch-all 规则,通常返回 http_status:404,否则启动时 cloudflared 会直接报错拒绝启动。这是我第一次配置时踩到的,印象非常深刻。
6.3 监控与告警
系统搭好之后不可能天天盯着 Dashboard 看,所以我用最简单的方式做了监控:从 cloudflared 的 Metrics 接口采集指标到 Prometheus,再用 Grafana 挂一个简单的面板,展示连接数、请求量、证书到期时间。
如果不想引入整套监控栈,也可以写一个只有十几行的 shell 脚本,每 5 分钟请求一次某个受保护的页面,检查 HTTP 状态码,非 200 就触发通知。这套“穷人版探活”方案我已经稳定运行了很久,对于个人服务器来说足够了。重要的是形成规则:每次变更配置后都去看一眼日志和指标,变化做到心里有数。
7. 扩展玩法与个人体会
主体功能稳定之后,这套“ cloudflare-os ”体系完全可以根据自己的需求继续扩展。我目前实际用上的几个方向是:多节点冗余、SSH 安全访问、自动化备份。
7.1 多隧道、SSH 与备份恢复等扩展
多节点冗余的思路非常直接:同一隧道可以在多台服务器上同时用同一个 Token 运行多个 connector。Cloudflare 会把请求分担到各节点,某台机器离线时,其他节点继续接管流量。家里一台、云上一台,形成简单的高可用组合后,日常维护时重启任意一台设备都不影响服务可用性。
SSH 访问也建议收编到这套体系里。Cloudflare 对 SSH 提供了专门的保护方式:先安装好 Access 的客户端,再通过cloudflared access ssh --hostname ssh.example.com建立代理连接,本机连接时修改 SSH 配置指向该代理即可。这样就不再需要在防火墙上开放 22 端口,也避免了暴力破解的批量攻击。SSH 密钥弹窗验证虽然比裸 ssh 多一步,但安全收益完全值得。
备份恢复这块,我长期坚持只备份两个关键目录:一个是 cloudflared 的配置目录,包含 config.yml 和隧道凭据;另一个是 Nginx 下的证书目录。隧道本身的逻辑是声明式的,只要凭据和配置完整,在新机器上恢复后几分钟就能重建整个入口,不用再从头梳理域名和路由规则。
7.2 我踩过几次坑之后的一些经验
按照惯例,最后说几句掏心窝的话。
第一次配置时,我把所有心思都放在隧道建立上,忽略了 Access 策略配置,结果域名解析生效后,恶意扫描器马上就开始打我的端口。后来我在日志里看到大量陌生 IP 的访问记录,才意识到“隧道通了”和“访问受控了”完全是两件事,从那以后我再也不会把隧道开通和访问控制分成先后两步做了。
还有一个感受很深的经验:不要过度追求对标的“大而全”。我最初给自己的目标是在这套体系里加入完整的日志分析、WAF 规则、负载均衡,结果折腾了整整两周,最后发现 90% 的日常需求只需要隧道加访问控制加证书管理这三块就能覆盖。越是简单的架构,越容易维护,出问题时定位也越快。
如果你正准备上手,我的建议是从一个最不重要的子域名开始,走通一次完整流程,再逐步迁移正式服务。这门技术的学习成本并不高,但每一步配置背后都有一套安全模型,想明白“为什么这么做”比背命令重要得多。让它自然长在自己的使用习惯里,比一开始就追求架构完美更靠谱。