速读#
Cloudflare Tunnel 解决的是“外部请求怎样到达内网服务”,Cloudflare Access 解决的是“到达之前先确认访问者是谁”。两者经常出现在同一个 Zero Trust 控制台里,但职责完全不同。
对个人站,最合理的边界通常不是全站弹人机挑战,而是:
- 主页和文章公开访问。
/admin先经过 Access 身份门禁。- OAuth 回调保持可达,由 OAuth 状态校验保护。
- 部署 webhook 使用签名验证,不接受浏览器身份代替。
- 健康检查只返回最小状态,不泄露内部信息。
先按用途分路径,再给每条路径放对应的保护,体验和安全都会更清楚。
Tunnel 只改变连接方向#
传统发布方式是让 Cloudflare 或访客从公网连接源站 80/443。Tunnel 则由 cloudflared 主动向 Cloudflare 建立出站连接,请求沿这条连接回到服务。
访客 -> Cloudflare 边缘 -> Tunnel -> 本机服务它带来的直接收益是源站可以不开放 Web 入站端口。但请求一旦进入 Tunnel,后面的服务仍需要决定是否允许这个访问者操作。
这和 Nginx 能把请求转给后台、却不能自动判断谁是管理员一样。可达不等于授权。
Access 在 Tunnel 前面加身份门禁#
Access 会在请求进入受保护应用前要求登录,并根据策略判断是否放行。身份可以来自 GitHub、Google、一次性邮箱验证码或企业身份提供方。
访客 -> Access 登录与策略 -> Cloudflare 边缘 -> Tunnel -> 管理页面未通过策略的请求不会到达源站。相比在应用里单独写一个管理密码,这样能减少登录接口暴露,并复用成熟的身份验证与会话管理。
但 Access 不是应用权限系统。通过 Access 只说明“这个人可以进入应用”,不代表他可以执行应用内所有操作。后台仍要保留服务端认证、权限校验和操作日志。
公开站和管理站不要用同一条规则#
如果给整个主域名加 Managed Challenge 或 Access,普通读者每次访问文章都要先过一道门。搜索引擎、RSS 阅读器和预览抓取也可能受影响。
个人博客的公开内容本来就应该公开,真正需要收紧的是管理路径。可以把应用范围限定在:
s1oopx.bond/admin*再用允许策略只放行自己的身份。这样文章、项目和 RSS 保持正常,管理 UI 在加载前就被挡住。
路径规则要覆盖 /admin、/admin/ 及其静态资源请求。配置后必须用未登录的隐私窗口验证,不能只在已经有 Access 会话的浏览器里看结果。
OAuth 回调为什么要单独看#
静态 CMS 通过 GitHub 登录时,通常会离开站点完成授权,再回到一个 OAuth callback。若 Access 规则过宽,把 callback 也拦住,浏览器会在两套登录之间跳转,最终表现为授权完成却回不到 CMS。
因此路径应该按角色分开:
| 路径 | 保护方式 |
|---|---|
/admin* | Access 身份门禁 + CMS 自身 GitHub 登录 |
/oauth* | OAuth state、回调白名单和服务端校验 |
/deploy/github* | webhook secret 或签名校验 |
/healthz | 最小响应、必要时限制来源 |
| 其他公开页面 | 正常 CDN/WAF,不做全站身份验证 |
Access 适合人访问的管理入口;webhook 是机器调用,应该验证请求签名。把两类流量硬塞进同一登录规则,只会让自动化失效。
人机挑战和身份验证不是一回事#
Managed Challenge 判断访问行为是否像真人或可信浏览器,Access 判断访问者是否符合身份策略。
| 目标 | 合适工具 |
|---|---|
| 减少自动化滥用 | WAF、限速、Managed Challenge |
| 只允许自己进入后台 | Access |
| 确认 GitHub 用户并获得仓库权限 | GitHub OAuth |
| 确认 webhook 来自 GitHub | webhook 签名 |
挑战通过后仍然可能是陌生人,所以不能拿它保护管理后台。反过来,已经通过 Access 的管理员也不该在每次打开页面时重复做人机验证。
最小策略比复杂规则更可靠#
对单人维护的博客,Access 策略不需要设计成企业权限矩阵:
- 建一个只覆盖
/admin*的 Self-hosted application。 - 选择一个自己长期可用的身份提供方。
- Allow 策略只写自己的账号或邮箱。
- 会话时间不要无限长,失窃设备才能自然失效。
- 保留应用自身的 GitHub OAuth,不让 Access 代替仓库授权。
无需提前加入 service token、多组用户和设备姿态规则。等真的出现第二位维护者或机器调用后台时,再增加对应策略。
配置后验证四种状态#
只看控制台显示 Active 不够。我会分别验证:
| 状态 | 预期结果 |
|---|---|
| 未登录访问主页 | 直接打开 |
未登录访问 /admin | 跳到 Access 登录 |
| 允许账号完成 Access | 能加载 CMS,再进入 GitHub OAuth |
非允许账号访问 /admin | 被拒绝,源站没有对应管理请求 |
然后再测试 OAuth 回调、部署 webhook 和健康检查,确认它们没有被路径规则误伤。规则一旦按路径拆开,排查也简单:先看 Access 是否放行,再看 Tunnel 是否连通,最后看应用认证。
我会保留的边界#
我的站点会把四件事分开:
Tunnel -> 服务怎样到达Access -> 谁能进入管理入口OAuth -> 谁能以 GitHub 身份操作仓库Webhook -> 自动部署请求是否可信它们不是四层重复防护,而是四个不同问题。把全站 Challenge 当成万能开关,既影响访客,也没有真正解决后台身份;把管理路径单独交给 Access,公开内容保持公开,管理入口才真正有了边界。
