Автоматическая инвентаризация сети: nmap и список хостов в CSV

0
10
Обложка статьи: Автоматическая инвентаризация сети: nmap и список хостов в CSV

Управлять активами, которых нет в списке, невозможно: неизвестный сервер не попадёт в план обновлений и не будет проверен сканером уязвимостей. Ручной список быстро устаревает, поэтому инвентаризацию стоит повторять автоматически. Самый доступный инструмент для сети — nmap: он находит отвечающие хосты и определяет, какая служба слушает на каждом открытом порту. Ниже скрипт и результаты проверки на тестовой сети с тремя узлами.

Статья опирается на логику направления «Управление ИТ-активами» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Проверка выполнена на изолированной тестовой сети Docker, после неё всё удалено.

Что должно получиться

Уровень Что это значит на практике
1. Начальный Есть актуальный список серверов и служб в сети, он обновляется автоматически, а не по памяти ответственного

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

Скрипт инвентаризации

Скрипт сначала находит отвечающие хосты в подсети (nmap -sn, без сканирования портов), затем для каждого хоста определяет открытые порты и службы и собирает результат в CSV:

#!/usr/bin/env bash
# Инвентаризация сети: какие хосты и службы отвечают в указанной подсети. Только обнаружение, без эксплуатации.
# Запускать с правом на сканирование этой сети (согласие владельца инфраструктуры).
set -euo pipefail
NET="${1:?укажите подсеть, например 10.77.0.0/24}"
# top-1000 nmap + типовые порты инфраструктуры, которые в топ-1000 не входят (базы, кэши, админки)
EXTRA_PORTS="3306,5432,6379,9200,11211,27017,5984,2181,9092,8443,8080,9090,3000"
OUT="inventory-$(date +%Y%m%d-%H%M).csv"
echo "ip,hostname,port,service,product,version" > "$OUT"
nmap -sn "$NET" -oG - | awk '/Up$/{print $2}' > /tmp/hosts.$$
while read -r ip; do
  nmap -sV -T4 --open -p "1-1000,$EXTRA_PORTS" "$ip" -oX - 2>/dev/null | python3 -c "
import sys, xml.etree.ElementTree as ET
root = ET.fromstring(sys.stdin.read())
for host in root.findall('host'):
    ip = host.find('address').get('addr')
    names = host.find('hostnames')
    name = names.find('hostname').get('name') if names is not None and names.find('hostname') is not None else ''
    for p in host.findall('.//port'):
        state = p.find('state').get('state')
        if state != 'open':
            continue
        svc = p.find('service')
        service = svc.get('name') if svc is not None else ''
        product = svc.get('product','') if svc is not None else ''
        version = svc.get('version','') if svc is not None else ''
        print(f'{ip},{name},{p.get(\"portid\")},{service},{product},{version}')
" >> "$OUT"
done < /tmp/hosts.$$
rm -f /tmp/hosts.$$
echo "готово: $OUT, строк: $(($(wc -l < "$OUT") - 1))"

Запуск: ./inventory.sh 10.0.5.0/24. Сканирование сети требует права её владельца: даже обнаружение портов посторонней сети без согласия может расцениваться как инцидент на стороне получателя.

Результат проверки

Тестовая сеть из трёх контейнеров: веб-сервер, Redis и PostgreSQL. Первый запуск с портами по умолчанию (топ-1000 портов nmap) дал только два хоста из трёх:

IP Порт Служба Версия
10.88.0.10 80 http nginx 1.25.5
10.88.0.30 5432 postgresql PostgreSQL

Redis на порту 6379 в список не попал, хотя порт был открыт (проверка отдельным сканированием -p 6379 и прямым запросом к службе). Причина — в nmap порты для сканирования по умолчанию выбираются по частоте встречаемости в его собственной базе, и 6379 в неё по частоте не попадает даже при --top-ports 2000. Полное сканирование всех 65535 портов (-p-) порт находит, но на крупной сети это ощутимо медленнее. Поэтому в скрипте топ-1000 портов явно дополнен списком типовых портов баз данных, кэшей и админок (3306, 5432, 6379, 9200, 11211, 27017, 5984, 2181, 9092 и другие). После этого Redis и PostgreSQL попали в список оба:

