上一篇 下一篇 分享链接 返回 返回顶部

Cloudflare 不是保险箱:源站暴露、缓存误配与防护实战源码

发布人:慈云数据-客服中心 发布时间:6小时前 阅读量:4

Cloudflare 安全漏洞分析|附源码

声明:本文面向安全研究、企业防护与工程实践,重点分析 Cloudflare 使用过程中常见的安全风险、配置误区与防御方案。文中源码仅用于本地实验环境、教学演示和安全加固,不包含针对真实第三方目标的攻击利用代码。请勿在未授权环境中进行扫描、测试或攻击行为。


一、引言

Cloudflare 是目前全球使用非常广泛的 CDN、DNS、WAF、DDoS 防护与边缘计算平台。很多网站接入 Cloudflare 后,可以获得以下能力:

  • 隐藏源站真实 IP;
  • 缓解 DDoS 攻击;
  • 使用 WAF 阻断常见 Web 攻击;
  • 通过 CDN 缓存提升访问速度;
  • 使用 SSL/TLS 加密传输;
  • 通过 Workers、Rules、Turnstile 等增强业务能力。

然而,很多企业在接入 Cloudflare 后,会产生一种误解:

“只要接入 Cloudflare,网站就安全了。”

实际上,Cloudflare 是安全体系中的重要一环,但不是万能防护层。
如果源站暴露、DNS 配置不当、缓存规则错误、WAF 策略过宽、回源策略缺少校验,攻击者依然可能绕过 Cloudflare 直接攻击源站,或利用业务自身逻辑缺陷造成安全问题。

本文将从以下几个方面进行分析:

  1. Cloudflare 常见安全风险类型;
  2. 源站 IP 暴露风险;
  3. DNS 与子域名配置问题;
  4. 缓存投毒与敏感信息缓存;
  5. WAF 绕过与安全规则误区;
  6. SSL/TLS 配置风险;
  7. Cloudflare Workers 安全注意事项;
  8. 本地实验源码与检测脚本;
  9. 企业级防护建议。

二、Cloudflare 的安全边界

在分析漏洞之前,需要先明确 Cloudflare 的安全边界。

Cloudflare 位于用户与源站之间,典型访问链路如下:

用户浏览器
   ↓
Cloudflare 边缘节点
   ↓
企业源站服务器

在这个架构中,Cloudflare 可以保护以下层面:

  • DNS 解析隐藏源站;
  • CDN 缓存静态资源;
  • WAF 过滤恶意请求;
  • Rate Limit 限制异常流量;
  • DDoS 防护;
  • TLS 证书托管;
  • Bot 管理;
  • 边缘访问控制。

但是,Cloudflare 不能天然解决以下问题:

  • 应用代码中的 SQL 注入、XSS、SSRF;
  • 后台弱口令;
  • 源站端口暴露;
  • 子域名解析错误;
  • API 鉴权逻辑缺陷;
  • 私有文件被错误缓存;
  • 服务器自身漏洞;
  • 错误的访问控制策略。

因此,Cloudflare 应当被视为“增强防护层”,而不是“替代安全开发和服务器加固的万能方案”。


三、风险一:源站真实 IP 暴露

1. 风险说明

很多网站接入 Cloudflare 的核心目的之一,是隐藏源站真实 IP。
如果攻击者获得源站 IP,就可以绕过 Cloudflare,直接访问源站服务器。

一旦源站允许公网直接访问,就可能导致:

  • Cloudflare WAF 被绕过;
  • DDoS 流量直接打到源站;
  • 暴露管理端口,如 SSH、Redis、MySQL、RDP;
  • 源站证书、服务指纹泄露;
  • 真实基础设施被定位。

2. 常见暴露原因

源站 IP 暴露通常不是 Cloudflare 本身漏洞,而是配置或运维问题:

1)历史 DNS 记录泄露

网站接入 Cloudflare 前,可能曾经直接解析到源站 IP。
历史 DNS 数据可能被第三方搜索引擎、安全平台或被动 DNS 系统记录。

