Cloudflare 配置别乱开:从 SSL、缓存到源站防护的实战避坑手册
问答社区 2026-06-05 21:56 57

Cloudflare 使用避坑指南|附源码

Cloudflare 是很多站长、开发者和企业团队都会使用的基础设施服务。它提供 DNS 解析、CDN 加速、DDoS 防护、WAF 防火墙、SSL/TLS 证书、Workers Serverless、Pages 静态部署、R2 对象存储、Zero Trust 等能力。对于个人开发者来说,Cloudflare 的免费额度已经足够强大;对于企业而言,它也能显著降低运维复杂度。

但是,Cloudflare 虽然好用,却并不是“无脑套一层就万事大吉”。很多人在使用过程中会遇到缓存不生效、HTTPS 循环跳转、真实 IP 获取不到、接口被缓存、网站打开变慢、国内访问不稳定、Workers 路由冲突、源站安全配置错误等问题。

本文将结合实际经验,系统整理 Cloudflare 使用过程中的常见坑点、排查思路、推荐配置,并附上一些可直接使用的源码示例,帮助你更安全、高效地使用 Cloudflare。


一、Cloudflare 适合解决什么问题?

在正式避坑之前,需要先明确 Cloudflare 的定位。Cloudflare 并不是万能加速器,它主要解决以下问题:

  1. DNS 托管与解析管理

    • 提供全球 Anycast DNS;
    • 支持 A、AAAA、CNAME、TXT、MX 等记录;
    • 支持代理模式,也就是常见的“小云朵”。
  2. CDN 缓存与静态资源加速

    • 对图片、CSS、JS、字体等静态资源进行边缘缓存;
    • 减少源站带宽消耗;
    • 提升海外访问速度。
  3. 安全防护

    • 隐藏源站 IP;
    • 抵御常见 DDoS;
    • 提供 WAF、安全规则、Bot Fight Mode 等能力。
  4. SSL/TLS 统一管理

    • 提供边缘证书;
    • 支持 Full、Full(strict) 等 HTTPS 模式;
    • 可自动开启 HTTPS 跳转。
  5. Serverless 与边缘计算

    • Workers 可在边缘节点运行 JavaScript/TypeScript;
    • Pages 可部署静态站点;
    • R2 可作为对象存储使用。

但需要注意:如果你的用户主要位于中国大陆,Cloudflare 免费版并不一定能带来稳定加速。由于网络环境复杂,某些地区访问 Cloudflare 节点可能会出现延迟高、丢包、甚至不可达的情况。因此,Cloudflare 更适合海外业务、全球化业务、API 防护、静态资源分发、源站隐藏等场景。


二、避坑一:DNS 代理模式不要乱开

Cloudflare DNS 记录中有一个非常关键的状态:是否开启代理。

在 Cloudflare 面板中,DNS 记录旁边的小云朵有两种状态:

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

很多新手看到“Cloudflare 是 CDN”,就把所有记录都打开橙色代理,这是非常常见的错误。

1. 哪些记录适合开启代理?

一般来说,以下类型适合开启代理:

www.example.com     A/CNAME    Proxied
example.com         A          Proxied
static.example.com  CNAME      Proxied
api.example.com     A/CNAME    视情况开启

适合代理的通常是 HTTP/HTTPS 服务。

2. 哪些记录不应该开启代理?

以下记录通常不建议开启代理:

mail.example.com    A          DNS only
smtp.example.com    A          DNS only
imap.example.com    A          DNS only
ftp.example.com     A          DNS only
ssh.example.com     A          DNS only

原因是 Cloudflare 免费版/常规代理主要支持 HTTP/HTTPS 流量。如果你把邮件服务器、SSH、FTP 等服务开启橙色代理,可能会导致连接失败。

3. 推荐配置

如果你的网站结构如下:

  • 主站:example.com
  • www:www.example.com
  • API:api.example.com
  • 邮件服务:mail.example.com
  • SSH 管理:ssh.example.com

建议:

example.com       Proxied
www.example.com   Proxied
api.example.com   根据接口情况决定
mail.example.com  DNS only
ssh.example.com   DNS only

三、避坑二:SSL/TLS 模式不要选 Flexible

