manag veth directly with sniffer
All checks were successful
Build and Deploy MITM Webserver / build (push) Successful in 10s

This commit is contained in:
2026-03-07 15:38:56 +01:00
parent a282b89d45
commit 264da68f11
7 changed files with 257 additions and 56 deletions

View File

@@ -34,6 +34,7 @@ from src.utilities.interface_bridge_helpers import (
from src.config import settings
from src.utilities.bridge_telemetry import bridge_telemetry_manager
from src.utilities.capture_header import parse_capture_header
from src.utilities.capture_pipeline import capture_pipeline_manager
from src.utilities.ndpi_classifier import ndpi_classifier
from src.utilities.packet_identity import build_packet_uid
from src.utilities.packet_tracker import packet_tracker
@@ -567,7 +568,7 @@ def _session_reader_loop(session_id: str) -> None:
try:
capture_meta = None
packet_bytes = raw
if settings.capture_header_enabled and settings.capture_interface and iface == settings.capture_interface:
if settings.capture_header_enabled:
capture_meta, packet_bytes = parse_capture_header(raw)
pkt = Ether(packet_bytes)
pkt.sniffed_on = iface
@@ -617,8 +618,8 @@ def start_afpacket_sniffer(target: str, target_is_interface: bool = False) -> st
"is_bridge": not target_is_interface,
"ports": [],
"capture_ifaces": [],
"capture_bridge": None,
}
sessions[session_id] = session
# determine ports for this session
if target_is_interface:
@@ -626,19 +627,35 @@ def start_afpacket_sniffer(target: str, target_is_interface: bool = False) -> st
capture_ifaces = [target]
else:
ports = get_bridge_ports_once(target)
capture_ifaces = [settings.capture_interface] if settings.capture_interface else list(ports)
capture_iface = None
if settings.capture_automanage:
capture_iface = capture_pipeline_manager.acquire(target)
session["capture_bridge"] = target
elif settings.capture_interface:
capture_iface = settings.capture_interface
capture_ifaces = [capture_iface] if capture_iface else list(ports)
session["ports"] = ports
session["capture_ifaces"] = capture_ifaces
sessions[session_id] = session
# create sockets for this session only
for iface in capture_ifaces:
if not check_interface_exists(iface):
logger.warning("Snapshot port %s missing for session %s, skipping", iface, session_id)
continue
s = _create_af_packet_socket(iface)
if s:
session["sockets"][iface] = s
try:
for iface in capture_ifaces:
if not check_interface_exists(iface):
logger.warning("Snapshot port %s missing for session %s, skipping", iface, session_id)
continue
s = _create_af_packet_socket(iface)
if s:
session["sockets"][iface] = s
except Exception:
sessions.pop(session_id, None)
if session.get("capture_bridge"):
try:
capture_pipeline_manager.release(session["capture_bridge"])
except Exception:
logger.exception("Failed to release capture pipeline after startup error")
raise
# start dedicated thread
t = threading.Thread(target=_session_reader_loop, args=(session_id,), daemon=True)
@@ -672,6 +689,12 @@ def stop_afpacket_sniffer(session_id: Optional[str] = None, target: Optional[str
t = s.get("thread")
if t and isinstance(t, threading.Thread):
t.join(timeout=settings.sniffer_thread_join_timeout_seconds)
capture_bridge = s.get("capture_bridge")
if capture_bridge:
try:
capture_pipeline_manager.release(capture_bridge)
except Exception:
logger.exception("Failed to release capture pipeline for bridge %s", capture_bridge)
_sync_bridge_telemetry()
logger.info("Stopped session %s", session_id)
return
@@ -681,6 +704,9 @@ def stop_afpacket_sniffer(session_id: Optional[str] = None, target: Optional[str
# For interface-mode: close that iface in any session that has it
for sid, s in list(sessions.items()):
if target in s.get("ports", []):
if s.get("capture_bridge") == target:
stop_afpacket_sniffer(session_id=sid)
continue
# close only that iface socket in that session
sock = s["sockets"].pop(target, None)
if sock:
@@ -748,6 +774,7 @@ def get_internal_debug_state() -> dict:
sid: {
"label": s.get("label"),
"is_bridge": s.get("is_bridge"),
"capture_bridge": s.get("capture_bridge"),
"ports": list(s.get("ports", [])),
"capture_ifaces": list(s.get("capture_ifaces", [])),
"sockets": list(s.get("sockets", {}).keys()),
@@ -757,5 +784,6 @@ def get_internal_debug_state() -> dict:
},
"buffer_len": len(_PACKET_BUFFER),
"telemetry_ports": sorted({iface for session in sessions.values() for iface in session.get("ports", [])}),
"capture_pipeline": capture_pipeline_manager.get_debug_snapshot(),
"packet_tracker": packet_tracker.get_debug_snapshot(),
}