release: version 1.1.6 - Add local IP filtering and SLL support
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled

Features:
- Add local_ips configuration option for filtering traffic to local machine
- Auto-detection of local IP addresses (excludes loopback 127.x.x.x, ::1)
- Support interface 'any' for capturing on all network interfaces
- Add Linux SLL (cooked capture) support for interface 'any'
- Generate BPF filter with 'dst host' for local IP filtering
- Add LinkType field to RawPacket for proper packet parsing

Testing:
- Add unit tests for local IP detection (detectLocalIPs, extractIP)
- Add unit tests for SLL packet parsing (IPv4 and IPv6)
- Update capture tests for new packetToRawPacket method

Configuration:
- Update config.yml.example with local_ips documentation
- Update RPM spec to version 1.1.6 with changelog

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
toto
2026-03-04 11:02:53 +01:00
parent 96372e6181
commit 027730b360
8 changed files with 714 additions and 67 deletions

View File

@ -128,20 +128,73 @@ func (p *ParserImpl) Process(pkt api.RawPacket) (*api.TLSClientHello, error) {
return nil, fmt.Errorf("empty packet data")
}
// Parse packet layers
packet := gopacket.NewPacket(pkt.Data, layers.LinkTypeEthernet, gopacket.Default)
// Get IP layer
ipLayer := packet.Layer(layers.LayerTypeIPv4)
var ipLayer gopacket.Layer
var tcpLayer gopacket.Layer
var data []byte
// Handle different link types
// LinkType 1 = Ethernet, LinkType 101 = Linux SLL (cooked capture)
const (
LinkTypeEthernet = 1
LinkTypeLinuxSLL = 101
SLL_HEADER_LEN = 16
)
// Check if this is a Linux SLL packet
if pkt.LinkType == LinkTypeLinuxSLL && len(pkt.Data) >= SLL_HEADER_LEN {
// Verify SLL protocol type (bytes 12-13, big-endian)
protoType := uint16(pkt.Data[12])<<8 | uint16(pkt.Data[13])
if protoType == 0x0800 || protoType == 0x86DD {
// Strip SLL header and parse as raw IP
data = pkt.Data[SLL_HEADER_LEN:]
} else {
data = pkt.Data
}
} else {
// Ethernet or unknown - use data as-is
data = pkt.Data
}
// Try parsing with Ethernet first (for physical interfaces)
packet := gopacket.NewPacket(data, layers.LinkTypeEthernet, gopacket.Default)
ipLayer = packet.Layer(layers.LayerTypeIPv4)
if ipLayer == nil {
ipLayer = packet.Layer(layers.LayerTypeIPv6)
}
tcpLayer = packet.Layer(layers.LayerTypeTCP)
// If no IP/TCP layer found with Ethernet, try direct IP decoding
// This handles raw IP data (e.g., after stripping SLL header)
if ipLayer == nil || tcpLayer == nil {
// Try IPv4
ipv4 := &layers.IPv4{}
if err := ipv4.DecodeFromBytes(data, nil); err == nil {
ipLayer = ipv4
// Try to decode TCP from IPv4 payload
tcp := &layers.TCP{}
if err := tcp.DecodeFromBytes(ipv4.Payload, nil); err == nil {
tcpLayer = tcp
}
}
}
// Try IPv6 if IPv4 didn't work
if ipLayer == nil {
ipv6 := &layers.IPv6{}
if err := ipv6.DecodeFromBytes(data, nil); err == nil {
ipLayer = ipv6
// Try to decode TCP from IPv6 payload
tcp := &layers.TCP{}
if err := tcp.DecodeFromBytes(ipv6.Payload, nil); err == nil {
tcpLayer = tcp
}
}
}
if ipLayer == nil {
return nil, nil // Not an IP packet
}
// Get TCP layer
tcpLayer := packet.Layer(layers.LayerTypeTCP)
if tcpLayer == nil {
return nil, nil // Not a TCP packet
}