Skip to content

Latest commit

 

History

History
890 lines (706 loc) · 58.3 KB

File metadata and controls

890 lines (706 loc) · 58.3 KB

蜂眼 BeeEye —— 家用 IoT 网关流量分析系统 需求文档 & 技术方案

版本:v1.1 日期:2026-08-19


一、项目背景

家庭网络中接入设备类型日益多样(电视、摄像头、NAS、路由器、门锁、手机、冰箱等),数量可达数十至上百台。这些设备的安全性参差不齐,尤其是门锁、摄像头等强隐私相关设备,一旦被入侵或异常外联,风险远高于普通娱乐设备。

蜂眼(BeeEye) 项目名称取意:"蜂"呼应 eBPF 技术底色与多网卡、多设备的分布式密布式采集特点;"眼"对应系统对全网流量的可视化洞察与异常行为检测能力。

现有家用路由器/软路由缺乏对设备级流量行为的深度可视化与异常检测能力。本项目(代号"蜂眼 BeeEye")旨在利用 Ubuntu 网关主机 + eBPF 技术,在不改变家庭网络拓扑的前提下,实现对全部接入设备流量的采集、指纹识别、行为建模与异常告警。


二、需求文档(PRD)

2.1 项目目标

在 Ubuntu 软路由主机上部署一套流量分析系统,实现:

  1. 识别接入家庭网络的每一台设备(类型、厂商、型号推测)
  2. 按设备类型分级监控,重点关注门锁、摄像头等高敏感设备
  3. 在不解密 TLS 内容的前提下,提取尽可能多的元数据用于异常检测
  4. 提供 Web 可视化界面,支持从 Mac/Windows/手机浏览器访问
  5. 系统资源占用可控,不影响网关本身的路由转发性能

2.2 适用范围与边界

适用场景:

  • 用户对家庭网络及其中设备拥有完整管理权限
  • 网关运行 Ubuntu(或其他现代 Linux 发行版),内核版本 ≥ 5.8(支持 BTF/CO-RE/ringbuf)
  • 家庭内网设备数量:数十至上百台

明确不做的事(需求边界):

  • 不在 Mac/Windows/IoT 终端本机部署采集代理
  • 不对访客设备做无告知的精细化追踪(仅做匿名聚合统计)
  • 不上传摄像头视频内容、门锁具体开锁记录等敏感数据至任何第三方云服务

作为可选功能的事(见 2.4 节 F14/F15、3.10 节技术方案):

  • TLS/DTLS 应用层内容解密
  • 主动 MITM 中间人代理

这两项默认关闭,仅在用户明确启用、且仅对自己拥有管理权限的设备(自己的 Mac/Windows/手机等可安装自定义 CA 证书的设备)生效;对无法安装自定义证书的 IoT 设备(门锁、摄像头等嵌入式固件,通常有证书锁定)天然不适用,不作为通用能力设计。

2.3 用户角色

角色 说明
家庭网络管理员(本人) 系统部署、规则配置、告警处理
家庭其他成员 仅通过 Web UI 查看设备流量概况,无配置权限

2.4 功能需求列表

必须实现(P0)

编号 功能 说明
F1 设备发现与身份识别 基于 MAC OUI、DHCP 指纹、mDNS/SSDP 广播识别设备类型与厂商
F2 连接级流量统计 按设备记录字节数、连接数、活跃时段
F3 TLS 握手信息提取 ClientHello 阶段提取 SNI、JA3 指纹(不涉及解密)
F4 明文协议解析 完整解析 MQTT/CoAP/HTTP/SSDP/mDNS 等明文协议内容
F5 设备分级监控策略 门锁/摄像头类设备全量记录连接事件;其他设备做统计采样
F6 异常检测规则引擎 JA3黑名单匹配、异常时间段外联、陌生 IP/端口告警
F7 Web 可视化界面 展示设备列表、流量趋势、告警事件时间线
F8 新设备接入告警 检测到未登记 MAC 首次入网时告警
F16 多网卡可配置采集 支持通过配置文件指定任意网卡接口(如 wlan0/eth0/自定义命名)进行抓取,支持同时挂载多个接口并行采集,不与具体网卡命名硬编码耦合
F17 采集流量来源接口标识 每条流量记录标注来源 ifindex/接口名,支持区分无线接入设备与有线接入设备
F18 Web UI 中英文切换 界面文案支持中文/英文双语,提供切换入口,记住用户选择
F19 Web UI 多主题配色 提供至少 6 套可选配色主题,支持实时切换并持久化用户偏好
F21 DNS 查询记录与域名映射 记录每台设备发起的 DNS 查询(查询域名、解析结果IP、查询时间),建立域名↔IP↔设备三方关联
F22 服务器 IP 地理位置标注 对通信目标 IP 做离线 GeoIP 查询,标注国家/地区/城市,用于识别异常地域外联
F23 通信协议识别与展示 识别并展示应用层协议(HTTP/HTTPS/MQTT/CoAP/DNS/SSH等),区分传输层协议(TCP/UDP)
F24 端口与服务名映射 展示源/目标端口号,并将知名端口映射为可读服务名(如443→HTTPS,1883→MQTT)
F25 按 IP 维度视图 支持以目标/源 IP 为主键的聚合视图,展示该 IP 关联的域名、地理位置、涉及设备、流量趋势
F26 按协议维度视图 支持以应用层协议为主键的聚合视图,展示各协议的流量占比、涉及设备、目标分布
F34 内网东西向流量监控 采集并记录内网设备之间(而非仅出站)的通信,用于发现设备被入侵后横向扫描/攻击其他内网设备的行为
F35 信标(C2心跳)检测 基于连接时间间隔规律性识别疑似 C2 周期性回连行为
F36 扇出/扫描检测 基于滑动窗口内唯一目标 IP/端口数量识别端口扫描、DDoS参与等攻击外发行为
F40 实时抓包分析 GUI 提供独立于 Web 总览界面的 Wireshark 式三窗格实时分析器:包列表 / 协议字段树 / 十六进制转储,支持开始-停止抓包、接口选择与实时刷新
F41 显示过滤器表达式 支持 Wireshark 兼容的显示过滤语法(字段比较 ==/!=/>/<、逻辑 &&/||/!、括号、containsmatches 正则、CIDR 匹配、裸协议名存在性判断),语法错误即时反馈而非静默失败
F42 双 UI 运行隔离 实时分析 GUI 与 Web 总览 UI 必须是独立进程、独立端口、独立前端产物,不共享数据库连接;任一侧崩溃、重启或升级不影响另一侧
F43 采集源降级与如实标注 采集源按 eBPF ringbuf → AF_PACKET 的优先级自动选择并降级,当前生效来源必须在 UI 明确标注;两者均不可用时直接报告"无数据",不存在合成数据兜底(2026-08-21 起模拟源已整体移除)

建议实现(P1)

