Documentation
¶
Index ¶
- func MakeKey(srcIP string, srcPort uint16, dstIP string, dstPort uint16, proto string) string
- type Connection
- func (c *Connection) AddFingerprint(fpType, fingerprint string, seenAt time.Time, packetNum uint64)
- func (c *Connection) AddRawFingerprint(fpType, raw string, seenAt time.Time, packetNum uint64)
- func (c *Connection) LatestFingerprint(fpType string) string
- func (c *Connection) LatestPacketNum(fpType string) uint64
- func (c *Connection) PrimaryFingerprint() (fpType, fingerprint string)
- func (c *Connection) Snapshot() *Connection
- type FingerprintEvent
- type Tracker
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Connection ¶
type Connection struct {
ID string // 5-tuple key
SrcIP string
SrcPort uint16
DstIP string
DstPort uint16
Protocol string // "tcp", "udp"
FirstSeen time.Time
LastSeen time.Time
PacketCount uint64
ByteCount uint64
// Fingerprints stores history per type with timestamps.
// Keyed by fingerprint type (lowercase: "ja4", "ja4s", "ja4h", ...).
Fingerprints map[string][]FingerprintEvent
// RawFPs stores raw (unhashed) fingerprints per type. Same cap policy.
RawFPs map[string][]FingerprintEvent
// Enrichment
IdentifiedApp string
IsKnownBad bool
IsNew bool // first-seen fingerprint on this network
MSSValue int // extracted from JA4T
TunnelIndicator string // VPN/tunnel detection from MSS
// SSHSessionType is populated from ja4plus.InterpretJA4SSH when a
// JA4SSH fingerprint is observed. Values include "Interactive SSH
// Session", "Reverse SSH Session", "SSH File Transfer", "SSH File
// Transfer (Upload)", or "Unknown". Empty string for non-SSH
// connections or when the JA4SSH fingerprint is malformed.
SSHSessionType string
// Anomalies triggered on this connection (human-readable descriptions).
Anomalies []string
}
Connection represents a network flow with accumulated fingerprints.
Connection lifecycle:
New (from Tracker.Update)
└─► Active (packets arrive, fingerprints added via AddFingerprint)
└─► Evicted (idle timeout or LRU)
└─► OnEvict callback → Store + Processor cleanup
Connection values are mutated by a single shard goroutine. To hand a Connection to any other goroutine (TUI, export), use Snapshot() to get an independent deep copy.
func NewConnection ¶
func NewConnection(srcIP string, srcPort uint16, dstIP string, dstPort uint16, proto string, ts time.Time) *Connection
NewConnection creates a Connection from a 5-tuple.
func (*Connection) AddFingerprint ¶
func (c *Connection) AddFingerprint(fpType, fingerprint string, seenAt time.Time, packetNum uint64)
AddFingerprint appends a fingerprint event to the history for the given type. Deduplicates consecutive identical values. Caps the history at maxEventsPerType per type.
The cap policy preserves the first 100 events (handshake context) plus the most recent 900, so you always see how the connection started AND what it's been doing recently.
func (*Connection) AddRawFingerprint ¶
func (c *Connection) AddRawFingerprint(fpType, raw string, seenAt time.Time, packetNum uint64)
AddRawFingerprint appends a raw (unhashed) fingerprint event to the history.
func (*Connection) LatestFingerprint ¶
func (c *Connection) LatestFingerprint(fpType string) string
LatestFingerprint returns the most recent fingerprint value for a given type, or "" if none. Preserved signature so rules in internal/anomaly still work without modification.
func (*Connection) LatestPacketNum ¶
func (c *Connection) LatestPacketNum(fpType string) uint64
LatestPacketNum returns the PacketNum of the most recent fingerprint event for the given type, or 0 if none. Used by the anomaly evaluator to link alerts to the fingerprint event that triggered them.
func (*Connection) PrimaryFingerprint ¶
func (c *Connection) PrimaryFingerprint() (fpType, fingerprint string)
PrimaryFingerprint returns the most relevant fingerprint for display. Prefers JA4 (TLS client), falls back to other types in priority order.
func (*Connection) Snapshot ¶
func (c *Connection) Snapshot() *Connection
Snapshot returns a deep copy of this Connection that is safe to read from any goroutine. The shard goroutine mutates the original; the TUI and export code read snapshots.
Deep copies: Fingerprints, RawFPs, and Anomalies. All other fields are either values or strings (immutable).
type FingerprintEvent ¶
type FingerprintEvent struct {
Value string `json:"value"`
SeenAt time.Time `json:"seen_at"`
PacketNum uint64 `json:"packet_num"`
}
FingerprintEvent is one observed fingerprint with when and which packet produced it. Used for the detail panel timeline and for linking alerts back to the specific fingerprint that triggered them.
Replaces the previous map[string][]string storage, which threw away the timing information needed for investigation.
type Tracker ¶
type Tracker struct {
// Callback when a connection is evicted (for storage and Processor cleanup)
OnEvict func(conn *Connection)
// contains filtered or unexported fields
}
Tracker maintains a table of active connections and evicts idle ones.
Two data structures are kept in sync:
connections: map[id]*Connection — O(1) lookup lru: doubly-linked list — O(1) insert/move/remove
On every Update we move the connection's list element to the back (most recently used). On LRU eviction we pop from the front (least recently used). This replaces the previous O(N) full-map scan that happened once per over-max insertion, which was a real scalability bug under SYN flood / high-churn workloads.
most recent
┌──────────────┐
│ │
back │ conn3 │ ← Update bumps to back
├──────────────┤
│ conn2 │
├──────────────┤
│ conn1 │
front │ conn0 │ ← LRU eviction pops from front
│ │
└──────────────┘
least recent
func NewTracker ¶
NewTracker creates a Tracker with the given max connection table size.
func (*Tracker) All ¶
func (t *Tracker) All() []*Connection
All returns a snapshot of all current connections.
func (*Tracker) Evict ¶
func (t *Tracker) Evict(now time.Time) []*Connection
Evict runs a single pass of idle connection eviction. Call this periodically (e.g., every 1 second).
Two phases:
- Idle eviction: scan the map and drop connections whose LastSeen exceeds the per-protocol timeout. O(N) but only fires for actually idle connections.
- LRU eviction: while we're over maxConns, pop from the front of the LRU list. O(1) per eviction (was O(N) per eviction in v0.2).
func (*Tracker) Get ¶
func (t *Tracker) Get(key string) *Connection
Get returns a connection by key, or nil if not found.
func (*Tracker) Update ¶
func (t *Tracker) Update(srcIP string, srcPort uint16, dstIP string, dstPort uint16, proto string, ts time.Time, packetLen uint64) *Connection
Update processes a packet's metadata and returns the associated Connection. Creates a new Connection if this is the first packet for this 5-tuple. O(1): map lookup + list move-to-back.