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

Cloudflare 企业落地指南:从边缘网关到安全加速的完整实战源码

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

Cloudflare 企业级实战方案|附源码

在企业级互联网架构中,性能、安全、稳定性和成本控制往往是最核心的几个目标。传统方案通常依赖自建 CDN、负载均衡、防火墙、对象存储、DNS、监控系统等多个组件,不仅维护复杂,而且对团队的运维能力要求较高。Cloudflare 的优势在于,它把 DNS、CDN、WAF、DDoS 防护、边缘计算、对象存储、零信任访问、Bot 管理等能力整合在一个全球边缘网络中,能够帮助企业快速构建高可用、高安全、低延迟的业务体系。

本文将从企业级落地角度,给出一套可执行的 Cloudflare 实战方案,并附带核心源码示例,适用于官网门户、API 网关、SaaS 平台、跨境业务、静态资源站、文件分发平台等场景。


一、方案目标

本文设计的 Cloudflare 企业级方案主要解决以下问题:

  1. 全球访问加速
    通过 Cloudflare CDN、智能路由和边缘缓存降低用户访问延迟。

  2. 统一安全防护
    使用 WAF、DDoS 防护、Bot 防护、速率限制和访问控制保护业务。

  3. 边缘 API 网关
    使用 Cloudflare Workers 在边缘节点处理鉴权、转发、灰度、限流和日志。

  4. 静态资源托管与分发
    使用 Cloudflare Pages 或 R2 构建低成本、高可用的静态资源站点。

  5. 数据与配置边缘化
    通过 KV、R2、Durable Objects 实现边缘配置、缓存和轻量状态管理。

  6. 自动化部署
    使用 Wrangler、GitHub Actions 或 Terraform 实现配置和代码自动发布。


二、整体架构设计

企业级 Cloudflare 架构可以分为以下几层:

用户浏览器 / App / 第三方客户端
        |
        v
Cloudflare DNS
        |
        v
Cloudflare CDN + WAF + DDoS + Bot Management
        |
        v
Cloudflare Workers 边缘网关
        |
        +-------------------+
        |                   |
        v                   v
源站 API 服务          Cloudflare R2 / KV / Durable Objects
        |
        v
企业内部服务 / 数据库 / 微服务集群

在这套架构中,Cloudflare 不只是 CDN,而是企业业务的第一层入口。所有请求先进入 Cloudflare,再由其完成安全检查、缓存命中、身份验证、流量控制和请求转发。


三、核心组件选型

1. Cloudflare DNS

Cloudflare DNS 是整套方案的入口。企业可以把域名 NS 切换到 Cloudflare,由 Cloudflare 统一管理 DNS 记录。

常见记录示例:

业务 域名 类型 目标
官网 www.example.com CNAME Cloudflare Pages
API api.example.com CNAME 源站负载均衡
静态资源 static.example.com CNAME R2 自定义域名
后台管理 admin.example.com A/CNAME 内部服务

建议企业开启:

  • DNSSEC
  • Proxy 模式,即橙色云朵
  • CAA 记录,限制证书签发机构
  • 合理配置 TTL

2. CDN 缓存策略

Cloudflare 缓存策略需要根据业务类型区分。

静态资源

如 JS、CSS、图片、字体、视频切片等,建议使用较长缓存时间:

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

同时资源文件名应带 hash,例如:

app.8fa31c2d.js
style.b381a01.css
logo.92ca.png

这样既能长期缓存,又不会出现用户拿到旧资源的问题。

动态接口

API 接口一般不建议直接全局缓存,但可以对部分只读接口做边缘缓存,例如:

  • 商品详情
  • 配置接口
  • 文章详情
  • 地区列表
  • 公共字典数据

可使用 Workers 根据路径、请求参数、请求头做细粒度缓存控制。


3. WAF 与安全规则

企业级场景中,Cloudflare WAF 是非常重要的一环。建议开启:

  • Managed Rules
  • OWASP Core Ruleset
  • SQL 注入防护
  • XSS 防护
  • 文件上传攻击防护
  • WordPress、Drupal 等应用规则,如果业务使用相关系统
  • IP Reputation 防护
  • Geo Blocking,根据业务限制国家或地区访问
  • Rate Limiting,防止接口爆破和恶意爬虫

示例规则:

如果请求路径以 /api/login 开头,并且 1 分钟内超过 20 次,则进行 JS Challenge 或 Block。

4. Workers 边缘 API 网关