Cloudflare 的 SSL/TLS 加密模式非常重要,常见模式包括:

  • Off
  • Flexible
  • Full
  • Full(strict)

其中最容易踩坑的是 Flexible

1. Flexible 为什么危险?

Flexible 模式下:

浏览器 ←HTTPS→ Cloudflare ←HTTP→ 源站

也就是说,用户到 Cloudflare 是 HTTPS,但 Cloudflare 到你的源站是 HTTP。这种配置会造成两个问题:

  1. 源站到 Cloudflare 之间没有加密;
  2. 如果源站本身也强制 HTTPS,容易出现无限重定向。

很多人会遇到:

ERR_TOO_MANY_REDIRECTS

也就是 HTTPS 循环跳转。这通常就是 Flexible 配置导致的。

2. 推荐使用 Full(strict)

推荐模式:

浏览器 ←HTTPS→ Cloudflare ←HTTPS→ 源站

也就是选择:

SSL/TLS encryption mode: Full (strict)

同时在源站配置有效证书。这个证书可以是:

  • Let's Encrypt 免费证书;
  • Cloudflare Origin Certificate;
  • 商业证书。

3. Nginx 源站 HTTPS 示例

下面是一个推荐的 Nginx HTTPS 配置示例:

server {
    listen 80;
    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    root /var/www/example;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ /index.html;
    }
}

当 Cloudflare 设置为 Full(strict),源站也正确配置 HTTPS 后,循环跳转问题基本可以避免。


四、避坑三:不要把 API 接口错误缓存

Cloudflare 默认会缓存静态资源,但很多人为了提升速度,会使用 Cache Rules 或 Page Rules 设置“Cache Everything”。如果配置不当,就可能把接口返回结果也缓存了。

比如:

https://example.com/api/user
https://example.com/api/order
https://example.com/api/profile

如果这些接口被缓存,可能导致严重问题:

  • 用户 A 看到用户 B 的数据;
  • 登录状态异常;
  • 订单状态不更新;
  • 后台数据迟迟不刷新。

1. 推荐规则

对于 API、后台、登录路径,应明确跳过缓存:

