边缘判定与脚本对接

把流量留在自己的网站上,用官方 PHP 包、Cloudflare Worker 或 Cloudflare Pages 接入平台判定:按访客规则放行、出页、打开本站路径、跳转或只回状态码。

访客访问你自己的网站时,官方脚本向平台询问结果,再按动作放行、出页、打开本站路径、302 跳转或只回状态码。域名和网站不必迁到平台。

官方提供三份脚本包,判定行为对齐,按站点环境任选其一:

  • PHP 包{name}-php.zip):传统主机或虚拟主机,使用 PHP 8.3 时放到站点同目录。始终一包,Apache / Nginx 只是同包内的伪静态示例
  • Cloudflare Worker{name}-cf-worker.zip):源站已接入 Cloudflare 并绑 Worker 路由时用
  • Cloudflare Pages{name}-cf-pages.zip):站点在 Cloudflare Pages 上时用。必须带 _routes.json

Worker 与 Pages 同一 Workers 运行时,但挂法不同,控制台分两个 zip 下载。不要把 Worker 与 Pages 中间件挂在同一路由。

适用场景

  • 希望域名和网站留在自己这边
  • 用官方脚本接入判定,不必自己对接接口

平台托管投放(把域名指到平台)仍然可用。

怎么选脚本

站点环境用哪个
自有服务器或虚拟主机,PHP 8.3{name}-php.zip
站点已接入 Cloudflare(源站 + 路由){name}-cf-worker.zip
站点在 Cloudflare Pages{name}-cf-pages.zip

三者都调用同一套判定接口(POST /v1/decision,Bearer)。脚本本身不做 PHP 版本探测。

怎么用

  1. 开通边缘判定,并确认套餐档位
  2. 在控制台「边缘对接」选择规则模板,并配置通过 / 拦截时的动作
  3. 按环境下载官方 PHP 包Cloudflare WorkerCloudflare Pages(三者并列,任选其一)
  4. 按下方对应步骤部署
  5. 访客访问该站点时,脚本按返回结果执行

场景配置

控制台「边缘对接」里每个场景对应一把密钥、一套规则模板和一组动作。字段如下。

字段取值说明
name1–128 字符场景名称
rule_template_id必填账号内可见的广告规则模板(国家、UA、IP 等)
pass_actionallow / html / redirect / path规则通过时的动作
pass_filehtml 时必填仅文件名,如 land.html
pass_urlredirect 时必填http/https 地址,或以 / 开头的站内路径
pass_pathpath 时必填/ 开头的站内路径
fail_actionhtml / redirect / path / deny规则不通过时的动作
fail_filehtml 时必填,缺省 safe.html仅文件名
fail_urlredirect 时必填pass_url
fail_pathpath 时必填pass_path
deny_status403 / 404 / 204 / 410,缺省 404deny 使用
append_query0 / 1,缺省 1redirectpath 是否把当前地址栏 query 接到目标
fail_modehtml / allow,缺省 html通信失败或无法解析时:出安全页或出落地页
statusnormal / disabled,缺省 normaldisabled 时判定接口返回 403

文件名、URL、路径约束:

  • HTML 文件名^[A-Za-z0-9._-]+\.html$,最长 128;禁止 ../\
  • 跳转目标:最长 1024。http/https 且带 host,或以 / 开头的站内路径;禁止 //evil.com..、反斜杠
  • 站内路径:最长 1024,必须以 / 开头;禁止 ..//http、反斜杠、空白。可带 query(? 后部分)

通过 / 拦截动作与目标在控制台保存后立即生效。密钥、场景 ID、fail_mode、包内默认 HTML 文件名写在脚本常量里,改这些需重新下载并覆盖脚本。

创建或轮换后可随时下载 PHP 包、Cloudflare Worker 与 Cloudflare Pages(Peek 打进 ZIP,可反复下同一把)。正式密钥只在轮换时更换;轮换或删除场景后旧钥立即失效,须重新下载并覆盖已部署脚本。

