From 721640817c84dc5c49ca474d477b06cf03a555a4 Mon Sep 17 00:00:00 2001 From: malmert Date: Sat, 10 Jan 2026 18:48:25 +0100 Subject: [PATCH] add initializer for nft --- backend/src/api/nftables_api.py | 87 --------------------------------- 1 file changed, 87 deletions(-) diff --git a/backend/src/api/nftables_api.py b/backend/src/api/nftables_api.py index 18631d0..2977ce1 100644 --- a/backend/src/api/nftables_api.py +++ b/backend/src/api/nftables_api.py @@ -24,7 +24,6 @@ import re import tempfile import os import logging -import sys # Router and logger --------------------------------------------------------- router = APIRouter(prefix="/nft", tags=["nftables"]) @@ -87,99 +86,13 @@ def run_nft(args: List[str]) -> Tuple[str, str]: logger.error("nft failed: %s -- %s", " ".join(e.cmd), e.stderr.strip()) raise RuntimeError(f"nft failed: {' '.join(e.cmd)} -- {e.stderr.strip()}") - -def _safe_run(cmd: List[str]) -> Tuple[int, str, str]: - """Run arbitrary command and capture exitcode, stdout, stderr. Never raise.""" - try: - p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) - return p.returncode, p.stdout.strip(), p.stderr.strip() - except Exception as ex: - return 255, "", f"exception: {ex}" - - -def _try_modprobe(module: str) -> Tuple[bool, str]: - """Try to modprobe the kernel module. Returns (ok, message).""" - if not shutil_which("modprobe"): - return False, "modprobe not found" - code, out, err = _safe_run(["modprobe", module]) - if code == 0: - return True, out or "ok" - return False, err or f"exit {code}" - - -def shutil_which(cmd: str) -> Optional[str]: - """Small local replacement for shutil.which to avoid extra import in some constrained envs.""" - from shutil import which - return which(cmd) - - -def enable_bridge_sysctls() -> None: - """Attempt to enable sysctls needed for bridge->netfilter interaction.""" - changed = [] - for key, want in [ - ("net.bridge.bridge-nf-call-iptables", "1"), - ("net.bridge.bridge-nf-call-ip6tables", "1"), - ]: - try: - proc = subprocess.run(["/bin/sh", "-c", f"sysctl -w {key}={want}"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) - if proc.returncode == 0: - logger.info("set sysctl %s=%s", key, want) - changed.append(key) - else: - # fallback: try write to /proc directly (requires root) - try: - path = "/proc/sys/" + key.replace(".", "/") - if os.path.exists(path): - with open(path, "w") as f: - f.write(want) - logger.info("wrote %s to %s", want, path) - changed.append(key) - else: - logger.warning("sysctl %s not present (and sysctl failed): %s", key, proc.stderr.strip()) - except Exception as e: - logger.warning("failed to write sysctl %s: %s", key, e) - except Exception as e: - logger.debug("sysctl attempt failed for %s: %s", key, e) - if changed: - logger.debug("sysctls changed: %s", changed) - - -def try_ensure_kernel_bridge_support() -> None: - """ - Try to load kernel modules and enable sysctls that are commonly required for 'bridge' family nftables use. - This function logs everything but does not raise. It is best-effort. - """ - logger.debug("attempting to ensure kernel bridge/netfilter support (modprobe + sysctl)") - - # try modprobe bridge and br_netfilter - for mod in ("bridge", "br_netfilter"): - if shutil_which("modprobe"): - code, out, err = _safe_run(["modprobe", mod]) - if code == 0: - logger.info("loaded kernel module: %s", mod) - else: - logger.debug("modprobe %s returned code=%s stderr=%s", mod, code, err) - else: - logger.debug("modprobe not available on this system; skipping module load for %s", mod) - - # enable bridge sysctls so bridged IP packets are seen by netfilter - enable_bridge_sysctls() - - def ensure_table_chain(family: str, table: str, chain: str) -> None: """ Ensure the nft table and chain exist. On serious failures this raises RuntimeError. This function: - - calls try_ensure_kernel_bridge_support() first (best-effort) - attempts `nft add table` and `nft add chain` - if those fail, tries to apply a tiny nft script with `nft -f` to create table and chain """ - # best-effort kernel prep (modprobe + sysctl) - try: - try_ensure_kernel_bridge_support() - except Exception as e: - logger.debug("kernel prep raised an exception (continuing): %s", e) - logger.info("ensuring table %s.%s exists", family, table) # Try simple add table first