2)子域名未接入 Cloudflare

例如:

www.example.com      → Cloudflare
api.example.com      → Cloudflare
test.example.com     → 真实源站 IP
admin.example.com    → 真实源站 IP

攻击者可能通过子域名发现源站所在 IP 段。

3)邮件服务器暴露

如果网站和邮件服务部署在同一台服务器上,MX、SPF、邮件头可能泄露源站 IP。

4)源站主动请求外部资源

应用服务器向第三方服务发起请求时,可能暴露出口 IP。

5)未限制源站访问来源

即使网站接入 Cloudflare,如果源站防火墙仍允许所有 IP 访问 80/443,也会造成绕过风险。


四、风险二:DNS 配置错误

Cloudflare DNS 中的记录通常有两种状态:

  • Proxied:橙色云朵,流量经过 Cloudflare;
  • DNS only:灰色云朵,只做 DNS 解析,不经过 Cloudflare。

如果敏感业务记录被设置为 DNS only,就会直接暴露真实服务器地址。

示例风险配置

A     example.com        Proxied
A     www.example.com    Proxied
A     admin.example.com  DNS only
A     api.example.com    DNS only

其中 admin.example.comapi.example.com 就可能绕过 Cloudflare 防护。

防护建议

  • 所有 Web 业务域名尽量启用 Proxied;
  • 非 Web 服务单独部署,不与 Web 源站共用 IP;
  • 对管理后台使用 Zero Trust、VPN 或 IP 白名单;
  • 定期检查 DNS 记录;
  • 删除废弃子域名;
  • 避免将测试环境暴露到公网。

五、风险三:缓存投毒与敏感信息缓存

Cloudflare 的缓存能力非常强,但缓存规则配置错误时,也可能引发严重安全问题。

1. 敏感页面被缓存

如果登录后页面、用户资料、订单详情、API 响应被错误缓存,则可能出现:

  • A 用户访问后,页面被缓存;
  • B 用户访问相同 URL;
  • B 看到 A 的敏感信息。

常见风险路径包括:

/user/profile
/order/detail?id=1001
/api/user/info
/account/settings

如果这些接口返回了用户隐私数据,却被 CDN 缓存,就会造成数据泄露。

2. 缓存键配置错误

缓存键通常与以下因素有关:

  • URL;
  • Query 参数;
  • Cookie;
  • Header;
  • Host;
  • 语言;
  • 设备类型。

如果缓存键没有包含必要的用户身份信息,就可能导致不同用户命中同一份缓存。

3. Header 引发的缓存污染

某些应用会根据 Header 返回不同内容,例如:

X-Forwarded-Host
Host
Accept-Language
User-Agent

如果源站基于这些 Header 动态生成响应,而缓存层没有正确区分,就可能产生缓存污染。

4. 防护建议

对于敏感接口,明确设置:

Cache-Control: no-store

或者:

Cache-Control: private, no-cache, no-store, must-revalidate

对于静态资源,可以设置长期缓存:

Cache-Control: public, max-age=31536000, immutable

对于 API,建议默认不缓存,除非明确确认响应不包含用户敏感数据。


六、风险四:WAF 规则误区与绕过风险

Cloudflare WAF 可以阻断很多常见攻击,例如:

  • SQL 注入;
  • XSS;
  • 命令注入;
  • 路径穿越;
  • 恶意爬虫;
  • 已知漏洞利用请求。

但是 WAF 不是应用安全的替代品。

1. WAF 只能过滤“已知特征”

如果业务存在逻辑漏洞,例如:

  • 越权访问;
  • 支付金额篡改;
  • 任意用户资料查看;
  • 未授权 API 调用;
  • 弱密码登录;
  • 验证码绕过;

这些问题通常不是 WAF 能完全解决的。

2. 规则过宽导致漏报

为了避免误拦截,很多企业会将 WAF 设置得非常宽松,甚至对部分路径关闭规则:

