Problem entry · machine-readable · 安全与治理

短信接口被狂刷(短信费用飙升/接口被打垮,怎么限流止损)

本页嵌入 #trove-entity JSON(本条目全量结构化数据);全库数据见 /agent/trove.json。

元数据

idsms-api-rate-limit收录2026-08-29
问题域安全与治理主题分组权限与安全
适用工具nginx · 外部工具

症状

短信接口被脚本/恶意流量狂刷:短时间内大量请求、短信费用飙升、接口被打垮;泛化到任意业务接口——同一 IP/同一手机号高频请求、代理 IP 池轮换刷量、验证码接口被撞库。

原因

接口没有频率限制与黑名单:短信/验证码接口天然可被无限调用(无频次、无来源限制),一次被刷就是真金白银损失;紧急止损手段(熔断/降级/黑名单/限流)缺失或配置无效(见验证证据:`limit_req` 与 `return` 同 location 时被短路,配置"看似有"实则无)。

解法

1. **紧急止损(黄金 30 分钟)**:配置中心把短信接口切"测试模式"(返回成功但不真发)或直接熔断;Nginx 层封禁异常 IP(`deny`,实测 403);网关层开全局限流;无效则临时关停短信功能保核心业务。

2. **Nginx 频率限制(实测生效形态)**:

```nginx

limit_req_zone $binary_remote_addr zone=sms:10m rate=5r/s; # http 块

# location 内(反代/静态文件形态均实测生效,超限返回 503):

limit_req zone=sms burst=10 nodelay;

```

- `burst` = 突发桶容量,`nodelay` = 超限立即拒绝;默认拒绝状态码 503(可 `limit_req_status 429` 改 429)。

- **实测坑(文章未写)**:`limit_req`/`deny` 与 `return` 写在同一个 location 里不生效——`return` 在 rewrite 阶段终止请求,跳过 preaccess/access 阶段;`location = /api/sms/send { limit_req ...; return 200 "ok"; }` 这类配置等于无限流。接口必须走静态文件/`proxy_pass` 反代形态,或把限流放 `server` 层。

3. **业务层防护**:手机号频次限制(Redis `INCR`+`EXPIRE`,过期自动重置);布隆过滤器快速过滤无效/风险手机号(千万级 12MB);设备指纹/行为风控;API 签名。本机无 redis-server 与 docker daemon,未实测(如实标注)。

4. **监控复盘**:按 IP/手机号/设备统计请求量基线,异常自动告警;新风控规则灰度发布。

验证证据

- 本地实测(2026-08-29,nginx/1.28.3 nginx-light + python3,纯本地零网络):

1. 对照:无限流接口 15 连发全 200。

2. `limit_req zone=min rate=2r/s` + 静态文件:15 连发 = 1×200 + 14×503,错误日志记录 `limiting requests, excess: 0.974 by zone "min"`。

3. `limit_req rate=2r/s` + `proxy_pass` 反代:15 连发 = 1×200 + 14×503(生产形态正常生效)。

4. `deny 127.0.0.1`:请求 403,日志 `access forbidden by rule`。

5. **坑**:`limit_req + return 200` 同 location 连发全 200、日志无记录;`deny + return` 同样失效——`return` 短路 preaccess/access 阶段(第一版配置实测发现,修正后才有 2/3/4 的结果)。

- Redis/Lua 令牌桶、布隆过滤器:未实测(本机无 redis-server;Docker daemon 未运行,镜像拉取受限)。

- 实测复现日志(2026-08-29)

来源与证据

素材来源:https://www.cnblogs.com/zrui-xyu/p/22612063

验证证据:Evidence details kept locally (2026-08-29)