判定请求

官方脚本对平台发起:

POST /v1/decision
Authorization: Bearer <场景密钥>
Content-Type: application/json
Accept: application/json

包内超时为 2500 ms。请求体:

字段必填约束脚本怎么采
ip合法 IPv4 / IPv6CF-Connecting-IPX-Real-IPX-Forwarded-For 左一 → REMOTE_ADDR
ua非空,最长 1024User-Agent
referer最长 2048Referer
language最长 256Accept-Language
url最长 4096,须含 scheme 与 host当前完整 URL(含 query)
scene_id正整数,且必须等于该密钥所属场景下载时写入脚本常量
{
  "ip": "203.0.113.10",
  "ua": "Mozilla/5.0 ...",
  "referer": "https://example.com/",
  "language": "zh-CN,zh;q=0.9",
  "url": "https://yoursite.com/",
  "scene_id": 12
}

scene_id 与密钥不匹配、场景停用时,接口返回 403。国家、ASN、代理等画像由平台根据 ip 等字段计算,脚本不在客户侧查第三方 IP 库。

判定响应

成功时 HTTP 200,正文:

{
  "code": 200,
  "msg": "SUCCESS",
  "data": { "action": "allow" }
}

dataaction 带不同字段:

actiondata 其它字段脚本行为
allow(无)出落地页。PHP / Cloudflare 使用包内 ALLOW_HTML_FILE(缺省 land.html
htmlpagelanding(通过)或 safe(拦截);file:HTML 文件名出该文件
redirecturlappend_query(布尔)302http/https 或站内路径
pathpathappend_query(布尔)打开本站路径,地址栏不变
denystatus403 / 404 / 204 / 410只回该 HTTP 状态码,无正文

code 不是 200、传输失败或 JSON 无法解析时,走场景的 fail_modehtml 出安全页,allow 出落地页)。脚本响应带 Cache-Control: no-store

公开判定常见失败(官方脚本一律走故障兜底,不向访客展示这些码):

HTTP含义
401密钥缺失或无效
403未开通、场景停用、scene_id 不匹配,或账号不可用
400请求字段不合法,或规则模板无效
429当日次数用尽
503平台暂不可用

PHP 与 Cloudflare

同一 action 对齐,实现随运行环境不同:

actionPHP(PHP 8.3Cloudflare
html / allow读与 index.php 同目录的文件无本地磁盘,对当前请求同源 GET 该文件名
path在网站文档根内 includerealpath 必须落在文档根内对本站同源路径 fetch 后返回正文
redirect均为 302;append_query 缺省开同左
deny对应 HTTP 状态码同左

path 必须以 / 开头;禁止 ..//http、反斜杠。redirect 禁止 //evil.com

控制台

  1. 开通后打开「边缘对接」
  2. 按上一节配置场景
  3. 下载官方 PHP 包、Cloudflare Worker 或 Cloudflare Pages
  4. 「判定记录」查看成功与失败,可按场景 / 通过 / 动作 / IP 筛选

页头显示今日已用 / 剩余,按套餐计算每日判定次数。

PHP 包

网站使用 PHP 8.3,并能出站 HTTPS 访问平台接口。包内脚本不会检查 PHP 版本号。官方 PHP 始终一包({name}-php.zip)。把文件放到站点目录,未命中真实文件的请求进 index.php

  1. 下载官方 PHP 包并解压
  2. 放到网站目录(index.php 与页面文件在同一目录)
  3. 按包内 .htaccessnginx.conf.example 配好伪静态(未命中真实文件的请求进 index.php)。站点根 / 必须进 index.php;若同目录已有 index.html,访问 / 可能直接出静态首页、绕过判定
  4. 把占位页换成真实 HTML,文件名与控制台配置一致

包内:index.php(已写入 https 判定口、密钥与场景常量)、按场景文件名生成的占位页、README.txt.htaccessnginx.conf.example。命中真实文件(含带后缀的静态资源)的请求不进判定。落地页应由脚本输出,不要靠直接打开 /land.html 走规则。

Cloudflare Worker

站点源站已接入 Cloudflare、要绑 Worker 路由时,下载 {name}-cf-worker.zip。与 Pages 同一运行时,采集与动作相同:优先 CF-Connecting-IP,再带 UA、Referer、Accept-Language 与完整 URL,以 Bearer 调用判定接口。无 Node fs。html / path 从同源取文件。带后缀的静态文件直出,不走判定。

包内:

  • worker.js
  • wrangler.toml.example
  • README.txt
  • 按场景文件名生成的占位 HTML

不含 functions/_routes.json。不要与 Pages 中间件挂在同一路由上。

  1. 在控制台下载 Cloudflare Worker
  2. land.html / safe.html(或场景里配置的文件名)放到源站同源可 GET 的位置
  3. 按 README 将 wrangler.toml.example 改成 wrangler.toml(填账号与路由)
  4. 用 wrangler 部署,并把 Worker 绑到站点路由

html 动作从同源拉取文件(fetch(new URL('/' + file, request.url))),请保证这些文件在源站可访问。

Cloudflare Pages

站点在 Cloudflare Pages 上时,下载 {name}-cf-pages.zip。用包内 functions/_middleware.js(Pages Functions,与 Worker 同一运行时)。官方写法是全站中间件,拦站点根路径,与只挂某个子路径(例如 /go)的测法不同。不要与 Worker 挂在同一路由上。

包内:

  • functions/_middleware.js
  • _routes.json(Pages 必须带上)
  • README.txt
  • 按场景文件名生成的占位 HTML
  1. functions/_middleware.js 放到 Pages 项目的 functions/ 目录
  2. 把包内 _routes.json 放到 Pages 项目根(与 functions 同级)。若静态输出在 public/(Astro / Vite 等),放到 public/_routes.json,保证发布产物根目录带上该文件。Pages 必须_routes.json
  3. land.html / safe.html(或场景文件名)放到站点根目录,与 functions 同级。不要放进与 Functions 同名的子目录(例如不要 functions/go 配静态 /go/*.html),否则 Pages 会自动排除 Functions,中间件不会执行
  4. 项目里如果已经有 functions/_middleware.js(语言跳转、地区拦截等),不要整文件覆盖官方中间件;合并逻辑,或把判定挂到单独子路径,并仍保留 _routes.jsoninclude /*
  5. 按 Pages 正常发布

Pages 没有本地磁盘。html / path 同源 GET:优先走 Pages 的 ASSETS;否则同源 fetch,并带内部头避免再次进入判定。

计次

仅公开判定成功计入当日次数。额度在平台统计。额度用尽或平台暂不可用时走故障兜底。

常见卡点

现象可检查
看不到「边缘对接」是否已开通;当前是否管理员
需要换钥或怀疑泄露点轮换,再下载覆盖已部署脚本
上传后一直出安全页规则是否符合预期;占位页是否已换成真实页;文件名是否一致
访问站点根 / 不出判定、一直静态首页伪静态是否进 index.php;同目录 index.html 是否抢了首页
Worker / Pages 一直出安全页或 html 未出页同源文件能否 GET;路由是否打到脚本;Pages 是否把 html 放在站点根目录,且带上 _routes.json
Pages 中间件完全不执行发布产物根是否有 _routes.jsoninclude /*);落地 HTML 是否与 Functions 同路径前缀导致自动排除;已有根 _middleware 是否整文件覆盖了官方文件
path 未出页PHP:路径是否在文档根内、伪静态是否进 index.php;Cloudflare:同源路径是否可 GET
平台不可用时仍出落地页故障兜底是否设成了放行(有风险)

相关页面:控制台总览 · 规则模板 · 常见问题