/api/*
/upload/*
/admin/*

如果关闭的位置正好是高风险接口,就可能导致攻击流量直接进入源站。

3. 只依赖托管规则不够

建议结合:

  • Cloudflare Managed Rules;
  • OWASP Core Ruleset;
  • 自定义 WAF 规则;
  • Rate Limiting;
  • Bot Fight Mode;
  • Turnstile;
  • 日志审计;
  • 源站应用安全校验。

七、风险五:SSL/TLS 配置不当

Cloudflare 提供多种 SSL/TLS 模式:

  • Off;
  • Flexible;
  • Full;
  • Full Strict。

其中比较容易产生风险的是 Flexible 模式。

1. Flexible 模式风险

Flexible 模式下:

用户 → Cloudflare:HTTPS
Cloudflare → 源站:HTTP

这意味着用户到 Cloudflare 是加密的,但 Cloudflare 到源站之间不是加密的。
如果源站链路经过不可信网络,就可能存在中间人风险。

此外,Flexible 模式还可能导致:

  • 重定向循环;
  • Cookie Secure 策略混乱;
  • 源站误判协议;
  • 安全 Header 配置错误。

2. 推荐配置

建议使用:

Full Strict

即:

用户 → Cloudflare:HTTPS
Cloudflare → 源站:HTTPS,并校验证书

源站证书可以使用:

  • 公共 CA 证书;
  • Cloudflare Origin Certificate。

同时建议开启:

  • Always Use HTTPS;
  • HSTS;
  • TLS 1.2/1.3;
  • Authenticated Origin Pulls;
  • Minimum TLS Version。

八、风险六:源站未校验 Cloudflare 请求来源

如果源站公网开放,即使域名流量经过 Cloudflare,攻击者也可以直接用源站 IP 访问。

典型问题

源站 Nginx 配置如下:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
    }
}

该配置没有限制访问来源。只要知道源站 IP,任何人都可以访问。

防护方案

应在源站防火墙或 Web 服务器层限制只允许 Cloudflare IP 回源访问。

例如 Nginx 中可以结合 allowdeny

location / {
    allow 173.245.48.0/20;
    allow 103.21.244.0/22;
    allow 103.22.200.0/22;
    allow 103.31.4.0/22;
    allow 141.101.64.0/18;
    allow 108.162.192.0/18;
    allow 190.93.240.0/20;
    allow 188.114.96.0/20;
    allow 197.234.240.0/22;
    allow 198.41.128.0/17;
    allow 162.158.0.0/15;
    allow 104.16.0.0/13;
    allow 104.24.0.0/14;
    allow 172.64.0.0/13;
    allow 131.0.72.0/22;

    deny all;

    proxy_pass http://127.0.0.1:3000;
}

注意:Cloudflare IP 段可能更新,应以 Cloudflare 官方文档为准,并定期同步。

更推荐在云安全组、防火墙层面限制源站入口,而不是只依赖 Nginx。


九、风险七:真实客户端 IP 处理错误

网站接入 Cloudflare 后,源站看到的访问 IP 通常是 Cloudflare 节点 IP,而不是用户真实 IP。

Cloudflare 会通过 Header 传递真实客户端 IP,例如:

CF-Connecting-IP: 203.0.113.10

如果源站应用直接信任客户端传入的 Header,就可能产生伪造风险。

错误示例

const ip = req.headers['cf-connecting-ip'] || req.ip;

如果攻击者直接访问源站 IP,就可以伪造:

CF-Connecting-IP: 127.0.0.1

从而绕过基于 IP 的限制。

正确思路

只有在确认请求来自 Cloudflare IP 段时,才信任 CF-Connecting-IP

伪代码逻辑:

如果 remote_addr 属于 Cloudflare IP 段:
    使用 CF-Connecting-IP
否则:
    使用 remote_addr

Nginx 中可以使用 real_ip_headerset_real_ip_from

set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;

real_ip_header CF-Connecting-IP;

十、Cloudflare Workers 安全风险

Cloudflare Workers 是边缘计算能力,可以在 Cloudflare 节点上运行 JavaScript/TypeScript 逻辑。

它常用于:

  • API 网关;
  • 请求转发;
  • 鉴权;
  • A/B 测试;
  • 边缘缓存控制;
  • Header 改写;
  • 图片处理;
  • 安全校验。

但 Workers 写得不好,也可能引入安全问题。

1. 开放代理风险

如果 Worker 根据用户传入的 URL 进行 fetch,且没有限制目标地址,就可能变成开放代理。

危险示例:

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const target = url.searchParams.get("url");
    return fetch(target);
  }
}

这种代码的问题在于:

  • 任意用户可以让 Worker 请求任意地址;
  • 可能被用于隐藏攻击来源;
  • 可能访问内部资源;
  • 可能造成流量滥用。

2. 安全版本示例

应限制目标域名白名单:

const ALLOW_HOSTS = new Set([
  "api.example.com",
  "static.example.com"
]);

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const target = url.searchParams.get("url");

    if (!target) {
      return new Response("missing url", { status: 400 });
    }

    let targetUrl;

    try {
      targetUrl = new URL(target);
    } catch {
      return new Response("invalid url", { status: 400 });
    }

    if (targetUrl.protocol !== "https:") {
      return new Response("https only", { status: 400 });
    }

    if (!ALLOW_HOSTS.has(targetUrl.hostname)) {
      return new Response("host not allowed", { status: 403 });
    }

    return fetch(targetUrl.toString(), {
      method: "GET",
      headers: {
        "User-Agent": "Safe-Cloudflare-Worker"
      }
    });
  }
}

十一、本地实验源码:模拟缓存误配置风险

下面给出一个本地 Node.js 示例,用于演示“敏感数据被错误缓存”的风险。
该示例只适合本地运行,帮助理解 CDN 缓存策略为什么需要谨慎配置。

1. 项目结构

cloudflare-security-demo/
├── package.json
├── server.js
└── README.md

2. package.json

{
  "name": "cloudflare-security-demo",
  "version": "1.0.0",
  "description": "Demo for understanding cache misconfiguration risks",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.18.3"
  }
}

3. server.js

const express = require("express");

const app = express();
const port = 3000;

/**
 * 模拟用户登录态
 * 实际业务中通常来自 Session、JWT 或 Cookie。
 */
