bcap/doc/api.md
2026-03-24 23:39:55 +08:00

12 KiB
Raw Permalink Blame History

bcap API 手册

开发者参考文档。快速接入说明见 ../README.md

1. 主包职责

主包负责:

  • 统一的报文事实层
  • 统一的 flow 表达
  • 统一的轻量 hint 层
  • 以 TCP 为重点的轻状态跟踪

主包不负责:

  • 报告生成
  • 业务规则判断
  • 用户侧展示文案
  • 动作编排
  • 深度流重组
  • 应用层协议解析框架

核心对象:

  • Decoder
    • 单包事实解码
  • Tracker
    • flow 状态与轻量提示
  • Analyzer
    • Decoder + Tracker 组合入口

2. 公开入口

2.1 Decoder

构造:

decoder := bcap.NewDecoder()

主要方法:

Decode(packet gopacket.Packet) (Packet, error)
DecodeWithOptions(packet gopacket.Packet, opts DecodeOptions) (Packet, error)

使用时机:

  • 只想获得单包事实
  • 自己维护状态机
  • 想把 bcap 当作标准化事实提取层

2.2 Tracker

构造:

tracker := bcap.NewTracker()
tracker := bcap.NewTrackerWithConfig(cfg)

主要方法:

Observe(packet Packet) (Observation, error)
CleanupExpiredFlows() int
ActiveFlowCount() int
Stop()

使用时机:

  • 已经在别处完成解码
  • 只想复用 bcap 的 flow / hint 跟踪能力

2.3 Analyzer

构造:

analyzer := bcap.NewAnalyzer()
analyzer := bcap.NewAnalyzerWithConfig(cfg)

主要方法:

ObservePacket(packet gopacket.Packet) (Observation, error)
ObservePacketWithOptions(packet gopacket.Packet, opts DecodeOptions) (Observation, error)
Decoder() *Decoder
Tracker() *Tracker
Stop()

使用时机:

  • 在线抓包
  • 离线遍历
  • 绝大多数直接接入型工具

3. DecodeOptions

DecodeOptions 目前包含两个字段:

type DecodeOptions struct {
    BaseTime       time.Time
    SrcMACOverride net.HardwareAddr
}

字段:

  • BaseTime
    • 用于计算 Packet.Meta.RelativeTime
    • Analyzer.ObservePacket(...) 未显式传入时,会自动以首包时间作为基准
  • SrcMACOverride
    • 用于覆盖源 MAC

4. 数据模型

4.1 Packet

Packet 表示单包事实。

type Packet struct {
    Meta      Meta
    Link      LinkFacts
    Network   NetworkFacts
    Transport TransportFacts
    Raw       RawFacts
}

不包含跨包推断结果。

4.2 Meta

type Meta struct {
    Timestamp       time.Time
    TimestampMicros int64
    RelativeTime    time.Duration
    CaptureLength   int
    Length          int
}

字段:

  • Timestamp / TimestampMicros
    • 捕获时间
  • RelativeTime
    • 相对 BaseTime 的时间差
  • CaptureLength
    • 实际捕获长度
  • Length
    • 原始报文长度

4.3 LinkFacts

type LinkFacts struct {
    Kind   LinkKind
    SrcMAC net.HardwareAddr
    DstMAC net.HardwareAddr
}

当前支持的链路类型:

  • LinkKindEthernet
  • LinkKindLinuxSLL
  • LinkKindLinuxSLL2
  • LinkKindUnknown

4.4 NetworkFacts

type NetworkFacts struct {
    Family         NetworkFamily
    SrcIP          string
    DstIP          string
    TTL            uint8
    HopLimit       uint8
    ProtocolNumber uint16
    ARP            *ARPFacts
}

当前支持的网络族:

  • NetworkFamilyIPv4
  • NetworkFamilyIPv6
  • NetworkFamilyARP
  • NetworkFamilyUnknown

备注:

  • IPv4 报文主要填 TTL
  • IPv6 报文主要填 HopLimit
  • ARP 报文会同时填充 ARP

4.5 TransportFacts

type TransportFacts struct {
    Kind    ProtocolKind
    Payload int
    TCP     *TCPFacts
    UDP     *UDPFacts
    ICMP    *ICMPFacts
    Unknown *UnknownTransportFacts
}

当前支持协议:

  • ProtocolTCP
  • ProtocolUDP
  • ProtocolICMPv4
  • ProtocolICMPv6
  • ProtocolARP
  • ProtocolUnknown

4.6 协议事实结构

TCPFacts

