技术指南

Cloudflare 源站收口:验证代理路径、真实 IP 与回滚

把 Cloudflare 源站收口拆成范围校验、代理准入、真实 IP 信任、绕过探测与可执行回滚。

把网站接入 Cloudflare 只改变默认访问路径,并不会让源站自动拒绝绕过请求。真正的收口是一次可回滚的网络变更:先证明边缘链路完整,再限制源站入口,同时保留管理、健康检查、证书和故障恢复需要的明确路径。

来源覆盖多层加固,本文只处理 Web 源站收口

归档来源把 SSH、端口敲门、Fail2ban、Nginx、iptables/nftables、Cloudflare WAF 和流量攻击放进一份清单。它提醒了历史 DNS、未代理子域和监控端口会暴露源站,也提出只允许 Cloudflare 访问 Web 端口。本文保留这些可验证的问题,删除‘绝对隐藏’、固定攻击阈值、直接下载后改防火墙、默认端口敲门和产品防护能力保证。

先写清源站契约和失效条件

对象上线前必须知道失败时保留什么
公开站点代理主机名、80/443、TLS 模式、关键路径上一份 DNS/代理状态和源站规则
源站入口公网 IPv4/IPv6、云防火墙、主机防火墙、监听控制台或独立管理路径
非 Cloudflare 调用方监控、Webhook、合作方、ACME 或负载均衡来源精确例外或替代代理路径
客户端地址可信代理、使用的头、日志和应用读取方式同时记录连接端与恢复后的访客地址
回滚触发门槛、负责人、最大恢复时间已验证的旧配置和执行顺序

目标不是证明源站 IP 永远无法被发现。历史 DNS、邮件、证书、其他服务和供应链记录都可能暴露地址。验收目标应写成:即使知道源站地址,未经批准的 Web 连接也不能绕过边缘策略获得应用响应。

冻结变更前的 DNS、监听与调用方证据

命令以只读盘点为主;云防火墙与控制台规则需另行导出。不要把完整规则、地址和密钥贴进公开工单
date -u
dig +short A app.example.com
dig +short AAAA app.example.com
ss -ltnp
sudo ufw status numbered
sudo nft list ruleset
nginx -T > nginx-before.txt 2>&1

# 记录云安全组、负载均衡、健康检查、ACME 和外部调用方
sha256sum nginx-before.txt

逐个核对 A、AAAA、CNAME、MX 和 DNS-only 子域。Cloudflare 当前文档明确提醒邮件和历史 DNS 可能暴露源站;如果同一地址还提供 SSH、邮件、数据库、游戏或 TURN,限制 80/443 不能保护其他端口,也不能把它们变成 Cloudflare HTTP 代理流量。

选择能说明安全边界的接入层

方案能证明什么不能单独证明什么
共享 Cloudflare IP allowlist连接来自 Cloudflare 公布的代理网段来自自己的账户或主机名
Authenticated Origin PullsHTTPS 客户端持有受信任的源站拉取证书全局共享证书不证明账户专属
自有 AOP 证书连接使用本区或主机名配置的客户端证书应用授权和业务请求合法性
Cloudflare Tunnel源站通过出站连接接入,不需公开 Web 监听daemon、账户和控制面一定可用
秘密请求头请求携带约定值不可重放;必须依赖加密和安全轮换

网络 allowlist 适合先缩小入口,AOP 再为 HTTPS 增加客户端证书认证。Cloudflare 的全局 AOP 证书在账户间共享,只保证请求来自 Cloudflare 网络;需要账户或主机名边界时使用自有 zone-level 或 per-hostname 证书,并管理到期与轮换。

把 IP 范围当作受审输入,不把 curl 接到防火墙

保存下载时间、URL、内容摘要和解析结果。下载、格式或空列表失败时保留当前已验收规则,不生成空 allowlist
work=$(mktemp -d)
chmod 700 "$work"
curl --fail --location --output "$work/ips-v4" \
  https://www.cloudflare.com/ips-v4
curl --fail --location --output "$work/ips-v6" \
  https://www.cloudflare.com/ips-v6

python3 - "$work/ips-v4" "$work/ips-v6" <<'PY'
import ipaddress, pathlib, sys
for path, version in zip(sys.argv[1:], (4, 6), strict=True):
    nets = [ipaddress.ip_network(line, strict=True)
            for line in pathlib.Path(path).read_text().splitlines() if line]
    assert nets and len(nets) == len(set(nets))
    assert all(net.version == version for net in nets)
    print(path, len(nets))
PY

Cloudflare 说明地址范围变更会先加入其列表,也提供 API 方式维护。自动化仍应采用下载、严格解析、差异审阅、候选验证、canary 和原子替换,而不是每次向 UFW 追加新规则;否则旧范围、重复规则和部分失败会持续累积。

用独立 nftables 表生成可检查的候选

