跳到正文
Tunnel 让服务能访问,Access 决定谁能访问
Tunnel 让服务能访问,Access 决定谁能访问

Tunnel 让服务能访问,Access 决定谁能访问

Cloudflare Tunnel 把内网服务接到公网,但它不负责识别访问者。公开主页、管理后台、OAuth 回调和部署接口需要按路径建立不同边界。

速读#

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 来自 GitHubwebhook 签名

挑战通过后仍然可能是陌生人,所以不能拿它保护管理后台。反过来,已经通过 Access 的管理员也不该在每次打开页面时重复做人机验证。

最小策略比复杂规则更可靠#

对单人维护的博客,Access 策略不需要设计成企业权限矩阵:

  1. 建一个只覆盖 /admin* 的 Self-hosted application。
  2. 选择一个自己长期可用的身份提供方。
  3. Allow 策略只写自己的账号或邮箱。
  4. 会话时间不要无限长,失窃设备才能自然失效。
  5. 保留应用自身的 GitHub OAuth,不让 Access 代替仓库授权。

无需提前加入 service token、多组用户和设备姿态规则。等真的出现第二位维护者或机器调用后台时,再增加对应策略。

配置后验证四种状态#

只看控制台显示 Active 不够。我会分别验证:

状态预期结果
未登录访问主页直接打开
未登录访问 /admin跳到 Access 登录
允许账号完成 Access能加载 CMS,再进入 GitHub OAuth
非允许账号访问 /admin被拒绝,源站没有对应管理请求

然后再测试 OAuth 回调、部署 webhook 和健康检查,确认它们没有被路径规则误伤。规则一旦按路径拆开,排查也简单:先看 Access 是否放行,再看 Tunnel 是否连通,最后看应用认证。

我会保留的边界#

我的站点会把四件事分开:

Tunnel -> 服务怎样到达
Access -> 谁能进入管理入口
OAuth -> 谁能以 GitHub 身份操作仓库
Webhook -> 自动部署请求是否可信

它们不是四层重复防护,而是四个不同问题。把全站 Challenge 当成万能开关,既影响访客,也没有真正解决后台身份;把管理路径单独交给 Access,公开内容保持公开,管理入口才真正有了边界。

版权许可

CC BY-NC-SA 4.0 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

相关文章

s1oopX

登录 s1oopX