type TCPFacts struct {
    SrcPort  string
    DstPort  string
    Seq      uint32
    Ack      uint32
    Window   uint16
    SYN      bool
    ACK      bool
    FIN      bool
    RST      bool
    ECE      bool
    CWR      bool
    PSH      bool
    Checksum uint16
    Payload  int
}

UDPFacts

type UDPFacts struct {
    SrcPort string
    DstPort string
    Length  uint16
    Payload int
}

ICMPFacts

type ICMPFacts struct {
    Version  int
    Type     uint8
    Code     uint8
    Checksum uint16
    ID       uint16
    Seq      uint16
    Payload  int
}

ARPFacts

type ARPFacts struct {
    Operation uint16
    SenderMAC net.HardwareAddr
    TargetMAC net.HardwareAddr
    SenderIP  string
    TargetIP  string
}

4.7 FlowKey / FlowRef

推荐使用结构化 flow不把字符串 key 当成唯一公共接口。

type Endpoint struct {
    IP   string
    Port string
}

type FlowKey struct {
    Family   NetworkFamily
    Protocol ProtocolKind
    Src      Endpoint
    Dst      Endpoint
}

type FlowRef struct {
    Forward FlowKey
    Reverse FlowKey
    Stable  string
}

方法:

func (f FlowKey) StableString() string

字段:

  • Forward
    • 当前方向
  • Reverse
    • 反向方向
  • Stable
    • 稳定字符串表达,可用于日志和 map key

4.8 Observation

type Observation struct {
    Packet Packet
    Flow   FlowRef
    Hints  HintSet
}
  • Packet
    • 报文事实
  • Flow
    • 流引用
  • Hints
    • 推断结果

5. Hint 模型

5.1 HintSet

type HintSet struct {
    Summary SummaryHint
    Tags    []Tag

    TCP  *TCPHint
    UDP  *UDPHint
    ICMP *ICMPHint
    ARP  *ARPHint
}
  • Summary
    • 摘要代码
  • Tags
    • 标签集合
  • 协议专属 hint
    • 放在对应子结构中

5.2 TCP hints

type TCPHint struct {
    Phase             TCPPhase
    Event             TCPEvent
    LegacyState       uint8
    Seq               uint32
    Ack               uint32
    Window            uint16
    Payload           int
    Retransmission    bool
    Keepalive         bool
    KeepaliveResponse bool
    RST               bool
    ECE               bool
    CWR               bool
}

Phase

  • TCPPhaseHandshake
  • TCPPhaseEstablished
  • TCPPhaseTeardown
  • TCPPhaseSpecial
  • TCPPhaseUnknown

Event

  • TCPEventSYN
  • TCPEventSYNACK
  • TCPEventHandshakeACK
  • TCPEventACK
  • TCPEventRetransmission
  • TCPEventKeepalive
  • TCPEventKeepaliveResp
  • TCPEventFIN
  • TCPEventFINACK
  • TCPEventTeardownACK
  • TCPEventRST
  • TCPEventECE
  • TCPEventCWR
  • TCPEventUnknown

常见 Tag

  • TagTCPHandshakeSYN
  • TagTCPHandshakeSYNACK
  • TagTCPHandshakeACK
  • TagTCPTeardownFIN
  • TagTCPTeardownFINACK
  • TagTCPTeardownACK
  • TagTCPPacket
  • TagTCPRetransmit
  • TagTCPKeepalive
  • TagTCPKeepaliveResp
  • TagTCPRst
  • TagTCPEce
  • TagTCPCwr

5.3 UDP / ICMP / ARP hints

UDPHint

type UDPHint struct {
    Payload int
}

对应 Tag

  • TagUDPPacket

ICMPHint

type ICMPHint struct {
    Version        int
    Type           uint8
    Code           uint8
    IsEcho         bool
    IsEchoReply    bool
    IsUnreachable  bool
    IsTimeExceeded bool
}

对应 Tag

  • TagICMPPacket
  • TagICMPEchoRequest
  • TagICMPEchoReply
  • TagICMPUnreachable
  • TagICMPTimeExceeded

ARPHint

type ARPHint struct {
    Operation uint16
    Request   bool
    Reply     bool
}

对应 Tag

  • TagARPRequest
  • TagARPReply

6. TCP 跟踪边界

Tracker 对 TCP 只做轻量跟踪,不做完整 TCP 栈模拟。

当前覆盖:

  • 握手识别
  • 挥手识别
  • 普通 ACK 识别
  • 重传识别
  • keepalive 识别
  • keepalive response 识别
  • RST / ECE / CWR 识别

实现说明:

  • 基于 flow 跟踪
  • 使用有限 segment 记忆辅助判断重传
  • keepalive 使用启发式判断
  • 支持超时清理

