DANGER

本页由 AI 工具参考代码编写,尚未经过人工审核,内容仅供参考。如果无法解决问题或需要协助部署,可邮箱联系:kuohu@getastra.cn

WAF 与 CDN 配置

Web 应用防火墙(WAF)和 CDN 是 AstraSchedule 外网部署方案的安全屏障。不同部署方案使用不同的安全组件,本章分别说明。

🤖 官方第一方流量标识约定

AstraSchedule 的第一方流量都会带上固定标识,便于在 WAF 和访问日志里把自家人与自动化扫描器区分开:

来源标识
桌面客户端(课表、倒计时、WebSocket 等全部请求)User-Agent: AstraSchedule/<客户端版本>
桌面客户端的自动更新由内置更新器决定,不带上面这个标识
机器到机器的后端调用(reg-to、sys-backend)User-Agent: AstraSchedule/System
浏览器里的网页(注册页、系统管理端、SaaS 用户端)无法自定义 UA,改用 Referer 标注第一方来源

💡 客户端版本取自应用自身的版本号(例如 AstraSchedule/1.6.1),升级后自动跟随,无需手工维护。服务端调用(reg-to、sys-backend)不经过浏览器,可以自由设置 UA,因此一律带上第一方标识;它们发出的请求没有 Referer,只能靠 UA 通过 WAF。

网页端:用 Referer 标注来源

浏览器无法自定义 User-Agent——它是 fetch/XHR 规范里的 forbidden header name,设置后会被浏览器静默丢弃。因此注册页、系统管理端、SaaS 用户端这些跑在浏览器里的页面,请求头里永远是浏览器自己的 UA。

替代方案是在页面里声明 referrer 策略,让跨域接口请求带上第一方 Referer,再由 WAF 按 Referer 放行:

<meta name="referrer" content="strict-origin-when-cross-origin" />

meta 标签会覆盖响应头里的 Referrer-Policy(例如 ESA Pages / OSS 默认的 same-origin,跨域时一个字节的 Referer 都不发),并且 CORS 预检 OPTIONS 也会带上 Referer(Chrome 实测)。

⚠️ 实测结论(2026-10,ESA):

  • ESA 的「修改入站请求头」可以在边缘改写 User-Agent,但对 WAF 判定没有影响——WAF 用的是客户端发来的原始请求头(实测:对某路径改写 UA 后,该请求依然会被基于 UA 的自定义规则质询)。边缘改写只影响源站与日志里看到的 UA。
  • WAF 表达式不支持自定义请求头字段(http.request.headers["x-..."] 报 Http.Request.Headers.NotSupport),「自定义标头标注来源」这条路走不通;Referer 是浏览器可用、WAF 也可判定的字段。
  • http.referer 在 http_custom 阶段只支持 contains 一类比较,lower() / starts_with() 会报 Expression.Invalid。

用 UA / Referer 识别扫描器(ESA 示例)

第一方 UA 统一以 AstraSchedule 开头(客户端带版本号、服务端带用途后缀),其余 UA 基本是自动化扫描。只在「非浏览器域名」上做质询,并把第一方网页的 Referer 加入豁免,就不会影响正常网页:

配置项值
规则名称非标 UA 质询
匹配表达式not http.user_agent contains "AstraSchedule" and not http.host in {"你的网页端域名"} and not http.referer contains "你的网页端域名"
动作JS 质询(或拦截)

把浏览器访问的域名全部放进 http.host 白名单;面向客户端和机器调用的域名(如 API 域名)则不豁免,让它们必须带 AstraSchedule 前缀;跨域调用 API 的第一方网页(如注册页 → API 域名)靠 http.referer 豁免放行。再配一条「异常 UA 拦截」直接拦掉 curl、python-requests、sqlmap、nikto 这类工具签名与上面的质询规则互补——Referer 可以伪造,异常 UA 拦截是兜底。

💡 JS 质询通过后写入的 cookie 按域名隔离(例如 acw_sc__v2@njx.getastra.cn):在 a.getastra.cn 上解开的质询,不会让 b.getastra.cn 的请求通过。浏览器能自行解决页面级质询,但页面里发往其它域名的 fetch/XHR 不能靠它过关。

📡 排障口径:响应来自边缘还是 FC

对接 FC(函数计算)的域名,/ 这类根路径不能用来说明 FC 层是否可用——它可能是边缘直接应答的。实测(2026-10,ESA)看响应头即可区分:

响应头特征响应方
带 x-fc-request-idFC:请求确实打到了函数
只有 Server: ESA、无 x-fc-request-id边缘:响应在 CDN/WAF 层就产生了,没有经过 FC

X-Site-Cache-Status 可作辅助判断:HIT 是边缘缓存,DYNAMIC 是回源(API 域名通常是 DYNAMIC)。实测结果:

请求响应方依据
静态站域名 /(Pages / OSS 站点,如 getastra.cn、www.、i.、dev.、go.)边缘HIT,无 x-fc-request-id
API 域名 /(class.、sys.、to.、njx. 等)FCDYNAMIC + x-fc-request-id,返回 {"message":"Hello World"}
被 WAF 拦截或质询的请求(任意路径)边缘403 或质询页,无 x-fc-request-id

⚠️ 所以 / 只是连通性探针。判断 FC 是否可用要打真实业务接口,并且必须带第一方标识(不带就会被 WAF 质询,拿到的仍然是边缘响应):

curl -A "AstraSchedule/1.6.1" "https://class.getastra.cn/web/countdown?scope=39%2F2023%2F1"
# 200 {"data":[],"hasConfig":false,"loading":false}

curl -A "AstraSchedule/1.6.1" "https://to.getastra.cn/api/check-subdomain/<名称>"
# 200 {"available":...,"providers":[...]}

反过来,排查「客户端报错但 FC 日志里没有记录」时,先看响应里有没有 x-fc-request-id:没有就说明请求在边缘就被拦下或质询了,与 FC 无关。

课表数据「改了不生效」的排查

课表接口带版本号协商时,可按下面的顺序区分问题在边缘还是源站:

  1. 手动带 version=0 强制回源(客户端点托盘「更新课表」等价),看是否拿到新数据——能拿到说明源站正常,问题在边缘缓存未失效
  2. 检查写入路径是否返回了 X-Astra-Purge-Scopes 响应头(管理端保存课表/设置、结构增删、自动任务与倒数日变更、备份导入都会声明失效范围)——缺失说明该写路径没声明失效,边缘 KV 会停留在旧版本号
  3. 检查响应是否压到了源站:无 x-fc-request-id 的响应产生于边缘(见上表)

缓存协商与失效机制的完整说明见系统架构 · 边缘缓存架构。

🔰 极低成本方案(Cloudflare)

极低成本方案使用 Cloudflare 免费套餐,已足够日常使用。

DNS 代理模式

在 Cloudflare DNS 设置中,确保你的域名记录开启了代理(橙色云朵图标)。代理模式下,所有流量先经过 Cloudflare 边缘节点,获得 CDN 加速和安全防护。

如何检查:

  1. 登录 Cloudflare 控制台 → 选择你的域名
  2. 进入 DNS → Records
  3. 确认 api 和 admin 两条 CNAME 记录的代理状态均为 🟢 已代理

WAF 基础规则

Cloudflare 免费套餐可以开启 Cloudflare Managed Ruleset(需在 WAF 页面手动启用),可防御:

  • SQL 注入攻击
  • 跨站脚本攻击(XSS)
  • 命令注入
  • 常见漏洞扫描行为

开启后无需额外配置。如果遇到客户端或管理端异常访问失败,可能是 WAF 误拦截,按照下方「查看拦截日志」排查。

速率限制规则

通过速率限制防止 API 被恶意高频调用。进入 Security → WAF → Rate limiting rules,创建以下规则:

⚠️ Cloudflare 免费套餐的速率限制规则数量与流量额度有限(免费版约 1 条规则、每月 1 万次请求额度,以 Cloudflare 当前套餐政策为准)。规则太多会无法保存,请按需取舍。

API 全局限速(建议)

配置项值
规则名称API Global Rate Limit
匹配条件Hostname = api.你的域名.com
速率同一 IP 每分钟 100 个请求
操作阻止(Block)
阻止时长1 分钟

API 路径单独限速

如果你的客户端数量较多,建议对部分敏感路径单独限速:

配置项值
规则名称API Path Rate Limit
匹配条件Hostname = api.你的域名.com AND URI Path contains /web/
速率同一 IP 每分钟 60 个请求
操作阻止(Block)
阻止时长1 分钟

速率选择建议:如果全校有 30 个班级,每个客户端定期拉取配置,则请求量很低。60 次/分钟的上限留有充足余量。如果你的客户端数量更多或刷新频率更高,请适当调高阈值。

管理端登录接口限速

配置项值
规则名称Admin Login Rate Limit
匹配条件Hostname = admin.你的域名.com AND URI Path contains /login
速率同一 IP 每分钟 10 个请求
操作阻止(Block)
阻止时长5 分钟

