跳转到内容

诊断与验证

本页提供一个分层 UAT 验证矩阵,用于端到端验证您的客户端防护(Client-Side Defense)部署。每个测试用例遵循基础设施依赖链——从 DNS 解析到 CSD 遥测——以便您系统地验证每个组件是否正常运行。

这些命令是 CSD 控制台演练API 等效操作——当您需要从终端进行验证、自动化监控或在无需 UI 的情况下演示 CSD 功能时使用。

按照 API 自动化 — 环境设置 中的说明配置您的环境变量:

Terminal window
set -a && source .env && set +a

以下所有命令均使用 xTOKENx 占位符格式。请替换为您的环境变量($F5XC_API_TOKEN$F5XC_NAMESPACE 等),或使用页面顶部的交互表单。

许多 CSD 端点需要 epoch 时间戳(自 Unix 纪元起的秒数)。以下单行命令可计算常用时间范围的起止时间。

跨平台(macOS + Linux):

Terminal window
# 当前时间的 epoch 秒数
NOW=$(date +%s)
# 1 小时前
START_1H=$(( NOW - 3600 ))
# 24 小时前
START_24H=$(( NOW - 86400 ))
# 7 天前
START_7D=$(( NOW - 604800 ))
# 30 天前
START_30D=$(( NOW - 2592000 ))
预设秒数Shell 表达式
1 小时3,600$(( $(date +%s) - 3600 ))
24 小时86,400$(( $(date +%s) - 86400 ))
7 天604,800$(( $(date +%s) - 604800 ))
30 天2,592,000$(( $(date +%s) - 2592000 ))

以下每个测试均遵循以下结构:

字段说明
测试 ID层号 + 顺序 ID(如 DNS-1、TLS-2)
验证内容所验证的具体基础设施事实
命令可直接运行的 curldig 命令
通过 / 失败正常与异常状态下的预期输出
修复指向相关设置或故障排除章节的链接

DNS 是基础——如果域名无法解析到负载均衡器的 VIP,其他一切均无法正常工作。

验证内容: 域名解析到负载均衡器的 VIP IP 地址。

Terminal window
dig +short xF5XC_DOMAINNAMEx A
结果含义
通过 — 返回 VIP IP(如 72.19.3.185域名解析到 LB 虚拟 IP
失败 — 空响应DNS A 记录未配置

修复: API 自动化 — 第 4 步:配置 DNS

验证内容: ACME 质询记录已存在,用于自动 TLS 证书签发。

Terminal window
dig +short _acme-challenge.xF5XC_DOMAINNAMEx CNAME
dig +short _acme-challenge.xF5XC_DOMAINNAMEx TXT
结果含义
通过 — CNAME 指向 *.autocerts.ves.volterra.io.(外部 DNS)ACME 质询 CNAME 已就位
通过 — TXT 记录包含域名值(F5 Distributed Cloud (F5 XC) 托管 DNS)平台通过 TXT 记录管理 ACME 质询
失败 — 两者均为空ACME 记录未配置;证书将保持 PreDomainChallengePending 状态

修复: 对于外部 DNS,请创建 CNAME:_acme-challenge.xF5XC_DOMAINNAMEx*.autocerts.ves.volterra.io。对于 F5 XC 托管 DNS,请在 DNS 区域上启用 allow_http_lb_managed_records — 参见 DNS-4。请参阅 API 自动化 — 第 4 步

验证内容: F5 XC 是否为根域的权威 DNS 提供商。

Terminal window
dig +short NS xF5XC_ROOT_DOMAINx
结果含义
包含 ns1.f5clouddns.comns2.f5clouddns.comF5 XC 托管 DNS — 记录可自动创建
其他域名服务器外部 DNS — 记录必须手动创建

修复: API 自动化 — 检测 DNS 权威性

验证内容: F5 XC DNS 区域允许为负载均衡器自动创建记录(仅适用于 F5 XC 托管 DNS)。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/dns/namespaces/system/dns_zones/xF5XC_ROOT_DOMAINx" \
| jq '.spec.primary.allow_http_lb_managed_records'
结果含义
通过true平台将为 LB 自动创建 A 记录和 ACME 记录
失败falsenull托管记录已禁用;请通过区域更新启用

修复: API 自动化 — 选项 A:F5 XC 托管 DNS


DNS 解析成功后,负载均衡器必须具备有效的 TLS 证书。

验证内容: HTTPS LB 上的自动 TLS 证书已签发。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '.spec.cert_state'
结果含义
通过"CertificateValid""AutoCertRenewing"证书有效且处于激活状态
警告"DomainChallengePending""DomainChallengeStarted"ACME 质询进行中 — 等待 5–10 分钟
信息"AutoCertDomainRateLimited"触发 Let’s Encrypt 速率限制 — 演示环境中属正常现象,不影响 HTTP LB
失败"PreDomainChallengePending"ACME 质询记录缺失 — 参见 DNS-2

修复: 确保 ACME 质询记录已就位(外部 DNS 使用 CNAME,F5 XC DNS 启用托管记录)。记录配置完成后,证书签发需要 5–10 分钟。若超过 15 分钟仍未完成,请参阅 证书卡住 — 清理重建。若触发速率限制,HTTP LB 不受影响。

验证内容: 证书覆盖了预期域名并显示过期信息。仅适用于 HTTPS LB。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
cert_state: .spec.cert_state,
auto_cert_info: .spec.auto_cert_info
}'
结果含义
通过auto_cert_info 包含 dns_records 和证书元数据证书签发详情可用
失败auto_cert_infonull 或为空证书尚未签发

