Detect the primary network interface
(self)
| 357 | |
| 358 | # Capture timing |
| 359 | self._start_time: Optional[datetime] = None |
| 360 | |
| 361 | # DNS query timestamps for rate detection |
| 362 | self._dns_query_times: Dict[str, deque] = defaultdict(lambda: deque(maxlen=200)) |
| 363 | |
| 364 | # Beacon detection state. |
| 365 | # _flow_history: (src_ip, dst_ip, dst_port) -> deque[(ts, bytes_out)] |
| 366 | # _beacon_scored: same key -> last confidence score that fired an alert |
| 367 | self._flow_history: Dict[Tuple[str, str, int], deque] = defaultdict( |
| 368 | lambda: deque(maxlen=self.BEACON_HISTORY_MAX) |
| 369 | ) |
| 370 | self._beacon_scored: Dict[Tuple[str, str, int], Dict[str, Any]] = {} |
| 371 | self._last_beacon_sweep = time.time() |
| 372 | |
| 373 | # State caps, sized for the board this is actually running on |
| 374 | caps_obj = get_server_capabilities(shared_data).capabilities |
| 375 | self._max_hosts, self._max_connections, self._max_flows = self._state_caps( |
| 376 | caps_obj.total_ram_gb |
| 377 | ) |
| 378 | self._last_state_prune = time.time() |
| 379 | |
| 380 | # Optional sidecar subsystems (lazy, only spawned if tshark exists) |
| 381 | self._ja3_collector = None |
| 382 | self._irc_parser = None |
| 383 | |
| 384 | # Callbacks |
| 385 | self._on_alert_callbacks: List[Callable] = [] |