ip,hostname,port,service,product,version
10.88.0.10,inv-web.inv-net,80,http,nginx,1.25.5
10.88.0.20,inv-redis.inv-net,6379,redis,Redis key-value store,7.4.11
10.88.0.30,inv-db.inv-net,5432,postgresql,PostgreSQL DB,9.6.0 or later

Вывод: список портов по умолчанию в любом сканере рассчитан на типичный интернет-хост, а не на внутреннюю инфраструктуру. Для инвентаризации собственной сети список портов нужно дополнять вручную под используемые системы.

Что делать с результатом

  • Сравнивайте с предыдущим запуском: новый IP или порт, которого не было вчера, — повод разобраться, легитимно это или нет.
  • Сверяйте с учётной системой: если хост отвечает, но не внесён в реестр активов, у него нет ответственного и плана обновлений.
  • Передавайте список в сканер уязвимостей: проверка нужна именно по отвечающим хостам и портам, а не по списку «что мы помним».
  • Отмечайте незнакомые службы отдельно: неожиданный порт на известном хосте стоит проверить до внесения в реестр.

Порядок внедрения

  1. Определите подсети, которые нужно инвентаризировать, и получите согласие владельцев инфраструктуры.
  2. Дополните список портов под используемые в компании системы (базы, оркестраторы, админ-панели).
  3. Запускайте по расписанию (еженедельно для рабочих сетей, чаще для периметра) и храните историю результатов, а не только последний снимок.
  4. Сверяйте с реестром активов и заводите запись на каждый новый хост.
  5. Настройте уведомление о новых IP или портах, которых не было в прошлом запуске.
  6. Передайте результат в процесс управления уязвимостями: от скана до закрытия.

Диагностика

Симптом Причина и что делать
Известная служба не попадает в список Её порт не входит в топ-1000 nmap. Добавьте порт в список явно или используйте -p- для полной проверки
Хост не отвечает на -sn, но работает ICMP может быть заблокирован файрволом. Используйте -Pn, чтобы считать хост доступным без предварительного пинга, и проверьте точечно известные порты
Сканирование долгое на крупной сети Увеличьте параллелизм (-T4, уже включён) и сканируйте подсети частями или по расписанию ночью
Результат отличается от запуска к запуску Нормально для динамических адресов (DHCP, контейнеры). Сверяйте по MAC-адресу или имени хоста, а не только по IP
Версия службы определена неверно Определение версии (-sV) работает по сигнатурам и может ошибаться, особенно на нестандартных портах. Используйте как ориентир, не как точный факт

Ограничения

Сканирование видит только то, что отвечает по сети: выключенные хосты, устройства за NAT без прямой видимости и узлы с полностью закрытым файрволом в список не попадут. Это не заменяет учёт активов через управление конфигурациями и агенты на хостах, а дополняет его независимой проверкой «что реально отвечает в сети сейчас».

Где это в модели зрелости

Материал относится к направлению «Управление ИТ-активами» (материалы направления, карта зрелости). Начальный уровень требует хотя бы актуального списка активов: автоматическая инвентаризация сети даёт такой список без постоянной ручной работы и служит входом для управления уязвимостями и учёта активов.

Как проверить

  1. Инвентаризация запускается по расписанию, а не только когда кто-то вспомнил.
  2. Список портов дополнен под используемые в компании системы, а не ограничен значениями по умолчанию.
  3. Новые хосты и порты, которых не было в прошлом запуске, попадают в уведомление.
  4. Каждый отвечающий хост сверен с реестром активов и имеет ответственного.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • Документация nmap: nmap.org.

Оставьте свой ответ