编号 功能 说明
F9 门锁/摄像头出站白名单 基于 eBPF/XDP 主动限制高敏感设备仅可访问厂商官方域名
F10 设备行为基线建模 基于历史数据建立设备正常行为画像,偏离时告警
F11 按需精细抓包 规则命中时触发指定五元组的完整 PCAP 落盘,便于事后取证
F20 接口热插拔自动发现 支持监听网络接口增删事件(如插拔 USB 无线网卡),按规则自动挂载/卸载采集程序,无需重启服务
F27 Top N 流量排行 按设备/域名/IP/国家维度展示流量或连接数排行榜,快速定位异常大户
F28 异常地理位置告警 设备首次访问预设关注地区之外的 IP,或短时间内访问多个不同国家 IP 时触发告警
F29 域名/IP 威胁情报比对 结合公开黑名单(恶意域名/C2 IP 库)比对通信目标,命中时告警,支持本地缓存离线比对
F30 多维组合检索 支持按设备/IP/域名/协议/端口/时间范围任意组合筛选历史通信记录
F37 多信号加权评分 综合多个弱信号(首次目标、地域异常、信标特征等)加权计算风险分,降低单一规则误报率
F38 高危事件自动响应联动 检测到高置信度入侵信号时,自动触发 F9 白名单/XDP 阻断隔离该设备,并可配置为仅告警不阻断
F44 PCAP 导出 实时分析 GUI 可将当前(过滤后)包集合导出为标准 pcap 文件,供 Wireshark/tshark 做离线深度分析与取证

可选实现(P2)

编号 功能 说明
F12 流量分类模型 基于包长序列/时序特征做流量类型分类(如区分心跳/数据上传)
F13 移动端告警推送 通过消息推送(如 ntfy/Bark)通知高危事件
F14 TLS 会话密钥被动获取 仅限自己管理的终端(Mac/Win/手机),通过导出 SSLKEYLOGFILE 方式,离线解密对应流量用于分析
F15 主动 MITM 代理 针对指定的自有设备,部署透明代理解密并检视明文内容,默认关闭,需逐设备显式启用并安装自定义 CA
F31 通信记录导出 支持将筛选后的记录导出为 CSV/JSON,便于离线分析或存档
F32 地理位置地图可视化 在世界地图上以热力图/连线形式展示设备的对外通信地理分布
F33 DNS 异常检测 检测异常 DNS 行为,如高频 NXDOMAIN(疑似 DGA 域名生成算法)、DNS 隧道特征(异常大的 TXT 记录查询频率)
F39 恶意软件下载特征检测 识别明文下载中可疑文件命名模式(如 .elf/架构后缀)及异常单向大流量下载,覆盖 Mirai 类 IoT 僵尸网络常见投递手法

F14、F15 仅适用于用户自己拥有管理权限、可安装自定义证书/配置环境变量的设备。对门锁、摄像头等采用证书锁定(certificate pinning)的嵌入式 IoT 设备,这两项功能均不适用,连接会被设备拒绝,此时仍应回退至元数据分析(见 F1-F8)。

2.5 非功能需求

类别 要求
性能 千兆内网流量下,eBPF 采集不造成可感知的转发延迟增加(目标 <1ms 附加延迟)
资源占用 全系统常驻内存占用 < 512MB(不含操作系统本身),CPU 占用 < 10%(4核心平台)
可靠性 分析组件崩溃不影响路由转发功能(采集与转发解耦)
可维护性 支持 Docker Compose 一键部署与回滚
隐私安全 高敏感设备(门锁/摄像头)事件日志仅本地存储,不上传第三方云服务
跨平台访问 Web UI 需在 Mac/Windows/iOS/Android 主流浏览器正常访问
拓扑适配 支持 NAT 模式(Wi-Fi独立网段)与桥接模式(Wi-Fi/有线同网段)两种常见组网方式,采集接口不硬编码
国际化 Web UI 文案(含图表标签、告警描述)中英文均需覆盖,不遗留未翻译文案
地理位置查询隐私 IP 地理位置查询使用本地离线数据库,不将设备访问的目标 IP 逐条发送至第三方在线查询接口

三、技术方案

3.1 总体架构

┌──────────────────────┐   ┌──────────────────────┐
│ 展示层A:自研 Web 总览  │   │ 展示层B:实时分析 GUI  │
│ BeeEye-web  :8080     │   │ BeeEye-gui  :8081     │
│ 设备/告警/多维视图      │   │ Wireshark 式三窗格    │
│ (家庭成员日常入口)      │   │ (管理员深度排查)      │
└──────────┬───────────┘   └───────────┬──────────┘
           │ REST                      │ SSE + REST
┌──────────┴───────────┐   ┌───────────┴──────────┐
│ 进程A:BeeEye-agent    │   │ 进程B:BeeEye-gui     │
│ 存储+检测+API         │   │ 实时抓包+协议解析      │
└──────────┬───────────┘   └───────────┬──────────┘
     两进程互不依赖,共享的只有编译期的 internal 包
┌──────────┴───────────────────────────┴──────────┐
│  展示层(可选):Grafana,管理员做原始指标钻取        │
├─────────────────────────────────────────────────┤
│  存储层:InfluxDB(指标) + SQLite(事件/资产库)      │
├─────────────────────────────────────────────────┤
│  分析层:规则引擎 + 设备指纹匹配 + 行为基线(Go/Py)  │
├─────────────────────────────────────────────────┤
│  Agent 层:libbpf+CO-RE 用户态程序(Go, cilium/ebpf)│
├─────────────────────────────────────────────────┤
│  采集层:eBPF 程序(TC/XDP,挂载于 LAN 口)           │
├─────────────────────────────────────────────────┤
│  Ubuntu 内核(≥5.8, 需 BTF 支持)                   │
└─────────────────────────────────────────────────┘

部署形态:单台 Ubuntu Server 主机(x86 mini PC / NUC 类设备),通过 Docker Compose 部署除 eBPF 内核程序加载点之外的全部组件。

3.2 关键技术选型

组件 选型 理由
eBPF 开发框架 libbpf + CO-RE 跨内核版本可移植,无需针对不同内核重新编译
用户态语言 Go(cilium/ebpf 库) 生态成熟,ringbuf 读取、map 操作封装完善,便于对接后续存储
挂载点 TC(ingress/egress,挂 LAN 口/br-lan) 家用带宽下性能足够,较 XDP 更易获取完整 skb 上下文
主动阻断(P1功能) XDP 需要毫秒级丢包响应时(如门锁白名单强制)使用
事件传输 BPF_MAP_TYPE_RINGBUF 内核 5.8+ 推荐,较 perf event array 开销更低
指标存储 InfluxDB(单机版) 时序数据,家用数据量级下单机版足够,原生支持 Grafana
事件/资产存储 SQLite 轻量、无需额外服务,适合家用规模的结构化数据
主展示层(设备总览/告警/配置) 自研 Web 前端(React + i18next + Ant Design/自定义组件) Grafana 原生仅支持明暗两套主题、无面向普通用户的中英文一键切换能力,无法满足 F18/F19(6套主题+双语切换),故主用户界面自研,通过 REST API 读取 InfluxDB/SQLite
辅助展示层(深度指标钻取,可选) Grafana 供高级用户/管理员做原始指标的自由钻取分析,不作为面向家庭成员的主入口
实时分析 GUI(F40) 独立 Go 进程 + 独立端口 + 独立前端产物 与 Web 总览 UI 完全隔离(F42);headless 网关无桌面环境,打包成 Electron/原生窗口反而无法在网关本机运行,浏览器形态可从 Mac/Win/手机直接访问
GUI 实时推流 Server-Sent Events(SSE) 包流是单向的服务端→客户端,SSE 用标准库即可实现、自动重连、无需 WebSocket 依赖与握手升级逻辑
GUI 抓包源 AF_PACKET raw socket(无 CGO) 不引入 gopacket+libpcap 的 CGO 依赖,保持静态链接与小镜像;有 CAP_NET_RAW 即真实抓包,否则直接报错,不存在合成数据兜底(F43)
显示过滤器(F41) 自研词法+递归下降解析器 语法对齐 Wireshark 使用者的既有肌肉记忆,零依赖,可对表达式做即时语法校验
部署方式 Docker Compose 简化部署与版本管理,eBPF Agent 容器需 host 网络模式

