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:
56
api/types.go
56
api/types.go
@ -50,19 +50,26 @@ type RawPacket struct {
|
||||
|
||||
// TLSClientHello represents a client-side TLS ClientHello with IP/TCP metadata
|
||||
type TLSClientHello struct {
|
||||
SrcIP string `json:"src_ip"`
|
||||
SrcPort uint16 `json:"src_port"`
|
||||
DstIP string `json:"dst_ip"`
|
||||
DstPort uint16 `json:"dst_port"`
|
||||
Payload []byte `json:"-"` // Not serialized
|
||||
IPMeta IPMeta `json:"ip_meta"`
|
||||
TCPMeta TCPMeta `json:"tcp_meta"`
|
||||
SrcIP string `json:"src_ip"`
|
||||
SrcPort uint16 `json:"src_port"`
|
||||
DstIP string `json:"dst_ip"`
|
||||
DstPort uint16 `json:"dst_port"`
|
||||
Payload []byte `json:"-"` // Not serialized
|
||||
IPMeta IPMeta `json:"ip_meta"`
|
||||
TCPMeta TCPMeta `json:"tcp_meta"`
|
||||
ConnID string `json:"conn_id,omitempty"` // Unique flow identifier
|
||||
SNI string `json:"tls_sni,omitempty"` // Server Name Indication
|
||||
ALPN string `json:"tls_alpn,omitempty"` // Application-Layer Protocol Negotiation
|
||||
TLSVersion string `json:"tls_version,omitempty"` // Max TLS version supported
|
||||
SynToCHMs *uint32 `json:"syn_to_clienthello_ms,omitempty"` // Time from SYN to ClientHello (ms)
|
||||
}
|
||||
|
||||
// Fingerprints contains TLS fingerprints for a client flow
|
||||
// Note: JA4Hash is kept for internal use but not serialized to LogRecord
|
||||
// as the JA4 format already includes its own hash portions
|
||||
type Fingerprints struct {
|
||||
JA4 string `json:"ja4"`
|
||||
JA4Hash string `json:"ja4_hash"`
|
||||
JA4Hash string `json:"ja4_hash,omitempty"` // Internal use, not serialized to LogRecord
|
||||
JA3 string `json:"ja3,omitempty"`
|
||||
JA3Hash string `json:"ja3_hash,omitempty"`
|
||||
}
|
||||
@ -81,14 +88,26 @@ type LogRecord struct {
|
||||
IPDF bool `json:"ip_meta_df"`
|
||||
|
||||
// Flattened TCPMeta fields
|
||||
TCPWindow uint16 `json:"tcp_meta_window_size"`
|
||||
TCPWindow uint16 `json:"tcp_meta_window_size"`
|
||||
TCPMSS *uint16 `json:"tcp_meta_mss,omitempty"`
|
||||
TCPWScale *uint8 `json:"tcp_meta_window_scale,omitempty"`
|
||||
TCPOptions string `json:"tcp_meta_options"` // comma-separated list
|
||||
TCPOptions string `json:"tcp_meta_options"` // comma-separated list
|
||||
|
||||
// Correlation & Triage
|
||||
ConnID string `json:"conn_id,omitempty"` // Unique flow identifier
|
||||
SensorID string `json:"sensor_id,omitempty"` // Sensor/captor identifier
|
||||
|
||||
// TLS elements (ClientHello)
|
||||
TLSVersion string `json:"tls_version,omitempty"` // Max TLS version announced by client
|
||||
SNI string `json:"tls_sni,omitempty"` // Server Name Indication
|
||||
ALPN string `json:"tls_alpn,omitempty"` // Application-Layer Protocol Negotiation
|
||||
|
||||
// Behavioral detection (Timing)
|
||||
SynToCHMs *uint32 `json:"syn_to_clienthello_ms,omitempty"` // Time from SYN to ClientHello (ms)
|
||||
|
||||
// Fingerprints
|
||||
// Note: ja4_hash is NOT included - the JA4 format already includes its own hash portions
|
||||
JA4 string `json:"ja4"`
|
||||
JA4Hash string `json:"ja4_hash"`
|
||||
JA3 string `json:"ja3,omitempty"`
|
||||
JA3Hash string `json:"ja3_hash,omitempty"`
|
||||
|
||||
@ -98,9 +117,10 @@ type LogRecord struct {
|
||||
|
||||
// OutputConfig defines configuration for a single log output
|
||||
type OutputConfig struct {
|
||||
Type string `json:"type"` // unix_socket, stdout, file, etc.
|
||||
Enabled bool `json:"enabled"` // whether this output is active
|
||||
Params map[string]string `json:"params"` // specific parameters like socket_path, path, etc.
|
||||
Type string `json:"type"` // unix_socket, stdout, file, etc.
|
||||
Enabled bool `json:"enabled"` // whether this output is active
|
||||
AsyncBuffer int `json:"async_buffer"` // queue size for async writes (e.g., 5000)
|
||||
Params map[string]string `json:"params"` // specific parameters like socket_path, path, etc.
|
||||
}
|
||||
|
||||
// AppConfig is the complete ja4sentinel configuration
|
||||
@ -191,6 +211,8 @@ type Logger interface {
|
||||
// Converts TCPMeta options to a comma-separated string and creates pointer values
|
||||
// for optional fields (MSS, WindowScale) to support proper JSON omitempty behavior.
|
||||
// If fingerprints is nil, the JA4/JA3 fields will be empty strings.
|
||||
// Note: JA4Hash is intentionally NOT included in LogRecord as the JA4 format
|
||||
// already includes its own hash portions (the full 38-character JA4 string is sufficient).
|
||||
func NewLogRecord(ch TLSClientHello, fp *Fingerprints) LogRecord {
|
||||
opts := ""
|
||||
if len(ch.TCPMeta.Options) > 0 {
|
||||
@ -221,12 +243,16 @@ func NewLogRecord(ch TLSClientHello, fp *Fingerprints) LogRecord {
|
||||
TCPMSS: mssPtr,
|
||||
TCPWScale: wScalePtr,
|
||||
TCPOptions: opts,
|
||||
ConnID: ch.ConnID,
|
||||
SNI: ch.SNI,
|
||||
ALPN: ch.ALPN,
|
||||
TLSVersion: ch.TLSVersion,
|
||||
SynToCHMs: ch.SynToCHMs,
|
||||
Timestamp: time.Now().UnixNano(),
|
||||
}
|
||||
|
||||
if fp != nil {
|
||||
rec.JA4 = fp.JA4
|
||||
rec.JA4Hash = fp.JA4Hash
|
||||
rec.JA3 = fp.JA3
|
||||
rec.JA3Hash = fp.JA3Hash
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user