示例地址不可用于生产。先把当前列表渲染到候选文件,运行 `nft --check --file candidate.nft`;再确认与现有规则的 hook、priority 和管理路径没有冲突
table inet origin_edge {
  set cloudflare_v4 {
    type ipv4_addr
    flags interval
    elements = { 192.0.2.0/24 } # 示例,必须替换为已验证的完整当前列表
  }
  set cloudflare_v6 {
    type ipv6_addr
    flags interval
    elements = { 2001:db8::/32 } # 文档示例地址
  }
  chain input {
    type filter hook input priority 0; policy accept;
    tcp dport { 80, 443 } ip saddr @cloudflare_v4 accept
    tcp dport { 80, 443 } ip6 saddr @cloudflare_v6 accept
    tcp dport { 80, 443 } counter drop
  }
}

按 allow、observe、deny 的顺序切换

  1. 确认代理记录已生效、边缘证书有效,Cloudflare 到源站的 TLS 模式符合预期。
  2. 把当前 Cloudflare IPv4/IPv6 集合加入源站允许路径,暂不删除原有 Web 入口。
  3. 从多个网络访问公开域名,核对状态、内容、登录、上传、API、WebSocket 和源站日志。
  4. 加入健康检查、合作方或迁移探针的精确例外,并记录负责人和到期时间。
  5. 只对一台源站或一个地址执行非 Cloudflare Web 拒绝,观察完整业务窗口。
  6. 扩大到其他源站;最后清理旧放行,并保留一键恢复的上一版本。

Cloudflare 的上线文档同样要求先核对 DNS、边缘证书和源站 allowlist,再切换记录到 Proxied。对现有站点可用 staging 主机名、单台源站或负载均衡池成员做 canary;不要把 DNS、TLS、WAF、缓存和源站防火墙同时改成无法归因的一次发布。

默认虚拟主机只负责未知 Host,不负责网络准入

Nginx 把不匹配的 Host 交给该地址和端口的 default server。444 是 Nginx 的非标准关闭响应,可减少未知 HTTP 请求信息,但不是来源认证
server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name _;
  return 444;
}

HTTPS 的服务器选择可能在 TLS 握手阶段先按 SNI 发生,HTTP 的 `return 444` 在握手之后执行。因此 444 不能保证‘不发送证书’或隐藏 TLS 服务;443 的默认服务器仍需安全的 TLS 配置。真正阻止直连的边界应在云/主机防火墙或 mTLS,而不是依赖陌生 Host 的应用响应。

只有可信连接端可以提供访客地址

`$remote_addr` 是恢复后的访客地址,`$realip_remote_addr` 保留原连接端。两者与 CF-Ray 一起记录,才能审计代理信任和边缘事件
log_format edge '$remote_addr peer=$realip_remote_addr '
                'host=$host status=$status ray=$http_cf_ray';

# 为所有当前 Cloudflare IPv4/IPv6 范围分别生成 set_real_ip_from
set_real_ip_from 192.0.2.0/24;  # 示例,不能照抄
real_ip_header CF-Connecting-IP;
real_ip_recursive off;
access_log /var/log/nginx/edge-access.log edge;

Nginx realip 模块只对 `set_real_ip_from` 中的可信地址使用替换头。若信任 `0.0.0.0/0`、`::/0` 或直接在应用里读取任意 `CF-Connecting-IP`,直连者就能伪造身份并污染限速、审计或授权。变更后分别从可信代理和非可信网络发送同一个伪造头,确认只有前者会替换客户端地址。

先观察客户端证书,再强制 AOP

全局 AOP 的 CA 与 Origin CA 不是同一份证书。Full 或 Full (strict) 是前提;直接强制前先在日志中确认代理请求携带了有效客户端证书
# 第一步:只观察,确认 Cloudflare 拉取成功
ssl_client_certificate /etc/nginx/certs/cloudflare-origin-pull-ca.pem;
ssl_verify_client optional;

# 第二步:边缘访问、日志和回滚均通过后再强制
# ssl_verify_client on;

强制后,用正常域名确认边缘路径成功,再用 `curl --resolve` 直连源站验证 TLS 客户端证书缺失会失败。自有 AOP 证书还需要到期告警、重叠轮换和紧急禁用流程;证书过期会把合法源站拉取一起阻断。

边缘限速从业务成本和误判预算开始

路径计数对象候选先观察什么首选初始动作
登录来源与账号/会话信号成功率、失败率、NAT 用户Managed Challenge 或短时缓解
搜索来源与查询成本缓存命中、后端耗时、机器人较宽阈值并排除健康检查
写 API身份、令牌和操作类型幂等、队列、数据库成本应用配额加边缘规则
静态资源通常不按源站动态请求同阈值缓存状态与回源比例先优化缓存

Cloudflare 当前说明 rate limiting 有检测与计数传播延迟,超量请求仍可能到达源站;套餐也影响表达式、计数特征和周期。它是缓解层,不是精确并发锁或账务配额。先用日志回放和 challenge 观察误判,再决定 block,并为可信自动化保留可审计例外。

用正向和绕过路径共同验收

