From 8dd31153539add002c3a34f354d51cad5a14a7bc Mon Sep 17 00:00:00 2001 From: Dicken Date: Sun, 26 Jul 2026 11:04:09 +0200 Subject: [PATCH] round51: Fortschrittsanzeige und Timing-Logs fuer den masscan-/httpx-Vorabscan im Sammel-Scan --- apps/backend/src/routes/scan.ts | 44 +++++++++++++++++++ .../frontend/src/routes/admin/ScannerPage.tsx | 11 ++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/apps/backend/src/routes/scan.ts b/apps/backend/src/routes/scan.ts index b308219..5e78441 100644 --- a/apps/backend/src/routes/scan.ts +++ b/apps/backend/src/routes/scan.ts @@ -250,8 +250,32 @@ export async function scanRoutes(app: FastifyInstance): Promise { // reinen HTTP-)Detailabfragen pro Port (Titel, Favicon, // Softwareerkennung). const deviceIps = devices.map((d) => d.ip); + + // Sichtbarer Fortschritt VOR dem eigentlichen Geräte-Scan: ohne das + // stand die Anzeige die ganze Vorabscan-Zeit über bei "1 von 120" und + // wirkte wie hängengeblieben, obwohl im Hintergrund der gemeinsame + // masscan-/httpx-Lauf arbeitete (siehe Bugreport). + updateJobProgress("devices", 0, `masscan läuft… (${deviceIps.length} Geräte, vollständiger Portscan)`); + const masscanStartedAt = Date.now(); const masscanBatch = await scanHostsWithMasscan(deviceIps, "1-65535"); + const masscanDurationMs = Date.now() - masscanStartedAt; const masscanBatchError = masscanBatch === null ? getMasscanLastError() : null; + const masscanPortsFound = masscanBatch + ? Array.from(masscanBatch.values()).reduce((sum, ports) => sum + ports.length, 0) + : 0; + + // Start- und Endzeit fest im Scan-Log protokollieren (nicht nur in + // der Konsole) - so ist die tatsächliche Dauer des Vorabscans auch im + // Nachhinein unter Admin -> Logs nachvollziehbar, nicht nur während + // eines laufenden Scans über die Fortschrittsanzeige. + logRepo.logScan({ + type: "device", + targetId: null, + level: masscanBatch ? "info" : "error", + message: masscanBatch + ? `Sammel-Scan: masscan-Vorabscan über ${deviceIps.length} Geräte abgeschlossen in ${(masscanDurationMs / 1000).toFixed(1)}s, ${masscanPortsFound} offene(r) Port(s) gefunden (Start: ${new Date(masscanStartedAt).toLocaleTimeString("de-DE")}, Ende: ${new Date().toLocaleTimeString("de-DE")})` + : `Sammel-Scan: masscan-Vorabscan über ${deviceIps.length} Geräte fehlgeschlagen nach ${(masscanDurationMs / 1000).toFixed(1)}s – ${masscanBatchError} (jedes Gerät fällt einzeln auf den TCP-Fallback zurück)`, + }); // httpx nur für die Geräte vorab bündeln, für die masscan Ergebnisse // geliefert hat - ist masscan für den GESAMTEN Batch fehlgeschlagen @@ -267,8 +291,28 @@ export async function scanRoutes(app: FastifyInstance): Promise { const ports = masscanBatch.get(device.ip) ?? []; for (const port of ports) httpxTargets.push({ ip: device.ip, port }); } + + updateJobProgress("devices", 0, `httpx läuft… (${httpxTargets.length} Port(s) über alle Geräte)`); + const httpxStartedAt = Date.now(); httpxBatch = await probeManyWithHttpx(httpxTargets); + const httpxDurationMs = Date.now() - httpxStartedAt; if (httpxBatch === null) httpxBatchError = getHttpxLastError(); + + logRepo.logScan({ + type: "device", + targetId: null, + level: httpxBatch ? "info" : "error", + message: httpxBatch + ? `Sammel-Scan: httpx-Vorabscan über ${httpxTargets.length} Ziel(e) (ip:port) abgeschlossen in ${(httpxDurationMs / 1000).toFixed(1)}s, ${httpxBatch.size} als HTTP/HTTPS bestätigt (Start: ${new Date(httpxStartedAt).toLocaleTimeString("de-DE")}, Ende: ${new Date().toLocaleTimeString("de-DE")})` + : `Sammel-Scan: httpx-Vorabscan über ${httpxTargets.length} Ziel(e) fehlgeschlagen nach ${(httpxDurationMs / 1000).toFixed(1)}s – ${httpxBatchError} (jeder Port wird stattdessen einzeln von jedem Gerät selbst geprüft)`, + }); + } else { + logRepo.logScan({ + type: "device", + targetId: null, + level: "info", + message: `Sammel-Scan: httpx-Vorabscan übersprungen, da der masscan-Vorabscan fehlgeschlagen ist (keine Portliste zum Prüfen vorhanden)`, + }); } // Mehrere Geräte GLEICHZEITIG scannen statt strikt nacheinander - diff --git a/apps/frontend/src/routes/admin/ScannerPage.tsx b/apps/frontend/src/routes/admin/ScannerPage.tsx index 8551326..83329cb 100644 --- a/apps/frontend/src/routes/admin/ScannerPage.tsx +++ b/apps/frontend/src/routes/admin/ScannerPage.tsx @@ -601,8 +601,17 @@ export function ScannerPage() { setBulkRunning(status.running); if (status.running && status.progress) { + // Während der masscan-/httpx-Vorabphase (siehe routes/scan.ts) wird + // current bewusst auf 0 gehalten, während currentLabel den + // Phasen-Text trägt ("masscan läuft…" / "httpx läuft…") - ohne + // diese Ausnahme hätte das bisher IMMER "(1 von N)" angehängt, + // auch während dieser Phasen, in denen noch gar kein einzelnes + // Gerät bearbeitet wird. Das sah aus wie ein hängender Scan + // (siehe Bugreport), obwohl im Hintergrund gearbeitet wurde. setBulkStatus( - `Scanne ${status.progress.currentLabel ?? "…"} (${status.progress.current + 1} von ${status.progress.total})` + status.progress.current === 0 + ? `Scanne ${status.progress.currentLabel ?? "…"}` + : `Scanne ${status.progress.currentLabel ?? "…"} (${status.progress.current + 1} von ${status.progress.total})` ); } else if (status.lastResult && status.startedAt !== getHandledResultId("scanner:bulkLastHandledAt")) { setHandledResultId("scanner:bulkLastHandledAt", status.startedAt);