验证内容: TLS 证书有效且握手从客户端侧成功完成。仅在 HTTPS LB 具有有效证书时适用。

Terminal window
curl -sv "https://xF5XC_DOMAINNAMEx/" 2>&1 \
| grep -E 'SSL connection|subject:|expire date:|issuer:'
结果含义
通过 — 显示 SSL connection using TLSv1.3、有效的主题和过期信息端到端 TLS 正常工作
失败 — 连接被拒绝或证书错误检查 DNS 解析和证书状态;若触发速率限制,请改用 HTTP

验证内容: HTTPS 负载均衡器报告了用于证书验证的正确 ACME 目标。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
vip_ip: .spec.dns_info[0].ip_address,
acme_target: .spec.auto_cert_info.dns_records
}'
结果含义
通过vip_ipacme_target 均已填充可根据这些值验证 DNS 记录
失败 — 值为 nullLB 可能未配置 https_auto_cert

负载均衡器必须处于就绪状态且配置正确。

验证内容: HTTP 负载均衡器(主要)完全运行并接受流量。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '.spec.state'
结果含义
通过"VIRTUAL_HOST_READY"LB 正常运行
失败"VIRTUAL_HOST_PENDING_A_RECORD"DNS A 记录未配置 — 参见 DNS-1

修复: LB 卡在 VIRTUAL_HOST_PENDING_A_RECORD

验证内容: HTTP 负载均衡器已为正确的域名配置。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '.spec.domains'
结果含义
通过 — 数组包含您的 FQDN(如 ["app.example.com"]LB 已为预期域名配置
失败 — 缺少或错误的域名使用正确的域名更新 LB 规格

验证内容: 负载均衡器上已启用客户端防护,并配置了正确的 JS 注入策略。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '{
csd_enabled: (if .spec.client_side_defense then true else false end),
js_policy: .spec.client_side_defense.policy
}'
结果含义
通过csd_enabled: true 且策略中包含 js_insert_all_pagesCSD 已激活并在所有页面注入 JS
失败csd_enabled: falseLB 上未配置 CSD

修复: API 参考 — 在负载均衡器上启用 CSD

验证内容: 负载均衡器引用了正确的源池,并具有预期的权重和优先级。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '.spec.default_route_pools[] | {
pool: .pool.name,
namespace: .pool.namespace,
weight: .weight,
priority: .priority
}'
结果含义
通过 — 显示您的源池名称及权重/优先级LB 正在路由到正确的后端
失败 — 池为空或错误更新 LB 的 default_route_pools 配置

验证内容: 负载均衡器已部署,并在所有站点报告健康状态。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '{
state: .spec.state,
dns_info: .spec.dns_info,
host_name: .spec.host_name
}'
结果含义
通过stateVIRTUAL_HOST_READYdns_info 已填充LB 已完全部署并分配了 VIP
失败 — 处于待处理状态或 dns_info 为空DNS 或证书问题阻碍了部署

