fix: architecture violations and pre-existing test bugs
- Remove JA4SENTINEL_LOG_LEVEL env override (architecture violation: log_level must be YAML-only) - Add TestLoadFromEnv_LogLevelIgnored test to verify env var is ignored - Fix yaml struct tags in api.Config/AppConfig/OutputConfig (yaml.v3 ignores json tags) - Fix isValidIP/isValidCIDR to use net.ParseIP/net.ParseCIDR for proper validation - Fix SLL packet parsing: use protoType from SLL header to select IPv4/IPv6 decoder - Fix TestLoadFromFile_ExcludeSourceIPs: t.Errorf → t.Fatalf to avoid nil dereference - Fix TestFromClientHello_NilPayload: use strings.HasPrefix for error message check - Fix TestValidate_ExcludeSourceIPs: add required FlowTimeoutSec/PacketBufferSize defaults Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@ -156,8 +156,7 @@ func (p *ParserImpl) Process(pkt api.RawPacket) (*api.TLSClientHello, error) {
|
||||
|
||||
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 (
|
||||
@ -165,43 +164,57 @@ func (p *ParserImpl) Process(pkt api.RawPacket) (*api.TLSClientHello, error) {
|
||||
LinkTypeLinuxSLL = 101
|
||||
SLL_HEADER_LEN = 16
|
||||
)
|
||||
|
||||
// Check if this is a Linux SLL packet
|
||||
|
||||
// For Linux SLL (cooked capture), strip the 16-byte SLL header and
|
||||
// decode directly as raw IP using the protocol type from the SLL header.
|
||||
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
|
||||
raw := pkt.Data[SLL_HEADER_LEN:]
|
||||
switch protoType {
|
||||
case 0x0800: // IPv4
|
||||
pkt4 := gopacket.NewPacket(raw, layers.LayerTypeIPv4, gopacket.Default)
|
||||
ipLayer = pkt4.Layer(layers.LayerTypeIPv4)
|
||||
if ipLayer != nil {
|
||||
tcpLayer = pkt4.Layer(layers.LayerTypeTCP)
|
||||
}
|
||||
case 0x86DD: // IPv6
|
||||
pkt6 := gopacket.NewPacket(raw, layers.LayerTypeIPv6, gopacket.Default)
|
||||
ipLayer = pkt6.Layer(layers.LayerTypeIPv6)
|
||||
if ipLayer != nil {
|
||||
tcpLayer = pkt6.Layer(layers.LayerTypeTCP)
|
||||
}
|
||||
}
|
||||
if ipLayer == nil {
|
||||
return nil, nil // Unsupported SLL protocol
|
||||
}
|
||||
} 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 parsing as raw IP
|
||||
// This handles stripped SLL data or other non-Ethernet formats
|
||||
if ipLayer == nil || tcpLayer == nil {
|
||||
// Try parsing as raw IPv4 packet
|
||||
rawPacket := gopacket.NewPacket(data, layers.LinkTypeIPv4, gopacket.Default)
|
||||
ipLayer = rawPacket.Layer(layers.LayerTypeIPv4)
|
||||
// Ethernet or unknown link type: try Ethernet first, then raw IP fallback.
|
||||
data := pkt.Data
|
||||
packet := gopacket.NewPacket(data, layers.LinkTypeEthernet, gopacket.Default)
|
||||
ipLayer = packet.Layer(layers.LayerTypeIPv4)
|
||||
if ipLayer == nil {
|
||||
// Try parsing as raw IPv6 packet
|
||||
rawPacket = gopacket.NewPacket(data, layers.LinkTypeIPv6, gopacket.Default)
|
||||
ipLayer = rawPacket.Layer(layers.LayerTypeIPv6)
|
||||
ipLayer = packet.Layer(layers.LayerTypeIPv6)
|
||||
}
|
||||
if ipLayer != nil {
|
||||
tcpLayer = rawPacket.Layer(layers.LayerTypeTCP)
|
||||
tcpLayer = packet.Layer(layers.LayerTypeTCP)
|
||||
|
||||
// If no IP/TCP layer found with Ethernet, try parsing as raw IP.
|
||||
// Use LayerTypeIPv4/IPv6 (not LinkTypeIPv4/IPv6) so gopacket decodes
|
||||
// the payload starting directly from the IP header.
|
||||
if ipLayer == nil || tcpLayer == nil {
|
||||
// Detect IP version from first nibble of first byte
|
||||
if len(data) > 0 && (data[0]>>4) == 4 {
|
||||
rawPacket := gopacket.NewPacket(data, layers.LayerTypeIPv4, gopacket.Default)
|
||||
ipLayer = rawPacket.Layer(layers.LayerTypeIPv4)
|
||||
if ipLayer != nil {
|
||||
tcpLayer = rawPacket.Layer(layers.LayerTypeTCP)
|
||||
}
|
||||
} else if len(data) > 0 && (data[0]>>4) == 6 {
|
||||
rawPacket := gopacket.NewPacket(data, layers.LayerTypeIPv6, gopacket.Default)
|
||||
ipLayer = rawPacket.Layer(layers.LayerTypeIPv6)
|
||||
if ipLayer != nil {
|
||||
tcpLayer = rawPacket.Layer(layers.LayerTypeTCP)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user