madebyjake/netpack

GitHub: madebyjake/netpack

netpack 是一个集成式现场网络故障排查工具集,提供从链路物理层到应用层的诊断命令、引导式 playbook 和自动证据捕获功能。

Stars: 1 | Forks: 1

# netpack (npk) 用于现场故障排除和证据收集的网络工具。 ## 安装说明 ``` # Clone git clone https://github.com/madebyjake/netpack.git ~/netpack # 依赖项 (需要 Debian; Python >= 3.10) sudo apt update sudo apt install python3 python3-scapy iproute2 iputils-ping dnsutils \ ethtool iw mtr-tiny tcpdump arp-scan lldpd iperf3 nftables iputils-tracepath \ curl # 将 netpack 和 npk 放入 PATH,然后报告就绪状态。通过 Symlinks 链入 # ~/.local/bin,因此 `git pull` 会更新它们;PREFIX=/usr/local 会进行 # 全系统范围的安装。 make -C ~/netpack install ``` `make install` 仅链接了两个启动器名称——通过它们可以访问所有工具(`npk linkstat`),如果您选择自行将 `~/netpack/bin` 添加到 PATH 中,这些工具也可以直接调用: ``` echo 'export PATH="$HOME/netpack/bin:$PATH"' >> ~/.bashrc # optional ``` 之后可以使用 `git -C ~/netpack pull` 进行更新;`make uninstall` 会移除这些链接。 如果只需要 Scapy,也可以使用:`pip install -r ~/netpack/requirements.txt` ## 启动器 ``` netpack | npk Interactive menu netpack | npk list List tools netpack | npk help Show this help (includes tool list) netpack | npk --version Print version netpack | npk [args] Run a tool netpack | npk playbooks List guided playbooks netpack | npk playbook Run a guided playbook netpack | npk -o DIR ... Capture evidence into DIR ``` 工具也可以直接调用(`dhcpprobe`、`linkstat` 等)。在任何工具上使用 `-h` / `--help`。 当您在不是 root 用户时从菜单中选择需要 root 权限的工具,菜单会自动为您调用 sudo(root 权限为可选的工具会先询问)。直接调用时绝不会自动添加 sudo。 菜单打开时会播放一段简短的启动动画;按下任意键可跳过,而 `NETPACK_NO_SPLASH=1` 会彻底禁用该动画(`npk splash` 可按需重播)。 无论是动画还是启动过程,都不会出现在管道输出或捕获的证据中。 ### 证据捕获 `-o DIR` 会记录通过启动器发起的每一次运行——无论是单次运行还是整个会话: ``` npk -o ~/evidence/site-visit # menu; everything run is captured npk -o ~/evidence/site-visit dnscheck # capture a single run ``` 每次运行都会写入 `DIR/-.log`(包含终端报告及其 stderr 的纯文本文件),并向 `DIR/manifest.tsv` 中追加一行记录,包含您可以重新输入的命令、其开始和结束时间以及退出码。该目录以 700 权限模式创建。这就是那些没有自带 `--dump` 的工具也能留下证据的方式;而会写入 JSON 的工具同样也会继续写入。 在捕获处于活动状态时,菜单的状态栏会显示 `rec `。 此捕获功能涵盖了通过启动器启动的运行——即 `npk `、菜单以及 playbook。通过名称直接调用的工具(如将 `bin/` 加入 PATH 后的 `dhcpprobe -i eth0`)会绕过此功能,不会被记录。如果您正在收集证据,请通过 `npk` 驱动整个会话;这也是 `make install` 仅链接启动器名称的原因。 ## 现场 playbook 请在故障现象出现时使用这些操作步骤。 单机操作步骤是可运行的:`npk playbooks` 会列出它们,`npk playbook ` 会逐步引导执行一个步骤(在运行前说明执行该步骤的原因),而 `p` 可在菜单中执行相同操作。结合 `-o DIR` 使用,整个操作步骤的结果都会存入同一个证据文件夹: ``` npk -o ~/evidence/site-visit playbook wan ``` 吞吐量和缓冲膨胀(bufferbloat)测试流程需要第二台机器运行 `testsrv`,因此这里以文档形式说明,而不是作为可直接运行的列表。 **IP 错误 / 无法访问本地局域网** — `npk playbook lan` 1. `linkstat` — 物理错误与丢包的对比 2. `sudo dhcpprobe` — 单个与多个 DHCP 服务器的对比(如果是带标签的 VLAN 接口,请使用对应 iface) 3. `sudo segscan` — LLDP 邻居、网关、ARP、冲突 IP 4. `discover` — 为发现的设备命名(媒体服务器、电视、打印机、视听设备) **有线端口出现错误或链路震荡(link flaps)** — `npk playbook cable` 1. `linkstat -t 30` — 确认是否为物理故障(错误/CRC/冲突计数增加,或 carrier 频繁震荡) 2. `sudo cabletest -y` — 哪一对线缆发生故障,以及故障在线路多远处。该操作会导致链路断开,因此只有在计数器指标证明有必要时才运行它 **Wi-Fi 不稳定或速度慢** — `npk playbook wifi` 1. `linkstat` — 当前连接状态:信号、比特率、carrier 震荡 2. `sudo wifiscan` — 信道拥塞和附近重叠的 AP **“断网”但链路正常** — `npk playbook wan` 1. `splitloss` — 网关与 WAN 的 ICMP 对比 2. `dnscheck` — 已配置的解析器与公共解析器对比 3. `webcheck` — 强制门户(captive portal)或 HTTP 劫持(ICMP/DNS 正常,但 HTTP 被劫持) 4. `mtucheck` — 路径 MTU 黑洞 5. `path3` / `udp-loss` — 路径与 UDP 传输证据 **特定服务无法访问(服务器、采集端、VPN)** — `npk playbook service` 1. `portcheck ` — 区分 REFUSED(主机在线,服务关闭)与 TIMEOUT(被过滤) 2. `dnscheck -n ` — 该名称的解析情况 3. `path3 ` — 指向该服务的路径证据 **间歇性断连或突发故障** — `npk playbook dropouts` 1. `sudo ringcap -d /path/to/dir` — 在故障时间窗口开始前或期间启动;记录墙上时钟时间 2. `linkstat -t 30` — 在故障现象活跃期间运行 3. 停止捕获;在 Wireshark/tshark 中打开对应的 ring 文件 **验证本地吞吐量或单向 UDP 丢包** 1. 在 uConsole 上:`sudo testsrv` 2. 在被测机器上:`testcli `(TCP)或 `testcli -u `(UDP) **验证负载下的延迟和抖动(bufferbloat)** 1. `splitloss -t 60` — 空闲基准;记录每个目标的 rtt 平均值/均方差 2. 在被测路径上启动计划好的负载(`testsrv`/`testcli` 对,或在测试上行链路时使用 `testcli -P 4 `) 3. 在负载运行期间再次执行 `splitloss -t 60` —— 如果平均延迟/均方差上升且没有丢包,说明是缓冲机制(bufferbloat);如果出现丢包增长,则说明是饱和性丢包 4. `testcli -u -b 5M ` — 在相同负载下获取类似游戏流的 iperf3 UDP 抖动数据 **Dante/NDI 多播在某个位置缺失** — `npk playbook multicast` 1. `discover` — 设备是否仍在广播? 2. 在受影响的接收点执行 `mcastcheck recv -g GROUP -p PORT` — 数据流是否到达?(组/端口信息来自 Dante Controller 或 NDI 发送端) 3. 在接收点执行 `mcastcheck recv`,并在源端的交换机位置执行 `mcastcheck send` — 针对该路径进行配对测试,检查丢包和抖动(同时检查 IGMP snooping/querier) **验证 WAN 上行吞吐量** netpack 出于设计考虑没有公共吞吐量测试目标;请使用您在 WAN 跨域控制的另一台主机(运行 `iperf3 -s` 的云 VM,或服务商认可的服务器)。 1. `testcli -P 4 ` — 上传方向(使用并行流填满宽带) 2. `testcli -R -P 4 ` — 下载方向 3. 同时运行 `splitloss -t 60` — 获取该负载下的延迟(参见 bufferbloat playbook) 使会场/场地的上行链路饱和会影响网络上的所有用户——仅限在计划内的测试中使用。 ## 工具 Root 和流量列使用与 `npk list` 及菜单相同的标签: `sudo` 需要 root 权限(菜单会自动提权),`sudo?` 表示有 root 权限更好(菜单会先询问),`probe` 会发送轻度诊断流量,`loud` 表示产生大流量、主动探测或导致链路中断——仅限经授权且计划内的使用。空白单元格表示被动或只读。 | 工具 | 用途 | Root | 流量 | |------|---------|------|---------| | `doctor` | 检查依赖项和就绪状态 | | | | `dhcpprobe` | 列出网段上的 DHCP 服务器(仅发送 DISCOVER) | `sudo` | `probe` | | `linkstat` | 采样链路计数器;物理故障与拥塞的对比 | | | | `cabletest` | TDR 线缆测试:每对线的故障和距离 | `sudo` | `loud` | | `segscan` | 接口、LLDP、网关、ARP 扫描、冲突 IP | `sudo?` | `loud` | | `wifiscan` | 附近的 Wi-Fi AP、信号、信道拥塞情况 | `sudo` | `probe` | | `discover` | 网段上的 SSDP/mDNS 服务发现 | | `probe` | | `splitloss` | 同时对比网关与 WAN 的丢包率、rtt 及丢包时间线 | | `probe` | | `dnscheck` | 已配置的 DNS 解析器与公共解析器对比 | | `probe` | | `webcheck` | 强制门户 / HTTP + TLS 劫持检查;时钟偏差 | | `probe` | | `portcheck` | 按端口检查 TCP 服务可达性 | | `probe` | | `mtucheck` | 到网关和 WAN 的路径 MTU 探测 | | `probe` | | `path3` | 基于 ICMP、UDP 和 TCP 的 mtr | `sudo?` | `loud` | | `udp-loss` | 通过带回复的 DNS 查询测试 UDP 传输 | | `probe` | | `mcastcheck` | 多播组传输(视听设备、IPTV、sACN、Dante/NDI) | | `probe` | | `ringcap` | 循环 pcap ring 捕获(默认仅抓取头部) | `sudo` | | | `testsrv` | iperf3 服务端;可选的 nft 集合 open/close | `sudo?` | `loud` | | `testcli` | 配合 `testsrv` 的 iperf3 客户端 | | `loud` | `segscan` 和 `path3` 可以在没有 root 权限的情况下运行,但会丢失其主要证据(ARP 扫描和 UDP/TCP 模式);`testsrv` 仅在需要操作 nftables 集合时才需要 root 权限。 ### 退出码(通用规则) | 代码 | 含义 | |------|---------| | 0 | 正常 / 符合预期 / 仅单个 DHCP 服务器 | | 1 | 用法、依赖项或权限错误 | | 2+ | 发现特定情况(因工具而异;参见 `--help`) | | 130 | 被中断(以 Ctrl-C 作为正常停止的工具除外:`ringcap`、`splitloss`、`mcastcheck recv`) | ## 生产环境说明 - 所有工具仅支持 IPv4(DHCP、ARP、MTU 标头计算、默认目标)。双栈故障中涉及 v6 的部分不在范围内。 - 遵循最小权限原则:需要 root 权限的工具会明确说明,并在权限不足时正常退出。 - 每个工具都会拒绝无法识别的参数(退出码 1),而不会 退回到默认值,因此像 `splitloss -t 60 8.8.8.8` 这样的输入错误 会明确报错,而不是悄悄地去测试默认目标。 - 工具报告以本地 ISO-8601 格式的开始时间戳开头(`tool — 2026-07-18T18:30:00-07:00`),并在打印完摘要后以 `finished: …` 结束,因此报告始终会包含其自身的起始和结束时间。 - JSON `--dump` 文件包含运行产生的数据字段,以及 `tool`、`timestamp` 和 `assessment_code`(运行产生的退出码)。`dhcpprobe` 还会记录 `assessment`(`none`/`single`/`multiple`),而 `mcastcheck send` 会记录 `interrupted`。 - JSON `--dump` 证据目前仅在 Python 工具(`dhcpprobe`、`linkstat`、`discover`、`mcastcheck`)上提供。Bash 工具仅输出终端证据;请将该输出(或通过 `-d` 保留的日志)附加到事件时间线中。 - `wifiscan` 会触发主动扫描,这会短暂中断接口当前的 Wi-Fi 连接;请在允许短暂断开连接的情况下运行此工具。 - `discover` 会请求单播 mDNS 回复(QU);仅支持多播的响应方将不会被捕获,因此这是尽力而为的发现,而不是详尽的清单。 - `discover` 会为已知的 mDNS 服务类型(Dante、NDI、AirPlay、打印机等)添加标签,并单独列出实时视听设备的广播。无法识别的类型将按原样显示。不同代际产品的供应商服务名可能会发生变化,因此请将标签视为一种便利,而非权威来源。 - `linkstat` 会在有线链路上报告 Energy Efficient Ethernet (EEE) 和流控制状态。EEE 允许 PHY 在数据帧之间进入低功耗空闲状态,从而增加唤醒延迟和抖动;这是导致 Dante/AES67 和 PTP 时钟不稳定以及 VoIP 抖动的已知原因。在传输这些数据流的端口上应禁用此功能。这些属于配置设置而非计数器,因此它们永远不会影响退出码。 - 当 systemd-resolved 正在运行时,`dnscheck` 会从 `resolvectl dns` 获取解析器列表,因为在这些系统上,`/etc/resolv.conf` 仅包含 `127.0.0.53` 存根(stub),而测试该存根无法证明其转发到的上游解析器是否正常。在没有 resolved 的情况下,将直接使用 `resolv.conf`。如果只能识别出环回存根,运行时会指出这一点并退出(返回 2),而不是报告一切正常。 - `dnscheck` 的基准默认会使用 `1.1.1.1`、`9.9.9.9`、`8.8.8.8`、`208.67.222.222` 中系统当前未使用的第一个地址,因此从机制上保证了对照组的独立性——如果使用固定默认值,在任何转发到该地址的主机上,就等同于将配置的解析器与自身进行对比,而与自身达成一致并不能作为证据。显式指定的 `-p` 将按输入值执行;如果发现该解析器同样已配置,运行时会发出警告并在评估(assessment)中说明,并且仅当完全没有第二个不同的解析器可供对比时,才会退出(返回 2)。 - `cabletest` 运行 ethtool 的 TDR 线缆测试,将每对线缆报告为正常或故障,并附带到故障点的大致距离——这直接回答了“线缆是否有问题,以及问题出在哪里”,适用于 `linkstat` 显示出物理层计数增长或 carrier 震荡的情况。它被标记为 `loud` 是因为会造成链路中断而非产生大流量:PHY 需要断开链路才能进行测量,因此在该期间端口会处于断开状态。它需要 root 权限和 `-y` 参数,并且菜单在运行前会进行询问。 - `cabletest` 依赖于 NIC 驱动程序提供 TDR 支持,而大多数台式机和服务器 NIC 并不支持——`e1000e`、`igb` 和 `r8169` 都会拒绝该请求,因此它无法用于典型工作站的板载网口。这种支持在嵌入式设备和交换机 PHY 中比较常见。无法运行测试的驱动程序会输出 ethtool 自身的报错信息,指明驱动名称,并退出(返回 1),而不是报告测试通过;被拒绝的请求绝不会干扰链路,报告也会说明这一点。 - `webcheck` 特意通过纯 HTTP 获取公共连通性端点(因为强制门户会拦截 HTTP),并且从不跟随重定向;重定向目标本身就是证据。其最后的 HTTPS 探测会根据系统信任库验证证书链(不受信任的链 = TLS 劫持),其时钟行会将本地时钟与 HTTP Date 标头进行对比。 - 默认情况下,`dhcpprobe` 不会完成 DORA 过程(没有 REQUEST/ACK),也不会绑定租约。`--full` 会针对第一个 offer 完成 DORA,并立即执行 RELEASE;这会短暂绑定一个 IP 地址,并出现在服务器的租约日志中。 - 对于带标签的 DHCP,请传入 `dhcpprobe -V ` 以创建临时的 VLAN 子接口(退出时移除;如果已存在子接口则会重用并保留),或者直接在子接口上运行(例如 `eth0.100`)。 - `udp-loss` 会以 1 秒的超时时间顺序发送查询,因此丢包严重的路径每个服务器最多可能需要花费 COUNT 秒的时间(默认设置下每个服务器约需 100 秒)。 - `splitloss` 会报告每个目标的 rtt 最小值/平均值/最大值/均方差,以及丢包情况。120 秒及以上的运行还会打印丢包时间线:包含丢包的每一个 60 秒区间,并标记有其墙上时钟的开始时间(根据运行的开始时间和 1 秒的发送间隔推算)。 - `mcastcheck recv` 除了执行 IGMP join 之外均处于被动状态——但这种 join 行为会使开启了 snooping 的交换机将该多播组转发到该端口,而这正是我们要测试的行为。默认组 `239.192.77.77:7788` 位于 RFC 2365 的组织本地(organization-local)范围内,处于 `239.255.0.0/16`(Dante 默认分配媒体流的范围)之外。`send` 若未添加 `-y` 参数会拒绝该范围,因为向正在使用的音频组发送数据会造成干扰;该防护措施仅涵盖了常见的默认设置,因此在发送前请务必确认该组未被使用。`send` 默认使用 TTL 1(仅限本地网段)。探测丢包/抖动需要使用 `mcastcheck send` 作为源端;速率/字节计数适用于任何数据流。 - `ringcap` 必须使用 `-d DIR` 参数,默认 snaplen 为 96。即便如此,仅抓取头部数据仍有可能暴露主机信息。 - 如果未传入 `-y`,`segscan` 将拒绝大于 /22 的 ARP 扫描。 - `testsrv` 仅在 nftables 集合 `inet filter test_tcp` 和 `test_udp` 存在时才会去操作它们;在收到 EXIT/INT/TERM 信号时会清空这些集合。`SIGKILL` 或断电会跳过清理过程——如有必要,请手动移除端口。非 root 运行会拒绝猜测这些集合是否存在(因为 nft list 需要特权)。 - 请仅在活动网络的计划测试期间使用产生负载的工具(`path3`、`splitloss`、`udp-loss`、`mtucheck`、`testsrv`、`testcli`)。 ## 示例 ``` npk doctor npk --version netpack dhcpprobe -i eth0 --dump /tmp/dhcp.json netpack linkstat -t 30 --dump /tmp/linkstat.json sudo netpack cabletest -y -i eth0 sudo netpack segscan -i eth0 sudo netpack wifiscan netpack discover -t 3 --dump /tmp/discover.json netpack splitloss -t 60 -w 1.1.1.1 -d /tmp/splitloss-logs netpack dnscheck netpack webcheck netpack portcheck 192.168.1.50 22 443 5201 sudo netpack dhcpprobe -V 100 --full netpack mtucheck netpack path3 -c 50 8.8.8.8 netpack udp-loss -c 100 netpack splitloss -t 3600 -d /tmp/splitloss-logs netpack mcastcheck recv -g 239.255.12.34 -p 4321 -t 10 netpack mcastcheck send -c 500 -r 50 netpack testcli -R -P 4 192.168.1.50 sudo netpack ringcap -d /tmp/ringcap -i eth0 -s 20 -n 10 sudo netpack testsrv -p 5201 netpack testcli 192.168.1.50 netpack testcli -u -b 5M 192.168.1.50 ```
标签:Python, 应用安全, 无后门, 网络工具, 网络排障, 运维, 逆向工具