feat: add Go-based eBPF helper using AF_PACKET raw sockets with automatic build in agent installer

Add nexafabric-ebpf.go implementing flow collection via Linux raw packet sockets (AF_PACKET) instead of tc/eBPF to enable immediate Proxmox deployment without kernel dependencies, implement packet parsing with VLAN/IP/TCP/UDP/ICMP support and flow aggregation by 5-tuple with vmid/nic/interface/direction metadata extraction from tap/fwbr interface names, add /agents/download/nexafabric-ebpf.go endpoint
This commit is contained in:
2026-07-10 14:19:28 +02:00
parent e6c9a92ff0
commit 3aa7ae0c65
3 changed files with 354 additions and 1 deletions
+16
View File
@@ -1410,9 +1410,19 @@ if ! command -v conntrack >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1;
apt-get install -y conntrack
fi
if ! command -v go >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then
apt-get update
apt-get install -y golang-go || true
fi
mkdir -p "$INSTALL_DIR" "$CONFIG_DIR"
curl -fsSL "$NEXAFABRIC_URL/api/v1/agents/download/nexafabric-agent.py" -o "$INSTALL_DIR/nexafabric-agent.py"
chmod 0755 "$INSTALL_DIR/nexafabric-agent.py"
curl -fsSL "$NEXAFABRIC_URL/api/v1/agents/download/nexafabric-ebpf.go" -o "$INSTALL_DIR/nexafabric-ebpf.go" || true
if command -v go >/dev/null 2>&1 && [ -f "$INSTALL_DIR/nexafabric-ebpf.go" ]; then
(cd "$INSTALL_DIR" && go build -o "$INSTALL_DIR/nexafabric-ebpf" "$INSTALL_DIR/nexafabric-ebpf.go") || true
[ -f "$INSTALL_DIR/nexafabric-ebpf" ] && chmod 0755 "$INSTALL_DIR/nexafabric-ebpf"
fi
cat > "$CONFIG_DIR/config.json" <<'JSON'
{{
@@ -1522,6 +1532,12 @@ def download_node_agent() -> FileResponse:
return FileResponse(path, media_type="text/x-python", filename="nexafabric-agent.py")
@api_router.get("/agents/download/nexafabric-ebpf.go")
def download_node_agent_ebpf_helper() -> FileResponse:
path = Path(__file__).resolve().parents[2] / "agent_assets" / "nexafabric-ebpf.go"
return FileResponse(path, media_type="text/x-go", filename="nexafabric-ebpf.go")
@api_router.post("/agents/heartbeat")
def agent_heartbeat(payload: AgentHeartbeat, authorization: str | None = Header(default=None), db: Session = Depends(get_db)) -> dict:
if not authorization or not authorization.lower().startswith("bearer "):