这其实不是什么复杂的事情,但是容易被经验不足的初学者忽略,在此献上我的中招记录。
长话短说:
重要
只开 Cloudflare 小黄云代理并不代表源站就安全了,甚至可以说源服务器依然处于裸奔状态。必须要辅以回源 IP 限制或是 mTLS 认证才能以避免未经授权的访问绕过 cf1 直击源服务器。
当然,如果你想了解这是为什么,或者想了解如何配置 EC2 实例的出入站策略,欢迎继续看下去。
1. cf 即 Cloudflare 的缩写,本文将会延续使用此缩写,并不再说明
一切的开端。。
笔者最近在打黑客松,提交需要部署 API 后端到公网上做演示用,然而我在英国并没有服务器,所以临时入坑了亚马逊云的 EC2,在上面部署了我的 API 后端。
因为没有钱,租的免费的实例性能实在弱鸡,我在前面套了一个 Cloudflare 代理,并设了一系列规则和速率限制防止被搞炸。Cloudflare TLS 设置为严格,且服务器只接受 443 端口上的 HTTPS。
这么操作看似没有问题,而且我从第一次设置 DNS 记录时就开启了 cf 的小黄云代理,我完全没有在 DNS 记录历史中泄露过源站 IP,理论上我的源站应该是安全的,对吗?
两天后,有人问我的项目网站怎么一直报错,我登上服务器一看发现崩了,再看 nginx 日志发现有许多显然通不过 cf 规则的请求,来源 IP 也不属于 cf,我才发现原来我的服务器能被跳过 cf 代理直接访问。
原因
在理想情况下,cf 的代理模式确实为源站提供了一层隐身衣:由于 DNS 解析记录全部指向 cf 的 IP,源站 IP 理论上与公网是物理隔离的。然而,事实证明,源站 IP 泄露的途径多到几乎难以防住,任何一个环节的疏忽都可能导致源站 IP 暴露。
你可以试试在 censys 等平台上查询你自己的主机名,也许会惊讶地发现自己的源 IP 早已暴露。
至于源服务器的仅 HTTPS,看似可以拦截直接对 IP 的访问,让我们举个例子:
假设你的源站 IP 是233.252.0.123,且源服务器开启了强制
HTTPS,此时正常的浏览器访问233.252.0.123或是curl 233.252.0.123是不会成功的。这造成了“源服务器是安全的”的假象。
这是因为服务器证书是对域名而不是对 IP 生效的,所以客户端这里证书校验失败就停止了;然而这里的证书校验就像 HSTS
一样,是一个君子协议,只在客户端发生,你只需要用curl -k就可以忽略它,攻击者也一样。
如果你的源服务器恰好没有严格 SNI 或 Host 验证,那么此时就可以绕过 cf 连上了,你可以用如下命令来测试:
curl -k <origin_ip>
将<origin_ip>替换为源服务器 IP
当然,使用前文说到的查询工具,或者其他方式,攻击者也可以较为轻松的获取到服务对应的主机名,此时加上源站 IP,即使是严格 SNI 或者 Host 验证也不好使了。
假设你的源站 IP
依然是233.252.0.123,并解析到了example.com这个主机名上,那么攻击者就可以轻松的让请求携带正确的主机名上下文,绕过
cf 进行连接,你可以用如下命令来测试:
curl -k <your_domain> --resolve <your_domain>:443:<origin_ip>
将<origin_ip>替换为源服务器
IP,并将<your_domain>替换为指向服务所在的主机名
此时因为服务端不对客户端做任何身份限制,只要主机名对上号了就允许访问,于是照样可以绕过 cf 直达源服务器。
解决方案
读到这里你应该已经理解问题所在了,cf 代理相当于只是给服务器加了个门卫当传话筒,但并没有把后门关掉,我们需要让服务器只听门卫的话。
你可以选择在 nginx 或 EC2 的配置中将回源 IP 限制为仅允许 Cloudflare IP 段。推荐在的 EC2 的安全组设置中进行限制,这样可以让非法流量在到达服务器前就被拦截下来。
在 EC2 中配置
说明
AWS 控制面板可能会随时间更改其 UI 样式或结构,本文提供的方案仅与撰写时(2025/12/9)UI 一致。
1. 在 AWS 控制中导航到「VPC 控制面板」→ 托管前缀列表
2. 创建两个前缀列表,分别存储 Cloudflare IPv4 和 IPv6 地址段。
请从这里获取最新的 Cloudflare IP 段。
3. 导航到「EC2 控制面板」→ 安全组,新建或修改一个现有的安全组
4. 在入站规则中将指定的端口的源设置为刚才创建的前缀列表
例如,我这里设置只允许 Cloudflare IP 段入站 443 端口。
说明
您无法为一个已有的安全组规则更改其源类型,若提示「您不能为现有的 {某某} 规则指定 一个 前缀列表。」,请创建一个新规则并选择应用到源的前缀列表,并删除不再需要的旧规则。
提示
请记得在新安全组中包含您的 SSH 入站规则,以免失去对实例的访问权限。
5. 导航到「EC2 控制面板」→ 实例,选中目标实例,单击右上角的操作 → 安全 → 更改安全组
6. 选择刚修改好的安全组作为新安全组
至此,所有非 Cloudflare 的回源流量都会被屏蔽。