fix empty null value db insert
All checks were successful
Build and Deploy MITM Webserver / traffic_target (push) Successful in 0s
Build and Deploy MITM Webserver / build (push) Successful in 10s

This commit is contained in:
2026-03-10 22:00:39 +01:00
parent e8bed95162
commit ce35be1e1e
4 changed files with 63 additions and 25 deletions

View File

@@ -426,11 +426,12 @@ def parse_packet(
pkt_info["icmp_embedded_src_port"] = _safe_get_attr(inner[UDP], "sport") pkt_info["icmp_embedded_src_port"] = _safe_get_attr(inner[UDP], "sport")
pkt_info["icmp_embedded_dst_port"] = _safe_get_attr(inner[UDP], "dport") pkt_info["icmp_embedded_dst_port"] = _safe_get_attr(inner[UDP], "dport")
pkt_info["packet_uid"] = build_packet_uid(pkt_info)
if pkt_info.get("packet_id"): if pkt_info.get("packet_id"):
pkt_info["correlation_key"] = f"pid:{pkt_info['packet_id']}" pkt_info["correlation_key"] = f"pid:{pkt_info['packet_id']}"
pkt_info["correlation_source"] = "kernel_mark" pkt_info["correlation_source"] = "kernel_mark"
else: else:
pkt_info["packet_uid"] = build_packet_uid(pkt_info)
pkt_info["correlation_key"] = f"uid:{pkt_info['packet_uid']}" pkt_info["correlation_key"] = f"uid:{pkt_info['packet_uid']}"
pkt_info["correlation_source"] = "legacy_hash" pkt_info["correlation_source"] = "legacy_hash"
@@ -541,16 +542,13 @@ def _ensure_socket_for_session(sockets: Dict[str, socket.socket], iface: str, br
def _sync_bridge_telemetry() -> None: def _sync_bridge_telemetry() -> None:
interfaces = sorted( bridge_session_interfaces = {
{ session_id: list(session.get("ports", []))
iface for session_id, session in sessions.items()
for session in sessions.values()
if session.get("is_bridge") if session.get("is_bridge")
for iface in session.get("ports", [])
} }
)
try: try:
bridge_telemetry_manager.update_interfaces(interfaces) bridge_telemetry_manager.update_sessions(bridge_session_interfaces)
except Exception: except Exception:
logger.exception("Failed to update bridge telemetry collector") logger.exception("Failed to update bridge telemetry collector")

View File

@@ -11,7 +11,7 @@ import subprocess
import sys import sys
import threading import threading
from pathlib import Path from pathlib import Path
from typing import Iterable, Optional from typing import Iterable, Mapping, Optional
from src.config import settings from src.config import settings
from src.utilities.packet_tracker import packet_tracker from src.utilities.packet_tracker import packet_tracker
@@ -24,17 +24,33 @@ class BridgeTelemetryManager:
def __init__(self) -> None: def __init__(self) -> None:
self._interfaces: set[str] = set() self._interfaces: set[str] = set()
self._session_ids_by_interface: dict[str, tuple[str, ...]] = {}
self._process: Optional[subprocess.Popen[str]] = None self._process: Optional[subprocess.Popen[str]] = None
self._reader_thread: Optional[threading.Thread] = None self._reader_thread: Optional[threading.Thread] = None
self._lock = threading.Lock() self._lock = threading.Lock()
def update_interfaces(self, interfaces: Iterable[str]) -> None: def update_sessions(self, session_interfaces: Mapping[str, Iterable[str]]) -> None:
"""Restart the collector when the active bridge interface set changes.""" """Restart the collector when the active bridge interface set changes."""
normalized = {iface.strip() for iface in interfaces if iface and iface.strip()} normalized: dict[str, set[str]] = {}
for session_id, interfaces in session_interfaces.items():
if not session_id:
continue
iface_set = {iface.strip() for iface in interfaces if iface and iface.strip()}
if iface_set:
normalized[session_id] = iface_set
normalized_interfaces = sorted({iface for ifaces in normalized.values() for iface in ifaces})
session_ids_by_interface = {
iface: tuple(sorted(session_id for session_id, ifaces in normalized.items() if iface in ifaces))
for iface in normalized_interfaces
}
with self._lock: with self._lock:
if normalized == self._interfaces: interfaces_changed = set(normalized_interfaces) != self._interfaces
self._interfaces = set(normalized_interfaces)
self._session_ids_by_interface = session_ids_by_interface
if not interfaces_changed:
return return
self._interfaces = normalized
self._restart_locked() self._restart_locked()
def stop(self) -> None: def stop(self) -> None:
@@ -123,11 +139,22 @@ class BridgeTelemetryManager:
"skb_mark": event.get("skb_mark"), "skb_mark": event.get("skb_mark"),
"capture_mode": "tc_ingress", "capture_mode": "tc_ingress",
} }
capture_iface = str(event.get("iface") or "")
capture_session_id: Optional[str] = None
with self._lock:
session_ids = self._session_ids_by_interface.get(capture_iface, ())
if session_ids:
capture_session_id = session_ids[0]
try: try:
from src.network_sniffer import parse_packet_bytes from src.network_sniffer import parse_packet_bytes
parse_packet_bytes(packet_bytes, str(event.get("iface")), capture_metadata=capture_metadata) parse_packet_bytes(
packet_bytes,
capture_iface,
capture_metadata=capture_metadata,
capture_session_id=capture_session_id,
)
except Exception: except Exception:
logger.exception("Failed to process ingress raw packet event") logger.exception("Failed to process ingress raw packet event")