自定义 WAF 规则示例

进入 Security → WAF → Custom rules,以下是一些常用规则:

阻止特定国家/地区之外的访问

如果学校的客户端和管理员都在国内,可以限制仅允许中国 IP 访问:

配置项值
字段Country
运算符is in
值选择你需要允许的国家/地区
操作阻止(Block)

⚠️ 使用此规则前请确认所有合法访问来源的 IP 归属地。如果使用 Cloudflare 的免费套餐,国家级别过滤精度有限,可能误拦截。

封禁恶意 IP

如果发现某个 IP 持续攻击,可以手动添加封禁规则:

配置项值
字段IP Source Address
运算符equals
值目标 IP 地址
操作阻止(Block)

查看拦截日志

当客户端或管理端出现异常的访问失败时,可以通过以下步骤排查是否被 WAF 拦截:

  1. 登录 Cloudflare 控制台 → 选择你的域名
  2. 进入 Security → Events
  3. 查看最近的「已阻止」事件,包含:
    • 被拦截的请求路径和来源 IP
    • 触发拦截的规则名称
    • 时间戳
  4. 如果确认是误拦截,可以针对该规则创建「跳过」规则或调整规则条件

🏫 内网方案

内网方案的服务器不暴露到公网,无需配置 WAF 和 CDN。但应确保基本的网络安全措施。

防火墙规则建议

运行 AstraSchedule 服务器的内网机器应配置以下防火墙规则:

规则说明
放行 TCP 80Nginx HTTP 端口,管理端访问入口
放行 TCP 443Nginx HTTPS 端口(如配置了 HTTPS)
放行 TCP 9000后端 API 端口
拒绝其他入站端口最小化攻击面

Linux 服务器(ufw)示例:

# 启用防火墙
sudo ufw enable

# 放行必要端口
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow 9000/tcp

# 查看规则
sudo ufw status

Windows 服务器示例:

# 以管理员身份运行,放行必要端口
New-NetFirewallRule -DisplayName "AstraSchedule HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "AstraSchedule HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
New-NetFirewallRule -DisplayName "AstraSchedule API" -Direction Inbound -Protocol TCP -LocalPort 9000 -Action Allow

访问控制

如需进一步限制访问来源,可以在 Nginx 中配置 IP 白名单:

server {
    listen 80;
    server_name _;

    # 仅允许内网 IP 段访问
    allow 192.168.0.0/16;
    allow 10.0.0.0/8;
    allow 172.16.0.0/12;
    deny all;

    location / {
        root /opt/astra-web/dist;
        try_files $uri $uri/ /index.html;
    }
}

🚀 高并发方案(阿里云 ESA)

高并发方案使用阿里云 ESA(全站加速),提供企业级安全防护。

DDoS 防护

ESA 默认提供 DDoS 基础防护,自动检测和清洗攻击流量。如果遭遇大规模 DDoS 攻击,可以在 ESA 控制台开启高级防护功能(需额外付费)。

WAF 自定义规则

ESA 提供比 Cloudflare 免费版更精细的 WAF 控制能力。进入 ESA 控制台 → WAF 管理,可创建以下规则:

API 防护规则

配置项建议值
规则类型正则匹配
匹配字段URI
匹配内容`^/web/(import
防护动作观察 或 拦截

💡 建议新规则先设为「观察」模式运行一周,确认无误报后再切换为「拦截」。

SQL 注入防护

ESA 内置 SQL 注入检测引擎。确保 Web 基础防护 中的 SQL 注入规则已启用,防护模式设为「拦截」。

速率限制

进入 ESA 控制台 → 频率控制:

规则速率动作
API 全局限速100 次/分钟拦截 1 分钟
/web/ 路径限速60 次/分钟人机识别
登录接口限速10 次/分钟拦截 5 分钟

Bot 管理

ESA 提供 Bot 检测和管理功能。建议启用:

  • 搜索引擎爬虫白名单:允许百度、Google 等合法爬虫
  • 恶意 Bot 拦截:自动拦截已知恶意爬虫和扫描工具
  • 异常行为检测:标记高频访问、异常 User-Agent 等行为

进入 ESA 控制台 → Bot 管理,选择适当的防护等级:

防护等级说明推荐场景
宽松仅拦截已知恶意 Bot追求低误杀率
正常拦截恶意 Bot + 行为分析推荐
严格严格的 Bot 检测遭遇攻击时临时提升