CDN 联调测试清单
你可以按下面顺序验证:解析 → 接入 → 回源 → 缓存 → Header → 静态资源加速。
确认 200cdn.xyz 已解析到 CDN 接入域名(CNAME)或节点 IP(A)。
建议:dig 200cdn.xyz 或 nslookup 200cdn.xyz。
访问首页 /,确认能看到页面;再访问接口:
- /api/status(查看服务信息)
- /api/hello(动态 JSON)
访问 /api/headers 或 /api/headers/forwarded-check,观察是否存在:
X-Forwarded-For/X-Forwarded-Host/X-Forwarded-ProtoVia/X-Cache/ 自定义节点标识(视你的 CDN 实现而定)
POST /referer/admin/config:配置启用防盗链、允许直接访问、来源域名允许一致、允许/禁止来源域名、检查Origin、例外URL、限制URLGET /referer/admin/status:查看当前防盗链策略GET /referer/protected或/referer/probe:观察命中结果与原因
完整步骤见:docs/REFERER_ANTI_HOTLINK_VERIFY.md。
- 打开
/referer/ui,在线修改防盗链字段并保存。 - 通过探针查看
reason/sourceHost/sourceFrom与 HTTP 状态。 - 支持“一键回放 / 仅回放失败项 / 导出 JSON”。
访问 /cacheable/a 两次,对比:
- 是否命中缓存(CDN 侧 HIT)
- 源站日志/回源次数是否减少
- 响应头中的
Age/X-Cache等是否变化
打开 /gallery,检查 CSS/JS/图片资源是否能正常加载;再在 CDN 配置静态缓存规则观察加速效果。
使用以下接口生成大文件样本,支持 sizeMB 参数(默认 20MB,最大 128MB):
/media/large.pdf?sizeMB=50/media/large.docx?sizeMB=50/media/large.mp3?sizeMB=50/media/large.mp4?sizeMB=50/media/large.svg?sizeMB=50/media/large.png?sizeMB=50/media/large.gif?sizeMB=50/encoding/large.gz?sizeMB=50
可用 curl -I 校验 Content-Type/Content-Length,并结合 CDN 做大文件回源、缓存、断点续传验证。说明:large.svg 可直接浏览器打开;large.png/large.gif 为大体积二进制样本(主要用于分发/缓存/限速/Range 验证,不保证浏览器可渲染)。
本页默认不展示长脚本。你可以先看配置要点与验证命令,需要时再点击查看完整部署脚本。
- 节点目标:同一节点启用双端口
9070 -> server-A、9010 -> server-B - CDN 配置:两条 FastCGI 服务分别指向
127.0.0.1:9070与127.0.0.1:9010 - 脚本路径:
/tmp/php/server_a.php与/tmp/php/server_b.php
部署脚本页面:
/fastcgi/deploy-script
(支持查看:一键部署脚本、启动成功检查、端口修改命令、验证命令)
点击查看:常用验证命令(不展开时默认不显示)
# 1) 两端口本机检查(在每个节点执行)
nc -vz 127.0.0.1 9070
nc -vz 127.0.0.1 9010
# 2) 从客户端验证随机分发(节点1)
for i in $(seq 1 20); do
resp=$(curl -s -w '\nHTTP_CODE:%{http_code}\n' http://150.109.79.244/ -H 'Host: test.300cdn.xyz')
code=$(echo "$resp" | sed -n 's/^HTTP_CODE://p')
body=$(echo "$resp" | sed '/^HTTP_CODE:/d')
server=$(echo "$body" | python3 -c "import sys,json;s=sys.stdin.read().strip();print(json.loads(s).get('server','<NO_SERVER>') if s.startswith('{') else '<NON_JSON>')" 2>/dev/null)
echo "$code $server"
done | sort | uniq -c
# 3) 节点2同样检查
for i in $(seq 1 20); do
resp=$(curl -s -w '\nHTTP_CODE:%{http_code}\n' http://150.109.156.154/ -H 'Host: test.300cdn.xyz')
code=$(echo "$resp" | sed -n 's/^HTTP_CODE://p')
body=$(echo "$resp" | sed '/^HTTP_CODE:/d')
server=$(echo "$body" | python3 -c "import sys,json;s=sys.stdin.read().strip();print(json.loads(s).get('server','<NO_SERVER>') if s.startswith('{') else '<NON_JSON>')" 2>/dev/null)
echo "$code $server"
done | sort | uniq -c
打开 /origin-timeout/ui,设置“最大等待时长”,再用探针模拟源站慢响应。
POST /origin-timeout/admin/set?wait=8s设置等待预算GET /origin-timeout/probe?originDelay=12s当 delay > wait 时返回504
GET /origin/timeout/read?ms=8000:首包延迟,用于 ReadTimeoutGET /origin/conn/hold?ms=15000+/origin/conn/status:并发/空闲连接压测GET /origin/flaky?key=demo&fail=2&code=502:前2次失败后成功,用于自动重试 50X/40XGET /lb/tcp-udp/status:查看connectFailPort(连接后立即断开),用于“连接失败/快速失败”验证
POST /req-limit/admin/config?enabled=1&maxConcurrent=2&maxConcurrentPerIp=1&singleConnKiBps=64&maxRequestKiB=16:开启并设置全部字段GET /req-limit/admin/status:查看当前配置与运行并发计数GET /req-limit/probe/hold?ms=8000:并发压测;超限应返回429GET /req-limit/probe/stream?seconds=5:观察单连接带宽限制(响应头X-Req-Limit-KiBps)POST /req-limit/probe/upload:上传超出maxRequestKiB后应返回413
完整步骤和命令见:docs/REQUEST_LIMIT_VERIFY.md。
POST /compression/admin/config:配置启用、扩展名、MimeType、算法顺序、长度、PartialContent、URL 例外/限制、匹配条件GET /compression/admin/status:查看当前压缩策略快照GET /compression/probe?path=/a.js&mime=application/javascript&size=4096:验证是否命中压缩- 查看响应头:
X-Compression-Hit/X-Compression-Reason/X-Compression-Algorithm/Content-Encoding
完整步骤见:docs/COMPRESSION_WEBP_VERIFY.md。
先访问 /lb/tcp-udp/status 获取端口(默认 TCP 10001、UDP 10002)。
echo 'ping' | nc -w 2 源站IP 10001(TCP)echo -n 'ping' | nc -u -w 2 源站IP 10002(UDP)
在控制台把调度算法改为 Sticky 后,依次测试 Cookie / HTTP Header / URL 参数:
curl -s -c - http://200cdn.xyz/sticky/cookiecurl -s -H "X-Sticky-Key: user-a" http://200cdn.xyz/sticky/headercurl -s "http://200cdn.xyz/sticky/url?stickykey=user-a"
同一参数值应返回同一 bucket,用于验证粘滞调度键是否稳定生效。
用于验证“回源跟随”开关是否生效(单跳/多跳)。
curl -sI "http://200cdn.xyz/origin-follow/start?code=302&hops=1"curl -sI "http://200cdn.xyz/origin-follow/start?code=302&hops=3"curl -sL "http://200cdn.xyz/origin-follow/start?code=302&hops=3"(跟随到 final)curl -sI "http://200cdn.xyz/origin-follow/compare?expected=on&hops=3"curl -sI "http://200cdn.xyz/origin-follow/compare?expected=off&hops=3"
POST /cluster/admin/config+GET /cluster/admin/status:调度、健康检查、重试、通知字段GET /cluster/probe/dispatch?key=user-a:验证调度算法效果(如 hash 稳定性)POST /node/admin/config+GET /node/admin/status:节点权重、连接、带宽、缓存、TLS/HTTP2/WS/IPv6GET /node/probe/dispatch?key=user-a:节点禁用时应返回503
完整字段级步骤见:docs/CLUSTER_NODE_FIELD_VERIFY.md;严格字段映射表见:docs/CLUSTER_NODE_FIELD_MAPPING.md。
POST /websocket/admin/config:配置启用WebSocket、允许所有来源域、传递请求来源域GET /websocket/admin/status:查看当前策略GET /websocket/probe:传Origin头检查是否允许及原因/ws、/ws/echo-headers:实际握手回显验证
完整步骤见:docs/WEBSOCKET_FIELD_VERIFY.md。
POST /webp/admin/config:配置启用 WebP、支持扩展名、支持 MimeType、最小/最大长度、匹配条件、Avif 开关GET /webp/admin/status:查看当前 WebP 策略GET /webp/probe:查看转换判定(X-WebP-Converted/Reason/Target)GET /webp/vary-accept:看真实 Accept 协商行为(Vary: Accept)
完整步骤见:docs/WEBP_FIELD_VERIFY.md。
POST /waf/admin/config:配置启用、人机识别方式、系统全局规则、条件参数/运算符/条件值、动作类型GET /waf/admin/status:查看当前 WAF 策略和字段枚举GET /waf/probe:查看匹配结果、动作和状态码(含X-WAF-Matched/X-WAF-Action)POST /api/data:入站 JSON/Form 参数验证探针(可用于requestJSON/requestForm场景)POST /api/upload:上传文件名验证探针(可用于requestUpload场景)- 兼容探针:
/waf/sql、/waf/xss、/waf/path-traversal/*
完整步骤见:docs/WAF_FIELD_VERIFY.md。
- 打开
/waf/ui,在线修改 WAF 字段并保存 - 点击“发起探针”查看当前字段命中结果
- 点击“一键回放”自动执行当前规则 + GET_302 动作验证
- 状态码样本:
/trigger-400、/trigger-500、/trigger-502、/trigger-503、/forbidden、/not-found、/redirect - 敏感内容样本:
/api/user-info(身份证)、/api/contact(手机号)、/api/db-error(SQL错误)、/api/path-leak(路径)、/api/internal-info(内网IP)、/api/exception(Traceback) - 密钥与支付样本:
/api/config(secret/password/token)、/api/payment(银行卡号)、/api/full-info(身份证+手机号) - 响应头样本:
/api/hello(Server/X-Powered-By)、/api/data(Access-Control-Allow-Origin: *) - 大响应体样本:
/api/large-data?bytes=2097152(用于bytesSent阈值)
与 yuanzhan 对齐覆盖(新增)
以下路径用于一一对照 CDN 功能:缓存、图片/视频、压缩编码、重定向、CORS、流式、上传。
- /platform(网站设置字段 ↔ 源站探针)
- /field-mapping(严格字段映射 + 复制curl + 批量回放)
- /api/matrix(机器可读覆盖清单)
- /api/headers/forwarded-check(自动添加报头专项验证)
- /trigger-500、/trigger-502、/trigger-503、/forbidden、/not-found
- /api/data、/api/upload(WAF 入站 JSON/Form/上传探针)
- /api/user-info、/api/contact、/api/db-error、/api/path-leak
- /api/internal-info、/api/exception、/api/config、/api/payment、/api/full-info
- /api/large-data?bytes=2097152(bytesSent 样本)
- /origin-follow/start、/origin-follow/final、/origin-follow/compare
- /lb/tcp-udp/status(TCP/UDP Echo 端口状态)
- /sticky/cookie、/sticky/header、/sticky/url
- /req-limit/admin/status、/req-limit/probe/hold、/req-limit/probe/upload
- /compression/admin/status、/compression/probe
- /websocket/admin/status、/websocket/probe、/ws/echo-headers
- /websocket/ui(WebSocket 可视化控制台)
- /webp/bench.json + /webp/vary-accept
- /media/video.mp4、/media/video.mp4.range、/网站设置.mp4
- /encoding/gzip-response、/encoding/sample.txt.gz、/encoding/sample-bundle.zip
- /cache/nocache、/cache/http-no-cache、/cache/stale-if-error
- /cors/api、/stream/chunked、/stream/sse
curl -s --data-binary @/etc/hosts http://200cdn.xyz/upload/raw
# Range 边界
curl -sI -H "Range: bytes=0-15" http://200cdn.xyz/range/binary
curl -sI -H "Range: bytes=0-1023" http://200cdn.xyz/media/video.mp4.range
# Range 严格边界矩阵(推荐都跑一遍)
# 1) 正常:首段 / 开区间 / 尾部区间(suffix-range)
curl -sI -H "Range: bytes=0-99" http://200cdn.xyz/range/strict
curl -sI -H "Range: bytes=100-" http://200cdn.xyz/range/strict
curl -sI -H "Range: bytes=-200" http://200cdn.xyz/range/strict
# 2) 越界 / 非法:应返回 416,并带 Content-Range: bytes */TOTAL
curl -sI -H "Range: bytes=9999999-10000000" http://200cdn.xyz/range/strict
curl -sI -H "Range: bytes=10-1" http://200cdn.xyz/range/strict
curl -sI -H "Range: items=0-10" http://200cdn.xyz/range/strict
curl -sI -H "Range: bytes=0-0,2-3" http://200cdn.xyz/range/strict
# 3) HEAD + Range:应返回 206,且包含 Content-Range/Content-Length
curl -sI -X HEAD -H "Range: bytes=0-15" http://200cdn.xyz/range/strict
# 4) If-Range(ETag 命中 -> 206;不命中 -> 忽略 Range 返回 200)
curl -sI -H 'If-Range: "200cdn-range-v1"' -H "Range: bytes=0-15" http://200cdn.xyz/range/strict
curl -sI -H 'If-Range: "not-match"' -H "Range: bytes=0-15" http://200cdn.xyz/range/strict
# 5) If-Range(HTTP-date 命中/不命中)
curl -sI -H "If-Range: Sat, 01 Jun 2024 12:00:00 GMT" -H "Range: bytes=0-15" http://200cdn.xyz/range/strict
curl -sI -H "If-Range: Sat, 01 Jun 2022 12:00:00 GMT" -H "Range: bytes=0-15" http://200cdn.xyz/range/strict
# 6) If-Match / If-None-Match + Range 组合
curl -sI -H 'If-Match: "200cdn-conditional-v1"' -H "Range: bytes=0-31" http://200cdn.xyz/range/conditional
curl -sI -H 'If-Match: "not-match"' -H "Range: bytes=0-31" http://200cdn.xyz/range/conditional
curl -sI -H 'If-None-Match: "200cdn-conditional-v1"' -H "Range: bytes=0-31" http://200cdn.xyz/range/conditional
curl -sI -H 'If-None-Match: "not-match"' -H "Range: bytes=0-31" http://200cdn.xyz/range/conditional
# 7) 301/302 + Range 继承(观察 CDN 是否透传 Range 到跳转后的请求)
curl -sI -H "Range: bytes=0-31" http://200cdn.xyz/redirect/range/301
curl -sI -L -H "Range: bytes=0-31" http://200cdn.xyz/redirect/range/301
curl -sI -L -H "Range: bytes=0-31" http://200cdn.xyz/redirect/range/302
curl -sI -L -H "Range: bytes=0-31" http://200cdn.xyz/redirect/range-hop/302
# ETag / 304
etag=$(curl -sI http://200cdn.xyz/cache/etag | tr -d "\r" | awk -F": " "/^ETag:/{print $2;exit}")
curl -sI -H "If-None-Match: $etag" http://200cdn.xyz/cache/etag
# Last-Modified / 304
curl -sI -H "If-Modified-Since: Sat, 01 Jun 2024 12:00:00 GMT" http://200cdn.xyz/cache/lastmodified
POST 回显(用于调试请求体和头)
把请求 JSON 发到 /api/echo,源站会把解析结果回显出来。
全站字段严格总表:docs/CDN_FIELD_MAPPING_STRICT.md。
curl -s -X POST http://200cdn.xyz/api/echo \\
-H 'Content-Type: application/json' \\
-d '{"name":"cdn-test","n":1}' | jq