自定义防护响应
适用版本:v3.8.0。让网站访客知道发生了什么,并能向你提供请求 ID;为 API 客户端返回可解析的 JSON。 打开 系统管理 → 设置 → 防护响应。这些设置适用于所有站点。在 防护场景 编辑指定场景,查看独立的草稿预览后点击 保存全部修改。
1. 编辑场景内容与共享模板
场景列表显示状态码和未保存标记。选中场景只改变编辑对象,标题、说明与状态码的修改适用于所有站点中的该场景。
在 响应模板 管理全局响应方式及六个场景共用的模板。顶部一行左侧为共享模板标题和说明,右侧为响应方式设置。选择框下方先说明格式规则,再说明适用于所有站点的全部防护场景。两侧标题与说明分别使用一致的字体和字号,通过一条横线与下方模板内容分隔。模板选择、编辑和预览使用完整宽度。自定义模板会标明实际输出格式。预览选择只改变展示,当前响应方式未使用的模板会明确标记。可以在光标处插入公开变量;模板未引用标题或说明时,字段旁会显示提示。
标题和说明位于同一行,旁边是保存全部修改等操作,更多操作排在最后。两个页签采用正常大小,紧接其下,当前响应方式显示在页签旁。保存按钮在滚动时保持可见;点击修改详情查看两个页签的改动,点击状态入口查看应用结果、错误与重试操作,一次保存全部修改。放弃全部修改 回到上次保存的内容。恢复本场景或此模板默认只修改对应范围;更多操作 → 恢复全部默认 经确认后替换整个草稿。所有恢复操作都需要保存后才会应用。保存失败会保留草稿;应用待处理或失败时,可以重试已保存的配置,之后的新修改仍会保留。未启用模板的错误也会列出,点击即可定位对应字段。
同一套 HTML/JSON/纯文本/自定义模板供以下六个场景共用,具体场景由实际拦截环节选择:
| 场景 | 默认状态码 |
|---|---|
WAF 拦截 waf_block |
403 |
IP 拒绝 ip_deny |
403 |
国家访问拒绝 country_deny |
403 |
限速 / CC rate_limit |
429 |
Bot 最终拒绝 bot_block |
403 |
服务保护 service_unavailable |
503 |
auto 根据请求 Accept 选择:含 text/html 返回 HTML,否则 JSON。
也可固定 html、json、plain、custom。各场景状态码范围为 400–599;API 校验与资源保护保留各自要求的 HTTP 状态码,修改场景默认值不会覆盖这些协议判定。
源站自身返回的普通 403 不会被替换。浏览器挑战的交互页面、机器验证和协议/正文资源错误保留各自的处理方式。
2. 可以直接修改的完整模板
本例保留默认状态码,只改公开文案与共享格式。需要 jq;先保存当前设置,再应用完整的单个配置项。 已有设置请先检查备份,选好窗口后执行。下载版:security-responses.json。
umask 077
cat > security-responses.json <<'JSON'
{
"security.responses.config": {
"templates": {
"active": "auto",
"html": {
"body": "<h1>{response.title}</h1><p>{response.message}</p><p>{request.id}</p>",
"contentType": "text/html; charset=utf-8"
},
"json": {
"body": "{\"status\":{response.status_code},\"title\":\"{response.title}\",\"message\":\"{response.message}\",\"request_id\":\"{request.id}\"}",
"contentType": "application/problem+json"
},
"plain": {
"body": "{response.title}. {response.message} Request ID: {request.id}",
"contentType": "text/plain; charset=utf-8"
},
"custom": {
"body": "{response.title}. {response.message}",
"contentType": "text/plain; charset=utf-8"
}
},
"scenarios": {
"waf_block": {
"statusCode": 403,
"title": "请求被拦截",
"message": "如需协助,请向网站管理员提供请求 ID。"
},
"ip_deny": {
"statusCode": 403,
"title": "访问被拒绝",
"message": "当前访问不被允许。"
},
"country_deny": {
"statusCode": 403,
"title": "访问被拒绝",
"message": "当前访问不被允许。"
},
"rate_limit": {
"statusCode": 429,
"title": "请求过于频繁",
"message": "请稍后重试。"
},
"bot_block": {
"statusCode": 403,
"title": "需要浏览器验证",
"message": "请使用 HTTPS 浏览器访问;API 接入请联系网站管理员。"
},
"service_unavailable": {
"statusCode": 503,
"title": "服务暂时不可用",
"message": "请稍后重试。"
}
}
}
}
JSON
sudo tiyi system settings get > settings-before.json
jq '{"security.responses.config": .settings.values["security.responses.config"]}' \
settings-before.json > responses-before.json
sudo tiyi system settings update --values-json "$(cat security-responses.json)"
只有 security.responses.config 这个键会更新。该对象必须包含全部格式和六个场景,即使某个格式没有启用。
不要继续写旧版分散的 WAF/限速响应键,IP/国家绑定也没有单独状态码选项。
3. 验证与恢复
在自己的演示站点分别请求 HTML 和 JSON:
curl -i --get -H 'Host: quickstart.test' -H 'Accept: text/html' \
--data-urlencode 'q=1 UNION SELECT password FROM users' http://127.0.0.1/
curl -i --get -H 'Host: quickstart.test' -H 'Accept: application/json' \
--data-urlencode 'q=1 UNION SELECT password FROM users' http://127.0.0.1/
两次都应为配置的 WAF 状态码,正文格式与 Content-Type 应匹配,响应包含太一生成的请求 ID。
正常请求仍应到达源站。多节点检查每个服务节点的发布结果。
恢复前检查 responses-before.json 中的值是完整对象而不是 null,再执行:
sudo tiyi system settings update --values-json "$(cat responses-before.json)"
若原配置未显式保存、备份值为 null,可在控制台选择“更多操作 → 恢复全部默认”,再保存;重置编辑器但不保存不会影响在线配置。
4. 支持的变量与边界
模板仅支持 {response.status_code}、{response.kind}、{response.source}、{response.title}、
{response.message}、{request.id}、{request.time}。来源是固定的大类,ID/时间由太一生成。
不支持嵌入请求 Cookie、正文、IP、路径、规则 ID、阈值、内部错误或剩余封禁时间。
未知变量和无效 JSON 会拒绝保存/应用;运行时保留最后有效配置。
模板不支持 JavaScript,终止响应有禁止脚本的 CSP;不要粘贴依赖脚本的完整页面。
太一不会自动发送 Retry-After,客户端应使用自己的有界重试策略。