DDoS取证怎么做?流量采样与pcap证据包

DDoS取证不是抓个包就算完。本文讲清抓包点怎么选、采样率定多少、pcap 怎么落盘不爆盘、三分钟判断攻击类型,以及交给运营商和清洗厂商的证据包该装什么。

Q:DDoS取证到底要证明什么?

  • 三件事:定性(是攻击还是自己业务涨)、定量(多大带宽、多少 PPS、打哪个 IP 和端口、持续多久)、来源(哪些网段、哪种手法)。
  • 证据的可用性比完整性重要。一份 2GB 的原包没人愿意看,一份 5 分钟切片加一张统计表加一条时间线,才是能交付的东西。
  • 对象不同要求不同:运营商和清洗厂商要五元组与 PPS 曲线;云厂商要你证明「不是我自己的业务跑满」;保险和法务要时间戳与保管链。
  • 最常见的错误是等打进黑洞了才想起来抓包。那时候流量已经被牵引走,源站抓到的是空的,反而证明不了攻击存在。

Q:抓包点应该选在哪一层?

  • 只有在流量真实经过的位置抓才有意义,位置选错等于白干。
  • 源站入口网卡:只能看到「漏进来的」那部分。适合源站已被打穿、要定位残留攻击特征;带宽型打满时抓不到完整画面。
  • 边界交换机镜像口:能看到全量,最理想,但需要机房配合开镜像,多数小站没有这个条件。
  • CDN 或高防侧:你自己抓不了,只能要报表,或者让厂商把清洗日志、拦截日志投递给你(不少厂商支持日志外发)。
  • 云上环境:开 VPC Flow Log 或 NAT 网关日志,粒度是五元组加字节数,没有 payload,但定量足够。
  • 先确认自己处在哪一层,再决定抓什么。在源站抓三天,不如在镜像口抓三分钟。

Q:采样率定多少才够用?

  • 分三档:1:1000 只能看趋势;1:100 能看协议、端口、包长的分布;1:1 才能拿 payload 做溯源。按目的选,不是越多越好。
  • 先算容量:每秒包数 × 平均包长 × 时长 ÷ 采样比。1Gbps 的 64 字节小包约 1.49Mpps,全量抓 10 分钟就是 8.9 亿个包。
  • 按作用域采样(sFlow 的 sampling-rate)比按时间抽帧安全,不会整段漏掉小流量攻击。
  • 只抓头部 96 字节:以太头 14 加 IP 头 20 加 TCP 头 20,足够取五元组和标志位,payload 一律不落盘。

Q:pcap 怎么存才不会把磁盘写爆?

  • 用环形缓冲,按分钟切片,固定文件数,写满自动覆盖最老的。这样不需要人去清理,也不会在凌晨三点把盘写满导致 MySQL 挂掉。
mkdir -p /data/pcap
tcpdump -i eth0 -n -nn -s 96 -B 32768 -Z root \
  -w /data/pcap/%Y%m%d-%H%M.pcap -G 60 -W 240 \
  'ip and not port 22' > /var/log/tcpdump.log 2>&1 &
  • -G 60 每分钟切一个文件,-W 240 只保留 240 个,合起来就是 4 小时环形窗口。
  • -s 96 是 snaplen,决定每个包最多存多少字节,这是控制体积最有效的参数。
  • -B 32768 加大内核缓冲(单位 KB),被打满时能明显减少丢包。
  • 别写系统盘。独立数据盘最稳;被打到极限时可以写内存盘(tmpfs),重启即失,但能保住最关键的那半小时。
  • 体积估算:100Mbps 混合流量、平均 500 字节包,96 字节 snaplen 下每分钟约 45MB,四小时不到 11GB,一块 40GB 的数据盘绰绰有余。

Q:日志里出现 dropped by kernel 怎么办?

  • 先确认丢了多少:tcpdump 退出时会打印 N packets dropped by kernel,运行时可以看 /proc/net/softnet_stat 的第三列。
  • 根因通常是单队列网卡把所有软中断压在一个核上,包还没进用户态就被丢了。
  • 处置顺序:开多队列并配 RPS/RSS 把软中断分散 → 用 taskset 把抓包进程绑到空闲核 → 继续加大 -B → 降低 snaplen → 最后才降采样率。
  • 已经丢包的 pcap 不能用来下「攻击有多大」的结论,只能做定性参考。定量必须用设备侧计数器或 flow 日志。
  • 实在抓不动就换 sFlow:1:1000 采样,CPU 占用几乎为零,定量够用。
