Перейти к содержимому

Сканирование портов (discovery)

Сканирование портов (port discovery) отвечает на вопрос «какие TCP-порты вообще открыты на этом хосте?». Notifly перебирает порты профиля или заданного диапазона, пробует подключиться к каждому и собирает список открытых. В отличие от порт-монитора, который непрерывно следит за известным набором портов, скан — это разовая (или периодическая) инвентаризация: вы ещё не знаете, что слушает на хосте, и хотите это выяснить.

Типичный путь: запустили скан → посмотрели найденные порты → одним запросом превратили результат в непрерывный порт-монитор, который будет алёртить, если какой-то из этих портов вдруг закроется.

создаёте задачу скана → status=pending
└─▶ сканер Notifly (запускается раз в минуту) берёт задачу,
резолвит хост в IP (resolvedIP) → status=running
└─▶ за каждый проход проверяет очередную порцию портов:
TCP-подключение с таймаутом timeoutSec на порт,
открытые порты сразу добавляются в foundPorts (CSV)
└─▶ порты кончились → status=completed, отчёт в канал appid
  • Скан выполняется из облака Notifly, поэтому хост должен быть доступен из интернета. Приватные, loopback- и link-local-адреса (10.x, 192.168.x, 127.0.0.1, 169.254.x и т. п.) сканер не опрашивает — подключения к ним блокируются, и такой скан завершится без открытых портов.
  • Скорость зависит от того, подтверждено ли владение хостом: для подтверждённого хоста за проход проверяется до 350 портов (16 подключений параллельно), для неподтверждённого — до 50 (6 подключений). Ориентировочно при свободной очереди: quick — около 1–2 минут, standard — около 4 минут с подтверждением и 20+ минут без, full — около 3 часов с подтверждением и сутки без.
  • cursor — сколько портов уже пройдено; по нему админка показывает прогресс. foundPorts накапливается на лету — частичный результат виден до завершения скана.
  • По ходу длинного скана в канал приходят уведомления о прогрессе (около 25, 50 и 75 %, приоритет 0), по завершении — отчёт (см. ниже).
  • У одного пользователя не может быть двух активных сканов одного хоста (409). Если тот же хост прямо сейчас сканирует другая задача, новая ждёт в pending; если есть завершённый скан этого хоста не старше 5 минут, его результат используется сразу (в lastError будет shared from recent scan).

Что сканировать, задаёт профиль (profile):

profileЧто сканируетПортов
quicknmap top-100 — самые частые TCP-порты99
standardпорты 1–1024 + 59 популярных портов выше 10241083
fullвесь диапазон 1–6553565535
customваш rangeFrom–rangeTo (по умолчанию 1–65535)задаёте сами

Для quick, standard и full сервер сам подставляет порты, а переданный диапазон игнорирует. В ответе у пресетных профилей rangeFrom/rangeTo — это 1…число портов профиля, а не номера портов.

  • appid — канал, в который придёт отчёт (обязательно): свой или расшаренный с правом отправки.
  • name — название задачи, 1–200 символов (обязательно).
  • host — имя хоста или IP (обязательно), без / и пробелов.
  • profile — quick / standard / full / custom, см. выше.
  • rangeFrom / rangeTo — границы диапазона для custom, каждая в [1, 65535], rangeFrom ≤ rangeTo. По умолчанию 1 и 65535.
  • timeoutSec — таймаут подключения к порту, по умолчанию 2, максимум 10.
  • repeatIntervalSec — 0 = одноразовый скан; > 0 = повторять каждые N секунд после завершения, минимум 3600 (1 час). См. Повторяющийся скан.
  • alertTitle / alertMessage / alertMessageMarkdown / alertPriority — оформление отчёта; alertPriority в [0, 10].

По завершении скана в канал appid приходит сообщение:

  • заголовок — alertTitle, а если он пуст — Скан портов завершён: <host>;
  • текст — ваш alertMessage (если задан) как префикс, затем сводка: хост и его IP, сколько портов просканировано, длительность, число открытых портов и их список (первые 50, дальше — «и ещё N»);
  • приоритет — alertPriority; при alertMessageMarkdown: true сообщение отображается как Markdown.

С repeatIntervalSec > 0 задача после завершения не остаётся completed: отчёт отправляется, найденные порты переезжают в prevFoundPorts, а сама задача возвращается в pending со стартом через repeatIntervalSec секунд. Поэтому между прогонами у повторяющегося скана foundPorts пуст, а результат последнего прогона — в prevFoundPorts; в админке по нему строится сравнение с предыдущим сканом (какие порты появились, какие закрылись).

Отменить повтор — POST /port-scan/:id/cancel или PATCH с "repeatIntervalSec": 0 (тогда очередной прогон станет последним).

Сканы расходуют отдельный дневной лимит тарифа portScansPerDay (в квоту событий dailyEvents они не входят). Лимит считает не задачи, а единицы: одна единица — каждая обработанная порция портов, каждое уведомление о прогрессе и итоговый отчёт.

ПланЕдиниц в день
Free10
Pro300
Business10000

Ориентировочный расход одного скана:

ПрофильХост подтверждёнХост не подтверждён
quick~2~4
standard~8несколько десятков
full~190больше 1300

То есть на Free помещается несколько quick-сканов в день, а полный скан реалистичен только для подтверждённого хоста на Pro или Business.