function mockAuth(req, res, next) {
  const user = req.query.user || "guest";

  const users = {
    alice: {
      id: 1,
      name: "Alice",
      email: "alice@example.com",
      balance: 8800
    },
    bob: {
      id: 2,
      name: "Bob",
      email: "bob@example.com",
      balance: 1200
    },
    guest: {
      id: 0,
      name: "Guest",
      email: null,
      balance: 0
    }
  };

  req.user = users[user] || users.guest;
  next();
}

/**
 * 错误示例:
 * 用户隐私接口却设置了 public cache。
 * 如果该响应被 CDN 缓存,可能导致用户信息泄露。
 */
app.get("/bad/profile", mockAuth, (req, res) => {
  res.setHeader("Cache-Control", "public, max-age=600");

  res.json({
    message: "This is a risky cache configuration.",
    user: req.user
  });
});

/**
 * 正确示例:
 * 敏感用户数据禁止缓存。
 */
app.get("/good/profile", mockAuth, (req, res) => {
  res.setHeader(
    "Cache-Control",
    "private, no-cache, no-store, must-revalidate"
  );
  res.setHeader("Pragma", "no-cache");
  res.setHeader("Expires", "0");

  res.json({
    message: "This response should not be cached by shared proxies.",
    user: req.user
  });
});

/**
 * 静态公共数据可以缓存。
 */
app.get("/public/news", (req, res) => {
  res.setHeader("Cache-Control", "public, max-age=3600");

  res.json({
    title: "Security News",
    content: "This is public content and can be cached safely."
  });
});

app.listen(port, () => {
  console.log(`Demo server running at http://localhost:${port}`);
});

4. 运行方式

npm install
npm start

访问示例:

http://localhost:3000/bad/profile?user=alice
http://localhost:3000/bad/profile?user=bob
http://localhost:3000/good/profile?user=alice
http://localhost:3000/good/profile?user=bob

