文章目录
-
- [一、为什么 DNS 是安全攻防的「隐形枢纽」?](#一、为什么 DNS 是安全攻防的「隐形枢纽」?)
- [二、DNS 快速回顾(安全视角)](#二、DNS 快速回顾(安全视角))
-
- [2.1 查询流程](#2.1 查询流程)
- [2.2 安全相关记录](#2.2 安全相关记录)
- [2.3 Wireshark 过滤器(复习)](#2.3 Wireshark 过滤器(复习))
- [三、DNS 欺骗 vs 缓存投毒](#三、DNS 欺骗 vs 缓存投毒)
- [四、DNS 缓存投毒原理](#四、DNS 缓存投毒原理)
-
- [4.1 经典条件](#4.1 经典条件)
- [4.2 Kaminsky 攻击(2008)简图](#4.2 Kaminsky 攻击(2008)简图)
- [4.3 现代缓解措施](#4.3 现代缓解措施)
- 五、缓存投毒实验思路(隔离靶场)
-
- [5.1 实验拓扑](#5.1 实验拓扑)
- [5.2 受害机配置](#5.2 受害机配置)
- [5.3 正常解析抓包](#5.3 正常解析抓包)
- [5.4 使用 Bettercap / 伪造响应(概念演示)](#5.4 使用 Bettercap / 伪造响应(概念演示))
- [5.5 抓包验证投毒效果](#5.5 抓包验证投毒效果)
- [六、DNS 隧道原理](#六、DNS 隧道原理)
-
- [6.1 为什么用 DNS 隧道?](#6.1 为什么用 DNS 隧道?)
- [6.2 典型架构](#6.2 典型架构)
- [6.3 常见工具(了解)](#6.3 常见工具(了解))
- [6.4 隧道流量长什么样?](#6.4 隧道流量长什么样?)
- [七、DNS 隧道简易实验(iodine 概念)](#七、DNS 隧道简易实验(iodine 概念))
-
- [7.1 拓扑](#7.1 拓扑)
- [7.2 抓包看什么?](#7.2 抓包看什么?)
- [八、检测实战:Wireshark + 手工分析](#八、检测实战:Wireshark + 手工分析)
-
- [8.1 检测缓存投毒 / 欺骗](#8.1 检测缓存投毒 / 欺骗)
- [8.2 检测 DNS 隧道(核心)](#8.2 检测 DNS 隧道(核心))
-
- [过滤器 1:长子域](#过滤器 1:长子域)
- [过滤器 2:高频查询同一二级域](#过滤器 2:高频查询同一二级域)
- [过滤器 3:TXT 响应异常](#过滤器 3:TXT 响应异常)
- [过滤器 4:查询类型分布](#过滤器 4:查询类型分布)
- [8.3 手工算「子域熵」(Python 思路)](#8.3 手工算「子域熵」(Python 思路))
- [8.4 检测清单表](#8.4 检测清单表)
- [九、蓝队检测:Sigma / SIEM 规则思路](#九、蓝队检测:Sigma / SIEM 规则思路)
-
- [9.1 示例:异常长子域查询](#9.1 示例:异常长子域查询)
- [9.2 示例:单主机 DNS 查询风暴](#9.2 示例:单主机 DNS 查询风暴)
- [9.3 Zeek / Suricata](#9.3 Zeek / Suricata)
- 十、防御措施汇总
- [十一、DNS 反射放大(补充)](#十一、DNS 反射放大(补充))
- 十二、四个实战剧本
-
- [剧本 A:内网 DNS 欺骗(Bettercap)](#剧本 A:内网 DNS 欺骗(Bettercap))
- [剧本 B:识别 iodine 隧道](#剧本 B:识别 iodine 隧道)
- [剧本 C:正常 vs 异常对比](#剧本 C:正常 vs 异常对比)
- [剧本 D:蓝队日志狩猎(假设)](#剧本 D:蓝队日志狩猎(假设))
- 十三、常见踩坑
- 十四、本篇小结
- [附录 A:DNS 类型号速查](#附录 A:DNS 类型号速查)
- [附录 B:Wireshark DNS 检测过滤器合集](#附录 B:Wireshark DNS 检测过滤器合集)
- [附录 C:dig 排障命令](#附录 C:dig 排障命令)
一、为什么 DNS 是安全攻防的「隐形枢纽」?
几乎所有上网行为都先问 DNS:
text
浏览器输入域名 → DNS 查询 → 得到 IP → TCP 连接
攻击者若控制 DNS 解析结果,就能:
| 后果 | 说明 |
|---|---|
| 钓鱼 | bank.com 解析到假 IP |
| 流量劫持 | 广告注入、中间人 |
| C2 通信 | DNS 隧道外传数据 |
| 绕过防火墙 | 53 端口 UDP 常放行 |
| DDoS 放大 | 小查询换大响应(反射) |
蓝队若不懂 DNS,大量告警会对不上号。本文聚焦三个实战高频主题:
text
1. DNS 缓存投毒(Cache Poisoning)
2. DNS 隧道(DNS Tunneling)
3. 检测与防御(Wireshark + 规则思路)
二、DNS 快速回顾(安全视角)
2.1 查询流程
text
客户端 递归服务器 权威服务器
│ │ │
│ A? www.example.com │ │
│ ───────────────────────► │ 逐级查询 .com → example│
│ │ ──────────────────────►│
│ │ ◄──────────────────────│
│ ◄─────────────────────── │ 返回 93.184.216.34 │
│ 缓存 + 返回 IP │ (并缓存 TTL 时间) │
| 概念 | 说明 |
|---|---|
| 递归查询 | 客户端问本地 DNS(如 8.8.8.8、公司内网 DNS) |
| 迭代查询 | 递归服务器一路问根、TLD、权威 |
| 缓存 | 递归 DNS 按 TTL 缓存记录,减少查询 |
| 记录类型 | A/AAAA(IP)、CNAME、MX、TXT、NS 等 |
2.2 安全相关记录
| 类型 | 攻击/防御用途 |
|---|---|
| A / AAAA | 缓存投毒篡改目标 |
| TXT | DNS 隧道常塞数据 |
| CNAME | 子域名接管、链式隧道 |
| NS | 域委派攻击 |
2.3 Wireshark 过滤器(复习)
text
dns
dns.qry.name contains "example.com"
dns.flags.response == 0 # 仅查询
dns.flags.response == 1 # 仅响应
三、DNS 欺骗 vs 缓存投毒
| DNS 欺骗(Spoofing) | DNS 缓存投毒(Cache Poisoning) | |
|---|---|---|
| 作用对象 | 单次查询的受害者 | DNS 服务器缓存 |
| 影响范围 | 一个用户/一次查询 | 所有使用该 DNS 的用户(在 TTL 内) |
| 持久性 | 短 | 可持续至 TTL 过期 |
| 典型手段 | 伪造响应包、MITM | 抢答合法响应、Kaminsky 型攻击 |
记忆:欺骗是「骗你一次」;投毒是「把 DNS 服务器的账本写错」。
四、DNS 缓存投毒原理
4.1 经典条件
DNS 基于 UDP 53,早期存在弱点:
text
1. 查询 ID(16 bit)可暴力猜测
2. 源端口可预测
3. 谁先返回「正确格式」的响应,客户端/递归 DNS 就信谁
攻击者思路:
text
1. 向递归 DNS 发起查询:random123.attacker.com(使自己成为权威链一环)
2. 同时伪造大量 DNS 响应包,猜测 ID + 端口
3. 在合法响应到达前,塞入伪造 A 记录:www.victim.com → 恶意 IP
4. 递归 DNS 缓存该错误记录 → 所有用户解析 victim.com 均中招
4.2 Kaminsky 攻击(2008)简图
text
攻击者 递归 DNS 权威 DNS
│ │ │
│ 查询 random.attacker.com │ │
│ ────────────────────────────►│ 去问 attacker.com 权威 │
│ │ │
│ 洪水伪造响应(夹带 victim.com A=恶意IP) │
│ ────────────────────────────►│ 若猜中 ID+端口 → 缓存污染 │
│ │ │
关键 :不仅污染 random.attacker.com,还顺带 写入 www.victim.com 的伪造 A 记录。
4.3 现代缓解措施
| 措施 | 说明 |
|---|---|
| 源端口随机化 | 不再固定 53 回复,暴力空间暴增 |
| 0x20 编码 | 查询大小写混合,响应需匹配 |
| DNSSEC | 响应签名验证,防篡改(部署率仍不完整) |
| 最小化 | 减少额外信息泄露 |
| DoH / DoT | DNS over HTTPS/TLS,防链路上窃听篡改 |
实战认知 :公网大型递归 DNS(8.8.8.8、114.114)已很难投毒;企业自建 DNS、老旧设备、内网测试环境仍是演练重点。
五、缓存投毒实验思路(隔离靶场)
以下仅在 VM 隔离网络 使用 dnsmasq 等自建 DNS 演示「信任错误响应」的逻辑,不对公网 DNS 操作。
5.1 实验拓扑
text
Kali(攻击机) 192.168.56.10
DNS 服务器 192.168.56.53 (dnsmasq / BIND)
受害客户端 192.168.56.30 (DNS 指向 56.53)
5.2 受害机配置
bash
# /etc/resolv.conf 或 NetworkManager
nameserver 192.168.56.53
5.3 正常解析抓包
bash
dig @192.168.56.53 www.test.local
Wireshark(DNS 服务器上):
text
dns && ip.addr == 192.168.56.30
观察:查询 ID、源端口、响应 A 记录。
5.4 使用 Bettercap / 伪造响应(概念演示)
内网 MITM 场景下,攻击者可:
text
1. ARP 欺骗(见后续 ARP 专题)使流量经 Kali
2. 拦截 DNS 查询
3. 抢先回复伪造 A 记录
Bettercap 示例(仅 Host-Only 靶场):
bash
sudo bettercap -iface eth1
# dns.spoof on
# 配置 hosts 条目:www.test.local → 192.168.56.10
受害机 ping www.test.local 应解析到 Kali IP。
5.5 抓包验证投毒效果
text
dns.qry.name contains "test.local"
对比:响应 IP 是否为攻击者指定;TTL 是否异常短。
六、DNS 隧道原理
6.1 为什么用 DNS 隧道?
text
· 企业防火墙常放行 UDP 53
· 流量像「正常域名查询」,不易被应用层代理识别
· 可将数据编码进子域名,经递归 DNS 到攻击者控制的权威 NS
6.2 典型架构
text
受害主机 企业递归 DNS 攻击者权威 DNS
│ │ │
│ 查询 TxR3f8k9.data.evil.com │ │
│ ────────────────────────────────►│ 迭代查询 .evil.com NS │
│ │ ───────────────────────►│
│ │ ◄───────────────────────│
│ ◄────────────────────────────────│ 响应(可夹带下行数据) │
上行数据 :编码在长子域名 标签里(每标签 ≤63 字符,总长 ≤253)。
下行数据 :常藏在 TXT 记录 或特定 A 记录。
6.3 常见工具(了解)
| 工具 | 说明 |
|---|---|
| iodine | 经典 DNS 隧道,可建虚拟网卡 |
| dnscat2 | C2 over DNS |
| dns2tcp | TCP over DNS |
| Cobalt Strike | DNS Beacon |
6.4 隧道流量长什么样?
异常特征:
text
· 子域名极长、随机字符串多
· 单标签熵值高(像 Base32/Base64)
· 查询频率稳定(心跳)
· 同一客户端大量 UNIQUE 子域
· TXT 记录频繁、响应体积大
· 查询类型异常(NULL、CNAME 滥用)
正常 CDN / 广告域名也可能长子域 ------检测要 基线 + 多特征,避免误报。
七、DNS 隧道简易实验(iodine 概念)
7.1 拓扑
text
攻击机:运行 iodined(权威端)+ 公网或内网 NS 指向
受害机:运行 iodine 客户端,DNS 走企业/本地递归
内网简化演示(全在 Host-Only):
bash
# DNS 服务器 56.53 为 evil.tunnel 配置 NS 指向 Kali 56.10
# Kali
sudo iodined -f -c -P secret123 10.0.0.1 tunnel.test
# 受害机
sudo iodine -f -P secret123 192.168.56.53 tunnel.test
成功后出现 dns0 虚拟网卡,可 ping 10.0.0.1。
7.2 抓包看什么?
text
dns.qry.name contains "tunnel.test"
可见子域携带编码数据,如:
text
4a3f2b1c9d8e7f6a5b4c3d2e1f0.tunnel.test
八、检测实战:Wireshark + 手工分析
8.1 检测缓存投毒 / 欺骗
| 检查项 | 方法 |
|---|---|
| 响应比权威还快 | 对比查询到响应时间(<1ms 内网可疑) |
| TTL 异常 | 与历史基线比,突然变很小 |
| 多源响应 | 同一查询 ID 收到多个响应 |
| IP 突变 | 同一域名 A 记录无故变更 |
Wireshark:
text
dns.flags.response == 1 && dns.a
Expert Info 看 Duplicate ACK、重传(非 DNS 层,需结合看)。
8.2 检测 DNS 隧道(核心)
过滤器 1:长子域
text
dns && dns.qry.name.len > 50
(部分版本用 strlen(dns.qry.name) 或导出后脚本统计)
过滤器 2:高频查询同一二级域
text
dns.qry.name contains ".evil.com"
Statistics → DNS 看 Query Name 排行。
过滤器 3:TXT 响应异常
text
dns && dns.txt
过滤器 4:查询类型分布
text
dns.qry.type == 16 # TXT
dns.qry.type == 10 # NULL(少见,可疑)
8.3 手工算「子域熵」(Python 思路)
python
import math
from collections import Counter
def entropy(s: str) -> float:
if not s:
return 0.0
c = Counter(s)
n = len(s)
return -sum((v/n) * math.log2(v/n) for v in c.values())
# 例:正常 www.baidu.com 子域熵低
# 隧道 4a3f2b1c9d8e7f6a.tunnel.evil.com 标签熵高
label = "4a3f2b1c9d8e7f6a"
print(entropy(label)) # 通常 > 3.5 值得留意
8.4 检测清单表
| 特征 | 阈值参考 | 权重 |
|---|---|---|
| 子域标签长度 | > 40 字符 | 高 |
| 标签熵 | > 3.5 | 高 |
| 每客户端 QPM(每分钟查询数) | > 60 且持续 | 中 |
| UNIQUE 子域数/小时 | > 500 | 高 |
| TXT 响应占比 | 突增 | 中 |
| 查询仅单一二级域 | 几乎 100% | 中 |
九、蓝队检测:Sigma / SIEM 规则思路
9.1 示例:异常长子域查询
yaml
title: DNS Long Subdomain Query Possible Tunnel
status: experimental
logsource:
category: dns
detection:
query_name_length:
QueryName|re: '.{60,}\\.' # 适配你的日志字段
condition: query_name_length
level: medium
9.2 示例:单主机 DNS 查询风暴
yaml
detection:
timeframe: 5m
selection:
EventType: DNS_Query
filter:
QueryCount|gt: 200
condition: selection and filter
9.3 Zeek / Suricata
text
Zeek: dns.log → 分析 query、qtype、answers
Suricata: 规则匹配 dns_query 关键字 + pcre 长子域
企业落地 :先对 内网 DNS 服务器日志 做基线(7 天正常流量),再告警偏离。
十、防御措施汇总
| 层级 | 措施 |
|---|---|
| 协议 | 部署 DNSSEC 验证;启用 DoT/DoH 对内网关键终端 |
| 架构 | 内网专用递归 DNS,禁止客户端直连外网 53 |
| 出口 | 防火墙限制仅允许公司 DNS 向外查询 |
| 监控 | DNS 日志集中 + 长子域/高频/熵检测 |
| 响应 | 发现隧道:隔离主机、查进程、查 iodine/dnscat 特征 |
| 开发 | 应用层勿仅靠 DNS 做安全决策;证书校验(HTTPS) |
重要 :DNSSEC 不加密,只防篡改;隐私用 DoH/DoT。
十一、DNS 反射放大(补充)
攻击者伪造源 IP 为受害者,向开放递归 DNS 发 ANY 查询,放大流量打向受害者。
| 项目 | 说明 |
|---|---|
| 特征 | 大体积 UDP 响应、源端口 53 |
| 防御 | 关闭递归对外、响应速率限制、BCP38 源地址过滤 |
Wireshark 受害侧:
text
udp.port == 53 && ip.dst == 受害IP
十二、四个实战剧本
剧本 A:内网 DNS 欺骗(Bettercap)
text
1. Host-Only 三台 VM
2. Bettercap ARP + dns.spoof
3. 受害机访问 http://www.test.local
4. 抓包验证 A 记录指向 Kali
剧本 B:识别 iodine 隧道
text
1. 跑 iodine 客户端 2 分钟
2. 过滤器 dns.qry.name contains "tunnel"
3. Statistics → DNS 统计查询次数
4. 写 3 条检测特征到实验报告
剧本 C:正常 vs 异常对比
| 域名 | 子域特点 |
|---|---|
www.baidu.com |
短、可读 |
cdn.example.com |
中等 |
4a3f2b1c9d.tunnel.evil.com |
长、随机 |
各抓 10 个包,对比熵与长度。
剧本 D:蓝队日志狩猎(假设)
text
给定 CSV:timestamp, src_ip, query_name
任务:找出可能的 DNS 隧道源 IP(提示:高频 + 长子域)
十三、常见踩坑
| 问题 | 正解 |
|---|---|
| 对 8.8.8.8 做投毒实验 | 禁止;仅自建 DNS |
| 把 CDN 长子域当隧道 | 需多特征 + 基线 |
| 只看 A 记录不看 TXT | 隧道下行常在 TXT |
| 未记录 DNS 服务器日志 | 检测靠日志,抓包是补充 |
| DoH 就万事大吉 | 仍要防恶意 DoH 外连、终端恶意软件 |
| TTL 忽略 | 投毒影响时长 = TTL |
十四、本篇小结
text
┌─────────────────────────────────────────────────────────────┐
│ DNS 安全实战 核心记忆 │
├─────────────────────────────────────────────────────────────┤
│ 投毒:污染递归 DNS 缓存,影响所有用户(TTL 内) │
│ 隧道:数据藏在长子域/TXT,走 UDP 53 绕过防火墙 │
│ 检测:子域长度 + 熵 + 频率 + TXT + 基线偏离 │
│ 防御:DNSSEC、内网 DNS、出口管控、日志监控、DoT/DoH │
│ 工具:Wireshark dns 过滤器、iodine/dnscat2(靶场) │
└─────────────────────────────────────────────────────────────┘
下一篇预告:《ARP 欺骗全解析:Ettercap 中间人攻击实验》------DNS 欺骗常配合 ARP MITM 使用。
附录 A:DNS 类型号速查
| 类型 | 值 | 常见用途 |
|---|---|---|
| A | 1 | IPv4 |
| NS | 2 | 域名服务器 |
| CNAME | 5 | 别名 |
| MX | 15 | 邮件 |
| TXT | 16 | 文本 / 隧道下行 |
| AAAA | 28 | IPv6 |
附录 B:Wireshark DNS 检测过滤器合集
text
dns # 全部 DNS
dns.flags.response == 0 # 仅查询
dns.qry.name contains "tunnel" # 含关键字
dns.qry.type == 16 # TXT 查询
udp.port == 53 # 所有 DNS 端口流量
附录 C:dig 排障命令
bash
dig @192.168.56.53 www.test.local A +trace # 跟踪迭代
dig @8.8.8.8 www.example.com +dnssec # DNSSEC 验证信息
dig @server evil.com TXT # 查 TXT