Cloudflare Workers 是本方案的核心。它可以在边缘节点执行 JavaScript/TypeScript 代码,实现类似 API Gateway 的功能。

常见用途包括:

  • JWT 鉴权
  • Header 重写
  • CORS 处理
  • 灰度发布
  • A/B 测试
  • 请求签名校验
  • 黑白名单控制
  • 边缘缓存
  • 转发到不同源站
  • 日志采集
  • 限流保护

四、项目目录结构

下面给出一个企业级 Workers 网关项目结构:

cloudflare-enterprise-gateway/
├── src/
│   ├── index.ts
│   ├── auth.ts
│   ├── cache.ts
│   ├── cors.ts
│   ├── limiter.ts
│   ├── router.ts
│   └── utils.ts
├── wrangler.toml
├── package.json
├── tsconfig.json
└── README.md

五、Workers 网关源码

1. package.json

{
  "name": "cloudflare-enterprise-gateway",
  "version": "1.0.0",
  "description": "Enterprise API Gateway based on Cloudflare Workers",
  "scripts": {
    "dev": "wrangler dev",
    "deploy": "wrangler deploy",
    "typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "jose": "^5.9.6"
  },
  "devDependencies": {
    "@cloudflare/workers-types": "^4.20240529.0",
    "typescript": "^5.4.5",
    "wrangler": "^3.57.0"
  }
}

2. wrangler.toml

name = "enterprise-api-gateway"
main = "src/index.ts"
compatibility_date = "2024-06-01"

routes = [
  { pattern = "api.example.com/*", zone_name = "example.com" }
]

[vars]
ORIGIN_API = "https://origin-api.example.internal"
JWT_ISSUER = "https://auth.example.com"
JWT_AUDIENCE = "enterprise-api"

[[kv_namespaces]]
binding = "CONFIG_KV"
id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

[[kv_namespaces]]
binding = "RATE_LIMIT_KV"
id = "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"

[[r2_buckets]]
binding = "LOG_BUCKET"
bucket_name = "enterprise-api-logs"

3. src/cors.ts

export function buildCorsHeaders(origin: string | null): HeadersInit {
  const allowedOrigins = [
    "https://www.example.com",
    "https://admin.example.com"
  ];

  const headers: HeadersInit = {
    "Access-Control-Allow-Methods": "GET,POST,PUT,PATCH,DELETE,OPTIONS",
    "Access-Control-Allow-Headers": "Content-Type,Authorization,X-Request-Id",
    "Access-Control-Max-Age": "86400"
  };

  if (origin && allowedOrigins.includes(origin)) {
    headers["Access-Control-Allow-Origin"] = origin;
    headers["Access-Control-Allow-Credentials"] = "true";
  }

  return headers;
}

4. src/auth.ts

import { jwtVerify, createRemoteJWKSet } from "jose";

export interface AuthResult {
  valid: boolean;
  userId?: string;
  role?: string;
  error?: string;
}

export async function verifyJwt(
  token: string,
  issuer: string,
  audience: string
): Promise {
  try {
    const jwks = createRemoteJWKSet(new URL(`${issuer}/.well-known/jwks.json`));

    const { payload } = await jwtVerify(token, jwks, {
      issuer,
      audience
    });

    return {
      valid: true,
      userId: String(payload.sub || ""),
      role: String(payload.role || "user")
    };
  } catch (err: any) {
    return {
      valid: false,
      error: err.message
    };
  }
}

5. src/limiter.ts

这里使用 KV 做一个简化版限流示例。生产环境中,如需更强一致性,可以结合 Durable Objects 实现。

export interface RateLimitResult {
  allowed: boolean;
  remaining: number;
  reset: number;
}

export async function checkRateLimit(
  kv: KVNamespace,
  key: string,
  limit: number,
  windowSeconds: number
): Promise {
  const now = Math.floor(Date.now() / 1000);
  const windowKey = `${key}:${Math.floor(now / windowSeconds)}`;

  const currentValue = await kv.get(windowKey);
  const current = currentValue ? Number(currentValue) : 0;

  if (current >= limit) {
    return {
      allowed: false,
      remaining: 0,
      reset: windowSeconds - (now % windowSeconds)
    };
  }

  await kv.put(windowKey, String(current + 1), {
    expirationTtl: windowSeconds + 5
  });

  return {
    allowed: true,
    remaining: limit - current - 1,
    reset: windowSeconds - (now % windowSeconds)
  };
}

6. src/cache.ts

