При наличии большого количества подсетей зачастую требуется аудит и мониторинг адресного пространства в них, для этого прекрасно подходит такой инструмент, как IPAM.
В качестве инструмента будем использовать Netbox и nmap.
Установка
Для установки нам потребуется скачать уже готовый скрипт от пользователя @lckrspirit с gitlab.
Для удобства его можно разместить где ни будь в каталоге c NetBox.
Качаем nmap, устанавливаем зависимости:
---Активируем виртуальное окружение (например в venv Netbox)--
$ cd/usr/local/share/netbox/
$ .venv/bin/activate
(venv)$ cd /usr/local/share/netbox/scripts
(venv)$ git clone https://gitlab.com/lckrspirit/netbox-ipam-auto-discovery.git
(venv)$ cd netbox-ipam-auto-discovery/
(venv)$ pip install python-nmap pynetbox
Так же его можно скачать
Заходим в NetBox в меню "Аутентификация" и получаем токен для обращения к API:

Генерируем токен (под суперпользователем это лучше не делать, а создать отдельного)

Открываем скрипт текстовым редактором и вводим адрес NetBox и сгенерированный Token

P.S. В netbox_url должны быть указаны адреса перечисленные в блоке "ALLOWED HOSTS" файла конфигурации Netbox configuration.py.
Запуск скрипта
Для запуска сканирования сети достаточно выполнить:
Теперь можно идти в меню IPAM и мы увидим отсканированные IP адреса.

Если мы еще добавим сеть в меню "Диапазоны IP- адресов мы сможем увидеть статистику использование адресного пространства в данном сегменте сети.

Скрипт сам обновляет и удаляет адреса, его можно назначить в задания cron на выполнение к примеру каждые 3 часа.
Дополнительно мы можем создать VLAN, группы и назначения, после чего связать с существующим диапазоном адресов.
Что бы мы могли видеть еще и свободные адреса, необходимо добавить префикс для нашей сети:

