☰
cloudflare-os实战:基于Cloudflare隧道与Access的自建服务安全入口
2026/10/28 11:50:38 网站建设 项目流程

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 cloudflared

Docker 方式适合已经全面容器化的环境。官方镜像 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,查看日志
返回 526TLS 加密模式不匹配,源站证书无效将 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% 的日常需求只需要隧道加访问控制加证书管理这三块就能覆盖。越是简单的架构,越容易维护,出问题时定位也越快。

如果你正准备上手,我的建议是从一个最不重要的子域名开始,走通一次完整流程,再逐步迁移正式服务。这门技术的学习成本并不高,但每一步配置背后都有一套安全模型,想明白“为什么这么做”比背命令重要得多。让它自然长在自己的使用习惯里,比一开始就追求架构完美更靠谱。

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

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

立即咨询