generated from Dicken/dickendock
round35: Vollstaendiger Portscan (1-65535) pro Geraet als Option, fuer Geraete mit vielen Diensten auf unueblichen Ports
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { resolveHostname, reverseLookup } from "./dns.js";
|
||||
import { isPortOpen, TYPICAL_PORTS } from "./ports.js";
|
||||
import { isPortOpen, scanPortsInBatches, fullPortRange, TYPICAL_PORTS } from "./ports.js";
|
||||
import { probeHttp } from "./http.js";
|
||||
import { detectSoftware } from "./softwareDetection.js";
|
||||
import { findBestIconMatch } from "./iconDb.js";
|
||||
@@ -102,17 +102,11 @@ export async function scanDeviceServices(
|
||||
|
||||
const candidatePorts = Array.from(new Set([80, 443, ...extraPorts, ...priorityPorts]));
|
||||
|
||||
// Die offenen Ports werden PARALLEL geprüft, nicht nacheinander - bei
|
||||
// einem nicht erreichbaren/gefilterten Gerät (z. B. ein schlafender
|
||||
// Laptop) würde ein sequenzieller Durchlauf sonst bis zu
|
||||
// Portanzahl × Timeout dauern (bei 20 Ports und 800ms Timeout: 16+
|
||||
// Sekunden PRO GERÄT) und den Scan wie hängengeblieben wirken lassen.
|
||||
// Danach wird nur noch für die tatsächlich offenen Ports (meist wenige)
|
||||
// die eigentliche HTTP-Abfrage gemacht.
|
||||
const openChecks = await Promise.all(
|
||||
candidatePorts.map(async (port) => ({ port, open: await isPortOpen(device.ip, port) }))
|
||||
);
|
||||
let openPorts = openChecks.filter((c) => c.open).map((c) => c.port);
|
||||
// Batches statt alles auf einmal parallel - bei der "typischen Ports"-Liste
|
||||
// (~30 Ports) macht das kaum einen Unterschied, ist aber zwingend nötig für
|
||||
// den optionalen VOLLSTÄNDIGEN Portscan (1-65535, siehe Admin -> Geräte),
|
||||
// wo alle Ports gleichzeitig öffnen würde.
|
||||
let openPorts = await scanPortsInBatches(device.ip, candidatePorts);
|
||||
|
||||
// Bereits bekannte Dienst-Ports (priorityPorts, vom Aufrufer übergeben -
|
||||
// siehe scan.ts), die im ersten, stark parallelen Durchlauf NICHT als
|
||||
|
||||
@@ -36,3 +36,36 @@ export function isPortOpen(host: string, port: number, timeoutMs = 800): Promise
|
||||
socket.once("error", () => finish(false));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft eine (ggf. sehr lange) Liste von Ports in Batches mit begrenzter
|
||||
* Parallelität - für den vollständigen Portscan (1-65535, siehe
|
||||
* scanDeviceServices mit fullScan=true). Alle Ports auf einmal parallel zu
|
||||
* prüfen wäre bei 65535 Ports zu viel gleichzeitig offener Sockets; komplett
|
||||
* nacheinander wäre selbst bei schnellen RSTs zu langsam. Ein Batch von 500
|
||||
* ist ein guter Mittelweg für ein Gerät im lokalen Netz.
|
||||
*/
|
||||
export async function scanPortsInBatches(
|
||||
host: string,
|
||||
ports: number[],
|
||||
batchSize = 500,
|
||||
timeoutMs = 600
|
||||
): Promise<number[]> {
|
||||
const open: number[] = [];
|
||||
for (let i = 0; i < ports.length; i += batchSize) {
|
||||
const batch = ports.slice(i, i + batchSize);
|
||||
const results = await Promise.all(
|
||||
batch.map(async (port) => ({ port, open: await isPortOpen(host, port, timeoutMs) }))
|
||||
);
|
||||
for (const r of results) if (r.open) open.push(r.port);
|
||||
}
|
||||
return open;
|
||||
}
|
||||
|
||||
/** Alle Ports von 1 bis 65535 - für den vollständigen (statt nur "typische Ports") Scan eines einzelnen Geräts. */
|
||||
export function fullPortRange(): number[] {
|
||||
const ports: number[] = [];
|
||||
for (let p = 1; p <= 65535; p++) ports.push(p);
|
||||
return ports;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user