3.3 数据流设计

网卡(LAN口) → TC eBPF程序(内核态过滤+特征提取)
            → ringbuf(内核→用户态事件通道)
            → Go Agent:
                ├─ 设备身份关联(MAC → 资产库查询/更新)
                ├─ JA3/JA3S 指纹计算
                ├─ 明文协议解析(MQTT/mDNS/SSDP/HTTP)
                ├─ 规则引擎匹配(黑名单/异常行为)
                └─ 输出:
                    ├─ 指标 → InfluxDB
                    ├─ 事件/告警 → SQLite
                    └─ (按需)PCAP → 本地文件系统
            → Grafana 读取 InfluxDB/SQLite 渲染仪表盘

3.4 内核态(eBPF)设计

3.4.1 挂载点

挂载点 用途
TC ingress/egress @ LAN 接口 主采集点:五元组统计、包长分布、TLS ClientHello 解析
XDP @ LAN 接口(P1功能启用时) 门锁/摄像头白名单强制丢包

关键要求:挂载于 LAN 口(内网侧接口,如 br-lan),而非 WAN 口,以保留设备真实内网 IP/MAC,避免 NAT 后丢失设备粒度。

3.4.2 核心数据结构(示意)

// 按设备MAC聚合的统计表
struct device_key {
    __u8 mac[6];
};

struct device_stat {
    __u64 tx_bytes, rx_bytes;
    __u64 conn_count;
    __u32 last_seen;
    __u8  category;   // 0=unknown 1=camera 2=lock 3=nas 4=tv ... (用户态回写)
};

// 连接级流表(LRU,防止无限增长)
struct flow_key {
    __u32 saddr, daddr;
    __u16 sport, dport;
    __u8  proto;
};

struct flow_stat {
    __u64 pkts, bytes;
    __u64 first_ts, last_ts;
    __u16 pkt_len_hist[16];
    __u8  tls_sni[64];
    __u8  is_tls;
};
  • device_key → category 的映射由用户态识别后写回,内核态据此决定该流量的处理策略(全量上报 vs 采样上报),实现"分级监控"下沉到内核态,降低用户态处理压力。
  • 流表使用 BPF_MAP_TYPE_LRU_HASH,避免连接数增长导致内存无界增长。

3.4.3 TLS ClientHello 解析

利用握手首包为明文的特性,在 TC 程序中定位 TCP payload,校验 TLS Record Header 与 Handshake Type,提取:

  • SNI 扩展(明文域名)
  • Cipher Suites 列表、扩展类型列表(用于用户态计算 JA3 指纹)

字符串拼接和 MD5 计算不在内核态完成(受 eBPF 验证器限制),仅提取原始字段,交由用户态 Go Agent 完成指纹计算。

3.4.4 事件上报策略

为控制吞吐与开销:

  • 握手阶段包(信息密度最高)→ 全量上报
  • 普通数据包 → 按连接聚合后定期批量上报(如每 5 秒一次统计快照),而非逐包上报
  • 门锁/摄像头类设备(category 已标记)→ 全量记录连接事件
  • 其余设备 → 采样/聚合上报

3.4.5 多网卡可配置采集设计

家庭网络常见两种组网拓扑,采集接口选择不同:

拓扑 说明 建议采集接口
NAT 模式 Wi-Fi(如 wlan0)与上联口(如 eth0)不同网段,主机做 NAT 挂载 wlan0(内网侧),可获得设备真实 IP/MAC;不建议只挂 eth0,NAT 后会丢失设备粒度
桥接模式 wlan0eth0 桥接为同一网段(如 br0) 挂载各物理接口(wlan0/eth0)而非桥接口 br0,以保留"来自哪个物理接口"的信息;若只需总流量视图则改为只挂 br0,二者不应同时挂载,避免同一包被计数两次

接口挂载不与具体网卡命名硬编码耦合,通过配置文件声明,支持任意接口名(包括 USB 网卡等不规则命名如 wlx*):

# config.yaml
interfaces:
  mode: explicit            # explicit(显式指定) 或 auto(自动发现)
  explicit_list:
    - name: wlan0
      role: wifi_ap          # 角色标签,驱动后续分级监控策略
    - name: eth0
      role: wan_uplink
  auto_discover:
    exclude_patterns:        # auto模式下排除的接口,避免误挂虚拟网卡
      - "lo"
      - "docker*"
      - "veth*"
      - "br-*"

用户态 Agent 启动时按配置列表逐个 attach,单个接口不存在或 attach 失败仅记录日志、跳过,不影响其余接口正常采集;auto 模式下用 netlink 监听接口增删事件,实现热插拔场景(如插拔 USB Wi-Fi 网卡)下的自动挂载/卸载,对应 F20。

同一份 eBPF 字节码,分别 attach 到多个接口,不需要为每个接口单独编译:

for _, ifcfg := range cfg.Interfaces {
    iface, err := net.InterfaceByName(ifcfg.Name)
    if err != nil {
        log.Printf("接口 %s 不存在,跳过: %v", ifcfg.Name, err)
        continue
    }
    l, err := link.AttachTCX(link.TCXOptions{
        Program:   bpfObjs.TcIngress,
        Attach:    ebpf.AttachTCXIngress,
        Interface: iface.Index,
    })
    if err != nil {
        log.Printf("attach到%s失败: %v", ifcfg.Name, err)
        continue
    }
    ifindexToRole[iface.Index] = ifcfg.Role   // 维护 ifindex→角色 映射,供用户态和展示层使用
    defer l.Close()
}

内核态 flow_key 携带来源接口信息,使得同一份流表能区分多网卡来源,不需要为每个接口单独维护一张 map:

struct flow_key {
    __u32 ifindex;      // 来源接口索引,TC程序中取自 skb->ifindex,XDP中取自 ctx->ingress_ifindex
    __u32 saddr, daddr;
    __u16 sport, dport;
    __u8  proto;
};

用户态据 ifindex → role 映射,决定该接口流量的展示分组与分级监控策略(例如 wifi_ap 角色走"设备级"精细监控,wan_uplink 角色仅做总流量统计),并在 Web UI 的设备详情中标注"接入方式:无线/有线"。

3.4.6 DNS 查询解析(对应 F21)

DNS 查询/响应默认走 UDP 53 明文传输(除非设备启用了 DoH/DoT,见下方说明),内容在 TC 挂载点即可直接解析,不涉及解密:

  • 在 TC ingress/egress 程序中,对目标/源端口为 53 的 UDP 包做 DNS 报文解析:提取查询域名(Question 部分)、响应中的 A/AAAA 记录(域名对应的解析 IP)、TTL、查询发起方 MAC。
  • 建立 域名 ↔ IP ↔ 设备 三方关联表,是后续"按 IP 视图""按协议视图"中"该 IP 对应哪个域名"这一展示能力的数据基础——单纯抓 TLS 流量只能拿到 ClientHello 里的 SNI,而 DNS 记录能补全"设备实际查询过哪些域名,即使该域名后续走的是无 SNI 或 ECH 的连接"这一信息缺口。
  • DoH/DoT 场景的局限性说明:如果设备使用 DNS over HTTPS(如访问 1.1.1.1/8.8.8.8 的 443 端口做 DoH)或 DNS over TLS(853端口),查询内容本身被加密,eBPF 无法解析出具体查询域名,此时只能退化为"检测到该设备正在使用 DoH/DoT 服务"这一元数据级别的识别(基于目标 IP+端口特征匹配已知 DoH/DoT 服务商),不强行尝试解密。这一局限应在 Web UI 上明确提示用户,而非静默展示不完整数据。