export async function cacheFetch(
  request: Request,
  cacheTtlSeconds: number,
  fetcher: () => Promise
): Promise {
  const cache = caches.default;
  const cacheKey = new Request(request.url, request);

  const cached = await cache.match(cacheKey);
  if (cached) {
    const response = new Response(cached.body, cached);
    response.headers.set("X-Cache-Status", "HIT");
    return response;
  }

  const response = await fetcher();

  if (response.ok) {
    const cachedResponse = new Response(response.body, response);
    cachedResponse.headers.set("Cache-Control", `public, max-age=${cacheTtlSeconds}`);
    cachedResponse.headers.set("X-Cache-Status", "MISS");

    await cache.put(cacheKey, cachedResponse.clone());
    return cachedResponse;
  }

  return response;
}

7. src/router.ts

export interface RouteConfig {
  authRequired: boolean;
  cacheTtl?: number;
  rateLimit?: {
    limit: number;
    windowSeconds: number;
  };
}

export function getRouteConfig(pathname: string): RouteConfig {
  if (pathname.startsWith("/api/public")) {
    return {
      authRequired: false,
      cacheTtl: 300,
      rateLimit: {
        limit: 200,
        windowSeconds: 60
      }
    };
  }

  if (pathname.startsWith("/api/user")) {
    return {
      authRequired: true,
      rateLimit: {
        limit: 120,
        windowSeconds: 60
      }
    };
  }

  if (pathname.startsWith("/api/admin")) {
    return {
      authRequired: true,
      rateLimit: {
        limit: 60,
        windowSeconds: 60
      }
    };
  }

  return {
    authRequired: true,
    rateLimit: {
      limit: 100,
      windowSeconds: 60
    }
  };
}

8. src/utils.ts

export function getClientIp(request: Request): string {
  return request.headers.get("CF-Connecting-IP") || "0.0.0.0";
}

export function jsonResponse(
  data: unknown,
  status = 200,
  headers: HeadersInit = {}
): Response {
  return new Response(JSON.stringify(data), {
    status,
    headers: {
      "Content-Type": "application/json;charset=UTF-8",
      ...headers
    }
  });
}

export function getRequestId(request: Request): string {
  return request.headers.get("X-Request-Id") || crypto.randomUUID();
}

9. src/index.ts

import { buildCorsHeaders } from "./cors";
import { verifyJwt } from "./auth";
import { checkRateLimit } from "./limiter";
import { cacheFetch } from "./cache";
import { getRouteConfig } from "./router";
import { getClientIp, getRequestId, jsonResponse } from "./utils";