# 看一眼有没有软中断丢包(第三列持续增长就是丢了)
awk '{print $1, $3}' /proc/net/softnet_stat | head

# 开启 RPS,把 eth0 的软中断分到 2、3 号核
echo 4 > /sys/class/net/eth0/queues/rx-0/rps_cpus

Q:抓到包之后怎么三分钟判断攻击类型?

  • 四步就够:看协议占比、看源端口是否固定、看包长分布、看 PPS 与带宽的比例。
capinfos -c -M attack.pcap

# 每秒包数,判断是不是 PPS 型攻击
tshark -r attack.pcap -q -z io,stat,1,"COUNT(frame) frame.len<=128"

# 源端口分布,固定还是随机一眼看出
tshark -r attack.pcap -T fields -e ip.src -e tcp.srcport \
  | sort | uniq -c | sort -rn | head -20
  • 判别口诀:源端口固定加包长大是反射放大;源端口随机加包长小是纯洪水;SYN 只来不回是 SYN Flood;单 IP 高 QPS 小请求那是应用层 CC,不在这个层面。
  • 单位换算:1Gbps 的 64 字节包约 1.49Mpps,10Gbps 线速接近 14.88Mpps。PPS 很高但带宽不高,说明瓶颈在清洗设备的包处理能力,不在带宽。

Q:交给运营商和清洗厂商的证据包要装什么?

  • 五件套,缺一件对方就会让你重做:
  • 时间线:起止时间精确到秒,统一标 UTC+8,写明峰值出现在哪一分钟。
  • pcap 切片:切 5 分钟,不要发原包。用 editcap 按时间裁剪。
  • 统计表:带宽峰值、PPS 峰值、协议分布、TOP 20 源 IP 与源端口、目标 IP 与端口。
  • 资产说明:被打的 IP、端口、承载的业务、是否有备案、是否有历史攻击记录。
  • 处置请求:要牵引还是清洗、期望的生效时间、你的联系人与值班电话。
editcap -A "2026-11-06 03:12:00" -B "2026-11-06 03:17:00" \
  attack.pcap evidence_slice.pcap

md5sum evidence_slice.pcap >> manifest.txt
capinfos -c -M evidence_slice.pcap >> manifest.txt
  • 先发摘要和切片,对方需要再给更多。一上来甩 30GB 原包,多半被当成附件超限丢掉。
  • 把 md5 和文件清单一起存下来,这是后面谈 SLA 赔付和追责时唯一能自证的东西。

Q:抓包会不会踩到用户隐私的坑?

  • 会,但完全可以规避。snaplen 96 只留头部,再加一条排除 443、8443 payload 的过滤,正文、密码、Cookie 都不会落盘。
  • 抓包文件放独立目录,权限 700,禁止放在网站根目录或对象存储公开桶里——这类「pcap 泄露」事故每年都有。
  • 保留期建议 7 天,够复盘和取证,过了就删。真要长期留存,先做脱敏和归档。
  • 对外提供前把内网拓扑、内部 IP 段、真实客户 IP 拿掉,只留攻击侧信息。

Q:小站没条件抓包,还能拿什么当证据?

  • CDN 或 WAF 日志:有五元组、UA、状态码、拦截动作,导出 CSV 就是原始材料。
  • 云厂商 flow log:VPC Flow Log、NAT 网关日志,定量够用。
  • 系统快照:ss -s 看连接状态分布,/proc/net/snmp 看 SYN_RECV 堆积,nstat -az 看丢包与重传计数。
ss -s
nstat -az | grep -Ei 'drop|overflow|prune'
cat /proc/net/snmp | grep -A1 Tcp
  • 这些数据凑起来能说明「攻击确实发生、规模多大」,走服务商工单和赔付流程已经够用,不必强求 pcap。

Q:还有什么补充建议?

  • 平时就开环形抓包,别等被打。攻击发生时人是懵的,机器不会。
  • 上线前做一次演练:自己用 100Mbps 的 UDP 打测试 IP,验证采样率、磁盘占用、丢包计数是否都符合预期。
  • 证据以时间线为主线,pcap 只是附件。决策者看的是「几点开始、多大、打了多久、损失多少」。
  • 和厂商提前对齐口径:带宽单位是 bit 还是 Byte,峰值取 1 秒还是 5 分钟均值,这两点没对齐,后面每个数字都会吵一遍。