数据结构示意:

struct dns_record {
    __u8  client_mac[6];
    __u32 query_ts;
    char  domain[128];      // 定长缓冲,eBPF验证器要求边界明确
    __u32 resolved_ips[8];  // 一次响应可能包含多个A记录
    __u8  resolved_count;
};

3.5 用户态 Agent 设计

3.5.1 模块划分

┌──────────────────────────────────────┐
│ Ringbuf Reader                         │  读取内核事件
├──────────────────────────────────────┤
│ Device Identity Engine                 │  MAC→设备类型识别与资产库维护
├──────────────────────────────────────┤
│ Fingerprint Engine                     │  JA3/JA3S计算与黑白名单比对
├──────────────────────────────────────┤
│ DNS Resolver Tracker                   │  域名↔IP↔设备关联维护
├──────────────────────────────────────┤
│ Protocol Identifier                    │  应用层协议识别(端口+DPI-lite+ALPN)
├──────────────────────────────────────┤
│ GeoIP Enrichment                       │  目标IP地理位置离线查询
├──────────────────────────────────────┤
│ Plaintext Protocol Parser              │  MQTT/CoAP/HTTP/mDNS/SSDP解析
├──────────────────────────────────────┤
│ Rule Engine                            │  异常检测规则匹配(含威胁情报比对)
├──────────────────────────────────────┤
│ Storage Exporter                       │  写入InfluxDB/SQLite
└──────────────────────────────────────┘

3.5.2 设备身份识别流程

  1. 新 MAC 出现 → 触发被动指纹采集(DHCP Option 55/60、mDNS/SSDP 广播、MAC OUI 前缀)
  2. 匹配开源指纹库(如 Fingerbank 数据集)得出初步设备类型
  3. 写入本地资产库(SQLite device_registry 表),包含:MAC、厂商、推测型号、类别、首次发现时间、当前 category 标签
  4. 将 category 标签回写至 eBPF device_key → category map,驱动内核态分级处理策略

3.5.3 分级监控策略实现

设备类别 监控粒度 特殊策略
门锁 全量连接事件记录 出站白名单(P1)、异常时段告警
摄像头 全量连接事件记录 出站白名单(P1)、异常上传流量告警(如凌晨大流量出站)
NAS 中等:登录尝试、入站连接、异常大流量 关注勒索软件加密特征(短时大量文件写入对应的流量突变,需结合宿主日志)
路由器自身 中等:管理接口访问监控
电视/冰箱等云服务类设备 低:基础流量统计+基线告警 不做精细指纹,避免误报
手机/电脑(含Mac/Win) 低:基础流量统计 通用计算设备流量模式复杂,仅做异常外联检测,不做深度画像

3.5.4 协议识别引擎(对应 F23)

应用层协议识别不依赖单一信号,按优先级组合判断,识别失败时明确标注为"未知(仅端口/传输层可见)",不做无依据的猜测展示:

优先级 判断依据 适用场景
1 明文协议解析结果直接命中(如成功解析出 MQTT CONNECT 包) MQTT/CoAP/HTTP/SSDP/mDNS 等已实现解析器的协议
2 TLS ClientHello 的 ALPN 扩展(Application-Layer Protocol Negotiation) 可识别 HTTP/2(h2)、HTTP/1.1(http/1.1)等,无需解密即可获取,和 SNI 同属握手明文部分
3 知名端口映射表 端口 443→HTTPS、8883→MQTT over TLS、22→SSH、53→DNS 等,作为前两者都未命中时的兜底判断
4 包长/时序特征启发式(可选,P2 范畴对应 F12) 无法通过前三者判断的私有协议,仅做粗粒度分类("疑似心跳类""疑似流媒体类"),明确标注为启发式推测而非确定结论

端口→服务名映射维护为可配置的本地表(而非硬编码),便于用户按自己网络中的实际厂商私有端口补充:

# port-service-map.yaml
443: HTTPS
8883: MQTT-TLS
1883: MQTT
5683: CoAP
53: DNS
22: SSH
80: HTTP

3.5.5 GeoIP 地理位置查询(对应 F22)

  • 使用 本地离线 GeoIP 数据库(如 MaxMind GeoLite2 或同类开源替代数据库),定期(如每周)增量更新数据库文件,查询过程完全在本机完成,不对每次访问的目标 IP 发起在线第三方 API 请求,避免把家庭设备的访问记录间接暴露给外部地理位置查询服务。
  • 查询结果(国家/地区/城市/经纬度)以目标 IP 为 key 做本地缓存(TTL 建议 7 天,IP 地理位置变动不频繁),避免重复查询消耗资源。
  • 私有地址段(内网 IP、CGNAT 地址段)直接标注为"本地/内网",不进行地理位置查询。

3.6 存储层设计

数据 存储 Schema要点
时序指标(流量、连接数) InfluxDB measurement按设备category分桶,tag含mac/category/protocol/ifindex,便于按协议、按接口聚合查询
设备资产库 SQLite device_registry(mac, vendor, model_guess, category, first_seen, last_seen)
事件/告警日志 SQLite events(ts, mac, event_type, severity, detail_json)
连接明细记录 SQLite/ClickHouse(数据量大时可选) connections(ts, mac, src_ip, src_port, dst_ip, dst_port, proto, app_protocol, bytes, ifindex),是"按IP视图""按协议视图"的核心数据源
DNS 查询记录 SQLite dns_records(ts, mac, domain, resolved_ips, ttl),支撑域名↔IP↔设备关联查询
GeoIP 查询缓存 SQLite 或内存缓存(如 Redis/本地 LRU) geoip_cache(ip, country, region, city, lat, lon, cached_at),TTL 过期后重新查询本地离线库
精细抓包样本(按需) 本地文件系统(可选加密) 仅规则命中时生成,定期清理策略(如保留30天)

connections 表是新增的关键表,记录粒度为"单次连接汇总"(而非逐包),字段设计直接服务于 F21-F26 的展示需求;数据量较大时(百台设备长期运行数月)可评估从 SQLite 迁移至 ClickHouse 或 DuckDB 以获得更好的聚合查询性能,迁移不影响上层 API 设计。

3.6.1 Web UI 多维视图设计(对应 F21-F26、F30)

在设备维度视图(已有 F7)基础上,新增两个平行的聚合视图入口,三者共享同一份 connections/dns_records 底层数据,仅聚合维度不同:

按设备视图(已有):选中一台设备 → 展示其全部通信记录

按 IP 视图(新增,F25):

展示字段 说明
目标/源 IP 支持内网 IP 和外部 IP
关联域名 来自 DNS 记录关联,若无 DNS 记录(如设备直连硬编码IP)则标注"无DNS解析记录"
地理位置 国家/地区/城市,标注在小地图缩略图上
涉及设备 该 IP 被哪些本地设备访问过(可能是多台设备共享同一云服务)
应用层协议 该 IP 通信中识别出的协议类型
端口分布 该 IP 上被访问的各端口及对应服务名
流量趋势 该 IP 的历史流量曲线

排序/筛选支持:按流量大小、按首次出现时间、按地理位置(可快速筛选"非中国大陆 IP"这类场景)。

按协议视图(新增,F26):