export interface Env {
  ORIGIN_API: string;
  JWT_ISSUER: string;
  JWT_AUDIENCE: string;
  CONFIG_KV: KVNamespace;
  RATE_LIMIT_KV: KVNamespace;
  LOG_BUCKET: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise {
    const url = new URL(request.url);
    const origin = request.headers.get("Origin");
    const corsHeaders = buildCorsHeaders(origin);
    const requestId = getRequestId(request);

    if (request.method === "OPTIONS") {
      return new Response(null, {
        status: 204,
        headers: corsHeaders
      });
    }

    const routeConfig = getRouteConfig(url.pathname);
    const clientIp = getClientIp(request);

    if (routeConfig.rateLimit) {
      const limitResult = await checkRateLimit(
        env.RATE_LIMIT_KV,
        `rate:${clientIp}:${url.pathname}`,
        routeConfig.rateLimit.limit,
        routeConfig.rateLimit.windowSeconds
      );

      if (!limitResult.allowed) {
        return jsonResponse(
          {
            code: "RATE_LIMITED",
            message: "请求过于频繁,请稍后再试",
            requestId
          },
          429,
          {
            ...corsHeaders,
            "X-RateLimit-Remaining": String(limitResult.remaining),
            "X-RateLimit-Reset": String(limitResult.reset)
          }
        );
      }
    }

    let userId = "";
    let userRole = "";

    if (routeConfig.authRequired) {
      const authHeader = request.headers.get("Authorization");

      if (!authHeader || !authHeader.startsWith("Bearer ")) {
        return jsonResponse(
          {
            code: "UNAUTHORIZED",
            message: "缺少访问令牌",
            requestId
          },
          401,
          corsHeaders
        );
      }

      const token = authHeader.slice("Bearer ".length);
      const authResult = await verifyJwt(token, env.JWT_ISSUER, env.JWT_AUDIENCE);

      if (!authResult.valid) {
        return jsonResponse(
          {
            code: "INVALID_TOKEN",
            message: "令牌无效或已过期",
            requestId
          },
          401,
          corsHeaders
        );
      }

      userId = authResult.userId || "";
      userRole = authResult.role || "user";

      if (url.pathname.startsWith("/api/admin") && userRole !== "admin") {
        return jsonResponse(
          {
            code: "FORBIDDEN",
            message: "无权访问管理接口",
            requestId
          },
          403,
          corsHeaders
        );
      }
    }

    const forwardUrl = new URL(env.ORIGIN_API);
    forwardUrl.pathname = url.pathname;
    forwardUrl.search = url.search;

    const headers = new Headers(request.headers);
    headers.set("X-Request-Id", requestId);
    headers.set("X-Forwarded-By", "cloudflare-workers");
    headers.set("X-Client-IP", clientIp);

    if (userId) {
      headers.set("X-User-Id", userId);
      headers.set("X-User-Role", userRole);
    }

    const proxyRequest = new Request(forwardUrl.toString(), {
      method: request.method,
      headers,
      body: request.method === "GET" || request.method === "HEAD" ? undefined : request.body
    });

    const fetchOrigin = async () => {
      const response = await fetch(proxyRequest);

      const newHeaders = new Headers(response.headers);
      Object.entries(corsHeaders).forEach(([key, value]) => {
        newHeaders.set(key, String(value));
      });

      newHeaders.set("X-Request-Id", requestId);
      newHeaders.set("X-Gateway", "cloudflare-workers");

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

    const response =
      request.method === "GET" && routeConfig.cacheTtl
        ? await cacheFetch(request, routeConfig.cacheTtl, fetchOrigin)
        : await fetchOrigin();

    ctx.waitUntil(writeAccessLog(env, request, response, requestId, clientIp));

    return response;
  }
};

async function writeAccessLog(
  env: Env,
  request: Request,
  response: Response,
  requestId: string,
  clientIp: string
): Promise {
  const url = new URL(request.url);

  const log = {
    requestId,
    time: new Date().toISOString(),
    method: request.method,
    path: url.pathname,
    query: url.search,
    status: response.status,
    ip: clientIp,
    country: request.headers.get("CF-IPCountry"),
    userAgent: request.headers.get("User-Agent")
  };

  const date = new Date().toISOString().slice(0, 10);
  const key = `logs/${date}/${requestId}.json`;

  await env.LOG_BUCKET.put(key, JSON.stringify(log), {
    httpMetadata: {
      contentType: "application/json"
    }
  });
}

六、静态站点方案:Cloudflare Pages

对于企业官网、文档中心、营销页、管理后台前端,可以使用 Cloudflare Pages 托管。

推荐技术栈:

  • Vue / React / Next.js / Astro / Nuxt
  • GitHub 或 GitLab 自动部署
  • Preview Deployments 预览环境
  • Production Branch 发布正式环境

典型部署流程:

npm install
npm run build
npx wrangler pages deploy dist --project-name enterprise-web

如果使用 GitHub Actions,可以配置如下。

.github/workflows/pages.yml

name: Deploy Cloudflare Pages

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout source
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Build project
        run: npm run build

      - name: Deploy to Cloudflare Pages
        run: npx wrangler pages deploy dist --project-name enterprise-web
        env:
          CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

七、对象存储方案:Cloudflare R2

Cloudflare R2 适合用于:

