通过 Cloudflare Access 为 Tunnel 增加网站鉴权 提升内网穿透安全性
前言
很久之前介绍过用 Cloudflare Tunnel 来内网穿透,可以在没有公网 IP 和服务器的情况下,只用一个域名实现在公网访问内网服务。这种方式相比通过公网 IP 直接开放端口来说,比较“合规”,安全性也更高。唯一的缺点就是速度受限于到 Cloudflare 的网络状况。

同时,Tunnel 还可以搭配 Access 一起使用,为内网服务额外添加一个访问验证,进一步提高安全性。
很多小白用户跟着教程部署的各种服务,觉得自己压根没有公网 IP,就忽略了鉴权的重要性,图方便直接不设置密码或者只设置了类似 123456 的弱密码。
尽管大部分宽带没有公网 IPv4 地址,但 IPv6 运营商一般还是会给公网的,如果跟着某些教程直接简单粗暴的把 IPv6 的防火墙关闭了,恰巧又做了 DDNS,那内网服务同样会暴露在公网中。
Tunnel 优点
如果你的网络到 Cloudflare 的速度尚可,直接使用 Cloudflare Tunnel 就可以非常简单的控制穿透哪些服务,相比公网 IPv4 的端口映射和公网 IPv6 的防火墙设置要简单的多(更何况很多路由器压根不支持)。
这样一来就可以将 IPv4 和 IPv6 的防火墙都打开,能避免一些敏感的内网服务意外暴露到了公网中,同时也不需要 DDNS 了。
Access 优点
通过 Cloudflare Tunnel 建立隧道实现内网穿透后,虽说没有使用到公网 IP,也没有开放任何端口,但终归还是会把需要用到的内网服务暴露到公网中来直接访问。
如果你没有给页面加密码或者用了弱密码,再加上部分在内网运行的程序本身鉴权就比较简陋,这种情况下穿透出去的内网服务仍然会有一些风险。

此时借助 Cloudflare Access 就可以给你的内网服务额外增加一层鉴权,可以是邮箱一次性验证、也可以是 GitHub、Google 等第三方账号验证。除此之外,还可以限制访问的 IP、地区等。
对于那些本身就是要公开的服务,则可以单独给 /admin 之类的管理后台路径单独添加鉴权,防止密码被爆破。
配置 Access
提示
在开始配置 Cloudflare Access 之前,默认已经使用 Cloudflare Tunnel 配置好了内网穿透。
如果你还不了解 Cloudflare Tunnel 是什么,可以回看之前的教程。
Access 和 Tunnel 一样都属于 Zero Trust,需要给 Cloudflare 账号绑定一下支付方式才能使用,好在 ZeroTrust 的免费计划就够我们用了,因此实际是不会产生费用的。
登录方式
既然是鉴权,我们自然是需要先添加一下身份认证方式,通俗的来说就是最终通过什么方式来登录。
默认情况下,只有一个 One-time PIN,可以通过邮箱接收一次性验证码来进行登录。

对于自用的应用来说,每次都要收验证码还是有些不方便,我们可以额外添加一个第三方账号登录,下面以 GitHub 为例演示一下如何添加(其他方式页面上也都有提示,按照步骤操作即可)

在 GitHub 的 Settings -> Developer Settings -> OAuth Apps -> New OAuth app 中创建一个新的应用,名字可以随意填写,
- Homepage URL:
https://<your-team-name>.cloudflareaccess.com - Authorization callback URL:
https://<your-team-name>.cloudflareaccess.com/cdn-cgi/access/callback
其中的 <your-team-name> 是自己设置的 Zero Trust 的团队名称,不记得的可以在 Zero Trust 的 Settings -> Team name and domain -> Team name 中查看。

创建完应用后,你就看到 Client ID 和 Client secrets,把他复制下来备用,secrets 只会显示一次,如果没有及时复制只能重新创建一个。

完成以上步骤后,返回 Zero Trust 的设置页面,把刚才复制的 ID 和 secrets 填写到这个页面中,App ID 对应的就是 Client ID,Client secret 就是刚才复制的密钥。

策略
接着,我们还需要配置策略,否则所有的邮箱都可以接收一次性验证码登录,所有的 GitHub 账号也都能授权登录,这肯定是我们不希望看到的。
因此,要添加一个策略,通过配置 Include、Require 以及 Exclude 这一系列规则来达到只有我们自己才能访问的目的。
其中 Include 的规则只需要满足一个条件,Require 的规则需要全部满足才可以通过验证,以下图为例
- IP ranges: 只允许指定 IP 段访问,其他 IP 访问直接会看到 Forbidden 页面
- Emails: 只允许指定邮箱登录(不单是邮箱验证码登录,GitHub 绑定的邮箱也同样生效)
- Login Methods: 只允许 GitHub 验证

创建应用
最后,我们只需要再创建一下应用,在 Access 中,应用对应的就是最终需要添加鉴权的页面,在应用中可以为对应的页面配置上刚才设置的登录方式以及策略。
添加应用时,类型选择自部署 Self-hosted。

我们需要先设置一下应用名称以及公共主机名,名称可以随意填写,后面的 Session Duration 代表每次登录后的有效期,可以根据自己的需求选择。
重点是下方的公共主机名 Public hostname,在这里添加的路径就是需要增加验证的页面,例如我需要为博客的管理页面添加验证,可以填写 zhichao.org/admin,如果你需要给整个网站加验证,将 Path 留空即可。

访问策略选择我们刚才创建好的策略,点击下方的 Test policies 还可以测试一下策略是否正确。

最后再勾选一下登录方式,默认会全部勾选,你也可以取消上方的选项后,选择其中一个登录方式。

后续的所有选项保持默认即可,稍等片刻等待生效。
最终效果
生效后,访问页面就会跳转到 Cloudflare Access,但如果通过策略外的 IP 访问,会直接显示 Forbidden,看不到验证的页面。

当访问 IP 正确时,才能进入验证页面进行下一步操作,此时点击 GitHub 验证方式,如果你已经登录过 GitHub 账号,就会自动通过验证跳转到目标网站,中途无需任何额外操作,非常的方便。

最后,还是要再提醒一下,策略中一定要配置好邮箱、IP 之类的限制,否则无论谁都可以通过验证。