展示字段 说明
协议名称 HTTPS/MQTT/CoAP/DNS/SSH等
流量占比 饼图/条形图展示各协议流量占比
涉及设备数 使用该协议通信的设备数量
目标分布 该协议下 Top N 目标域名/IP
端口分布 该协议实际使用的端口列表(可能存在非标准端口使用,是潜在异常信号)

多维组合检索(F30):提供统一的筛选面板,支持任意组合:设备(多选)+ IP/域名(模糊搜索)+ 协议(多选)+ 端口(范围)+ 时间范围,筛选结果同时驱动"按设备/按IP/按协议"三个视图联动刷新,并支持导出(F31)。

3.7 Docker 化部署方案

version: "3.8"
services:
  BeeEye-agent:                 # 蜂眼采集分析核心(eBPF Agent)
    build: ./BeeEye-agent
    network_mode: host        # 必须:需访问宿主机真实LAN网卡
    cap_add:
      - CAP_BPF                # 内核5.8+专用,权限收敛于CAP_SYS_ADMIN
      - CAP_NET_ADMIN
      - CAP_PERFMON
    volumes:
      - /sys/kernel/debug:/sys/kernel/debug
      - /sys/fs/bpf:/sys/fs/bpf
      - ./data/sqlite:/data
    restart: unless-stopped

  BeeEye-influxdb:
    image: influxdb:2
    volumes:
      - influx-data:/var/lib/influxdb2
    restart: unless-stopped

  BeeEye-grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    depends_on: [BeeEye-influxdb]
    restart: unless-stopped

  BeeEye-gui:                   # 蜂眼实时分析器(Wireshark 式三窗格,F40)
    build: ./BeeEye-agent        # 与 agent 同一 Go module,产出第二个二进制
    command: ["/usr/local/bin/BeeEye-gui"]
    network_mode: host        # 必须:AF_PACKET 需要访问宿主机真实网卡
    cap_add:
      - CAP_NET_RAW            # 抓包所需的最小权限,不需要 CAP_BPF
      - CAP_NET_ADMIN          # 混杂模式
    volumes:
      - ./BeeEye-gui/dist:/web:ro
    restart: unless-stopped
    # 与 BeeEye-agent 之间没有 depends_on:两者互不依赖(F42),
    # 任一侧重启或崩溃都不影响另一侧继续工作。

  BeeEye-web:                   # 蜂眼主展示前端
    build: ./BeeEye-web          # React前端 + 轻量API服务(读取InfluxDB/SQLite)
    ports:
      - "8080:8080"
    volumes:
      - ./data/sqlite:/data:ro
    depends_on: [BeeEye-influxdb]
    restart: unless-stopped

volumes:
  influx-data:

说明:

  • BeeEye-agent 容器需要特权配置(host 网络 + CAP_BPF等),其余组件按普通容器隔离运行,便于安全审计与资源限制。
  • 若宿主机内核版本不支持细粒度的 CAP_BPF(早于 5.8),需退化为 CAP_SYS_ADMIN
  • 内核需具备 BTF 支持(/sys/kernel/btf/vmlinux 存在)以启用 CO-RE,现行 Ubuntu 20.04+ 默认满足。
  • BeeEye-web 为家庭成员的默认访问入口(端口 8080);BeeEye-grafana(端口 3000)作为管理员可选的深度指标钻取工具,两者共享同一份底层数据,不重复采集。

3.8 跨平台策略说明

需求 方案
Mac/Windows 设备接入监控 作为普通终端经由 Ubuntu 网关的 eBPF 系统统一覆盖,无需在其本机部署任何组件
Mac/Windows 查看分析结果 通过浏览器访问自研 Web UI(默认入口)或 Grafana(深度钻取),天然跨平台
Mac/Windows 离开家庭网络时的临时抓包(边缘场景) 使用系统自带工具(macOS: tcpdump/Wireshark;Windows: npcap+Wireshark)导出 PCAP,回传至 Ubuntu 侧用 tshark/Zeek 离线分析,不纳入常规系统范围

3.8.1 Web UI 国际化设计(F18)

  • 前端技术栈采用 React + react-i18next(或 Vue + vue-i18n,视团队熟悉度选择),所有界面文案(导航、按钮、表格表头、图表坐标轴标签、告警描述、规则引擎提示文案)统一走 i18n key,不允许硬编码中/英文字符串。
  • 语言资源文件结构:
locales/
  zh-CN/
    common.json      # 通用文案(导航、按钮)
    device.json       # 设备相关文案
    alert.json         # 告警相关文案
  en-US/
    common.json
    device.json
    alert.json
  • 后端返回的动态内容(如设备类别名 category、告警类型 event_type)以枚举 key 形式返回(而非直接返回中文/英文字符串),前端按当前语言环境查表渲染,避免语言切换时出现"表格是英文、告警描述还是中文"这类不一致问题。例如后端返回 category: "camera",前端渲染为"摄像头"或"Camera"。
  • 语言切换入口置于顶部导航栏,切换后通过浏览器 localStorage 持久化用户选择,下次访问自动应用,不需要每次手动切换。
  • 默认语言:根据浏览器 Accept-Language 自动识别,识别失败时默认中文(可配置)。

3.8.2 Web UI 多主题配色设计(F19)

提供 6 套预设配色主题,通过 CSS 变量(Design Tokens)实现,不侵入组件逻辑,新增/调整主题只需改动 token 文件:

主题名 风格定位 主色调示例
极简白(Light) 默认浅色,日间使用 白底 + 靛蓝主色
深邃黑(Dark) 默认深色,夜间使用 深灰底 + 青色主色
科技蓝(Tech Blue) 强调数据可视化场景的专业感 深蓝底 + 荧光蓝/青绿点缀
暖橙护眼(Warm Amber) 长时间盯屏场景,减少蓝光刺激 米色/暖灰底 + 琥珀色主色
森绿静谧(Forest Green) 柔和低干扰,适合作为常驻监控背景墙 墨绿底 + 浅绿/米白点缀
高对比无障碍(High Contrast) 面向弱视/强光环境下的可读性优化 纯黑底 + 高饱和黄色文字,符合 WCAG AA 对比度标准

实现要点:

  • 每套主题定义一组 CSS 变量(背景色、文字色、主色、告警色阶——成功/警告/危险三级颜色需在所有主题下保持语义一致,不能出现"危险"在某主题下不够醒目的情况):
:root[data-theme="tech-blue"] {
  --bg-primary: #0b1e3a;
  --bg-secondary: #142d52;
  --text-primary: #e6edf7;
  --accent-primary: #3ac6ff;
  --status-success: #2ecc71;
  --status-warning: #f5a623;
  --status-danger: #ff4d4f;
}
  • 主题切换入口同样置于顶部导航栏(与语言切换并列),切换后持久化至 localStorage,并支持"跟随系统"选项(读取 prefers-color-scheme)。
  • 图表组件(流量趋势图、告警时间线)的配色需从当前主题 token 动态取值,不允许在图表库配置里写死颜色,确保切换主题时图表同步变化。
  • 高对比无障碍主题需额外验证文字与背景的对比度达到 WCAG 2.1 AA 标准(至少 4.5:1),作为该主题验收的硬性指标。

3.9 安全与隐私设计要点

  1. 高敏感设备(门锁、摄像头)事件日志仅本地存储,不接入任何第三方云端日志服务。
  2. 系统默认不做视频内容分析,仅采集连接元数据(时间、字节数、目标地址),避免制造新的隐私风险点。
  3. 访客设备默认仅纳入匿名聚合统计,不做个体行为画像,除非用户主动配置。
  4. BeeEye-agent 容器权限收敛至最小必要 capability 集合,不默认使用 --privileged
  5. 精细 PCAP 抓包功能默认关闭,仅在规则命中时按需短时启用,并设置自动清理周期。