重点观察响应头中的 Cache-Control


十二、防护检测脚本:检查响应缓存头

下面提供一个简单的 Python 脚本,用于检查指定 URL 的缓存相关 Header。
它适合企业内部对自己资产进行合规检查。

cache_header_check.py

import sys
import requests

SENSITIVE_HINTS = [
    "/user",
    "/profile",
    "/account",
    "/order",
    "/payment",
    "/admin",
    "/api"
]

def is_sensitive_url(url: str) -> bool:
    lower_url = url.lower()
    return any(hint in lower_url for hint in SENSITIVE_HINTS)

def check_cache_header(url: str):
    try:
        resp = requests.get(url, timeout=10)
    except requests.RequestException as e:
        print(f"[ERROR] request failed: {e}")
        return

    cache_control = resp.headers.get("Cache-Control", "")
    cdn_cache = resp.headers.get("CF-Cache-Status", "")
    content_type = resp.headers.get("Content-Type", "")

    print("=" * 80)
    print(f"URL: {url}")
    print(f"Status Code: {resp.status_code}")
    print(f"Content-Type: {content_type}")
    print(f"Cache-Control: {cache_control}")
    print(f"CF-Cache-Status: {cdn_cache}")

    if is_sensitive_url(url):
        if "no-store" not in cache_control.lower():
            print("[WARN] Sensitive-looking URL does not contain 'no-store'.")
        else:
            print("[OK] Sensitive-looking URL contains 'no-store'.")
    else:
        print("[INFO] URL does not match built-in sensitive path hints.")

    print("=" * 80)

def main():
    if len(sys.argv) < 2:
        print("Usage: python cache_header_check.py  [url2] ...")
        sys.exit(1)

    for url in sys.argv[1:]:
        check_cache_header(url)

if __name__ == "__main__":
    main()

使用方式

pip install requests
python cache_header_check.py https://example.com/api/user/info

该脚本不会进行攻击测试,只读取响应头并给出缓存策略提示。


十三、防护检测脚本:校验是否存在直接源站访问风险

企业可以在内部维护源站 IP 清单,并检查源站是否仍然允许非 Cloudflare 来源直接访问。

下面是一个安全版检测示例,假设你已经拥有合法授权,并且只检测自己的服务器。

origin_access_check.py

import sys
import requests

def check_origin(origin_ip: str, host: str):
    url = f"http://{origin_ip}/"

    headers = {
        "Host": host,
        "User-Agent": "Internal-Origin-Access-Check/1.0"
    }

    try:
        resp = requests.get(url, headers=headers, timeout=10)
    except requests.RequestException as e:
        print(f"[ERROR] {origin_ip} request failed: {e}")
        return

    print("=" * 80)
    print(f"Origin IP: {origin_ip}")
    print(f"Host Header: {host}")
    print(f"Status Code: {resp.status_code}")

    text = resp.text[:120].replace("\n", " ")

    if resp.status_code in [200, 301, 302, 403]:
        print(f"Preview: {text}")

    if resp.status_code == 200:
        print("[WARN] Origin may be directly accessible. Consider firewall restrictions.")
    elif resp.status_code in [403, 401]:
        print("[INFO] Origin returned access control response.")
    else:
        print("[INFO] Check result requires manual review.")

    print("=" * 80)

def main():
    if len(sys.argv) != 3:
        print("Usage: python origin_access_check.py  ")
        sys.exit(1)

    origin_ip = sys.argv[1]
    host = sys.argv[2]

    check_origin(origin_ip, host)

if __name__ == "__main__":
    main()

使用方式

pip install requests
python origin_access_check.py 192.0.2.10 example.com

说明:192.0.2.0/24 是文档示例网段。请仅检测你拥有授权的源站 IP。


十四、推荐的 Cloudflare 安全配置清单

下面是一份实践清单,适合网站上线前或安全巡检时使用。