不要用关闭 Cloudflare 代理来测试绕过;那会改变公共流量。`--resolve` 只影响本次客户端连接并保留正确 Host/SNI
host=app.example.com
origin=203.0.113.10 # 文档示例,替换为真实源站

# 正常边缘路径:应成功并看到边缘响应信息
curl --fail --silent --show-error --dump-header edge.headers \
  "https://$host/health"

# 直接把域名/SNI 指向源站:收口后应失败或被明确拒绝
curl --verbose --resolve "$host:443:$origin" \
  "https://$host/health"

# 同时从外部 IPv4/IPv6、监控和合作方路径运行
# 保存 UTC 时间、出口地址、TLS/HTTP 结果与源站日志关联字段
探测预期失败说明
公开域名经边缘关键路径成功代理、TLS、allowlist 或源站故障
源站 IP + 正确 Host/SNI超时、拒绝或 mTLS 失败存在可绕过边缘的直连入口
源站 IP + 未知 Host不返回应用内容默认虚拟主机暴露业务
非可信连接 + 伪造访客头日志仍使用连接端地址代理信任范围过宽
Cloudflare 连接 + 访客头访客与连接端都可关联realip 或日志链路不完整

把 52x、拒绝和配置版本关联起来

  • 公开探针记录状态、延迟、证书、关键内容和 Cloudflare Ray ID。
  • 源站日志同时保存恢复后的访客地址、原连接地址、Host、状态和 CF-Ray。
  • 防火墙只对拒绝进行有界采样,避免攻击期间日志反过来耗尽磁盘。
  • 按部署版本记录 Cloudflare IP 列表摘要、nftables/Nginx 候选摘要和生效时间。
  • 对 521、522、523、525、526 与源站 4xx/5xx 分开告警,避免把边缘错误都归为攻击。

回滚时先恢复入口,再撤销代理侧变更

触发条件可以是公开探针连续失败、关键业务错误超过预算、合法调用方被拒绝、IPv6 单栈失败、日志地址异常或证书验证错误。先原子恢复上一份主机/云防火墙规则,确认边缘和必要例外恢复;再回退 AOP、realip、WAF 或 DNS 变更。每一步都从外部路径复测,不以‘命令成功’代替服务恢复。

自动更新必须失败关闭变更,不是关闭现有流量

  • 使用 HTTPS 固定端点下载 IPv4/IPv6 列表,并保存时间和摘要。
  • 严格解析 CIDR、地址族、空文件、重复与异常规模;任何错误都停止发布。
  • 生成完整候选而非增量追加,先执行 `nft --check` 和 `nginx -t`。
  • 显示范围差异并要求审阅;新增允许可先发布,删除旧范围要等官方生效窗口和探针证明。
  • 原子替换后执行边缘、绕过、IPv6、日志和回滚探测。
  • 保留上一版与自动回滚门槛,限制更新程序权限和输出中的敏感数据。

隔离演练验证了来源信任、拒绝和回滚

VPScope 在 2026-08-17 下载并严格解析 Cloudflare 当前列表,得到 15 个 IPv4 和 7 个 IPv6 CIDR;一个畸形输入被拒绝。生成的 nftables 独立表通过 `nft --check`,没有加载进内核。Nginx 1.24.0 的 baseline 与候选配置通过 `nginx -t`,一个缺少分号的候选被拒绝。

Nginx 只监听 127.0.0.1:18024。直接请求与从非可信 127.0.0.1 伪造 `CF-Connecting-IP` 都返回 403;从可信测试边缘 127.0.0.2 发送同一头时,响应记录访客 203.0.113.77 和原连接端 127.0.0.2。未知 Host 以 curl 52 结束,随后恢复 baseline 并得到原响应。进程停止、端口关闭、临时目录删除。该演练不证明真实 Cloudflare、云防火墙、TLS/AOP、WAF、IPv6 公网路径或抗攻击容量。

源站收口发布前的可复查清单

  • 代理主机名、源站地址、IPv4/IPv6、监听、云/主机防火墙和非代理调用方已盘点。
  • 源站契约明确成功路径、绕过路径、日志字段、回滚门槛与独立管理入口。
  • 当前 Cloudflare 地址列表经过严格解析、差异审阅和候选语法检查,更新失败不会清空现有规则。
  • 边缘证书与源站 TLS 模式已验证,Cloudflare allow 先于其他 Web 来源 deny。
  • 未知 Host 不返回业务内容;没有把 Nginx 444 当作 TLS 隐身或来源认证。
  • 只有当前可信代理范围可恢复 `CF-Connecting-IP`,日志同时保留访客、连接端和 CF-Ray。
  • AOP 若启用,已区分全局共享证书与自有证书,并演练观察、强制、到期和回滚。
  • 边缘限速来自业务成本与误判预算,承认计数延迟并保留应用侧配额。
  • 公开边缘、直接源站、未知 Host、伪造头、IPv4/IPv6 和必要例外均从外部路径验收。
  • 部署版本、拒绝采样、52x、证书和回滚结果可关联;旧配置已实际恢复一次。

返回知识库