feature: 1.1.18
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
Some checks failed
Build RPM Package / Build RPM Packages (CentOS 7, Rocky 8/9/10) (push) Has been cancelled
+- FEATURE: Add comprehensive metrics for capture and TLS parser monitoring +- Capture metrics: packets_received, packets_sent, packets_dropped (atomic counters) +- Parser metrics: retransmit_count, gap_detected_count, buffer_exceeded_count, segment_exceeded_count +- New GetStats() method on Capture interface for capture statistics +- New GetMetrics() method on Parser interface for parser statistics +- Add DefaultMaxHelloSegments constant (100) to prevent memory leaks from fragmented handshakes +- Add Segments field to ConnectionFlow for per-flow segment tracking +- Increase DefaultMaxTrackedFlows from 50000 to 100000 for high-traffic scenarios +- Improve TCP reassembly: better handling of retransmissions and sequence gaps +- Memory leak prevention: limit segments per flow and buffer size +- Aggressive flow cleanup: clean up JA4_DONE flows when approaching flow limit +- Lock ordering fix: release flow.mu before acquiring p.mu to avoid deadlocks +- Exclude IPv6 link-local addresses (fe80::) from local IP detection +- Improve error logging with detailed connection and TLS extension information +- Add capture diagnostics logging (interface, link_type, local_ips, bpf_filter) +- Fix false positive retransmission counter when SYN packet is missed +- Fix gap handling: reset sequence tracking instead of dropping flow +- Fix extractTLSExtensions: return error details with basic TLS info for debugging
This commit is contained in:
@ -503,17 +503,15 @@ func TestExtractTLSExtensions(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := extractTLSExtensions(tt.payload)
|
||||
if err != nil {
|
||||
t.Errorf("extractTLSExtensions() unexpected error = %v", err)
|
||||
return
|
||||
}
|
||||
if (got == nil) != tt.wantNil {
|
||||
t.Errorf("extractTLSExtensions() = %v, wantNil %v", got == nil, tt.wantNil)
|
||||
got, _ := extractTLSExtensions(tt.payload)
|
||||
// For empty/too short payloads, nil is acceptable
|
||||
// For valid ClientHellos, got should contain at least partial info
|
||||
if !tt.wantNil && got == nil {
|
||||
t.Errorf("extractTLSExtensions() = %v, want non-nil with partial info", got)
|
||||
return
|
||||
}
|
||||
if got != nil {
|
||||
if got.TLSVersion != tt.wantVersion {
|
||||
if got.TLSVersion != tt.wantVersion && tt.wantVersion != "" {
|
||||
t.Errorf("TLSVersion = %v, want %v", got.TLSVersion, tt.wantVersion)
|
||||
}
|
||||
}
|
||||
@ -1661,13 +1659,18 @@ func TestProcess_TCPGap_DropsFlow(t *testing.T) {
|
||||
t.Fatal("Process(gap) should return nil")
|
||||
}
|
||||
|
||||
// Verify flow was removed
|
||||
// Verify flow was NOT removed (gap handling now continues with available data)
|
||||
key := flowKey(srcIP, srcPort, dstIP, dstPort)
|
||||
parser.mu.RLock()
|
||||
_, exists := parser.flows[key]
|
||||
parser.mu.RUnlock()
|
||||
if exists {
|
||||
t.Fatal("flow should be removed after sequence gap")
|
||||
if !exists {
|
||||
t.Fatal("flow should NOT be removed after sequence gap (gap handling changed)")
|
||||
}
|
||||
// Verify gap was detected (counter incremented)
|
||||
_, gapDetected, _, _ := parser.GetMetrics()
|
||||
if gapDetected == 0 {
|
||||
t.Fatal("gapDetected counter should be incremented")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1790,3 +1793,32 @@ func TestProcess_TLS13ClientHello_CorrectVersion(t *testing.T) {
|
||||
t.Errorf("SNI = %q, want \"tls13.example.com\"", result.SNI)
|
||||
}
|
||||
}
|
||||
|
||||
// TestProcess_MissedSYN_NoFalseRetransmit verifies Bug 7 fix:
|
||||
// when SYN is missed, the first data packet must NOT increment retransmitCount
|
||||
// even though seq < NextSeq would evaluate to true (because NextSeq was
|
||||
// initialised from that very same packet).
|
||||
func TestProcess_MissedSYN_NoFalseRetransmit(t *testing.T) {
|
||||
parser := NewParser()
|
||||
defer parser.Close()
|
||||
|
||||
srcIP := "10.0.0.1"
|
||||
dstIP := "10.0.0.2"
|
||||
srcPort := uint16(12345)
|
||||
dstPort := uint16(443)
|
||||
|
||||
// Build a minimal TLS ClientHello payload.
|
||||
payload := createMinimalTLSClientHelloWithSNIAndALPN("test.example.com", nil)
|
||||
|
||||
// Send without a preceding SYN — seq starts from 100.
|
||||
pkt := buildRawPacketWithSeq(t, srcIP, dstIP, srcPort, dstPort, payload, 100)
|
||||
_, err := parser.Process(pkt)
|
||||
if err != nil {
|
||||
t.Fatalf("Process() error: %v", err)
|
||||
}
|
||||
|
||||
retransmit, _, _, _ := parser.GetMetrics()
|
||||
if retransmit != 0 {
|
||||
t.Errorf("retransmitCount = %d after first packet on a new flow (SYN missed); want 0", retransmit)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user