1. DNS 与源站

  • [ ] 所有 Web 域名启用 Proxied;
  • [ ] 删除废弃 DNS 记录;
  • [ ] 测试环境不直接暴露公网;
  • [ ] 管理后台不使用公开子域名;
  • [ ] 源站安全组只允许 Cloudflare IP 访问 80/443;
  • [ ] SSH、数据库、Redis 等端口禁止公网访问;
  • [ ] 邮件服务器与 Web 源站分离;
  • [ ] 定期检查历史 DNS 暴露风险。

2. SSL/TLS

  • [ ] 使用 Full Strict 模式;
  • [ ] 源站部署有效证书;
  • [ ] 开启 Always Use HTTPS;
  • [ ] 开启 HSTS;
  • [ ] 禁用过旧 TLS 版本;
  • [ ] 开启 Authenticated Origin Pulls。

3. WAF

  • [ ] 开启 Cloudflare Managed Rules;
  • [ ] 开启 OWASP 规则集;
  • [ ] 对后台路径设置更严格规则;
  • [ ] 对登录接口配置 Rate Limit;
  • [ ] 对 API 接口做鉴权;
  • [ ] 对上传接口进行文件类型和大小限制;
  • [ ] 定期查看 WAF 日志;
  • [ ] 避免随意关闭规则。

4. 缓存

  • [ ] 敏感接口设置 Cache-Control: no-store
  • [ ] 用户页面禁止公共缓存;
  • [ ] 静态资源使用版本号或 hash;
  • [ ] API 默认不缓存;
  • [ ] 避免缓存基于 Cookie 的动态页面;
  • [ ] 检查 Page Rules、Cache Rules、Transform Rules;
  • [ ] 对缓存命中进行日志审计。

5. Header 安全

建议配置:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Content-Security-Policy: default-src 'self'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: geolocation=(), microphone=(), camera=()

6. 日志与监控

  • [ ] 开启 Cloudflare Analytics;
  • [ ] 关注异常国家、ASN、路径访问;
  • [ ] 记录 WAF 命中日志;
  • [ ] 对 403、429、5xx 异常告警;
  • [ ] 对登录失败次数告警;
  • [ ] 对源站直接访问告警;
  • [ ] 将日志接入 SIEM 或集中日志系统。

十五、企业加固方案示例

一个较为安全的 Cloudflare 接入架构如下:

用户
 ↓
Cloudflare DNS / CDN / WAF / Rate Limit
 ↓
Authenticated Origin Pulls
 ↓
云防火墙,只允许 Cloudflare IP
 ↓
Nginx / API Gateway
 ↓
业务服务
 ↓
数据库内网访问

关键点包括:

  1. 边缘层过滤:使用 WAF、Bot 管理、Rate Limit;
  2. 传输层加密:Cloudflare 到源站使用 HTTPS 且严格校验证书;
  3. 源站访问控制:源站不允许公网任意 IP 访问;
  4. 应用层安全:业务代码自身完成鉴权、输入校验、权限控制;
  5. 缓存隔离:敏感数据不进入共享缓存;
  6. 日志追踪:边缘日志与源站日志关联分析;
  7. 持续巡检:定期检查 DNS、端口、证书、Header、WAF 命中情况。

十六、总结

Cloudflare 能显著提升网站的可用性和安全性,但它不是“接入即安全”的银弹。
多数所谓的“Cloudflare 安全漏洞”,本质上并不是 Cloudflare 平台自身漏洞,而是由以下原因造成:

  • 源站 IP 暴露;
  • DNS 记录配置错误;
  • 灰云解析误用;
  • 源站防火墙未限制;
  • SSL/TLS 模式选择不当;
  • 敏感数据错误缓存;
  • WAF 策略过宽;
  • Workers 编写不安全;
  • 应用自身存在逻辑漏洞。

企业在使用 Cloudflare 时,应从“边缘防护 + 源站加固 + 应用安全 + 持续监控”四个维度建立完整防护体系。

最终目标不是单纯依赖 Cloudflare 拦截攻击,而是让攻击者即使绕过某一层防护,也无法轻易触达核心资产。

安全不是一个开关,而是一套持续演进的工程体系。

目录结构
全文