release: version 1.0.9 - Add SNI, ALPN, TLS version extraction and architecture.yml compliance
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
New features: - Extract SNI (Server Name Indication) from TLS ClientHello - Extract ALPN (Application-Layer Protocol Negotiation) protocols - Detect TLS version from ClientHello using tlsfingerprint library - Add ConnID field for TCP flow correlation - Add SensorID field for multi-sensor deployments - Add SynToCHMs timing field for behavioral detection - Add AsyncBuffer configuration for output queue sizing Architecture changes: - Remove JA4Hash from LogRecord (JA4 format includes its own hash portions) - Update api.TLSClientHello with new TLS metadata fields - Update api.LogRecord with correlation, TLS, and timing fields - Ensure 100% compliance with architecture.yml specification Tests: - Add unit tests for TLS extension extraction (SNI, ALPN, Version) - Update tests for new LogRecord schema without JA4Hash - Add tests for AsyncBuffer configuration Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@ -45,3 +45,91 @@ func TestNewEngine(t *testing.T) {
|
||||
t.Error("NewEngine() returned nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFromClientHello_ValidPayload(t *testing.T) {
|
||||
// Use a minimal valid TLS 1.2 ClientHello with extensions
|
||||
// Build a proper ClientHello using the same structure as parser tests
|
||||
clientHello := buildMinimalClientHelloForTest()
|
||||
|
||||
ch := api.TLSClientHello{
|
||||
SrcIP: "192.168.1.100",
|
||||
SrcPort: 54321,
|
||||
DstIP: "10.0.0.1",
|
||||
DstPort: 443,
|
||||
Payload: clientHello,
|
||||
}
|
||||
|
||||
engine := NewEngine()
|
||||
fp, err := engine.FromClientHello(ch)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("FromClientHello() error = %v", err)
|
||||
}
|
||||
if fp == nil {
|
||||
t.Fatal("FromClientHello() returned nil")
|
||||
}
|
||||
|
||||
// Verify JA4 is populated (format: t13d... or t12d...)
|
||||
if fp.JA4 == "" {
|
||||
t.Error("JA4 should not be empty")
|
||||
}
|
||||
|
||||
// JA4Hash is populated for internal use (but not serialized to LogRecord)
|
||||
// It contains the hash portions of the JA4 string
|
||||
if fp.JA4Hash == "" {
|
||||
t.Error("JA4Hash should be populated for internal use")
|
||||
}
|
||||
}
|
||||
|
||||
// buildMinimalClientHelloForTest creates a minimal valid TLS 1.2 ClientHello
|
||||
func buildMinimalClientHelloForTest() []byte {
|
||||
// Cipher suites (minimal set)
|
||||
cipherSuites := []byte{0x00, 0x04, 0x13, 0x01, 0x13, 0x02, 0xc0, 0x2f}
|
||||
// Compression methods (null only)
|
||||
compressionMethods := []byte{0x01, 0x00}
|
||||
// No extensions
|
||||
extensions := []byte{}
|
||||
extLen := len(extensions)
|
||||
|
||||
// Build ClientHello handshake body
|
||||
handshakeBody := []byte{
|
||||
0x03, 0x03, // Version: TLS 1.2
|
||||
// Random (32 bytes)
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, // Session ID length: 0
|
||||
}
|
||||
|
||||
// Add cipher suites (with length prefix)
|
||||
cipherSuiteLen := len(cipherSuites)
|
||||
handshakeBody = append(handshakeBody, byte(cipherSuiteLen>>8), byte(cipherSuiteLen))
|
||||
handshakeBody = append(handshakeBody, cipherSuites...)
|
||||
|
||||
// Add compression methods (with length prefix)
|
||||
handshakeBody = append(handshakeBody, compressionMethods...)
|
||||
|
||||
// Add extensions (with length prefix)
|
||||
handshakeBody = append(handshakeBody, byte(extLen>>8), byte(extLen))
|
||||
handshakeBody = append(handshakeBody, extensions...)
|
||||
|
||||
// Now build full handshake with type and length
|
||||
handshakeLen := len(handshakeBody)
|
||||
handshake := append([]byte{
|
||||
0x01, // Handshake type: ClientHello
|
||||
byte(handshakeLen >> 16), byte(handshakeLen >> 8), byte(handshakeLen), // Handshake length
|
||||
}, handshakeBody...)
|
||||
|
||||
// Build TLS record
|
||||
recordLen := len(handshake)
|
||||
record := make([]byte, 5+recordLen)
|
||||
record[0] = 0x16 // Handshake
|
||||
record[1] = 0x03 // Version: TLS 1.2
|
||||
record[2] = 0x03
|
||||
record[3] = byte(recordLen >> 8)
|
||||
record[4] = byte(recordLen)
|
||||
copy(record[5:], handshake)
|
||||
|
||||
return record
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user