12 KiB
12 KiB
bcap API 手册
开发者参考文档。快速接入说明见 ../README.md。
1. 主包职责
主包负责:
- 统一的报文事实层
- 统一的 flow 表达
- 统一的轻量 hint 层
- 以 TCP 为重点的轻状态跟踪
主包不负责:
- 报告生成
- 业务规则判断
- 用户侧展示文案
- 动作编排
- 深度流重组
- 应用层协议解析框架
核心对象:
Decoder- 单包事实解码
Tracker- flow 状态与轻量提示
AnalyzerDecoder + 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
}
当前支持的链路类型:
LinkKindEthernetLinkKindLinuxSLLLinkKindLinuxSLL2LinkKindUnknown
4.4 NetworkFacts
type NetworkFacts struct {
Family NetworkFamily
SrcIP string
DstIP string
TTL uint8
HopLimit uint8
ProtocolNumber uint16
ARP *ARPFacts
}
当前支持的网络族:
NetworkFamilyIPv4NetworkFamilyIPv6NetworkFamilyARPNetworkFamilyUnknown
备注:
- IPv4 报文主要填
TTL - IPv6 报文主要填
HopLimit - ARP 报文会同时填充
ARP
4.5 TransportFacts
type TransportFacts struct {
Kind ProtocolKind
Payload int
TCP *TCPFacts
UDP *UDPFacts
ICMP *ICMPFacts
Unknown *UnknownTransportFacts
}
当前支持协议:
ProtocolTCPProtocolUDPProtocolICMPv4ProtocolICMPv6ProtocolARPProtocolUnknown
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:
TCPPhaseHandshakeTCPPhaseEstablishedTCPPhaseTeardownTCPPhaseSpecialTCPPhaseUnknown
Event:
TCPEventSYNTCPEventSYNACKTCPEventHandshakeACKTCPEventACKTCPEventRetransmissionTCPEventKeepaliveTCPEventKeepaliveRespTCPEventFINTCPEventFINACKTCPEventTeardownACKTCPEventRSTTCPEventECETCPEventCWRTCPEventUnknown
常见 Tag:
TagTCPHandshakeSYNTagTCPHandshakeSYNACKTagTCPHandshakeACKTagTCPTeardownFINTagTCPTeardownFINACKTagTCPTeardownACKTagTCPPacketTagTCPRetransmitTagTCPKeepaliveTagTCPKeepaliveRespTagTCPRstTagTCPEceTagTCPCwr
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:
TagICMPPacketTagICMPEchoRequestTagICMPEchoReplyTagICMPUnreachableTagICMPTimeExceeded
ARPHint
type ARPHint struct {
Operation uint16
Request bool
Reply bool
}
对应 Tag:
TagARPRequestTagARPReply
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() intActiveFlowCount() intStop()
Analyzer:
Decoder() *DecoderTracker() *TrackerStop()
备注:
- 长生命周期进程退出前调用
Stop() - 如需自行控制清理节奏,可将
CleanupInterval设为0,再手动调用CleanupExpiredFlows()
8. 错误模型
bcap 使用 *ParseError 表达解析问题:
type ParseError struct {
Type ParseErrorType
Layer string
Message string
Err error
}
错误类型:
ErrTypeLinkLayerErrTypeNetworkErrTypeTransportErrTypeUnsupported
常见触发条件:
- 没有有效网络层
- 协议层对象类型不匹配
- 跟踪阶段缺少必须的协议事实
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
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) stringFormatBytes(uint64) string
用于轻量日志与终端展示。
12. 迁移说明
主包旧接口已经被清理,删除项包括:
PacketsPacketInfoParsePacketNewPacketsNewPacketsWithConfigLegacyPacketInfoFromObservationGetStateDescriptionPrintStatsExportConnectionsToJSON
迁移方向:
- 旧的单包解析入口迁到
Decoder - 旧的“包 + 状态”混合对象迁到
Observation - 旧的连接跟踪职责迁到
Tracker - 大部分调用场景直接迁到
Analyzer
旧代码如果大量依赖字符串 key:
- 新代码优先改为使用
FlowRef.Forward/FlowRef.Reverse - 如果只是为了日志或 map key,可以继续使用
FlowRef.Stable
13. 相关文档
- 快速入口见
../README.md - 设计备忘见
dev.md