3.10 可选功能:TLS 解密与主动 MITM(F14/F15)

默认不启用,仅作为可插拔扩展模块设计,与核心的元数据分析链路解耦,启用与否不影响 F1-F8 的正常运行。

3.10.1 适用范围判断

设备类型 是否可行 说明
自己的 Mac/Windows(浏览器/自建应用) 可行 可控制客户端环境变量或安装自定义 CA
自己的 Android 手机 部分可行 需手动安装用户级 CA 证书;Android 7+ 默认 App 不信任用户 CA,除非目标 App 未做网络安全配置限制
自己的 iPhone 部分可行 需安装描述文件并在“证书信任设置”中手动启用完全信任,系统级限制较多
门锁、摄像头等嵌入式 IoT 通常不可行 固件内置证书锁定(pinning),无法安装自定义 CA,MITM 会导致连接失败

3.10.2 方案 A:被动方式 —— SSLKEYLOGFILE 密钥导出

原理:在自己控制的客户端进程启动时设置环境变量,进程会将每个 TLS 会话的密钥材料写入指定文件,eBPF/网关旁路捕获的密文流量可用该文件离线解密,不需要改变网络路径,是相对温和的方式。

# 在自己的 Mac/Linux 终端上,启动支持该机制的应用(如浏览器)前设置
export SSLKEYLOGFILE=~/tls-keys.log
  • 主流浏览器(Chrome/Firefox)原生支持该环境变量。
  • 密钥文件需定期同步至网关侧(如通过内网共享目录),供 tshark -o tls.keylog_file:xxx 或 Wireshark 离线解密时使用。
  • 局限:仅对支持该机制的客户端有效,大多数 IoT 固件不支持,自制/闭源 App 也大概率不支持。

3.10.3 方案 B:主动方式 —— 透明 MITM 代理

原理:网关对指定设备的出站 443/8883 等端口流量做 DNAT 转发至本地代理进程(如 mitmproxy),代理动态签发证书伪装成目标站点,与客户端和真实服务端分别建立两段 TLS 连接,从而在代理进程内以明文形式获得应用层内容。

指定设备 → (DNAT至网关本地代理) → mitmproxy → 真实服务端
              ↑ 需设备信任网关自签CA

实现要点:

  • 使用 iptables/nftables(或 eBPF sk_msg/sockops 做透明转发)仅对逐台显式启用的设备 MAC/IP 做重定向,禁止默认全局启用。
  • mitmproxy 以独立容器运行,解密后的内容仅用于本地规则匹配和日志摘要,不做全量正文持久化存储(除非用户明确要精细取证并接受隐私权衡)。
  • 需要在目标设备上手动安装 mitmproxy 生成的 CA 根证书,这一步只能在自己管理的 Mac/Windows/手机上完成,构成事实上的“仅对自有可控设备生效”边界。
  • 对开启 HSTS 预加载、证书锁定(如银行 App、部分厂商 App)的目标站点/App,MITM 会直接失败,预期内且不应强行绕过。

3.10.4 风险与使用限制

  • 启用 MITM 后,该设备与目标服务器之间的机密性保护事实上被网关取代,一旦网关本身被入侵,解密后的数据存在集中泄露风险,需评估是否值得为分析目的承担这一新增攻击面。
  • 仅应在自己单人使用、自己拥有完全管理权限的设备上启用,不应对家庭其他成员的设备静默启用,涉及通信隐私,建议启用前明确告知使用者并取得同意。
  • 解密得到的明文内容默认只用于实时规则匹配后立即丢弃(如检测敏感词/异常域名),不建议默认落盘存储完整正文;如确需存储用于事后分析,应加密存储并设置较短的自动过期时间。

3.11 入侵后异常行为检测与响应(对应 F34-F39)

设备被入侵后的异常行为通常经历"下载后门→接收C2指令→对外攻击"三个阶段,由于流量多为 TLS 加密,检测思路以行为侧信道的时间/空间统计特征为主,不依赖解密内容。本节检测器均基于第 3.6 节 connections/dns_records 表实现,属于规则引擎模块(3.5.1)的具体展开,不需要额外的采集能力。

3.11.1 检测器总览

检测器 对应阶段 依赖数据 核心逻辑
首次目标检测器 投递阶段 device_registry 基线 + 新连接 设备首次访问从未出现过的 IP/域名
直连IP检测器 投递阶段 connections vs dns_records TLS连接的目标IP在近期DNS记录中无对应解析记录
恶意下载特征检测器(F39) 投递阶段 明文HTTP解析结果 URI含 .elf/架构后缀等可疑命名,或单向大流量下载
威胁情报比对器(已有F29) 投递/C2阶段 目标IP/域名/JA3 vs 黑名单 命中公开恶意软件情报库
信标检测器(F35) C2阶段 connections 时间戳序列 连接间隔规律性统计
DNS异常检测器(已有F33) C2阶段 dns_records 高频NXDOMAIN、域名高熵值(DGA特征)
扇出/扫描检测器(F36) 攻击阶段 connections 滑动窗口聚合 唯一目标IP/端口数超阈值
内网横向检测器 攻击阶段 connections 中源目的均为内网 设备访问从未通信过的内网其他设备
半连接堆积检测器 攻击阶段 TCP状态(SYN未完成握手计数) 疑似SYN Flood外发

3.11.2 信标(Beaconing)检测算法

对每个 (设备MAC, 目标IP) 二元组,维护滑动窗口(如最近 2 小时)内的连接发起时间戳序列 t1, t2, ..., tn:

1. 计算相邻间隔序列: Δt_i = t_i - t_{i-1}
2. 计算间隔的均值 μ 和标准差 σ
3. 计算变异系数 CV = σ / μ
4. 若满足以下条件同时成立,标记为疑似信标:
   - n ≥ N_min(如连接次数 ≥ 6,避免样本太少导致统计不稳定)
   - CV < CV_threshold(如 0.15,即间隔波动小于均值的15%,越机械化CV越接近0)
   - μ 在可疑区间内(如 10秒~1小时,过短可能是正常保活,过长统计意义弱)
  • 该算法对固定间隔+小幅随机抖动的信标(常见恶意软件行为)有效;对完全自适应间隔的高级 C2(会主动规避统计特征)效果有限,需配合其他信号联合判断(见 3.11.5)。
  • 需要为常见合法周期性行为建立白名单豁免,避免误报:NTP 同步、正常的固件/App 心跳保活(尤其是这类行为在 IoT 设备上本身就很常见)、云服务厂商已知的官方域名周期性检查更新等,应在规则引擎中优先排除。

3.11.3 扇出/扫描检测算法

对每台设备维护滑动窗口(如 1 分钟、5 分钟两档)内的:

- unique_dst_ip_count:窗口内连接的唯一目标IP数量
- unique_dst_port_count(按单一目标IP统计):窗口内对该IP尝试的唯一端口数量

按设备类别设定差异化阈值(避免"一刀切"导致高误报或漏报):

设备类别 5分钟内唯一目标IP阈值 5分钟内对单一目标唯一端口阈值
门锁/摄像头 > 5 即告警 > 3 即告警
NAS/路由器 > 20 即告警 > 10 即告警
电视/手机/电脑 > 50 即告警(更宽松,通用设备本身多目标并发是常态) > 15 即告警

