3. 流量数据采集与预处理工程

流量数据是网络威胁情报落地最关键的原始证据来源。情报平台给出“某IP与C2通信”的结论,最终要靠流量侧的数据来验证、扩线和回溯。本节围绕一条完整的流量数据工程链路展开:从采集点的选择,到全流量与元数据两种采集形态的取舍,再到协议解析、会话重组与字段提取,最终形成可供关联分析使用的结构化记录。

一、采集点与采集形态的选择

采集点决定了“能看到什么”。常见位置包括出口边界、核心交换镜像口、服务器区汇聚、终端EDR旁路以及云上VPC流量镜像。选择原则是:越靠近被观测对象,越能拿到完整载荷;越靠近边界,越能覆盖横向与出网行为。工程上通常采用“边界全流量 + 关键区元数据”的组合,兼顾覆盖度与存储成本。

采集形态主要有两类。全流量采集保存完整数据包,典型格式是PCAP/PCAPNG,优势是载荷可回溯、可做深度检测,代价是存储与I/O压力大,1Gbps持续流量一天约产生10TB量级数据。元数据采集只记录流级统计与部分字段,典型格式是NetFlow v5/v9、IPFIX、sFlow,单条流记录通常几十到几百字节,压缩后存储成本可下降两到三个数量级,但丢失载荷,无法做内容级检测。

实践建议:对出网流量、DNS、TLS握手、HTTP Host等关键维度保留全流量并设置短周期滚动(如7天);对东西向大流量以IPFIX元数据为主,保留30天以上用于行为基线。

二、PCAP与NetFlow/IPFIX的字段差异

PCAP以包为单位,包含时间戳、五元组、TCP标志、载荷;NetFlow/IPFIX以流为单位,核心字段是五元组、起止时间、包数、字节数、TCP标志聚合、输入输出接口,IPFIX还支持通过模板自定义字段,例如导出TLS的SNI、HTTP的User-Agent、DNS查询名等。二者不是替代关系,而是互补:元数据用于快速筛选“哪些流可疑”,PCAP用于对可疑流做载荷级确认。

下表给出同一段通信在两种形态下的记录差异(示例数据,用于说明字段结构):

维度PCAP记录IPFIX流记录
时间粒度每包微秒级时间戳流起止时间(毫秒级)
标识五元组 + 包序号五元组 + 流标签
统计需自行聚合直接给出包数/字节数
载荷完整保留不保留,可导出部分应用层字段
典型用途取证、深度检测、重放行为基线、异常筛选、长期留存

三、协议解析:从链路层到应用层

协议解析的目标是把字节流还原成有语义的字段。解析顺序自下而上:以太网帧头 → IP头(版本、源/目的IP、协议号、TTL)→ 传输层(TCP/UDP端口、标志、序列号)→ 应用层(DNS、HTTP、TLS、SMB等)。工程实现通常基于DPDK、PF_RING或libpcap抓包,再用Suricata、Zeek、nDPI等引擎做协议识别与字段抽取。

解析中要处理几个现实问题:分片与重组、TCP乱序与重传、TLS加密后只能看到握手元数据(SNI、证书、JA3)、非标准端口协议识别。以TLS为例,即使载荷加密,仍可从ClientHello中提取SNI、支持的加密套件、扩展顺序,计算JA3指纹,这些字段对识别恶意客户端非常有效。

四、会话重组与字段提取

会话重组是把属于同一TCP/UDP会话的包按序列号排序、去重、拼接成完整应用层消息。TCP重组需维护每个方向的序列号窗口,处理重传、乱序、重叠与缺口;UDP则按五元组和超时窗口聚合。重组完成后才能做HTTP请求/响应配对、DNS查询/应答配对、SMB命令序列还原。

字段提取是在重组结果上按需抽取结构化字段,形成统一记录。典型字段包括:时间、五元组、协议、应用层动作(如HTTP方法、状态码)、Host/SNI、URI、User-Agent、DNS查询名与应答、TLS指纹、文件哈希(如提取到可执行文件)。这些字段是后续与情报IOC做关联匹配的直接输入。

流量采集与预处理工程链路 采集点 出口边界镜像 核心交换SPAN 服务器区汇聚 云VPC流量镜像 采集形态 全流量 PCAP/PCAPNG 元数据 NetFlow/IPFIX sFlow 采样 协议解析引擎 Suricata / Zeek nDPI 协议识别 DPDK / PF_RING 抓包 会话重组 TCP序列号排序 去重/补缺口 UDP超时聚合 字段提取(结构化记录) 时间戳 · 五元组 · 协议 · 应用动作 Host/SNI · URI · User-Agent DNS查询名/应答 · TLS JA3指纹 文件哈希 · 流包数/字节数 输出:统一流量记录 / 会话日志 供情报关联、IOC匹配、行为基线使用 解析难点 分片/乱序/重传 TLS加密仅见握手 非标准端口识别 重叠与缺口处理

五、工程实现要点与示例

以Zeek为例,它默认输出conn.log、dns.log、http.log、ssl.log等结构化日志,可直接作为字段提取结果。若需要自定义字段,可通过脚本扩展。下面是一段简化的Zeek脚本示例,用于在SSL日志中额外记录JA3指纹(示例代码,用于说明扩展方式):

event ssl_client_hello(c: connection, version: count, record_version: count,
                        possible_ts: time, client_random: string,
                        session_id: string, ciphers: index_vec,
                        comp_methods: index_vec) {
    local ja3 = fmt("%s,%s,%s,%s,%s",
        version, cat(ciphers), cat(comp_methods),
        "", "");  # 实际需按JA3规范拼接扩展与椭圆曲线
    Log::write(SSL::LOG, [$ts=network_time(), $id=c$id,
        $uid=c$uid, $ja3=ja3]);
}

在采集侧,若使用Suricata做全流量检测,可通过eve.json输出流级与应用层事件,再经Logstash或Fluent Bit写入Elasticsearch。元数据侧则用softflowd或nProbe将镜像流量转为IPFIX,发送至采集器。两条链路最终在数据平台按五元组和时间窗口对齐,形成“元数据筛选 → PCAP回溯 → 字段确认”的闭环。

注意:全流量采集必须评估合规与隐私边界,对载荷中的敏感信息(如账号、Cookie)应做脱敏或限制访问权限;元数据虽不含载荷,但五元组与访问关系本身也可能构成敏感信息,需纳入数据分级管理。

六、结果判读与质量校验

预处理是否可靠,可通过几个指标判断:流记录与PCAP的包数/字节数是否一致(偏差应小于1%)、会话重组后HTTP请求响应是否配对成功、DNS查询与应答是否成对出现、时间戳是否单调且与采集点时钟同步(NTP偏差应小于10ms)。若发现大量流只有单向记录,通常是采集点镜像配置不完整或超时窗口设置过短;若JA3字段大量为空,则可能是TLS握手未被完整捕获或解析引擎版本不支持。

最终交付物是一份可被下游关联引擎直接消费的流量记录集,字段命名、时间格式、IP表示(IPv4/IPv6统一)、协议枚举值都应在工程初期约定并写入数据字典,避免后续关联时因字段不一致产生漏匹配。