View File

@@ -91,9 +91,14 @@ def _derive_flow_id(payload: Dict[str, Any]) -> Optional[str]:
def _attach_derived_fields(payload: Dict[str, Any]) -> None: def _attach_derived_fields(payload: Dict[str, Any]) -> None:
if payload.get("flow_id") in (None, ""):
flow_id = _derive_flow_id(payload) flow_id = _derive_flow_id(payload)
if flow_id is not None: if flow_id is not None:
current_flow_id = payload.get("flow_id")
if current_flow_id in (None, ""):
payload["flow_id"] = flow_id
else:
session_id = payload.get("capture_session_id")
if session_id not in (None, "") and current_flow_id == flow_id.split(":", 1)[1]:
payload["flow_id"] = flow_id payload["flow_id"] = flow_id
if payload.get("raw_present") is None: if payload.get("raw_present") is None:
@@ -172,6 +177,9 @@ class DatabasePool:
if self._pool is None: if self._pool is None:
await self.init_pool() await self.init_pool()
_normalize_json_fields(pkt_info)
_attach_derived_fields(pkt_info)
dpi_metadata = pkt_info.get("dpi_metadata") dpi_metadata = pkt_info.get("dpi_metadata")
telemetry_metadata = pkt_info.get("telemetry_metadata") telemetry_metadata = pkt_info.get("telemetry_metadata")

View File

@@ -180,6 +180,7 @@ class PacketTracker:
"correlation_source": None, "correlation_source": None,
"packet_id": None, "packet_id": None,
"packet_uid": None, "packet_uid": None,
"capture_session_id": None,
"skb_mark": None, "skb_mark": None,
"verdict": "pending", "verdict": "pending",
"verdict_reason": None, "verdict_reason": None,
@@ -205,6 +206,15 @@ class PacketTracker:
if payload.get("verdict_hint") is None and skb_mark is not None: if payload.get("verdict_hint") is None and skb_mark is not None:
payload["verdict_hint"] = verdict_from_mark(skb_mark) payload["verdict_hint"] = verdict_from_mark(skb_mark)
packet_uid = payload.get("packet_uid")
if packet_uid in (None, ""):
try:
packet_uid = build_packet_uid(payload)
except Exception:
packet_uid = None
if packet_uid not in (None, ""):
payload["packet_uid"] = packet_uid
packet_id = payload.get("packet_id") packet_id = payload.get("packet_id")
if packet_id not in (None, ""): if packet_id not in (None, ""):
packet_id = str(packet_id) packet_id = str(packet_id)
@@ -214,13 +224,8 @@ class PacketTracker:
payload["correlation_source"] = "kernel_mark" payload["correlation_source"] = "kernel_mark"
return payload["correlation_key"] return payload["correlation_key"]
packet_uid = payload.get("packet_uid")
if packet_uid in (None, ""): if packet_uid in (None, ""):
try:
packet_uid = build_packet_uid(payload)
except Exception:
return None return None
payload["packet_uid"] = packet_uid
payload["correlation_key"] = f"uid:{packet_uid}" payload["correlation_key"] = f"uid:{packet_uid}"
if not payload.get("correlation_source"): if not payload.get("correlation_source"):
payload["correlation_source"] = "legacy_hash" payload["correlation_source"] = "legacy_hash"