阈值应支持在 Web UI 中按设备/类别自定义调整,初始值仅作为默认基线,系统运行一段时间后可结合 F10 行为基线建模自动校准。

3.11.4 内网东西向流量监控(F34)

之前的设计默认只关注"内网设备→外网"的流量,但设备被入侵后攻击其他内网设备(如摄像头扫描NAS)不会经过网关的 WAN 侧,必须专门覆盖:

  • 采集范围调整:3.4.5 节的多网卡挂载天然覆盖了内网接口(wlan0/br0)上的全部双向流量,包括内网设备互相通信的流量,因此不需要新增挂载点,只需要在用户态处理逻辑上不要过滤掉目的地为内网地址的连接记录(容易被无意中当作"不关心的内部流量"而丢弃)。
  • 基线预期:大多数家用 IoT 设备之间本不应该互相通信(摄像头不需要主动连接冰箱),因此内网设备间出现的连接,尤其是由通常"哑设备"发起、指向其他设备管理端口(如22/23/80/445/3389)的连接,信号置信度较高,建议直接作为中高优先级告警,不需要像外网流量那样依赖复杂的统计模型。
  • 对家庭内网建议默认建立一份"允许通信矩阵"(如智能音箱可以连接路由器管理页面属正常,门锁不应该连接任何其他内网设备除了路由器本身),偏离矩阵即告警。

3.11.5 多信号加权评分模型(F37)

单一规则命中容易产生误报(比如设备访问一个从未访问过的新域名,很可能只是厂商推送了固件更新服务器变更),因此建议采用加权评分而非单一规则触发告警:

risk_score = Σ (信号权重 × 信号是否命中)

示例权重设计:
  威胁情报直接命中(域名/IP/JA3)     : 权重 50(单独命中即可判定高危)
  内网横向异常连接                   : 权重 40
  信标特征命中                       : 权重 25
  扇出/扫描特征命中                  : 权重 30
  DNS异常(DGA/隧道特征)              : 权重 20
  首次访问陌生目标                   : 权重 10
  异常地理位置                       : 权重 10
  非活跃时段通信                     : 权重 5
  JA3指纹与设备历史不符              : 权重 15

风险等级划分:
  score ≥ 50  → 高危(建议自动阻断,见3.11.6)
  30 ≤ score < 50 → 中危(告警,人工确认)
  15 ≤ score < 30 → 低危(记录,仅在Web UI展示,不主动推送告警)
  score < 15  → 不告警

权重和阈值应作为配置项而非硬编码,便于用户根据自己的误报/漏报容忍度调整;系统运行初期建议先以"只记录不阻断"模式观察一段时间,积累数据校准阈值后再启用自动响应。

3.11.6 高危事件自动响应联动(F38)

高危事件触发(risk_score ≥ 阈值)
        │
        ▼
  是否为高敏感设备(门锁/摄像头等,见3.5.3分级策略)?
        │                           │
      是                          否
        │                           │
        ▼                           ▼
 自动触发XDP阻断(复用F9出站白名单机制,
  临时封禁该设备除路由器管理口外的所有出站)   仅告警,推送通知(F13),
        │                          等待人工确认后手动阻断
        ▼
 记录阻断事件+触发原因快照(命中的具体规则、
  相关连接记录)到events表,便于事后审查
  • 自动阻断功能默认关闭,需要用户在 Web UI 显式启用,并可按设备/设备类别单独配置是否允许自动阻断,避免因误报导致设备被意外断网(尤其是像门锁这类设备,断网本身也可能带来使用风险,需要用户自行权衡)。
  • 阻断动作需要有明确的解除机制(Web UI 一键解除+可配置的自动解除超时,如 30 分钟后自动恢复网络并重新观察),避免误报导致设备长期失联而用户未察觉。
  • 所有自动响应动作均需完整记录审计日志(谁/什么规则/什么时间触发了阻断),保证可追溯。

3.12 实时抓包分析 GUI 设计(对应 F40-F44)

3.12.1 为什么是第二套独立 UI 而不是 Web UI 的一个页签

两套界面服务的是完全不同的使用场景,强行合并会让两边都变差:

Web 总览 UI(BeeEye-web) 实时分析 GUI(BeeEye-gui)
使用者 家庭成员 + 管理员 仅管理员
时间尺度 小时/天/周的聚合趋势 毫秒级的逐包时序
数据来源 SQLite/InfluxDB 中的历史记录 网卡上正在流过的实时帧
交互重心 看懂"发生了什么" 追查"具体是哪个字节"
失败代价 页面刷新即可 抓包中断会永久丢失现场

因此按 F42 拆成两个进程:

  • 独立进程、独立端口:BeeEye-agent 监听 :8080,BeeEye-gui 监听 :8081。
  • 独立前端产物:BeeEye-web/distBeeEye-gui/dist 分别构建,互不引用。
  • 不共享数据库连接:GUI 不打开 agent 的 SQLite,实时分析完全在内存中完成,因此 GUI 的任何负载都不会拖慢总览 UI 的查询,反之亦然。
  • 只共享编译期代码:两者都 import internal/dissectinternal/geoip 等包,这是源码级复用,不构成运行期耦合。

3.12.2 界面布局(三窗格)

沿用 Wireshark 的经典布局,降低已有经验用户的学习成本:

┌ 工具栏:接口选择 | ▶开始 ■停止 | 显示过滤器输入框 | 采集源标注 ┐
├──────────────────────────────────────────────────────────┤
│ 窗格1 包列表:No / Time / Source / Destination / Protocol / │
│               Length / Info,按协议着色,新包自动滚动          │
├────────────────────────────┬─────────────────────────────┤
│ 窗格2 协议字段树            │ 窗格3 十六进制转储             │
│ ▼ Ethernet II              │ 0000  3c 84 6a 11 00 02 ...  │
│ ▼ Internet Protocol v4     │ 0010  00 54 1a 2b 40 00 ...  │
│ ▼ Transmission Control     │                             │
│   ▼ TLS ClientHello        │ 选中字段对应的字节高亮显示      │
│       SNI / ALPN / JA3     │                             │
├────────────────────────────┴─────────────────────────────┤
│ 状态栏:已捕获 N 包 / 丢弃 M 包 / 显示 K 包 / 采集源 / 接口   │
└──────────────────────────────────────────────────────────┘

关键行为:选中协议树中的任一字段,窗格3 中对应的字节区间同步高亮——这要求解析器为每个字段记录 offset/length,而不仅仅是字段值。

3.12.3 采集源优先级与降级(F43)

统一的 live.Source 接口下有两种实现,按优先级自动选择:

优先级 实现 前提条件 说明
1 eBPF ringbuf 内核 ≥5.8 + BTF + CAP_BPF 生产路径,与 agent 共用 §3.4 的内核程序
2 AF_PACKET raw socket CAP_NET_RAW 当前默认;无 CGO、无 libpcap 依赖

2026-08-21 起不再有第三级兜底:两者都打不开时,live.Open/capsource.Open 直接返回错误,不合成任何数据。如实标注是硬性要求:当前生效的来源必须在 UI 状态栏明确显示(ebpf/af_packet/unavailable)。曾经存在过的模拟源会合成结构完整的真实以太网帧(经过同一套解析器)来兜底,但它终究不是这张网卡上真实发生的流量——把它呈现为真实抓包,比什么都不显示更糟糕,所以这条兜底路径已被整体移除,而不是仅仅要求标注。

3.12.4 显示过滤器语法(F41)