Указываем нашу сеть в поле префикс, статус, и ставим флаг, что данная сеть является пулом.
Синхронизация DNS записей.
Если в качестве DNS сервера используется роль Windows Server, то можно при помощи powershell-скрипта сопоставить найденные nmap ip адреса с записями DNS.
Пример скрипта:
.SYNOPSIS
Скрипт для синхронизации DNS записей с NetBox
.DESCRIPTION
Получает A-записи из DNS и обновляет соответствующие IP-адреса в NetBox с DNS именами
.NOTES
Требует модуля DnsServer для работы с DNS (устанавливается через Install-WindowsFeature RSAT-DNS-Server)
#>
#region Параметры
param (
[string]$ConfigFile = "config.json" # Файл конфигурации
)
# Загрузка конфигурации
try {
if (-not (Test-Path $ConfigFile)) {
throw "Конфигурационный файл не найден"
}
$config = Get-Content $ConfigFile | ConvertFrom-Json
# Обязательные параметры
$netboxUrl = $config.netboxUrl
$netboxToken = $config.netboxToken
$dnsServer = $config.dnsServer
$dnsZone = $config.dnsZone
# Проверка обязательных параметров
if ([string]::IsNullOrEmpty($netboxUrl) -or
[string]::IsNullOrEmpty($netboxToken) -or
[string]::IsNullOrEmpty($dnsServer) -or
[string]::IsNullOrEmpty($dnsZone)) {
throw "Не все обязательные параметры указаны в конфигурации"
}
}
catch {
Write-Error "Ошибка загрузки конфигурации: $_"
exit 1
}
#endregion
#region Вспомогательные функции
function Test-NetBoxConnection {
try {
$uri = "$netboxUrl/api/status/"
Write-Host "Проверка подключения к NetBox..."
$headers = @{
"Authorization" = "Token $netboxToken"
"Accept" = "application/json"
}
$response = Invoke-RestMethod -Uri $uri -Method Get -Headers $headers -TimeoutSec 5
if ($response) {
Write-Host "Подключение успешно. Версия NetBox: $($response.netbox_version)" -ForegroundColor Green
return $true
}
}
catch {
Write-Error "Ошибка подключения к NetBox: $($_.Exception.Message)"
return $false
}
}
function Invoke-NetBoxRequest {
param(
[string]$Endpoint,
[string]$Method = "GET",
[object]$Body = $null
)
$uri = "$netboxUrl/api/$($Endpoint.TrimStart('/'))"
try {
$headers = @{
"Authorization" = "Token $netboxToken"
"Accept" = "application/json"
}
$params = @{
Uri = $uri
Method = $Method
Headers = $headers
TimeoutSec = 10
}
if ($Body -ne $null) {
$params["ContentType"] = "application/json"
$params["Body"] = $Body | ConvertTo-Json -Depth 3
}
return Invoke-RestMethod @params
}
catch {
Write-Warning "Ошибка запроса к $uri : $($_.Exception.Message)"
return $null
}
}
function Get-NetBoxIpRecord {
param([string]$ipAddress)
$response = Invoke-NetBoxRequest "ipam/ip-addresses/?address=$ipAddress"
if (-not $response) { return $null }
foreach ($record in $response.results) {
$recordIp = ($record.address -split '/')[0]
if ($recordIp -eq $ipAddress) {
return $record
}
}
return $null
}
function Test-DnsServerConnection {
try {
Write-Host "Проверка подключения к DNS серверу $dnsServer..."
$test = Get-DnsServerZone -ComputerName $dnsServer -Name $dnsZone -ErrorAction Stop
return $true
}
catch {
Write-Error "Ошибка подключения к DNS серверу: $_"
return $false
}
}
function Clean-DnsName {
param([string]$name)
# Удаляем лишние символы и лишние точки
$cleanName = $name -replace '[^a-zA-Z0-9\-\.]', '' -replace '\.+', '.' -replace '^\.|\.$', ''
return $cleanName
}
#endregion
#region Основной процесс
try {
# Проверка подключений
if (-not (Test-NetBoxConnection)) { exit 1 }
if (-not (Test-DnsServerConnection)) { exit 1 }
Write-Host "Получение DNS записей из зоны $dnsZone..."
$dnsRecords = Get-DnsServerResourceRecord -ZoneName $dnsZone -ComputerName $dnsServer -ErrorAction Stop |
Where-Object { $_.RecordType -eq "A" }
$totalRecords = $dnsRecords.Count
$processed = 0
$updated = 0
foreach ($record in $dnsRecords) {
$processed++
$ip = $record.RecordData.IPv4Address.IPAddressToString
$name = $record.HostName
$cleanName = Clean-DnsName -name $name
Write-Progress -Activity "Синхронизация с NetBox" -Status "Обработка $processed из $totalRecords" -PercentComplete ($processed/$totalRecords*100)
$nbRecord = Get-NetBoxIpRecord -ipAddress $ip
if (-not $nbRecord) {
Write-Warning "IP $ip ($cleanName) не найден в NetBox"
continue
}
if ([string]::IsNullOrWhiteSpace($cleanName)) {
Write-Warning "Не удалось получить корректное DNS имя для IP $ip"
continue
}
if ($nbRecord.dns_name -ne $cleanName) {
Write-Host "Обновление: $ip ($(if ($nbRecord.dns_name) { $nbRecord.dns_name } else { 'нет имени' }) → $cleanName)"
$result = Invoke-NetBoxRequest "ipam/ip-addresses/$($nbRecord.id)/" -Method PATCH -Body @{dns_name = $cleanName}
if ($result) {
$updated++
Write-Host "Успешно обновлено" -ForegroundColor Green
}
}
}
Write-Host "Синхронизация завершена. Обработано записей: $processed, обновлено: $updated" -ForegroundColor Cyan
}
catch {
Write-Error "Критическая ошибка: $_"
exit 1
}
#endregion
Конфигурационный файл в формате json (должен находиться в одном каталоге со скриптом при запуске через планировщик).
"netboxUrl": "https://netbox.example.com",
"netboxToken": "1234546789qaweasdzxc456789qwe456",
"dnsServer":example.com"
}
Данный скрипт можно закинуть в планировщик задач и запускать его по расписанию.
$trigger = New-ScheduledTaskTrigger -Daily -At 3am
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopOnIdleEnd -ExecutionTimeLimit (New-TimeSpan -Hours 1)
Register-ScheduledTask -TaskName "Sync NetBox DNS" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest -Description "Синхронизация A-записей DNS с NetBox"