验证内容: 两个 LB 配置的综合快照,用于调试。

HTTP LB(主要):

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '{
name: .metadata.name,
state: .spec.state,
domains: .spec.domains,
csd_enabled: (if .spec.client_side_defense then true else false end),
route_pools: [.spec.default_route_pools[] | .pool.name],
advertise: (if .spec.advertise_on_public_default_vip then "public_default_vip" else "custom" end)
}'

HTTPS LB(次要 — 包含证书状态):

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https" \
| jq '{
name: .metadata.name,
state: .spec.state,
cert_state: .spec.cert_state,
domains: .spec.domains,
csd_enabled: (if .spec.client_side_defense then true else false end),
route_pools: [.spec.default_route_pools[] | .pool.name]
}'

源池定义了负载均衡器将流量路由到的后端服务器。

验证内容: 源池存在,并配置了正确的后端服务器、端口和 LB 算法。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx" \
| jq '{
name: .metadata.name,
origin_servers: [.spec.origin_servers[] | {
ip: .public_ip.ip,
labels: .labels
}],
port: .spec.port,
lb_algorithm: .spec.loadbalancer_algorithm,
endpoint_selection: .spec.endpoint_selection
}'
结果含义
通过 — 显示正确的 IP、端口和算法源池配置正确
失败404 或值错误源池缺失或配置错误

修复: API 自动化 — 第 2 步:创建源池

验证内容: LB 与源服务器之间的连接是否配置了 TLS。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx" \
| jq '{
tls_config: (if .spec.no_tls then "no_tls (plaintext)" elif .spec.use_tls then "use_tls (encrypted)" else "unknown" end)
}'
结果含义
no_tls (plaintext)LB 通过 HTTP 连接到源(Juice Shop 演示的预期行为)
use_tls (encrypted)LB 通过 HTTPS 连接到源

验证内容: 源池已关联正确的健康检查(如适用)。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/origin_pools/xF5XC_ORIGIN_POOLx" \
| jq '.spec.healthcheck'
结果含义
通过 — 包含健康检查引用的数组(名称、命名空间、类型)健康检查已关联
正常 — 空数组 []无健康检查(可接受 — CSD 不要求)
失败 — 预期有健康检查但数组为空创建时未找到健康检查 — 参见 健康检查未关联

验证内容: 源服务器可从客户端侧访问(不测试 LB 到源的路径)。

Terminal window
curl -s -o /dev/null -w '%{http_code}' \
"http://xF5XC_ORIGIN_IPx:xF5XC_ORIGIN_PORTx/"
结果含义
通过200(或其他有效 HTTP 状态码)源服务器正在响应
失败000 或连接被拒绝源服务器无法从当前网络访问

健康检查监控后端可用性。对于 CSD 是可选的,但对于生产部署很有用。