不覆盖:

  • 严格 TCP 协议验证
  • 深度重组
  • 业务级根因结论

7. 配置

7.1 PacketsConfig

type PacketsConfig struct {
    ConnectionTimeout time.Duration
    CleanupInterval   time.Duration
}

字段:

  • ConnectionTimeout
    • flow 状态保留时长
  • CleanupInterval
    • 自动清理周期

默认值:

const (
    DefaultConnectionTimeout = 5 * time.Minute
    DefaultCleanupInterval   = 1 * time.Minute
)

默认配置:

cfg := bcap.DefaultConfig()

7.2 生命周期方法

Tracker

  • CleanupExpiredFlows() int
  • ActiveFlowCount() int
  • Stop()

Analyzer

  • Decoder() *Decoder
  • Tracker() *Tracker
  • Stop()

备注:

  • 长生命周期进程退出前调用 Stop()
  • 如需自行控制清理节奏,可将 CleanupInterval 设为 0,再手动调用 CleanupExpiredFlows()

8. 错误模型

bcap 使用 *ParseError 表达解析问题:

type ParseError struct {
    Type    ParseErrorType
    Layer   string
    Message string
    Err     error
}

错误类型:

  • ErrTypeLinkLayer
  • ErrTypeNetwork
  • ErrTypeTransport
  • ErrTypeUnsupported

常见触发条件:

  • 没有有效网络层
  • 协议层对象类型不匹配
  • 跟踪阶段缺少必须的协议事实

9. 子包

9.1 libpcap

libpcap 子包负责在线抓包输入。

入口:

  • FindAllDevs()
  • NewCatch(host, filter)
  • NewCatchEth(eth, filter)
  • SetRecall(func(gopacket.Packet))
  • Run()
  • Stop()

常见组合:

  • 子包接收 gopacket.Packet
  • 主包 Analyzer 做解析和提示
  • 上层工具做展示和统计

9.2 nfq

nfq 子包负责 NFQUEUE 输入适配。

入口:

  • NewNfQueue(ctx, queid, maxqueue)
  • SetRecall(func(id uint32, q *nfqueue.Nfqueue, p Packet))
  • Run()
  • Stop()

备注:

  • nfq.Packet 只是 NFQUEUE 输入包装
  • 它不是主包的 bcap.Packet
  • 一般仍然从其中取 gopacket.Packet,再交给 AnalyzerDecoder

10. 示例

10.1 直接用 Analyzer

analyzer := bcap.NewAnalyzer()
defer analyzer.Stop()

obs, err := analyzer.ObservePacket(packet)
if err != nil {
	return err
}

fmt.Println(obs.Flow.Stable)
fmt.Println(obs.Packet.Transport.Kind)
fmt.Println(obs.Hints.Summary.Code)

10.2 自己管理解码和跟踪

decoder := bcap.NewDecoder()
tracker := bcap.NewTracker()
defer tracker.Stop()

decoded, err := decoder.DecodeWithOptions(packet, bcap.DecodeOptions{
	BaseTime: firstPacketTS,
})
if err != nil {
	return err
}

obs, err := tracker.Observe(decoded)
if err != nil {
	return err
}

10.3 典型离线遍历

f, err := os.Open("sample.pcap")
if err != nil {
	return err
}
defer f.Close()

reader, err := pcapgo.NewReader(f)
if err != nil {
	return err
}

source := gopacket.NewPacketSource(reader, reader.LinkType())
analyzer := bcap.NewAnalyzer()
defer analyzer.Stop()

for packet := range source.Packets() {
	obs, err := analyzer.ObservePacket(packet)
	if err != nil {
		continue
	}
	fmt.Println(obs.Packet.Network.SrcIP, obs.Hints.Summary.Code)
}

11. 辅助函数

主包还提供两个轻量格式化函数:

  • FormatDuration(time.Duration) string
  • FormatBytes(uint64) string

用于轻量日志与终端展示。

12. 迁移说明

主包旧接口已经被清理,删除项包括:

  • Packets
  • PacketInfo
  • ParsePacket
  • NewPackets
  • NewPacketsWithConfig
  • LegacyPacketInfoFromObservation
  • GetStateDescription
  • PrintStats
  • ExportConnectionsToJSON

迁移方向:

  • 旧的单包解析入口迁到 Decoder
  • 旧的“包 + 状态”混合对象迁到 Observation
  • 旧的连接跟踪职责迁到 Tracker
  • 大部分调用场景直接迁到 Analyzer

旧代码如果大量依赖字符串 key

  • 新代码优先改为使用 FlowRef.Forward / FlowRef.Reverse
  • 如果只是为了日志或 map key可以继续使用 FlowRef.Stable

13. 相关文档