语法刻意做成 Wireshark 的子集,让已经会用 Wireshark 的人不必学第二套词汇:

tcp.port == 443 && !mdns
ip.addr == 192.168.1.0/24 and dns.qry.name contains "tuya"
tls.handshake.extensions_server_name matches "^ota\."
dns.flags.rcode == 3 || (tcp.flags.syn == 1 && tcp.flags.ack == 0)

支持:&& || !(及 and or not)、括号、== != > < >= <=containsmatches(正则)、地址字段上的 CIDR 匹配、裸协议名的存在性判断。

一处有意的分歧:本实现中 a != b 表示"a 的所有取值都不等于 b"。Wireshark 的 != 语义是"存在某个取值不等于 b",在 tcp.port 这类多值字段上会让 tcp.port != 443 对所有包都成立(因为另一端端口永远不是 443),几乎总是用户不想要的结果。这里取符合直觉的语义,!(a == b) 与之等价。

3.12.5 与 Web 总览 UI 的一致性约束

尽管两套 UI 独立运行,以下三点必须保持一致,否则同一份流量会在两个界面得出不同结论:

  1. 协议识别口径一致:两者都走 §3.5.4 的优先级链(明文解析 > ALPN > 端口表 > 未知),不得一边显示 "HTTPS" 另一边显示 "TCP 443"。
  2. 字段命名一致:GUI 的过滤器字段名与 Web UI 的检索字段名同源,ip.addr 在两边指的是同一件事。
  3. 国际化策略一致:界面外壳文案走 i18n(F18),但协议字段名(ip.srctls.handshake.type)保持技术标识符原样不翻译——它们是可输入的过滤器语法的一部分,翻译它们会让过滤器无法输入。

四、里程碑与实施顺序建议

状态口径:已完成 = 功能可运行且有测试覆盖;部分完成 = 核心路径可用但有明确缺口;进行中 = 正在实现;未开始。 逐条功能(F1-F44)的实现状态见 PROGRESS.md,该文件与代码同步更新。

阶段 内容 目标 状态
M1 基础流量可视化 部署 InfluxDB+Grafana,用现成工具(ntopng等)摸清现状设备与流量模式 部分完成 — 改用 SQLite + 自研 REST API 承载,InfluxDB/Grafana 未接入
M2 门锁/摄像头专项监控 针对高风险设备类别,单独实现 eBPF 采集+全量事件记录+基础告警 部分完成 — 内核态分级上报已实现并通过验证器,告警界面待建
M3 全量设备指纹识别框架 扩展至全部设备类型的被动指纹识别与分级监控策略 部分完成 — OUI/hostname/DHCP 55·60/mDNS/SSDP 采集齐备,指纹库匹配未接入
M4 DNS/GeoIP/协议识别与多维视图 实现域名映射、地理位置标注、协议识别,交付按IP/按协议视图与自研Web UI(含i18n与多主题) 进行中 — 后端 API 全部就绪,自研 Web 前端待建
M5 规则引擎与行为基线 完善异常检测规则库,引入行为基线建模 部分完成 — 规则引擎已实现,行为基线建模未开始
M6 入侵后异常行为检测 实现信标检测、扇出检测、内网东西向监控、多信号加权评分 已完成(后端) — 四类检测器均已实现并有单元测试
M7(可选) 主动防护能力 门锁/摄像头出站白名单、XDP主动阻断、高危事件自动响应联动 未开始
M8 实时抓包分析 GUI 交付独立进程的 Wireshark 式三窗格分析器,含显示过滤器与 PCAP 导出(F40-F44) 进行中 — 抓包源、协议解析器、过滤器引擎已完成并有测试,GUI 服务与前端待建

五、验收标准(示例)

  • 系统可自动发现并识别接入设备,准确归类至预定义类别(至少覆盖:电视/摄像头/NAS/路由器/门锁/手机/电脑/其他)
  • 门锁、摄像头类设备的全部出站连接均有事件记录,可在 Web UI 时间线中查询
  • 新设备接入 5 分钟内触发告警
  • 千兆内网流量峰值下,系统整体 CPU 占用 < 10%(4核平台基准)
  • Web UI 与 Grafana 面板均可在 Mac/Windows/iOS/Android 主流浏览器正常访问与渲染
  • 系统异常退出不影响宿主机路由转发功能
  • 通过配置文件指定的任意网卡接口(含非标准命名如 wlx*)均可正常挂载采集,且支持同时挂载 2 个以上接口并行工作
  • 流量记录中可正确区分来源接口(无线接入 vs 有线接入),多接口场景下无重复计数
  • Web UI 中英文切换后,全部界面文案(含图表标签、告警描述)均正确翻译,无遗留未翻译文案
  • Web UI 提供 6 套主题一键切换,切换后图表配色同步更新,且切换偏好可持久化(刷新/重新打开浏览器后保持)
  • 高对比无障碍主题的文字与背景对比度达到 WCAG 2.1 AA 标准(≥4.5:1)
  • 明文 DNS 查询(UDP 53)可正确解析出查询域名与解析结果 IP,并与发起设备正确关联
  • 对 DoH/DoT 场景,系统能识别"该设备正在使用加密DNS"并在 UI 明确提示查询内容不可见,不展示错误或猜测数据
  • 目标 IP 地理位置标注准确率达到所用离线 GeoIP 库的标称精度,内网/CGNAT地址正确标注为本地,不产生虚假地理位置
  • 应用层协议识别覆盖至少:HTTP/HTTPS/MQTT/CoAP/DNS/SSH,未知协议明确标注"未知"而非留空或报错
  • 按 IP 视图与按协议视图均可正常聚合展示,并与按设备视图的筛选条件联动一致
  • 多维组合检索(设备+IP+协议+端口+时间)可正确返回符合全部条件的记录,支持导出为 CSV/JSON
  • 内网设备间(东西向)通信记录被正常采集并可在 Web UI 查询,不因目的地为内网地址而被过滤丢弃
  • 模拟固定间隔周期性回连流量时,信标检测器可在设定的最小样本数内正确标记疑似信标,且对已知合法周期性行为(如NTP同步)不误报
  • 模拟短时间内对多个目标IP/端口发起连接时,扇出检测器可按设备类别差异化阈值正确触发告警
  • 多信号加权评分模型可正确计算风险分并按配置阈值划分高/中/低危等级,阈值可在配置中调整
  • 高危事件自动响应默认关闭,显式启用后可正确触发设备阻断,且阻断/解除操作均有完整审计日志可查
  • 实时分析 GUI 与 Web 总览 UI 可同时运行于不同端口,停止其中任一进程后另一进程仍可正常访问与工作
  • 实时分析 GUI 的包列表在抓包运行时持续刷新,选中任一包可展开完整协议字段树,并在十六进制窗格中高亮该字段对应字节
  • 显示过滤器可正确解析并生效于至少:字段等值/大小比较、containsmatches 正则、CIDR 匹配、逻辑组合与括号;语法错误时给出明确提示且不中断正在进行的抓包
  • 当前采集源(eBPF / AF_PACKET)在 GUI 状态栏如实标注,两者均不可用时如实报告"无数据",不存在合成数据可标注为真实抓包
  • 截断的抓包数据(受 snaplen 限制)不导致解析器崩溃,能解析多少展示多少
  • TLS ClientHello 可正确提取 SNI、ALPN 与 JA3,且同一客户端的多次握手 JA3 保持一致、不同 cipher 列表的 JA3 不同
  • 导出的 pcap 文件可被 Wireshark/tshark 正常打开且包内容一致