验证内容: 健康检查存在,并配置了正确的类型、路径、时间和阈值。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks/xF5XC_HC_NAMEx" \
| jq '{
name: .metadata.name,
type: (if .spec.http_health_check then "HTTP" elif .spec.tcp_health_check then "TCP" else "unknown" end),
path: .spec.http_health_check.path,
expected_status: .spec.http_health_check.expected_status_codes,
timeout: .spec.timeout,
interval: .spec.interval,
unhealthy_threshold: .spec.unhealthy_threshold,
healthy_threshold: .spec.healthy_threshold
}'
结果含义
通过 — 显示 HTTP 类型,路径为 /,预期状态码为 200健康检查配置正确
失败404 响应健康检查不存在(可能已跳过 — 参见 第 1 阶段第 1 步

验证内容: 枚举命名空间中的所有健康检查,以验证命名和数量。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/healthchecks" \
| jq -r '
["NAME", "NAMESPACE", "DESCRIPTION"],
(.items[] | [
.name,
.namespace,
(.description | if length == 0 then "—" else . end)
])
| @tsv' | column -t

CSD 必须在租户级别启用,并配置 JavaScript 注入标签。

验证内容: CSD 已为租户配置并启用。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status" \
| jq '{isConfigured, isEnabled}'
结果含义
通过 — 两者均为 trueCSD 对此租户处于激活状态
失败isConfigured: falseCSD 未在租户级别启用 — 请联系 F5 XC 管理员
失败isEnabled: falseCSD 已配置但未激活

验证内容: CSD JavaScript 注入标签已生成并准备好注入。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/js_configuration" \
| jq '{has_script_tag: (.scriptTag | length > 0)}'
结果含义
通过has_script_tag: trueJS 注入标签已配置
失败has_script_tag: false无脚本标签 — 请验证 CSD 是否已启用且已注册受保护域名

验证内容: 显示完整的脚本标签以供验证或手动注入。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/js_configuration" \
| jq '.scriptTag'

验证内容: 根域已作为 CSD 受保护域名在租户上注册。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \
| jq '.items[] | {name, namespace, description}'
结果含义
通过 — 显示一个具有非空 name 的条目域名已受保护
失败 — 条目的 namenamespace 字段为空未注册受保护域名 — 参见 第 1 阶段第 6 步

验证内容: CSD JavaScript 实际上正在注入到负载均衡器提供的页面响应中。

Terminal window
curl -s "http://xF5XC_DOMAINNAMEx/" \
| grep -oE '(zeronaught|shape)\.com[^"]*' | head -1
结果含义
通过 — 返回 zeronaught.comshape.com URL 片段(如 zeronaught.com/__imp_apg__/js/...CSD JavaScript 正在注入到页面中
失败 — 空输出JS 未注入 — 检查 LB-3CSD-1

验证实时流量正在到达负载均衡器并被正确处理。

验证内容: 流量正在到达负载均衡器。零结果意味着没有流量到达。

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'"
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs/aggregation" \
| jq '{total_requests: .total_hits}'
结果含义
通过total_requests 为非零字符串(如 "380"流量正在通过 LB
失败"0" 或无数据没有流量到达 LB — 检查 DNS-1LB-1

验证内容: 响应状态码的分布揭示错误模式。

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
"sort": "DESCENDING",
"limit": 100
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs" \
| jq -r '
[.logs[] | fromjson | .rsp_code_class]
| group_by(.) | map({class: .[0], count: length})
| sort_by(-.count)
| ["STATUS_CLASS", "COUNT"], (.[] | [.class, .count])
| @tsv' | column -t

健康站点的预期输出:

STATUS_CLASS COUNT
2xx 82
downstream_remote_disconnect 18
结果含义
通过 — 大多数为 2xx站点正在提供成功响应
警告 — 高 4xx 数量客户端错误(错误的 URL、缺少资源)
失败 — 高 5xx 数量服务器错误 — 检查源服务器健康状况

downstream_remote_disconnect 类表示客户端在响应完成之前关闭了连接(常见于长轮询或 WebSocket 升级请求)。

验证内容: 单个请求已正确记录并包含正确字段。

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-1H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
"sort": "DESCENDING",
"limit": 10
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs" \
| jq -r '
["TIMESTAMP", "METHOD", "PATH", "STATUS", "SRC_IP"],
(.logs[] | fromjson | [.["@timestamp"], .method, .req_path, .rsp_code, .src_ip])
| @tsv' | column -t

验证内容: 访问日志确认 CSD JavaScript 正在注入到响应中。

Terminal window
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d '{
"start_time": "'"$(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-1H +%Y-%m-%dT%H:%M:%SZ)"'",
"end_time": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'",
"sort": "DESCENDING",
"limit": 20
}' \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs" \
| jq '[.logs[] | fromjson | select(.csd_js_injection == "true")] | length as $injected |
{injected_count: $injected, total_sampled: 20}'
结果含义
通过injected_count > 0CSD JS 正在注入到页面响应中
失败injected_count: 0JS 未注入 — 检查 CSD-1LB-3

验证内容: 完整请求从客户端经 DNS、LB 和源服务器流转,并返回有效响应。

Terminal window
curl -sv "http://xF5XC_DOMAINNAMEx/" 2>&1 \
| grep -E 'Connected to|< HTTP|< content-type'
结果含义
通过 — 显示连接、HTTP 200 和内容类型完整堆栈正常运行
失败 — 连接被拒绝或 DNS 错误第 1 层:DNS 开始排查

这些命令查询 CSD 控制台 仪表板、脚本列表、表单字段和网络视图中显示的相同数据。

验证内容: CSD 正在检测并编目在受保护域上运行的脚本。

Terminal window
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"startTime\": \"${START}\",
\"endTime\": \"${NOW}\"
}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts" \
| jq -r '
["SCRIPT", "RISK", "STATUS", "FIELDS", "USERS"],
(.scripts[] | [
(.script_name | if length > 50 then .[:47] + "..." else . end),
.risk_level,
.status,
(.form_fields_read // 0),
(.affected_users_count // 0)
])
| @tsv' | column -t
结果含义
通过 — 列出了带有风险级别的脚本CSD 正在主动监控脚本
失败 — 空数组参见 故障排除:脚本数组为空

验证内容: CSD 已检测到脚本来源域名并按状态对其分类。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{
summary: {
action_needed: .domain_summary.actionNeededCount.count,
mitigated: .domain_summary.mitigatedDomains.count,
allowed: .domain_summary.allowedDomains.count,
total: .domain_summary.totalDomains.count
},
domains: [.domains_list[] | {
domain: .domain,
category: .category,
status: .status,
first_seen: (.firstSeenDate | tonumber | todate),
latest_seen: (.latestSeenDate | tonumber | todate)
}]
}'
结果含义
通过total > 0 且列出了域名CSD 正在跟踪脚本域名
警告action_needed > 0某些域名需要审查
失败 — 空响应无遥测数据 — 检查 CSD-5

验证内容: 显示允许与已缓解域名的分布,以及策略是否一致。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{
action_needed: .domain_summary.actionNeededCount.count,
mitigated: .domain_summary.mitigatedDomains.count,
allowed: .domain_summary.allowedDomains.count,
total: .domain_summary.totalDomains.count,
domains_needing_action: [.domains_list[] | select(.status == "AN") | .domain]
}'
结果含义
通过action_needed: 0所有域名已审查并分类
警告action_needed > 0domains_needing_action 中列出的域名需要审查

验证内容: CSD 已检测到脚本正在读取的表单字段,并进行了敏感性分类。

Terminal window
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/formFields?startTime=${START}&endTime=${NOW}" \
| jq -r '
["FIELD", "SENSITIVITY", "SCRIPTS"],
(.form_fields[] | [
.name,
.analysis,
(.scripts_count // 0)
])
| @tsv' | column -t
结果含义
通过 — 列出了带有敏感性的表单字段CSD 正在跟踪表单字段访问
信息 — 空数组未检测到表单字段(若站点没有表单,属预期行为)

验证内容: 关于特定脚本的详细信息,包括风险、行为和网络交互。

首先从 TEL-1 获取脚本 ID,然后查询其详情:

Terminal window
SCRIPT_ID="your-script-id"
# 概览(风险级别、类型、来源域名)
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/dashboard" \
| jq '{script_name, risk_level, type, source_domain, status}'
# 随时间变化的行为
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/behaviors" \
| jq '.behaviors'
# 网络交互(脚本与之通信的域名)
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/networkInteractions" \
| jq '.network_interactions'

验证内容: 列出受特定脚本影响的用户,显示暴露范围。

Terminal window
SCRIPT_ID="your-script-id"
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"startTime\": \"${START}\",
\"endTime\": \"${NOW}\"
}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts/${SCRIPT_ID}/affectedUsers" \
| jq -r '
["IP_ADDRESS", "DEVICE_ID", "GEO", "CHANNEL", "USER_AGENT"],
(.affected_users[] | [
.ip_address,
(.device_id | if length > 12 then .[:12] + "..." else . end),
.geolocation,
.channel,
(.user_agent | if length > 30 then .[:27] + "..." else . end)
])
| @tsv' | column -t

验证内容: 所有检测到的脚本的汇总风险分布。

Terminal window
NOW=$(date +%s)
START=$(( NOW - 604800 ))
curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"startTime\": \"${START}\",
\"endTime\": \"${NOW}\"
}" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/scripts" \
| jq '[.scripts[] | .risk_level] | group_by(.) | map({risk_level: .[0], count: length}) | sort_by(-.count)'
结果含义
通过 — 全部为 No Risk未检测到风险脚本
警告 — 存在 Low RiskHigh RiskTEL-5 中审查标记的脚本

验证内容: CSD 遥测数据是最新的,确认主动监控正在进行。

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/detected_domains" \
| jq '{
total_domains: .domain_summary.totalDomains.count,
latest_update: (.domain_summary.totalDomains.lastUpdated // "unknown"),
most_recent_domain: (.domains_list | sort_by(.latestSeenDate) | last | {
domain: .domain,
latest_seen: (.latestSeenDate | tonumber | todate)
})
}'
结果含义
通过latest_seen 在过去 24 小时内遥测正在主动收集数据
警告latest_seen 早于 24 小时前流量可能已停止或 CSD 处理存在延迟

运行一条命令,检查每一层的所有关键健康指标并生成摘要表:

Terminal window
echo "=== CSD Verification Dashboard ==="
echo ""
# 第 1 层:DNS
DNS_A=$(dig +short xF5XC_DOMAINNAMEx A | head -1)
DNS_ACME=$(dig +short _acme-challenge.xF5XC_DOMAINNAMEx CNAME | head -1)
# 第 2-3 层:LB + TLS
LB=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http")
LB_HTTPS=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-https")
LB_STATE=$(echo "$LB" | jq -r '.spec.state // "UNKNOWN"')
CERT_STATE=$(echo "$LB_HTTPS" | jq -r '.spec.cert_state // "UNKNOWN"')
CSD_ON_LB=$(echo "$LB" | jq -r 'if .spec.client_side_defense then "ENABLED" else "DISABLED" end')
DOMAINS=$(echo "$LB" | jq -r '.spec.domains | join(", ")')
ROUTE_POOL=$(echo "$LB" | jq -r '[.spec.default_route_pools[] | .pool.name] | join(", ")')
# 第 6 层:CSD 状态
CSD=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/status")
CSD_CONFIGURED=$(echo "$CSD" | jq -r '.isConfigured // false')
CSD_ENABLED=$(echo "$CSD" | jq -r '.isEnabled // false')
# 第 6 层:JS 配置
JS_TAG=$(curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/js_configuration" \
| jq -r 'if (.scriptTag | length) > 0 then "PRESENT" else "MISSING" end')
# 第 7 层:流量(过去 24 小时)
TRAFFIC=$(curl -s -X POST \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
-H "Content-Type: application/json" \
-d "{
\"start_time\": \"$(date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-24H +%Y-%m-%dT%H:%M:%SZ)\",
\"end_time\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"
}" \
"xF5XC_API_URLx/api/data/namespaces/xF5XC_NAMESPACEx/access_logs/aggregation" \
| jq -r '.total_hits // "0"')
printf "%-28s %s\n" "CHECK" "STATUS"
printf "%-28s %s\n" "----------------------------" "----------------------------"
printf "%-28s %s\n" "[DNS] A Record" "${DNS_A:-NOT_FOUND}"
printf "%-28s %s\n" "[DNS] ACME CNAME" "${DNS_ACME:-NOT_FOUND}"
printf "%-28s %s\n" "[TLS] Certificate" "$CERT_STATE"
printf "%-28s %s\n" "[LB] State" "$LB_STATE"
printf "%-28s %s\n" "[LB] Domains" "$DOMAINS"
printf "%-28s %s\n" "[LB] Route Pool" "$ROUTE_POOL"
printf "%-28s %s\n" "[LB] CSD on LB" "$CSD_ON_LB"
printf "%-28s %s\n" "[CSD] Configured (tenant)" "$CSD_CONFIGURED"
printf "%-28s %s\n" "[CSD] Enabled" "$CSD_ENABLED"
printf "%-28s %s\n" "[CSD] JS Script Tag" "$JS_TAG"
printf "%-28s %s\n" "[Traffic] Requests (24h)" "$TRAFFIC"

字段类型说明
@timestampstring请求时间戳(ISO 8601)。注意 @ 前缀 — 在 jq 中使用 .["@timestamp"] 访问
methodstringHTTP 方法(GET、POST 等)
req_pathstring请求 URI 路径
rsp_codestringHTTP 响应状态码(字符串形式,如 "200""404"
rsp_code_classstring状态码类别(2xx3xx4xx5xxdownstream_remote_disconnect
src_ipstring客户端源 IP 地址
dst_ipstring目标(VIP)IP 地址
domainstring请求 Host 头部值
user_agentstring客户端 User-Agent 字符串
rsp_sizestring响应正文大小(字节,以字符串形式返回)
req_sizestring请求正文大小(字节,以字符串形式返回)
duration_with_data_tx_delaystring请求总持续时间(秒,以字符串形式返回,如 "0.024219"
csd_js_injectionstringCSD JavaScript 已注入时为 "true"(仅在激活时存在)
字段端点说明
isConfiguredstatusCSD 在租户级别已启用
isEnabledstatusCSD 对此命名空间处于激活状态
scripts[]scripts检测到的脚本对象数组
.script_namescriptsJavaScript 文件的完整 URL
.risk_levelscripts风险级别(No Risk、Low Risk、High Risk)
.statusscriptsAN(需要操作)或 NA(无需操作)
.form_fields_readscripts脚本读取的表单字段数量
.affected_users_countscripts受影响的唯一用户/会话数量
domain_summarydetected_domains按状态统计:.actionNeededCount.count.mitigatedDomains.count.allowedDomains.count.totalDomains.count(每个均有 .count.lastUpdated
domains_list[]detected_domains检测到的域名对象数组,包含 .domain.status.category.firstSeenDate.latestSeenDate(epoch 秒数,以字符串形式表示)
form_fields[]formFields检测到的表单字段对象数组
.analysisformFields敏感性分类(Sensitive、Not Sensitive)

如果 TV-1 返回 0

  1. 检查 DNS 解析 — 验证域名是否解析到 LB VIP:

    Terminal window
    dig +short xF5XC_DOMAINNAMEx A

    如果为空,则 DNS 未配置。参见 API 自动化 — 第 4 步

  2. 检查 LB 状态 — 负载均衡器必须处于 VIRTUAL_HOST_READY 状态:

    Terminal window
    curl -s \
    -H "Authorization: APIToken xF5XC_API_TOKENx" \
    "xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
    | jq '.spec.state'
  3. 发送测试请求 — 生成流量以确认端到端连接性:

    Terminal window
    curl -sv "http://xF5XC_DOMAINNAMEx/" 2>&1 | head -20

    查找成功的 HTTP 响应。仅在 HTTPS LB 证书有效时才使用 https://

如果 DNS-4 返回 false,即使 F5 XC 是权威 DNS 提供商,自动记录创建也被禁用。这是一种常见的配置错误,会导致 A 记录和 ACME CNAME 均缺失,从而阻止负载均衡器达到 VIRTUAL_HOST_READY 状态以及证书的签发。

要启用托管记录,请更新 DNS 区域配置以设置 allow_http_lb_managed_records: true。有关 API 调用,请参阅 API 自动化 — 选项 A:F5 XC 托管 DNS

负载均衡器正在等待指向其 VIP 的 DNS A 记录。有关详细解决步骤,请参阅 LB 卡在 VIRTUAL_HOST_PENDING_A_RECORD

自动 TLS 证书需要 ACME 质询记录。具体方法取决于您的 DNS 提供商:

F5 XC 托管 DNS: 在 DNS 区域上启用 allow_http_lb_managed_recordsDNS-4)。平台将在 x-ves-io-managed RR 集组中自动创建基于 TXT 的 ACME 质询记录。如果启用托管记录后证书仍然卡住,请删除并重新创建负载均衡器以触发新的证书请求。

外部 DNS: 在您的 DNS 提供商处创建 CNAME 记录:

_acme-challenge.xF5XC_DOMAINNAMEx CNAME *.autocerts.ves.volterra.io

验证记录是否存在:

Terminal window
dig +short _acme-challenge.xF5XC_DOMAINNAMEx CNAME
dig +short _acme-challenge.xF5XC_DOMAINNAMEx TXT

如果两者均为空,则 ACME 记录未配置。记录就位后,证书签发需要 5–10 分钟。检查 LB 错误状态以获取具体的 ACME 验证错误:

Terminal window
curl -s \
-H "Authorization: APIToken xF5XC_API_TOKENx" \
"xF5XC_API_URLx/api/config/namespaces/xF5XC_NAMESPACEx/http_loadbalancers/xF5XC_LB_NAMEx-http" \
| jq '[.status[]? | select(.virtual_host_status != null) | .virtual_host_status.error_description]'

CSD 必须由 F5 XC 管理员在租户级别启用。这是一个全租户范围的设置,无法通过命名空间 API 配置。请联系您的管理员以启用客户端防护。

如果 TEL-1 返回空数组:

  1. 检查受保护域名 — CSD 仅监控已注册域名上的脚本:

    Terminal window
    curl -s \
    -H "Authorization: APIToken xF5XC_API_TOKENx" \
    "xF5XC_API_URLx/api/shape/csd/namespaces/xF5XC_NAMESPACEx/protected_domains" \
    | jq '.items[] | {name, namespace}'
  2. 验证 JS 注入 — 确认 CSD 脚本标签正在注入到页面中:

    Terminal window
    curl -s "http://xF5XC_DOMAINNAMEx/" | grep -oE '(zeronaught|shape)\.com[^"]*' | head -1

    如果无匹配,则 CSD JavaScript 未被注入。检查 LB 是否已启用 client_side_defense

  3. 等待处理时间 — 在首次启用 CSD 或注册新的受保护域名后,脚本检测可能需要 5–15 分钟。在重新检查之前,请向站点生成流量并等待。

周期Epoch 偏移量ISO 8601(Linux)ISO 8601(macOS)
1 小时$(( $(date +%s) - 3600 ))date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-1H +%Y-%m-%dT%H:%M:%SZ
24 小时$(( $(date +%s) - 86400 ))date -u -d '24 hours ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-24H +%Y-%m-%dT%H:%M:%SZ
7 天$(( $(date +%s) - 604800 ))date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-7d +%Y-%m-%dT%H:%M:%SZ
30 天$(( $(date +%s) - 2592000 ))date -u -d '30 days ago' +%Y-%m-%dT%H:%M:%SZdate -u -v-30d +%Y-%m-%dT%H:%M:%SZ
测试覆盖内容
1. DNS 解析DNS-1 至 DNS-4A 记录、ACME CNAME、域名服务器权威性、托管记录
2. TLS 证书TLS-1 至 TLS-4证书状态、证书详情、实时握手、ACME 目标
3. HTTP 负载均衡器LB-1 至 LB-6状态、域名、CSD 标志、路由池、部署、摘要
4. 源池OP-1 至 OP-4配置、TLS 模式、HC 关联、源连接性
5. 健康检查HC-1 至 HC-2HC 配置、列出所有 HC
6. CSD 配置CSD-1 至 CSD-5租户状态、JS 标签、受保护域名、实时注入
7. 流量验证TV-1 至 TV-5请求数、状态码、样本、日志中的 JS、端到端测试
8. CSD 遥测TEL-1 至 TEL-8脚本、域名、策略、表单字段、深度分析、用户、风险、新鲜度
诊断端点方法时间格式
请求数/api/data/namespaces/\{ns\}/access_logs/aggregationPOSTISO 8601
状态码/api/data/namespaces/\{ns\}/access_logsPOSTISO 8601
近期请求/api/data/namespaces/\{ns\}/access_logsPOSTISO 8601
LB 状态/api/config/namespaces/\{ns\}/http_loadbalancers/\{name\}GET
源池/api/config/namespaces/\{ns\}/origin_pools/\{name\}GET
健康检查/api/config/namespaces/\{ns\}/healthchecks/\{name\}GET
DNS 区域/api/config/dns/namespaces/system/dns_zones/\{zone\}GET
CSD 状态/api/shape/csd/namespaces/\{ns\}/statusGET
JS 配置/api/shape/csd/namespaces/\{ns\}/js_configurationGET
受保护域名/api/shape/csd/namespaces/\{ns\}/protected_domainsGET
脚本列表/api/shape/csd/namespaces/\{ns\}/scriptsPOSTEpoch 秒数
检测到的域名/api/shape/csd/namespaces/\{ns\}/detected_domainsGET
表单字段/api/shape/csd/namespaces/\{ns\}/formFieldsGETEpoch 秒数(查询参数)
脚本详情/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/dashboardGET
脚本行为/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/behaviorsGET
脚本网络/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/networkInteractionsGET
受影响用户/api/shape/csd/namespaces/\{ns\}/scripts/\{id\}/affectedUsersPOSTEpoch 秒数