Итерация 2: сканирование сети
- Phinx миграции: network_ranges, scan_jobs, discovered_hosts, audit_log - Models: NetworkRange, ScanJob, DiscoveredHost - Repositories с CRUD для всех сущностей - NetworkScanner: ping sweep + TCP connect + ARP table + reverse DNS - PingScanner, TcpPortScanner (curl_multi для параллелизма), ArpTableReader - HostFingerprintService: vendor detection + confidence scoring - ScanJobRunner + CLI worker (bin/run-scan-worker.php) - Discovery UI: управление диапазонами, запуск скана, таблица находок - NetworkRangeController с валидацией CIDR - Обновлён public/index.php с DI конфигурацией для новых сервисов
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CLI worker for running pending scan jobs.
|
||||
*
|
||||
* Usage:
|
||||
* php bin/run-scan-worker.php # Run one pending job and exit
|
||||
* php bin/run-scan-worker.php --loop # Infinite loop, process all pending jobs
|
||||
*/
|
||||
|
||||
require dirname(__DIR__) . '/vendor/autoload.php';
|
||||
|
||||
$dotenv = \Dotenv\Dotenv::createImmutable(dirname(__DIR__));
|
||||
$dotenv->safeLoad();
|
||||
|
||||
$pdo = new PDO(
|
||||
sprintf(
|
||||
'mysql:host=%s;port=%d;dbname=%s;charset=utf8mb4',
|
||||
getenv('DB_HOST') ?: 'db',
|
||||
(int)(getenv('DB_PORT') ?: 3306),
|
||||
getenv('DB_DATABASE') ?: 'domovoy'
|
||||
),
|
||||
getenv('DB_USERNAME') ?: 'domovoy',
|
||||
getenv('DB_PASSWORD') ?: 'domovoy',
|
||||
[
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
]
|
||||
);
|
||||
|
||||
// Build dependencies manually (no DI container in CLI)
|
||||
$logger = new \Monolog\Logger('domovoy');
|
||||
$logger->pushHandler(new \Monolog\Handler\StreamHandler(dirname(__DIR__) . '/storage/logs/scan-worker.log', \Monolog\Level::Debug));
|
||||
|
||||
$networkRangeRepository = new \Domovoy\Repositories\NetworkRangeRepository($pdo);
|
||||
$scanJobRepository = new \Domovoy\Repositories\ScanJobRepository($pdo);
|
||||
$discoveredHostRepository = new \Domovoy\Repositories\DiscoveredHostRepository($pdo);
|
||||
|
||||
$pingScanner = new \Domovoy\Services\Discovery\PingScanner();
|
||||
$tcpPortScanner = new \Domovoy\Services\Discovery\TcpPortScanner();
|
||||
$arpTableReader = new \Domovoy\Services\Discovery\ArpTableReader();
|
||||
$fingerprintService = new \Domovoy\Services\Discovery\HostFingerprintService();
|
||||
|
||||
$networkScanner = new \Domovoy\Services\Discovery\NetworkScanner(
|
||||
$pingScanner,
|
||||
$tcpPortScanner,
|
||||
$arpTableReader,
|
||||
$fingerprintService,
|
||||
$discoveredHostRepository
|
||||
);
|
||||
|
||||
$runner = new \Domovoy\Services\Jobs\ScanJobRunner($scanJobRepository, $networkScanner);
|
||||
|
||||
$loopMode = in_array('--loop', $argv, true);
|
||||
|
||||
if ($loopMode) {
|
||||
echo "Scan worker running in loop mode. Press Ctrl+C to stop.\n";
|
||||
$logger->info('Scan worker started in loop mode');
|
||||
|
||||
// Handle SIGTERM for graceful shutdown
|
||||
if (function_exists('pcntl_signal')) {
|
||||
pcntl_signal(SIGTERM, function () use ($logger) {
|
||||
$logger->info('Received SIGTERM, shutting down gracefully');
|
||||
exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
while (true) {
|
||||
$job = $runner->runNext();
|
||||
if ($job === null) {
|
||||
sleep(5);
|
||||
continue;
|
||||
}
|
||||
$logger->info('Scan job completed', ['job_id' => $job->id, 'status' => $job->status]);
|
||||
if (function_exists('pcntl_signal_dispatch')) {
|
||||
pcntl_signal_dispatch();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$job = $runner->runNext();
|
||||
if ($job === null) {
|
||||
echo "No pending scan jobs found.\n";
|
||||
} else {
|
||||
echo "Scan job #{$job->id} completed: {$job->status}\n";
|
||||
if ($job->errorMessage !== null) {
|
||||
echo "Error: {$job->errorMessage}\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user