/api/*
/admin/*
/login*
/logout*
/user/*
/account/*

在 Cloudflare Cache Rules 中可以配置:

If URI Path starts with /api/
Then Cache eligibility: Bypass cache

2. 源站响应头控制缓存

推荐在 API 响应中添加:

Cache-Control: no-store, no-cache, must-revalidate, max-age=0
Pragma: no-cache
Expires: 0

Node.js Express 示例:

import express from "express";

const app = express();

app.use("/api", (req, res, next) => {
  res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
  res.setHeader("Pragma", "no-cache");
  res.setHeader("Expires", "0");
  next();
});

app.get("/api/user", (req, res) => {
  res.json({
    id: 1,
    name: "demo-user",
    time: new Date().toISOString()
  });
});

app.listen(3000, () => {
  console.log("API server running at http://localhost:3000");
});

如果你的接口涉及登录态、隐私数据、支付、订单,一定不要依赖 Cloudflare 自动判断,而应主动设置响应头并配置缓存绕过规则。


五、避坑四:真实客户端 IP 获取错误

网站套上 Cloudflare 之后,源站看到的访问 IP 通常会变成 Cloudflare 节点 IP,而不是用户真实 IP。如果你的业务需要记录真实 IP,例如:

  • 登录风控;
  • 评论系统;
  • 访问日志;
  • IP 限流;
  • 地区判断;
  • 安全审计;

就必须正确读取 Cloudflare 提供的请求头。

Cloudflare 会传递真实 IP:

CF-Connecting-IP: 1.2.3.4

此外也可能有:

X-Forwarded-For: 1.2.3.4, 172.68.x.x

推荐优先读取 CF-Connecting-IP

1. Express 获取真实 IP 示例

function getClientIp(req) {
  return (
    req.headers["cf-connecting-ip"] ||
    req.headers["x-forwarded-for"]?.split(",")[0]?.trim() ||
    req.socket.remoteAddress
  );
}

app.get("/", (req, res) => {
  const ip = getClientIp(req);
  res.send(`Your IP is: ${ip}`);
});

2. Nginx 恢复真实 IP

如果源站是 Nginx,需要安装并启用 ngx_http_realip_module,然后配置 Cloudflare IP 段:

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;

然后日志中就可以记录真实用户 IP。


六、避坑五:源站 IP 没有真正隐藏

很多人以为只要开启 Cloudflare 橙色云朵,源站 IP 就自动安全了。但实际上,如果配置不当,源站 IP 依然可能暴露。

常见暴露方式包括:

  1. 历史 DNS 记录泄露;
  2. 子域名未代理;
  3. 邮件服务器与 Web 服务同 IP;
  4. 源站主动发起请求暴露 IP;
  5. GitHub、配置文件、日志中泄露;
  6. SSL 证书透明日志暴露子域;
  7. 直接访问源站 IP 仍返回网站内容。

推荐做法

1. 源站防火墙只允许 Cloudflare IP 访问

以 Ubuntu ufw 为例:

ufw default deny incoming
ufw default allow outgoing

# 允许 SSH,仅示例:建议换成自己的固定 IP
ufw allow from 你的管理IP to any port 22 proto tcp

# 允许 Cloudflare IPv4 访问 80/443
for ip in \
173.245.48.0/20 \
103.21.244.0/22 \
103.22.200.0/22 \
103.31.4.0/22 \
141.101.64.0/18 \
108.162.192.0/18 \
190.93.240.0/20 \
188.114.96.0/20 \
197.234.240.0/22 \
198.41.128.0/17 \
162.158.0.0/15 \
104.16.0.0/13 \
104.24.0.0/14 \
172.64.0.0/13 \
131.0.72.0/22
do
  ufw allow from $ip to any port 80 proto tcp
  ufw allow from $ip to any port 443 proto tcp
done

ufw enable
ufw status verbose

2. 直接访问 IP 不返回站点

Nginx 可以配置默认站点拒绝访问:

server {
    listen 80 default_server;
    listen 443 ssl default_server;

    server_name _;

    ssl_certificate     /etc/nginx/ssl/default.crt;
    ssl_certificate_key /etc/nginx/ssl/default.key;

    return 444;
}

这样攻击者即使知道 IP,也无法直接通过 IP 正常访问网站。


七、避坑六:缓存规则要分层设计

Cloudflare 的缓存不是越激进越好。合理的缓存设计应该按资源类型分层。

1. 静态资源长期缓存

例如:

/static/*
/assets/*
/images/*
/fonts/*
*.css
*.js
*.png
*.jpg
*.webp
*.svg

可设置较长时间缓存:

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

适合带 hash 的静态文件:

app.8f3a1c.js
style.92ab0.css
logo.a91df.webp

2. HTML 短缓存或不缓存

HTML 通常不建议长期缓存,特别是首页、文章页、后台页面。

推荐:

Cache-Control: public, max-age=60

或直接:

Cache-Control: no-cache

对于静态博客,可以适度缓存 HTML,但发布文章后需要主动清理缓存。

3. 文件命名推荐

前端构建工具通常会生成带 hash 的文件名。这样可以放心长期缓存:

/assets/index-3d9c12.js
/assets/index-7a0b43.css

如果没有 hash,不建议设置一年缓存,否则用户可能长期加载旧版本文件。


八、避坑七:Workers 不要滥用,注意路由和成本

Cloudflare Workers 非常强大,可以用来做:

  • 请求转发;
  • API 网关;
  • A/B 测试;
  • 边缘鉴权;
  • 图片处理;
  • 简单反向代理;
  • Header 修改;
  • 缓存控制。

但 Workers 也有坑。

1. 路由不要覆盖全站

例如你配置了:

example.com/*

所有请求都会进入 Worker。如果代码中没有正确处理静态资源、API、错误请求,可能导致整个网站异常。

更安全的方式是只绑定特定路径:

example.com/api/proxy/*
example.com/edge/*

2. Worker 简单反向代理源码

以下是一个基础 Worker,用于代理请求到源站,同时增加安全响应头:

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);

    const targetHost = "origin.example.com";
    url.hostname = targetHost;

    const newRequest = new Request(url.toString(), {
      method: request.method,
      headers: request.headers,
      body: request.body,
      redirect: "follow"
    });

    const response = await fetch(newRequest);
    const newHeaders = new Headers(response.headers);

    newHeaders.set("X-Content-Type-Options", "nosniff");
    newHeaders.set("X-Frame-Options", "SAMEORIGIN");
    newHeaders.set("Referrer-Policy", "strict-origin-when-cross-origin");

    return new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers: newHeaders
    });
  }
};

注意:如果代理的是用户上传内容、登录接口、支付接口,要谨慎处理 Cookie、Header、缓存和跨域。

3. Worker 缓存示例

下面是一个只缓存 GET 请求的 Worker 示例:

export default {
  async fetch(request, env, ctx) {
    if (request.method !== "GET") {
      return fetch(request);
    }

    const url = new URL(request.url);

    if (url.pathname.startsWith("/api/")) {
      return fetch(request);
    }

    const cache = caches.default;
    const cacheKey = new Request(url.toString(), request);
    const cached = await cache.match(cacheKey);

    if (cached) {
      return cached;
    }

    const response = await fetch(request);
    const headers = new Headers(response.headers);

    headers.set("Cache-Control", "public, max-age=300");

    const cachedResponse = new Response(response.body, {
      status: response.status,
      statusText: response.statusText,
      headers
    });

    ctx.waitUntil(cache.put(cacheKey, cachedResponse.clone()));

    return cachedResponse;
  }
};

这个示例避免缓存 /api/,并且只缓存 GET 请求,是比较安全的基本写法。


九、避坑八:WAF 规则不要一刀切

Cloudflare WAF 能拦截攻击,但如果规则太粗暴,会误伤正常用户。

常见误伤场景:

  • 后台富文本编辑器提交 HTML;
  • API 提交 JSON 字段中包含脚本字符串;
  • 海外用户访问被国家/地区规则拦截;
  • 搜索引擎爬虫被挑战;
  • 移动端 App 请求缺少常规浏览器 UA 被拦截。

推荐做法

不要直接用“拦截所有非本国 IP”这种规则,而应分层:

  1. 对后台路径启用更严格规则;
  2. 对登录接口启用速率限制;
  3. 对静态资源放宽检查;
  4. 对可信 IP 白名单放行;
  5. 对可疑请求使用 Managed Challenge,而不是直接 Block。

示例规则思路:

if URI Path starts with /admin
and Country not in [你的国家]
then Managed Challenge

登录接口可以做:

if URI Path equals /login
and request rate too high
then Challenge or Block

这样比全站封禁更稳妥。


十、避坑九:Always Use HTTPS 与源站跳转要协调

Cloudflare 有一个选项:

Always Use HTTPS

开启后,Cloudflare 会把 HTTP 自动跳转到 HTTPS。与此同时,很多源站 Nginx 也会配置 HTTP 到 HTTPS 的跳转。

正常情况下,这没问题。但如果 SSL 模式错误,尤其是 Flexible,就容易循环跳转。

推荐组合:

Cloudflare SSL/TLS: Full(strict)
Always Use HTTPS: On
源站:HTTP 301 到 HTTPS

不推荐:

Cloudflare SSL/TLS: Flexible
源站:强制 HTTPS

如果遇到循环跳转,排查顺序:

  1. 检查 SSL/TLS 模式;
  2. 检查源站是否强制 HTTPS;
  3. 检查应用层是否根据 X-Forwarded-Proto 跳转;
  4. 清理浏览器缓存;
  5. 暂时关闭 Always Use HTTPS 进行测试。

十一、避坑十:国内访问 Cloudflare 不一定更快

很多人认为 CDN 一定能加速,但对于中国大陆用户来说,Cloudflare 免费版并不总是最优选择。

可能出现的问题:

  • 延迟较高;
  • 部分地区连接失败;
  • 晚高峰不稳定;
  • 回源链路不可控;
  • 图片、JS、CSS 加载慢。

如果你的主要用户在国内,可以考虑:

  1. 国内 CDN;
  2. 香港、新加坡、日本节点源站;
  3. 多 CDN 调度;
  4. 仅海外用户走 Cloudflare;
  5. 静态资源放到国内对象存储/CDN;
  6. 使用 DNS 根据地区分流。

Cloudflare 的优势更多体现在全球网络、安全防护、边缘计算和源站隐藏,而不是保证国内免费加速。


十二、常用排查命令

1. 查看 DNS 解析

dig example.com
dig www.example.com
nslookup example.com

2. 查看响应头

curl -I https://example.com

重点关注:

CF-Cache-Status
Cache-Control
Server
Ray ID

CF-Cache-Status 常见值:

HIT      命中缓存
MISS     未命中缓存
BYPASS   绕过缓存
DYNAMIC  动态请求未缓存
EXPIRED  缓存过期后重新拉取

3. 测试源站

如果你知道源站 IP,可以通过 --resolve 测试:

curl -I https://example.com --resolve example.com:443:你的源站IP

这可以绕过 DNS,直接测试源站 HTTPS 配置是否正常。

4. 查看 TLS 信息

openssl s_client -connect example.com:443 -servername example.com

可用于排查证书链、域名不匹配、过期证书等问题。


十三、推荐初始化配置清单

如果你刚开始使用 Cloudflare,可以按以下清单配置:

1. DNS
   - 主站开启 Proxied
   - 邮件、SSH、FTP 不开启代理

2. SSL/TLS
   - 选择 Full(strict)
   - 源站安装有效证书

3. HTTPS
   - 开启 Always Use HTTPS
   - 源站保留 HTTP 到 HTTPS 跳转

4. Cache
   - 静态资源长期缓存
   - API、后台、登录路径 Bypass
   - HTML 不长期缓存

5. Security
   - 开启基础 WAF
   - 后台路径增加 Challenge
   - 登录接口增加速率限制

6. Origin
   - 防火墙只允许 Cloudflare IP 访问 80/443
   - 直接访问 IP 返回 444 或默认页

7. Logs
   - Nginx 配置 real_ip_header
   - 应用读取 CF-Connecting-IP

8. Workers
   - 不要默认覆盖全站
   - 先绑定测试子路径

十四、附:完整 Nginx 站点配置示例

下面给出一个较完整的 Nginx 配置,适合套 Cloudflare 的常规静态站点或前端项目。

server {
    listen 80;
    server_name example.com www.example.com;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;

    real_ip_header CF-Connecting-IP;

    root /var/www/example;
    index index.html;

    access_log /var/log/nginx/example.access.log;
    error_log  /var/log/nginx/example.error.log;

    location /api/ {
        proxy_pass http://127.0.0.1:3000/;
        proxy_set_header Host $host;
        proxy_set_header CF-Connecting-IP $http_cf_connecting_ip;
        proxy_set_header X-Real-IP $http_cf_connecting_ip;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
    }

    location ~* \.(js|css|png|jpg|jpeg|gif|webp|svg|ico|woff|woff2)$ {
        expires 365d;
        add_header Cache-Control "public, max-age=31536000, immutable";
        try_files $uri =404;
    }

    location / {
        try_files $uri $uri/ /index.html;
        add_header Cache-Control "public, max-age=60";
    }
}

十五、总结

Cloudflare 的核心价值不是“简单加速”,而是把 DNS、CDN、安全、证书、边缘计算整合在一起,帮助网站获得更好的可用性和安全性。但它的配置细节很多,如果不了解原理,很容易踩坑。

最重要的几个原则是:

  1. 只给 HTTP/HTTPS 服务开启代理
  2. SSL/TLS 优先选择 Full(strict)
  3. API、登录、后台路径必须绕过缓存
  4. 正确获取真实客户端 IP
  5. 源站防火墙只允许 Cloudflare 回源
  6. 缓存规则按资源类型分层设计
  7. Workers 从小范围路由开始测试
  8. WAF 规则以挑战优先,避免误伤
  9. 国内访问不要盲目期待 Cloudflare 免费版加速

只要遵循这些原则,Cloudflare 会是一个非常强大的基础设施工具。它既能帮助你降低源站压力,也能提升网站安全性,还能通过 Workers、Pages、R2 等服务扩展更多能力。对于个人开发者和中小团队来说,Cloudflare 值得深入学习,但更值得谨慎配置。

标签:

  • Cloudflare
  • DNS
  • SSL/TLS
  • 缓存