- 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 конфигурацией для новых сервисов
44 lines
1.2 KiB
PHP
44 lines
1.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Domovoy\Services\Discovery;
|
|
|
|
class ArpTableReader
|
|
{
|
|
/**
|
|
* Read ARP table from system.
|
|
* Returns array keyed by IP => ['mac' => '...', 'vendor' => '...']
|
|
*/
|
|
public function read(): array
|
|
{
|
|
$entries = [];
|
|
|
|
// Try ip neigh first (modern Linux)
|
|
$output = [];
|
|
$exitCode = 0;
|
|
exec('ip neigh show 2>/dev/null', $output, $exitCode);
|
|
if ($exitCode === 0) {
|
|
foreach ($output as $line) {
|
|
if (preg_match('/^(\d+\.\d+\.\d+\.\d+)\s+.*lladdr\s+([0-9a-f:]+)/i', $line, $m)) {
|
|
$entries[$m[1]] = ['mac' => strtolower($m[2]), 'vendor' => null];
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback: arp -a
|
|
if (empty($entries)) {
|
|
exec('arp -a 2>/dev/null', $output, $exitCode);
|
|
if ($exitCode === 0) {
|
|
foreach ($output as $line) {
|
|
if (preg_match('/\((\d+\.\d+\.\d+\.\d+)\)\s+at\s+([0-9a-f:]+)/i', $line, $m)) {
|
|
$entries[$m[1]] = ['mac' => strtolower($m[2]), 'vendor' => null];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $entries;
|
|
}
|
|
}
|