  • 图片资源存储
  • 用户上传文件
  • 软件包分发
  • 日志归档
  • 静态下载站
  • 音视频文件存储

R2 的一个重要优势是没有传统意义上的出口流量费,适合企业做大规模文件分发。

Workers 上传文件示例

export interface Env {
  FILE_BUCKET: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env): Promise {
    if (request.method !== "PUT") {
      return new Response("Method Not Allowed", { status: 405 });
    }

    const url = new URL(request.url);
    const key = url.pathname.replace(/^\/upload\//, "");

    if (!key) {
      return new Response("Missing file key", { status: 400 });
    }

    await env.FILE_BUCKET.put(key, request.body, {
      httpMetadata: {
        contentType: request.headers.get("Content-Type") || "application/octet-stream"
      }
    });

    return new Response(
      JSON.stringify({
        success: true,
        key
      }),
      {
        headers: {
          "Content-Type": "application/json"
        }
      }
    );
  }
};

Workers 下载文件示例

export interface Env {
  FILE_BUCKET: R2Bucket;
}

export default {
  async fetch(request: Request, env: Env): Promise {
    const url = new URL(request.url);
    const key = url.pathname.replace(/^\/files\//, "");

    const object = await env.FILE_BUCKET.get(key);

    if (!object) {
      return new Response("Not Found", { status: 404 });
    }

    const headers = new Headers();
    object.writeHttpMetadata(headers);
    headers.set("Cache-Control", "public, max-age=86400");

    return new Response(object.body, {
      headers
    });
  }
};

八、配置中心方案:Workers KV

企业业务中经常需要边缘配置,例如:

  • 黑白名单
  • 灰度比例
  • 特定地区开关
  • 活动配置
  • 路由映射
  • 维护模式开关

可以使用 KV 存储配置。

示例配置:

{
  "maintenance": false,
  "gray_percent": 20,
  "blocked_countries": ["RU", "KP"],
  "api_origin": "https://origin-api.example.internal"
}

读取配置示例:

export async function getGatewayConfig(kv: KVNamespace) {
  const raw = await kv.get("gateway_config");

  if (!raw) {
    return {
      maintenance: false,
      gray_percent: 0,
      blocked_countries: []
    };
  }

  return JSON.parse(raw);
}

在主入口中可以这样使用:

const config = await getGatewayConfig(env.CONFIG_KV);

if (config.maintenance) {
  return new Response("系统维护中,请稍后再试", {
    status: 503
  });
}

九、灰度发布方案

Cloudflare Workers 非常适合做边缘灰度。比如将 10% 的用户流量转发到新版本源站。

function shouldUseGray(request: Request, percent: number): boolean {
  const cookie = request.headers.get("Cookie") || "";
  const match = cookie.match(/uid=([^;]+)/);

  const seed = match ? match[1] : request.headers.get("CF-Connecting-IP") || "";

  let hash = 0;
  for (let i = 0; i < seed.length; i++) {
    hash = (hash * 31 + seed.charCodeAt(i)) >>> 0;
  }

  return hash % 100 < percent;
}

根据灰度结果选择源站:

const useGray = shouldUseGray(request, 10);

const origin = useGray
  ? "https://gray-api.example.internal"
  : "https://origin-api.example.internal";

这种方式比在源站做灰度更早、更轻量,而且可以减少后端网关压力。


十、零信任访问方案

对于企业后台、运维平台、Grafana、Kibana、Jenkins 等敏感系统,建议使用 Cloudflare Zero Trust。

典型策略:

  1. 后台域名接入 Cloudflare。
  2. 开启 Cloudflare Access。
  3. 配置身份源,例如 Google Workspace、Azure AD、Okta。
  4. 设置访问策略,例如仅允许公司邮箱域、指定团队、指定国家访问。
  5. 可结合 WARP Client 实现企业设备校验。

示例策略:

允许访问 admin.example.com 的用户:
- 邮箱后缀为 @example.com
- 并且属于 Engineering 组
- 并且通过 MFA

这样可以减少 VPN 维护成本,并避免后台系统直接暴露在公网。


十一、Terraform 自动化配置示例

对于企业来说,手动在控制台点击配置不可持续。推荐使用 Terraform 管理 Cloudflare 资源。

main.tf

terraform {
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = "~> 4.0"
    }
  }
}

provider "cloudflare" {
  api_token = var.cloudflare_api_token
}

variable "cloudflare_api_token" {}
variable "zone_id" {}
variable "account_id" {}

resource "cloudflare_record" "api" {
  zone_id = var.zone_id
  name    = "api"
  value   = "origin-api.example.com"
  type    = "CNAME"
  proxied = true
}

resource "cloudflare_record" "www" {
  zone_id = var.zone_id
  name    = "www"
  value   = "enterprise-web.pages.dev"
  type    = "CNAME"
  proxied = true
}

resource "cloudflare_ruleset" "cache_rules" {
  zone_id = var.zone_id
  name    = "enterprise-cache-rules"
  kind    = "zone"
  phase   = "http_request_cache_settings"

  rules {
    action = "set_cache_settings"

    action_parameters {
      cache = true

      edge_ttl {
        mode    = "override_origin"
        default = 86400
      }
    }

    expression  = "(http.host == \"static.example.com\")"
    description = "Cache static assets"
    enabled     = true
  }
}

十二、日志与监控

企业落地 Cloudflare 后,必须建立可观测体系。

建议关注:

  • 请求总量
  • 4xx / 5xx 状态码
  • WAF 拦截数量
  • 缓存命中率
  • 源站回源流量
  • Worker CPU 时间
  • Worker 错误率
  • R2 请求数
  • API 限流触发次数

