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

727 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# bcap API 手册
开发者参考文档。快速接入说明见 [`../README.md`](../README.md)。
## 1. 主包职责
主包负责:
- 统一的报文事实层
- 统一的 flow 表达
- 统一的轻量 hint 层
- 以 TCP 为重点的轻状态跟踪
主包不负责:
- 报告生成
- 业务规则判断
- 用户侧展示文案
- 动作编排
- 深度流重组
- 应用层协议解析框架
核心对象:
- `Decoder`
- 单包事实解码
- `Tracker`
- flow 状态与轻量提示
- `Analyzer`
- `Decoder + Tracker` 组合入口
## 2. 公开入口
### 2.1 `Decoder`
构造:
```go
decoder := bcap.NewDecoder()
```
主要方法:
```go
Decode(packet gopacket.Packet) (Packet, error)
DecodeWithOptions(packet gopacket.Packet, opts DecodeOptions) (Packet, error)
```
使用时机:
- 只想获得单包事实
- 自己维护状态机
- 想把 `bcap` 当作标准化事实提取层
### 2.2 `Tracker`
构造:
```go
tracker := bcap.NewTracker()
tracker := bcap.NewTrackerWithConfig(cfg)
```
主要方法:
```go
Observe(packet Packet) (Observation, error)
CleanupExpiredFlows() int
ActiveFlowCount() int
Stop()
```
使用时机:
- 已经在别处完成解码
- 只想复用 `bcap` 的 flow / hint 跟踪能力
### 2.3 `Analyzer`
构造:
```go
analyzer := bcap.NewAnalyzer()
analyzer := bcap.NewAnalyzerWithConfig(cfg)
```
主要方法:
```go
ObservePacket(packet gopacket.Packet) (Observation, error)
ObservePacketWithOptions(packet gopacket.Packet, opts DecodeOptions) (Observation, error)
Decoder() *Decoder
Tracker() *Tracker
Stop()
```
使用时机:
- 在线抓包
- 离线遍历
- 绝大多数直接接入型工具
## 3. `DecodeOptions`
`DecodeOptions` 目前包含两个字段:
```go
type DecodeOptions struct {
BaseTime time.Time
SrcMACOverride net.HardwareAddr
}
```
字段:
- `BaseTime`
- 用于计算 `Packet.Meta.RelativeTime`
- `Analyzer.ObservePacket(...)` 未显式传入时,会自动以首包时间作为基准
- `SrcMACOverride`
- 用于覆盖源 MAC
## 4. 数据模型
### 4.1 `Packet`
`Packet` 表示单包事实。
```go
type Packet struct {
Meta Meta
Link LinkFacts
Network NetworkFacts
Transport TransportFacts
Raw RawFacts
}
```
不包含跨包推断结果。
### 4.2 `Meta`
```go
type Meta struct {
Timestamp time.Time
TimestampMicros int64
RelativeTime time.Duration
CaptureLength int
Length int
}
```
字段:
- `Timestamp` / `TimestampMicros`
- 捕获时间
- `RelativeTime`
- 相对 `BaseTime` 的时间差
- `CaptureLength`
- 实际捕获长度
- `Length`
- 原始报文长度
### 4.3 `LinkFacts`
```go
type LinkFacts struct {
Kind LinkKind
SrcMAC net.HardwareAddr
DstMAC net.HardwareAddr
}
```
当前支持的链路类型:
- `LinkKindEthernet`
- `LinkKindLinuxSLL`
- `LinkKindLinuxSLL2`
- `LinkKindUnknown`
### 4.4 `NetworkFacts`
```go
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`
```go
type TransportFacts struct {
Kind ProtocolKind
Payload int
TCP *TCPFacts
UDP *UDPFacts
ICMP *ICMPFacts
Unknown *UnknownTransportFacts
}
```
当前支持协议:
- `ProtocolTCP`
- `ProtocolUDP`
- `ProtocolICMPv4`
- `ProtocolICMPv6`
- `ProtocolARP`
- `ProtocolUnknown`
### 4.6 协议事实结构
#### `TCPFacts`
```go
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`
```go
type UDPFacts struct {
SrcPort string
DstPort string
Length uint16
Payload int
}
```
#### `ICMPFacts`
```go
type ICMPFacts struct {
Version int
Type uint8
Code uint8
Checksum uint16
ID uint16
Seq uint16
Payload int
}
```
#### `ARPFacts`
```go
type ARPFacts struct {
Operation uint16
SenderMAC net.HardwareAddr
TargetMAC net.HardwareAddr
SenderIP string
TargetIP string
}
```
### 4.7 `FlowKey` / `FlowRef`
推荐使用结构化 flow不把字符串 key 当成唯一公共接口。
```go
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
}
```
方法:
```go
func (f FlowKey) StableString() string
```
字段:
- `Forward`
- 当前方向
- `Reverse`
- 反向方向
- `Stable`
- 稳定字符串表达,可用于日志和 map key
### 4.8 `Observation`
```go
type Observation struct {
Packet Packet
Flow FlowRef
Hints HintSet
}
```
- `Packet`
- 报文事实
- `Flow`
- 流引用
- `Hints`
- 推断结果
## 5. Hint 模型
### 5.1 `HintSet`
```go
type HintSet struct {
Summary SummaryHint
Tags []Tag
TCP *TCPHint
UDP *UDPHint
ICMP *ICMPHint
ARP *ARPHint
}
```
- `Summary`
- 摘要代码
- `Tags`
- 标签集合
- 协议专属 hint
- 放在对应子结构中
### 5.2 TCP hints
```go
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`
```go
type UDPHint struct {
Payload int
}
```
对应 Tag
- `TagUDPPacket`
#### `ICMPHint`
```go
type ICMPHint struct {
Version int
Type uint8
Code uint8
IsEcho bool
IsEchoReply bool
IsUnreachable bool
IsTimeExceeded bool
}
```
对应 Tag
- `TagICMPPacket`
- `TagICMPEchoRequest`
- `TagICMPEchoReply`
- `TagICMPUnreachable`
- `TagICMPTimeExceeded`
#### `ARPHint`
```go
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`
```go
type PacketsConfig struct {
ConnectionTimeout time.Duration
CleanupInterval time.Duration
}
```
字段:
- `ConnectionTimeout`
- flow 状态保留时长
- `CleanupInterval`
- 自动清理周期
默认值:
```go
const (
DefaultConnectionTimeout = 5 * time.Minute
DefaultCleanupInterval = 1 * time.Minute
)
```
默认配置:
```go
cfg := bcap.DefaultConfig()
```
### 7.2 生命周期方法
`Tracker`
- `CleanupExpiredFlows() int`
- `ActiveFlowCount() int`
- `Stop()`
`Analyzer`
- `Decoder() *Decoder`
- `Tracker() *Tracker`
- `Stop()`
备注:
- 长生命周期进程退出前调用 `Stop()`
- 如需自行控制清理节奏,可将 `CleanupInterval` 设为 `0`,再手动调用 `CleanupExpiredFlows()`
## 8. 错误模型
`bcap` 使用 `*ParseError` 表达解析问题:
```go
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`,再交给 `Analyzer``Decoder`
## 10. 示例
### 10.1 直接用 `Analyzer`
```go
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 自己管理解码和跟踪
```go
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 典型离线遍历
```go
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. 相关文档
- 快速入口见 [`../README.md`](../README.md)
- 设计备忘见 [`dev.md`](./dev.md)