sun-pcap Traffic Analysis V2.0
对用户提供的一个或多个网络流量文件做多维度客观分析,产出结论先行、证据可复现、附专家建议的 HTML 报告。报告版式已内置固化,不要向用户索要模板素材。
0. 能力边界
| 说明 | |
|---|---|
| 输入 | 一个或多个 pcap / pcapng / cap / dmp 等 libpcap 系文件;分片抓包、多点同时抓包、前后两次对比,都走同一条流程 |
| 输出 | 单个自包含 HTML 报告(可直接打印为 PDF)写到流量文件同目录,命名见 Step 5 |
| 依赖 | tshark(脚本自动探测:环境变量 TSHARK → PATH → 常见安装目录),缺失时给安装指引 |
| 不做 | 不代替用户抓包;不修改/转换原始流量文件;不臆造任何数字 |
1. 先对齐任务意图
判读重点随用户意图变化,先归类再动手——同样一份流量,问"为什么慢"和问"是不是被打了",该展开的维度完全不同。
| 用户意图 | 典型问法 | 必看 | 常看 |
|---|---|---|---|
| 故障定位 | "时断时续/连不上/哪一段坏了" | tcp_anomalies(重传/乱序/零窗口/RST)、分段对比 |
expert、protocol_hierarchy |
| 性能劣化 | "慢/带宽异常/拥塞" | 会话 bytes_total/duration、derived.*_rate、分段 data_bit_rate |
-z io,stat 分桶 |
| 安全排查 | "是不是被扫/有没有外传" | syn_unanswered_by_source、nxdomain_top_sources、明文凭据、单向端点 |
HTTP UA/URI、DNS 异常、ICMP |
| 资产与合规 | "都有哪些外联/有没有明文协议" | 端点清单、http.hosts_top、非标准端口承载常见协议 |
DNS 解析结果、明文协议 |
报告要显式回答用户的问题(Step 4 的自检项),而不是只罗列指标。
2. 工作流
Step 0 · 校验与口径确认(必做,不可跳过)
# 注意:本机不一定把 python 放在 PATH 上(Windows 尤其常见)。
# 先探 `command -v python3 || command -v python`,探不到就用本机实际可用的解释器绝对路径。
python scripts/pcap_profile.py <文件1> [文件2 ...] --out profile.json
脚本逐个文件给结论。无论退出码是多少,都必须先读 inputs.files[],再如实转述:
| 字段 | 含义 | 你要做的 |
|---|---|---|
status: ok |
可解析 | 正常继续 |
status: unusable |
不可用 | 点名是哪个文件、失败原因(error)。不要跳过不吭声,也绝不能带着报错硬编数据 |
format_warnings[] |
扩展名可疑但仍在尝试 | 口头说明后继续 |
note |
如「文件有效但包数为 0」 | 明确提示,并建议用户确认抓包过滤条件 |
- 不可用文件不会出现在
per_file[]——那是可用文件的画像列表;它同样不会进
merge.source_files/aggregate.merged_from(即"总览覆盖范围")。
列"本次一共给了哪些文件"永远以inputs.files[]为准。 - 退出码:
0= 至少产出一份总览(可能含个别不可用文件);2= 全部输入不可用或找不到 tshark —— 只能如实报告,不能编造分析。 - 常用参数:
--top N(默认 10)、--no-merge(多文件时不调 mergecap)、--per-file(单文件时也保留一份per_file)。 --top截断与合并口径是两件事:--top对所有模式都生效,syn_attempts_top_pairs、
conversations、endpoints等列表都只保留前 N 条。"第 N 名以后还有谁"必须自己补一条
tshark 查询,不能因为没出现在列表里就断言"不存在"。需要更大范围时用--top 50重跑。
口径确认(多文件时必做):读 merge.mode 与 merge.coverage,在动手判读前就把下面三件事定下来,并写进报告:
mergecap= 已按时间戳合并后重新全量采集,可信;sum(fallback)= 各文件画像合并,排名类与集合类字段是近似值或下界,逐条见aggregate.combine_note。coverage.per_file_duration_sum_s才是"实际观测了多久";coverage.merged_span_s含分片之间的抓包空档,不能当观测时长。coverage.time_ranges_overlap为真时,合并后的包数/字节偏大(重叠区间的包被保留两份),判读总量时要说明。
Step 1 · 固定维度画像(必做)
数据在 profile.json 的 aggregate。对照 references/analysis-playbook.md「固定维度」逐项判读:
- 会话排名 Top N ——
conversations.ip/tcp/udp+counts+bytes_all,算集中度(用derived.top3_bytes_share,别自己算) - 协议分布 ——
protocol_hierarchy:非常规端口承载常见协议、加密/明文占比 - 端点收发比 ——
endpoints.ip的tx_*/rx_*:只发不收、收发严重失衡 - 异常标志位 ——
tcp_flags_distribution+tcp_anomalies:RST、连接尝试的接受/拒绝/无应答归类、非常规标志组合 - 小体积数据包占比 ——
small_packets.ratio(frame.len < 90),判读顺序见 playbook
比值一律取 derived 字段,不要自己拿散字段做除法——derived.formulas 已把每个比值的分母口径钉死,自己算容易和口径表对不上。
呈现要求:给具体数字(计数、占比、字节),不用「较多/较少」这类模糊表述。
Step 2 · 多源整合(仅当输入文件数 > 1)
这一步产出的东西决定报告能不能回答"问题出在哪一段"。
- 总览看
aggregate,并先确认 Step 0 定的口径。aggregate.merged_from列出参与合并的文件。 - 逐段差异看
per_file[](每项含该文件完整画像与path):盯同一实体在文件间的变化,而不是比总量——
- 同一端点的收发比是否突变(A 段 ≈1:1 → B 段只发不收)→ 单向外传的时间定位;
- 重传/乱序/RST 是否集中在某一段 → 说清"何时开始坏";
-nxdomain_top_sources、syn_unanswered_by_source的源是否只在某段出现 → 事件起止;
-http.status_codes4xx/5xx 是否在某段骤增 → 服务异常窗口。 - 主动排除伪影(判读前先问自己是不是观测问题):分片时间重叠、链路类型不一致、不同抓包点导致的观测非对称、某段抓包过滤条件不同。对照 playbook「必须主动排除的伪影」表。
- 定位结论:报告里要有一节"时间线与分段概览",把"哪一段、什么时间窗、什么事件"写清楚。
Step 3 · 线索驱动深挖(自主选 2~5 个维度)
从 playbook「扩展维度」里选。选择必须由 Step 1/2 的线索驱动,并在报告中写明选择理由,例如:
> endpoints 显示 10.0.1.66 只发不收(30:0),且 syn_unanswered_by_source 显示它向 24 个不同目的端口发起连接均无应答,故追加「可疑连接」维度核查端口扫描。
深挖查询用 references/tshark-cheatsheet.md 的命令模板;判读基准用 playbook「判读基准速查」。
Step 4 · 结论成形
每条发现按固定结构写,并分级:
结构(五段式):现象 → 证据(数字加 <code>)→ 技术解释 → 影响面 → 处置指向。
分级判据(对应模板 crit/warn/info/ok):
| 分级 | 判据 | 例子 |
|---|---|---|
严重 crit |
正在发生的攻击/数据外传、明文传输凭据、服务不可用、数据完整性受损 | 明文登录 + 连续 5xx;扫描叠加外联 |
关注 warn |
明确异常但影响可控或未证实 | 重传率 > 5%;单源多端口无应答但目标在线 |
提示 info |
值得留意、不构成问题的事实 | 分片间存在抓包空档 |
正常 ok |
主动排除掉的疑似问题 | 小包占比高,但为纯 ACK 保活形态 |
输入文件本身不可用怎么分级:它属于「分析输入质量」问题,不在流量层分级表里。
判据是它是否损伤了结论的完整性——若不可用文件恰好是用户关心的时段/对象、导致问题无法回答,
记 warn 并在结论中点明"结论不完整";若可用数据足以完整回答用户的问题,作为 info 提示列出即可。
不要因为"文件读不了"就整份报告判 crit。
硬性要求:
- 事实用肯定句;推断必须标注「推测,依据是……」。数据缺失写「未采集 / 无法确认」,不臆造。
- 每条
crit/warn级发现都必须给出可复现命令(一条能重跑的tshark -Y …),写进发现的「复现命令」框。
关于输入文件质量的发现(文件不可用/空捕获)也要给,命令换成校验类(tshark -r f -c 1/capinfos -c f)。 - 阈值不等于分级:指标超出经验阈值只说明"值得深查"。证明不了意图的(如 NXDomain 速率高但无 C2/DGA 证据)定
warn,crit只留给有直接证据的"正在发生的攻击/外传"。 - 多文件时,结论要能回答「问题出在哪一段」,并给出时间窗。
- 最后自检:把用户的问题原话贴在旁边,确认报告里有明确答案。
Step 5 · 生成 HTML 报告并通过门禁
- 复制
assets/report-template.html到输出路径。只替换占位符,不要重写文件,更不要改动样式表里任何一个字符。 - 注意 4 个占位符在模板中出现两次,两处都要替换且取值一致:
{{REPORT_TITLE}}(<title>+ 封面大标题)、{{RISK_CLASS}}/{{RISK_LEVEL}}/{{RISK_NOTE}}(封面判定条 + 正文首屏判定条)。建议用全局替换,不要用"替换第一处"的做法。 - 块级占位符(
{{KPI_SECTION}}、{{FILES_SECTION}}、{{FINDINGS_SECTION}}…)的内容照抄 references/report-snippets.md 的片段,不要自创 class;占位符清单与填写口径见该文件第 0 节。 - 删掉模板顶部那段「填充规则」注释(其余区块定位注释可保留)。
- 区块顺序固定:结论速览 → 数据源与校验 → 时间线 → 流量总览 → 重点发现 → 专家建议 → 附录。
- 只有「数据源与校验」「时间线」两节可整节删除,其余区块必须保留。
- 「数据源与校验」的删除条件:单文件 且status=ok且 无format_warnings且 无note;否则(多文件 / 有不可用文件 / 有空捕获文件)必填。
- 「时间线」多文件时必填,单文件时可省。
- 保留但确实无内容的小节,写一行本节无内容:原因,不要留空白标题。 - 封面
{{FILE_NAME}}:多文件时写摘要,如shard1.pcap 等 3 个文件。 - KPI 取 4~6 个最有决策价值的指标,异常指标用
crit/warn,每个 KPI 的.src写字段来源。 - 输出文件名(去掉原扩展名再加后缀):
- 单文件:<原文件名去扩展名>_分析报告.html(如scan_extra.pcap→scan_extra_分析报告.html)
- 多文件:<inputs.files[0] 的文件名去扩展名>_等N个文件_分析报告.html,其中 N = 本次输入的文件总数(含不可用文件),"第一个"固定取inputs.files[0](即命令行里第一个输入),与它是否可用无关。
- 用户指定目录时以用户为准。 - 跑门禁:
python scripts/check_report.py <报告.html>
必须 PASS 才能交付;有致命项就按提示修好后重跑(常见的:残留占位符、样式表被改、封面与首屏风险等级不一致、crit/warn 发现漏了复现命令、KPI 数量不在 4~6)。
- 用
present_files呈现给用户。
3. Resources
| 文件 | 何时读 |
|---|---|
scripts/pcap_profile.py |
Step 0~3,一键采集画像 JSON(可直接执行,无需读源码) |
scripts/check_report.py |
Step 5,报告交付前的质量门禁 |
references/analysis-playbook.md |
Step 1~4:数据结构速查 + 判读基准 + 指标定义 + 扩展维度 + 多文件规范 |
references/report-snippets.md |
Step 5:各区块的可照抄 HTML 片段与分级对应 |
references/tshark-cheatsheet.md |
Step 3 深挖查询、多文件校验与合并、tshark 定位/安装、字段解析的坑、排障 |
assets/report-template.html |
Step 5,唯一报告模板(样式表禁改) |
4. 硬性禁令与常见误读
口径类(最容易判错的地方)
- 判扫描要分清方向,并说清"谁在扫谁"。
syn_attempts_by_source/syn_unanswered_by_source的src是发起方:一个源向多个目的端口发起尝试 → 它是扫描方。用户常把方向问反(说"我被扫了",实际是他这台在扫别人)。 - 被探测端口全集用
syn_attempts_by_source[].distinct_dst_ports(= 被接受 + 被拒绝 + 无应答,三者之和等于该行的count);只想看"被过滤"那部分再用syn_unanswered_by_source。 - 如何认定哪台是"本机":抓包点信息缺失时没有绝对判据,按以下顺序推断并在报告中标注为推测——① 用户在提问中点名的那台;② 出现在最多会话一端的地址;③ 私网地址一侧(
10./172.16-31./192.168.)相对公网对端。三者冲突时以①为准,并写明"推测,依据是……"。 syn_attempts_total不是"被扫描"的证据。它统计所有未置 ACK 的 SYN,即"新建连接尝试次数",正常三次握手的首包也算。判断"发了没人理"必须用syn_unanswered_total,其按对端反应分为syn_attempts_accepted_total(收到 SYN+ACK)、syn_attempts_rejected_total(收到 RST)、syn_unanswered_total(静默丢弃)。tcp_anomalies里为 0 的键会被省略:缺键 = 0,不是"未采集"。想确认某类异常确实为 0,可自己跑tshark -Y "tcp.analysis.retransmission"复核。derived里已有比值,不要自己再算一遍;top3_bytes_share的分母是bytes_all(全量),sum(fallback)模式下分子只覆盖各文件 Top N,属近似。- 小包占比高 ≠ 异常。先看
protocol_hierarchy是否以纯 ACK 保活为主(正常),再看是否同时出现多端口无应答特征(异常);只有占比没有第二步证据时,写"偏高但缺乏异常佐证"。 *_text字段是带单位的字符串("50 kB"),要算术就用file_size_bytes/packets/capture_duration_s。- 多文件 ≠ 简单相加:先确认
merge.mode;sum(fallback)下排名类与集合类字段为近似或下界,报告必须标注口径。
数据质量类
- 别用
-z conv,ip/-z endpoints,ip做统计:字节被渲染成人类可读字符串(2214 bytes/10 kB),精度有损且随版本漂移,解析失败时整行静默丢弃。本技能的脚本已改为-T fields精确累加,所有数字以它的输出为准。 -T fields逐行必须先rstrip("\r\n"),否则最后一列恒为真(统计值等于总行数)。自己写补充查询时注意。http.request.uri也会出现在响应帧上,不加限制地累加会把 1 个请求算成 2 次;判定"请求帧"要看http.request.method非空。- NXDomain 的源要取
ip.dst(响应帧里ip.src是 DNS 服务器)。profile 的nxdomain_top_sources已处理好,直接用。 - 单段超过 MSS 的 TCP 段不被解析成上层协议:Wireshark 标为
TCP segment data,http/dns 字段全空、expert 里出现"length exceeds MSS"。这是 TSO/大段合并的正常现象,不是文件损坏——遇到"整段流量协议识别不出来"先想到它。 accounting.frames与capture.packets不一致(或key_overflow=true)说明统计不完整,报告要写明覆盖率,不要假装全覆盖。
操作类
- 不要替用户"顺手"抓包:只分析已有文件;需要新数据时明确告诉用户用 dumpcap/tcpdump 抓什么、抓多久、过滤条件是什么。
- 敏感信息要脱敏:引用 URI/域名/凭据类字段(password / token / Authorization)前先脱敏,并提醒用户报告对外分享的风险。
- 路径含空格或中文必须加引号(Windows 下
"C:\Program Files\Wireshark\tshark.exe"常因漏引号而命令分裂)。 - 不要改模板样式表——风格一致性优先于单次美观诉求;新形态内容用已有 class 组合,若确实需要新模式,完成后同步回技能模板并重跑门禁。