日志方案可以选择:

  1. Cloudflare Analytics
    适合基础分析。

  2. Logpush
    推送到 R2、S3、BigQuery、Datadog、Splunk 等。

  3. Workers 自定义日志
    对关键业务接口写入 R2 或外部日志系统。

  4. Security Events
    分析攻击来源、规则命中情况和误拦截情况。


十三、性能优化建议

1. 提高缓存命中率

  • 静态资源使用 hash 文件名
  • 避免无意义 query 参数
  • 对公共接口设置边缘缓存
  • 使用 Cache Rules 而不是过度依赖源站响应头
  • 对图片开启 Polish 或使用 Cloudflare Images

2. 减少源站压力

  • Workers 中缓存公共响应
  • 对高频接口做 KV 缓存
  • 登录、短信、验证码接口开启严格限流
  • 对异常 IP 触发 Challenge
  • 使用 Argo Smart Routing 优化回源链路

3. 提升安全性

  • 源站只允许 Cloudflare IP 访问
  • 开启 Full Strict SSL
  • 使用 Origin Certificate
  • 管理后台接入 Zero Trust
  • API 增加 JWT 或签名校验
  • 对上传文件进行 MIME 类型校验和大小限制

十四、源站安全加固

很多企业接入 Cloudflare 后,容易忽视一个问题:如果攻击者知道源站真实 IP,就可能绕过 Cloudflare 直接攻击源站。

因此必须做到:

  1. 源站防火墙只放行 Cloudflare IP。
  2. 不要将源站 IP 暴露在历史 DNS、邮件头、证书记录中。
  3. 源站使用 Cloudflare Origin Certificate。
  4. 后台系统不要与公网 API 共用源站地址。
  5. 对源站接口仍然保留鉴权,不要完全信任边缘层。

Nginx 示例:

server {
    listen 443 ssl;
    server_name origin-api.example.internal;

    ssl_certificate     /etc/nginx/ssl/origin.pem;
    ssl_certificate_key /etc/nginx/ssl/origin.key;

    location / {
        proxy_set_header X-Real-IP $http_cf_connecting_ip;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://backend_cluster;
    }
}

防火墙层面应结合 Cloudflare 官方 IP 列表动态更新规则。


十五、部署步骤

1. 安装 Wrangler

npm install -g wrangler

2. 登录 Cloudflare

wrangler login

3. 创建 KV

wrangler kv namespace create CONFIG_KV
wrangler kv namespace create RATE_LIMIT_KV

4. 创建 R2 Bucket

wrangler r2 bucket create enterprise-api-logs

5. 本地调试

npm install
npm run dev

6. 发布 Worker

npm run deploy

十六、企业落地最佳实践

  1. 生产和测试环境隔离
    建议使用不同域名、不同 Worker、不同 KV、不同 R2 Bucket。

  2. 权限最小化
    Cloudflare API Token 不要使用全局 Key,应按资源授权。

  3. 配置代码化
    DNS、WAF、Cache Rules、Workers Routes 尽量使用 Terraform 或 CI 管理。

  4. 发布前预览
    Pages 使用 Preview Deployments,Workers 使用 staging 路由。

  5. 安全规则先观察后阻断
    新 WAF 规则建议先设置为 Log,再根据误伤情况切换为 Block。

  6. 关键接口多层保护
    登录、注册、支付、验证码、上传接口应同时使用 WAF、Rate Limit、业务风控。

  7. 监控成本
    注意 Workers 请求数、R2 操作数、日志写入量,避免无意义高频写日志。


十七、总结

Cloudflare 在企业级架构中的价值,已经远远超过传统 CDN。它可以作为全球流量入口、安全防护层、边缘计算平台、静态资源平台、对象存储平台和零信任访问入口。通过 DNS、CDN、WAF、Workers、Pages、R2、KV、Zero Trust 等能力的组合,企业可以用较低的运维成本构建一套高性能、高安全、高可用的全球化业务架构。

本文给出的方案重点在于实战落地:使用 Workers 构建边缘 API 网关,完成鉴权、限流、缓存、转发和日志;使用 Pages 托管前端;使用 R2 存储文件与日志;使用 KV 管理边缘配置;使用 Terraform 和 GitHub Actions 实现自动化部署。

如果企业正在做全球化业务、SaaS 平台、跨境电商、开发者平台或高访问量内容分发,Cloudflare 是非常值得纳入核心架构的一套基础设施。合理使用 Cloudflare,不仅可以提升访问速度和安全性,还可以显著降低源站压力与运维复杂度。

目录结构
全文