Если счётчик уже исчерпан, создание скана вернёт 429 (daily scan limit reached). Если лимит кончился посреди скана, задача завершается со статусом failed и lastError: "quota exceeded", а вам приходит уведомление о квоте. Счётчик обнуляется раз в сутки вместе с остальными дневными квотами — подробнее в Квотах и тарифах.

  1. Откройте app.notifly.ru → Мониторы → вкладка Порты → подвкладка Discovery.
  2. Нажмите «Просканировать хост», заполните название и хост, выберите профиль (Quick, Standard, Full или Диапазон), повторение, канал и, при желании, префикс сообщения отчёта. Таймаут на порт в диалоге создания — 2 секунды.
  3. Запустите — прогресс и найденные порты обновляются в списке. По кнопке «Подробности» — открытые порты, длительность и сравнение с предыдущим сканом.

Скан хоста, для которого уже есть порт-монитор, можно запустить и прямо из строки монитора — кнопкой «Просканировать все порты хоста (Discovery)».

Окно терминала
# Быстрый скан (top-100 портов), одноразовый
curl -X POST "$NOTIFLY_URL/port-scan" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <api-token>" \
-d '{
"appid": 12345,
"name": "Инвентаризация prod-хоста",
"host": "prod.example.com",
"profile": "quick",
"timeoutSec": 2,
"alertTitle": "Скан завершён",
"alertMessage": "Найдены открытые порты на prod.example.com",
"alertPriority": 5
}'
Окно терминала
# Свой диапазон, повторять раз в сутки
curl -X POST "$NOTIFLY_URL/port-scan" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <api-token>" \
-d '{
"appid": 12345,
"name": "Порты 8000–9000 на app-хосте",
"host": "app.example.com",
"profile": "custom",
"rangeFrom": 8000,
"rangeTo": 9000,
"timeoutSec": 3,
"repeatIntervalSec": 86400,
"alertMessage": "Диапазон 8000–9000 на app.example.com просканирован"
}'

Ответ — 201 и созданный объект скана со status: "pending", cursor: 0, пустым foundPorts и присвоенным id. Ошибки приходят в виде {"error": "..."}.

Окно терминала
# Список всех скан-задач
curl "$NOTIFLY_URL/port-scan" -H "X-Notifly-Key: <api-token>"
# Один скан — прогресс и найденные порты
curl "$NOTIFLY_URL/port-scan/777" -H "X-Notifly-Key: <api-token>"

В ответе смотрите status (pending → running → completed/failed/cancelled), cursor (сколько портов пройдено), foundPorts (CSV открытых портов), prevFoundPorts (результат прошлого прогона), resolvedIP, startedAt, completedAt. При failed причина — в lastError (например, ошибка резолва хоста или quota exceeded).

Окно терминала
# Отменить незавершённый скан
curl -X POST "$NOTIFLY_URL/port-scan/777/cancel" \
-H "X-Notifly-Key: <api-token>"
# Перезапустить завершённый/отменённый/упавший скан заново
curl -X POST "$NOTIFLY_URL/port-scan/777/restart" \
-H "X-Notifly-Key: <api-token>"
  • Отмена переводит скан в cancelled; для уже completed/cancelled скана вернётся 400.
  • Перезапуск доступен для скана, который не активен: предыдущий foundPorts уезжает в prevFoundPorts, прогресс сбрасывается, скан стартует заново. Если скан ещё pending/running — 400 (сначала отмените); если по этому хосту уже идёт другой ваш скан — 409.
  • Правка — PATCH /port-scan/:id с любым подмножеством полей appid, name, host, rangeFrom, rangeTo, timeoutSec (1–10), repeatIntervalSec, alertTitle, alertMessage, alertMessageMarkdown, alertPriority. Профиль не меняется. Пока скан running, правка запрещена (400); изменения действуют с ближайшего запуска скана.

Завершённый скан можно одним запросом превратить в непрерывный порт-монитор. Найденные порты (foundPorts) становятся expectedPorts нового монитора в режиме closed — он будет алёртить, если любой из обнаруженных портов закроется.

Окно терминала
curl -X POST "$NOTIFLY_URL/port-scan/777/to-monitor" \
-H "Content-Type: application/json" \
-H "X-Notifly-Key: <api-token>" \
-d '{
"name": "Порты prod.example.com",
"intervalSec": 300,
"timeoutSec": 5,
"alertTitle": "Port alert: prod.example.com",
"alertMessage": "Закрылся ожидаемый порт на prod.example.com",
"alertPriority": 7
}'

Тело запроса необязательно — у полей есть значения по умолчанию: name = Monitor <host>, intervalSec = 300, timeoutSec = 5, alertTitle = Port alert: <host>, alertMessage = Port closed on <host>, alertPriority = 0. Монитор наследует appid и host скана и создаётся без сообщения о восстановлении — его можно добавить потом через PUT /port-monitor/:id. Ответ — 201 и объект монитора.

Ограничения:

  • Скан должен быть в статусе completed (иначе 400). У повторяющегося скана этот статус не держится — сначала отключите повтор и дождитесь очередного прогона.
  • В скане должны быть найдены открытые порты — пустой foundPorts даст 400.
  • Дубли монитора по хосту сервер отсекает с 409, но пока ловит только монитор, который ещё не прошёл первую проверку, — перед созданием загляните в список порт-мониторов.

Авторизация — заголовок X-Notifly-Key с API-токеном. Токены каналов и share-токены на этих ручках не принимаются (403).

МетодПутьОписание
GET/port-scanСписок скан-задач пользователя
GET/port-scan/:idОдин скан: статус, прогресс (cursor), foundPorts
POST/port-scanСоздать скан (201; 429 — дневной лимит или 24-часовой cooldown полного скана; 409 — по хосту уже идёт ваш скан)
PATCH/port-scan/:idИзменить настройки (нельзя для running-скана)
DELETE/port-scan/:idУдалить скан-задачу
POST/port-scan/:id/cancelОтменить незавершённый скан
POST/port-scan/:id/restartПерезапустить неактивный скан заново
POST/port-scan/:id/to-monitorСоздать порт-монитор из найденных портов