攻击者每秒换几万个不存在的子域名,你的页面一次都没被请求,DNS 和缓存先倒了。本文用 10 个问答讲清 随机子域攻击 的原理、日志识别方式,以及 DNS、源站、CDN 三层该怎么配。
Q:随机子域攻击是什么?为什么叫 DNS 水刑?
- 攻击者构造海量随机子域名(如
a8f3k2.example.com),向递归 DNS 发起查询。递归缓存里没有这个名字,只能一路问到你的权威 DNS。 - 权威返回 NXDOMAIN,但下一个查询又是全新名字,缓存永远命中不了。每个查询都要走完整解析流程。
- 所以它的效率不在流量大小,而在”每次一滴、永不重复”——这就是 DNS water torture(DNS 水刑) 这个名字的由来。
- 关键差别:带宽型 DDoS 拼的是 Gbps,这种攻击拼的是 QPS 和缓存条目。几十 Mbps 甚至十几 Mbps 就足以打满一个中小站点的权威 DNS 配额。
Q:它具体打谁?哪一层先倒?
- 三层依次受害,顺序基本固定:
- 递归/公共 DNS:被大量 NXDOMAIN 拖慢,运营商侧可能对你的域名限速,甚至临时拒绝解析。
- 权威 DNS:QPS 打满,正常子域也查不出来。用户侧表现是”整站打不开”,但服务器 CPU、带宽全都正常——这是最容易误判的地方。
- CDN / 边缘:开了泛解析时,每个随机 Host 都会被当成一个独立站点处理,证书查找、回源探测、缓存条目全部新建,边缘节点的内存和连接数先扛不住。
- 结论:先出问题的通常是权威 DNS 的 QPS 配额,不是你的服务器 CPU。查故障时先看解析成功率,别一头扎进 Nginx 日志。
Q:怎么从日志里认出它?
- 五个特征,凑齐三个基本可以定性:
- NXDOMAIN 比例骤升:正常站点一般低于 5%,攻击时能到 60% 以上。
- 每分钟唯一子域数超过正常值一个数量级——这是最灵敏的指标,比 QPS 早报警。
- 子域名字符串无意义,长度集中在 8~20 位,字符分布接近随机(数字与小写字母混排、无元音规律)。
- 查询类型集中在 A / AAAA / ANY,几乎不查 MX、TXT。
- 源 IP 集中在少数递归解析器出口——攻击者不直接查权威,而是借公共 DNS 当放大器。
# 从源站日志看 Host 基数与随机 Host 特征(按分钟聚合)
zcat /var/log/nginx/access-2026-10-30.log.gz \
| awk -F'\t' '{split($1,t,"T"); m=substr(t[1],1,16); h[m"\t"$3]=1}
END {for (k in h) {split(k,a,"\t"); c[a[1]]++}
for (m in c) print m, c[m]}' | sort | tail -20
# 找出明显随机的主机名:长度大于 20 且不含常见业务前缀
zcat /var/log/nginx/access-2026-10-30.log.gz \
| awk -F'\t' 'length($3) > 20 {print $3}' | sort | uniq -c | sort -rn | head -30
- 源站侧还能看一个倒挂信号:回源 QPS 上升但缓存命中率断崖下跌。正常的量涨会带着命中率一起涨,随机 Host 只会把命中率打到很低。
Q:泛解析是帮凶吗?
- 是。一条
*.example.com让任何随机子域都能解析成功,等于告诉攻击者”随便编都算数”。 - 泛解析 + 泛域名证书 + CDN 全通配,配起来最省事,但也最容易被打:每个随机 Host 都会在边缘新建一份站点上下文。
- 可现实里泛解析往往删不掉——很多业务和多租户站点确实依赖它。折中方案是保留解析、收紧入口:泛解析继续存在,但在边缘和源站对 Host 做白名单校验,未登记的子域直接丢弃,不回源、不查证书、不建缓存。
- 判断标准很简单:这个子域是否在可枚举清单里(备案域名表、sitemap、内部服务登记表)。不在清单里的一律按未知处理。
Q:随机 URL 参数打缓存又是怎么回事?
- 同一个路径后面挂随机参数:
/news/123.html?v=8392017。缓存键带了 query,命中率瞬间归零,每个请求都回源。 - 它和随机子域是同一个思路,只是从 Host 层换到 URL 层。成本更低——不需要 DNS,一个脚本就能刷,所以更常见。
- 识别三件套:请求量与回源 QPS 同步上涨、缓存命中率跌破 30%、Top URL 相同但 query 全不相同。
- 这类攻击最阴的地方在于:它看起来像”真实用户访问详情页”,规则的误伤风险很高,不能靠封 IP 硬扛。
Q:DNS 层怎么防?
- 三件事:限速、响应速率限制、权威分散。
- 自建 BIND 就开 RRL(Response Rate Limiting),对同名字、同网段的响应做限速,NXDOMAIN 的错误响应单独设更严的阈值——因为水刑打出来的就是 NXDOMAIN。
- 权威 DNS 至少两家、不同网络、不同供应商。单家权威被打满,换配置也救不了。
- 用云 DNS 的,务必问清套餐的 QPS 上限和超限行为:是限速、是计费翻倍,还是直接停止解析。三种结果对应三种完全不同的故障表现。
// BIND 9 开启 RRL:对错误响应更严格
options {
rate-limit {
responses-per-second 20;
errors-per-second 5; // NXDOMAIN 等错误响应单独限速
nxdomains-per-second 3; // 水刑攻击的核心,卡到很低
window 5;
slip 2; // 超限时每 2 个包回 1 个 truncated
ipv4-prefix-length 24;
ipv6-prefix-length 56;
};
};
Q:源站 Nginx 怎么兜底?
- 核心一句话:不认识 Host 的请求,不进业务。
- 建一个
default_server直接return 444。444 是 Nginx 私有状态码,直接关连接不返回任何内容,比 403 更省资源,也不会被当成一个正常响应去做日志聚合。 - 业务 server 块里再用 map 做第二道 Host 白名单,双保险:漏配一个 server_name 也不会把流量放进后端。
# 未定义 Host 直接丢弃,不进入任何业务 location
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_reject_handshake on; # 1.19.4+ 直接拒绝未知 SNI 的握手
return 444;
}
# 业务侧再做一层 Host 白名单
map $host $host_allowed {
default 0;
www.example.com 1;
m.example.com 1;
api.example.com 1;
~^[a-z0-9-]{2,20}\.example\.com$ 1; # 受控的多租户子域
}
server {
listen 443 ssl http2;
server_name www.example.com;
if ($host_allowed = 0) { return 444; }
# ... 正常业务
}
Q:CDN 和 WAF 侧怎么配?
- 三件事:Host 白名单、缓存键规范化、未知参数处理。
- 缓存键只保留业务参数,其余全部忽略。图片、附件、CSS/JS 这类静态资源直接按”忽略 query”缓存,收益最大。
- 对带未知参数的页面请求,可以 302 跳转到规范 URL。这一步能把大量随机参数化掉,同时不影响真实用户。
- WAF 上加一条行为规则:同一 IP 在 1 分钟内请求超过 20 个不同子域,直接挑战或封禁。正常人不会这么访问。
# 缓存键归一:只认白名单里的参数,其余参数不进 key
map $args $cache_args {
default "";
"~*(?:^|&)(id|page|cat)=([^&]*)" "$1=$2";
}
proxy_cache_key "$scheme$host$uri$cache_args";
# 未知参数统一跳规范地址(避免随机参数打穿缓存)
if ($args ~ "^[a-z]{1,3}=\d{4,}$") {
rewrite ^(.*)$ $uri? permanent;
}
Q:怎么和正常的长尾流量区分,避免误杀?
- 三个判据,同时成立才判为攻击:
- 可枚举性:正常子域能从 sitemap、站内链接、历史日志里找到;攻击的子域全是没见过的面孔,且第二天不再出现。
- 行为配套:正常访问会连带请求 CSS/JS/图片;随机攻击一个 Host 只发一个请求就走,静态资源请求占比极低。
- 时间分布:正常长尾平稳起伏,攻击是陡起的方波,起止都很突然。
- 落地节奏:新规则先只记不拦跑 24 小时,导出误伤名单核对,再开拦截。这一步能挡掉九成的误杀投诉。
- 白名单必须包含三类:已备案子域、监控拨测域名、合作方回调域名。这三类被拦,后果比攻击本身还严重。
Q:还有什么补充建议?
- 把“每分钟唯一子域数”做成常驻监控指标。它比总 QPS 更早反映问题,而且几乎不受业务波动干扰。
- 提前问清 CDN 厂商一件事:未配置的域名打过来时,默认行为是什么。各家策略不同,有的返回错误页,有的直接回源到你服务器——后者等于免费帮攻击者绕过防护。
- 泛域名证书解决的是握手,解决不了回源。证书配好只说明不会因为 SNI 报错,Host 该拦还是要拦。
- 反常识的一条:如果加了 CDN 和 WAF 之后,权威 DNS 依然被打满,说明攻击走的是 DNS 直查,HTTP 层防护根本没参与。这种情况下加带宽、升 WAF 套餐都没用,必须从 DNS 服务商那一侧解决——先确认攻击面在哪一层,再谈买什么。