Вы когда-нибудь заходили в супермаркет, где никого нет на кассе? Все вроде на месте, но чувство тревоги не отпускает: кто тут вообще отвечает за порядок? Так же и с инфраструктурой. Сервисы запускаются, тестовые окружения забываются, админы временно открывают порты – и периметр живет сам по себе. Когда мы в VK впервые попытались охватить его сканированием с помощью обычного nmap, стало ясно: это как вычерпывать море ложкой. Пока сканируешь, сеть уже изменилась.
Автор: Максим Казенков, DevOps-специалист, VK
Эту тему мы обсуждали на конференции OFFZONE – международной конференции по практической кибербезопасности, которая ежегодно собирает в Москве тысячи специалистов и сотни экспертов.
Живучие тени инфраструктуры
Легаси-сервисы – самые живучие создания на свете. Их не трогаешь годами, никто уже не помнит, кто их писал и зачем, но они все еще отвечают на запросы из интернета. А рядом – тестовые окружения, которые когда-то временно открыли наружу для отладки и так и забыли закрыть. Иногда бывает еще веселее: сетевой инженер ночью подкрутил настройки, что-то пошло не так, и внезапно внутренний сервис стал доступен извне. Все это не теория – обычные находки нашего сканера. Мы видели открытые панели управления, старые API с токенами, неубранные баннеры с именами систем. И каждая такая мелочь – потенциальная точка входа. Один забытый порт может стоить миллиона, как в кейсе университета Сан-Франциско [1]. Периметр не рушится одномоментно – он просто постепенно зарастает сорняками, если за ним не следить.
Почему стандартные сканеры не справляются?
Когда мы только начинали разбираться с периметром, казалось, что все просто: поставь nmap, запусти cron, собери отчет. Но через пару дней стало очевидно – на масштабе VK это не работает. Nmap хорош, когда у тебя десяток серверов. Когда их десятки тысяч, он превращается в тихий, но бесконечный процесс. Даже минимальное сканирование могло занять часы, а то и сутки, и пока мы ждали результат, часть сети уже успевала измениться.
Mascan, наоборот, летал как Доминик Торетто – быстро, шумно и с вау-эффектом. Но co скоростью приходила неточность: до 40% открытых портов он просто не видел. Да и с баннерами – беда. Хотели узнать, что реально висит на 443-м? А он отвечает: "Ну, вроде HTTPS". А на деле там SSH или админка, переименованная для маскировки.
Коммерческие сканеры сначала казались спасением – готовые базы CVE, интерфейсы, интеграции. Но быстро выяснилось, что стрелять из пушки по воробьям – дорого и медленно. Они не вписывались в наши SLA, а главное, не умели гибко адаптироваться под реальную инфраструктуру с IPv6, разными подсетями и геораспределением.
Так стало ясно: готовых решений под BigTech просто нет. Если хочешь контролировать свой периметр, придется строить систему под себя – быструю, распределенную и достаточно умную, чтобы отличить реальную дыру от ложноположительных срабатываний.
Как мы построили свой сканер nmon
Когда стало понятно, что стандартные решения не вытягивают, мы решили сделать свое – не ради амбиций, а потому что иначе просто ничего не получалось. Нам нужно было покрывать огромный периметр, укладываться в SLA, поддерживать IPv6 и при этом не утонуть в ложных срабатываниях. Так родился nmon – внутренний распределенный сканер, построенный под логику большого периметра VK.
Мы начали с простого: разделили инфраструктуру на ассеты – отдельные сервисы вроде VK Pay, GeekBrains, Одноклассников или ВКонтакте. Для каждого настроили собственные политики: какие порты смотреть, с какой скоростью сканировать, какие адреса не трогать. Белые списки спасают от бессмысленных тревог – например, когда агент пытается лезть в ханипот и срабатывает SOC.
Главная идея – распределенность. Агенты стоят в разных точках: Москва, Санкт-Петербург, Сочи и другие локации. Один и тот же сервис сканируется с нескольких направлений. Если Москва видит открытый порт, а Питер – нет, значит где-то сбоит сетевой фильтр. Такая перекрестная проверка убирает половину шумовых алертов.
Nmon работает в многопоточном режиме, синхронизируется с центральным модулем управления и складывает результаты в систему Vulnerability Management, где все визуализируется и уходит на обработку. Мы добавили обязательное снятие баннеров – теперь сканер не просто видит, что 443 порт открыт, а говорит "это Nginx такой-то версии".
В цифрах это выглядело впечатляюще: nmap сканировал 150 тыс. адресов почти два часа, mascan – 139 сек., а наш nmon справился за 28 сек., не потеряв точности. Он не такой быстрый, как mascan, но почти столь же легкий и при этом работает точнее, потому что видит контекст. С тех пор для нас это стало стандартом – скорость без понимания мало чего стоит.
Сложности и инженерные находки
Как только ты перестаешь думать о периметре в теории и начинаешь сканировать его по-настоящему, приходят неприятные, но полезные уроки. Первый и самый неожиданный – провайдеры и хостеры. Мы не раз натыкались на ситуацию, когда одно и то же задание с разных площадок давало разные результаты: с одного виртуального сервера все шло гладко, с другого – пакеты просто дропались. Звонки в поддержку, логирование, смена провайдера – и в итоге выяснялось, что сеть реагирует на высокую частоту запросов как на DDoS и защищается. Вывод прост: надо не только уметь гонять трафик, но и договариваться с инфраструктурой – снижать рейты, варьировать источники, согласовывать белые списки.
Второй момент – самозащита целевых систем. Когда сервис начинает видеть десятки агентов с разных концов страны,
он может временно заблокировать вас, применить капчу или Rate Limit. Поэтому мы постепенно научились делать сканы аккуратно: адаптивные скорости, выбор времени, привязка к бизнес-окнам. И да, это неизбежно требует диалога с владельцами сервисов – никакой автомат не должен ломать рабочие процессы.
Третий важный прием – корреляция. Один агент может показать порт открытым, другой — закрытым. Такая рассинхронизация не повод для паники, а сигнал разобраться в сетевой маршрутизации. Если, скажем, из Москвы порт виден, а из Петербурга — нет, значит где-то на уровне сети фильтр или ошибка конфигурации. Такой подход резко снижает шум и ускоряет реальное реагирование.
И последнее, о чем нельзя забывать, – надежность самой системы. Агенты умирают, правила меняются, конфиги теряются. Мы строили nmon так, чтобы при падении одного экземпляра другие подхватывали его задания – как в кластере: если одна нода легла, остальные перераспределяют нагрузку. Мониторинг живости агентов, алерты о деградации и автоматический фоллбек оказались не менее важны, чем сама логика сканирования.
Все эти инженерные пазлы не делают систему красивее на диаграммах, но они делают ее рабочей в реальном мире – а это то, ради чего все и затевалось.
Machine Learning как второй друг сканера
Когда nmon начал стабильно работать, мы поняли: дальше упираемся не в скорость, а в понимание. Найти открытый порт – полдела, но что за ним скрывается? Это обычный лендинг, микросервис, админка или вообще страница логина ВКонтакте? Так в проекте появился машинный интеллект – не ради хайпа, а чтобы отсеивать шум и подсвечивать действительно важное.
Мы начали с простых задач: классификация страниц по скриншотам, поиск аномалий в дизайне (вдруг кто-то перекрасил страницу после взлома), определение административных панелей. За основу взяли готовые архитектуры вроде MobileNet, а дальше начали обучать их на собственных данных. Оказалось, это небыстро: страниц много, интерфейсы у всех разные, баннеры то появляются, то исчезают. Но постепенно модель начала различать, где просто маркетинговая страница, а где панель администрирования, выставленная в интернет по ошибке.
Важно понимать – ML не заменяет людей. Мы постоянно проверяем, как модель себя ведет: где ошибается, где теряет точность, где, наоборот, начинает заучивать примеры и перестает видеть новое. Модель может ошибаться – принять Jira за блог или наоборот. Поэтому мы выстроили процесс обратной связи: если алгоритм ошибся, человек помечает пример, и система учится заново.
Постепенно стало ясно: машинное обучение не панацея, а инструмент приоритизации. Оно помогает быстрее понять, куда смотреть, какие сигналы критичны, а где просто фон. И главное – это живой цикл. Модель, как и сеть, постоянно меняется. Мы не стремимся к идеальному интеллекту, мы просто растим помощника, который каждый день становится чуть точнее.
Как мы ищем уязвимости и расставляем приоритеты
Сканер сам по себе не делает инфраструктуру безопасной – он лишь показывает, где что-то пошло не так. Дальше начинается самое скучное и при этом самое важное: анализ. Мы сознательно не лезем внутрь сервисов и не ломаем их. Первичная логика простая: сняли баннер, посмотрели версию, сверили с известными уязвимостями. Если совпадает – передаем на углубленное сканирование коммерческим инструментам или запускаем Open Source-решения вроде Nuclei.
Так мы делим процесс на два слоя. Первый – быстрый, наш nmon, который закрывает вопрос покрытия: кто вообще торчит наружу, какие сервисы живы, где внезапно появился новый порт. Второй – детальный, когда на основании этих данных уже идут точечные проверки, часто с применением ручного анализа. Особенно это касается кастомных систем, которых у нас немало. Они не попадают ни в одни шаблоны, и тут без участия инженера не обойтись: приходится заходить, смотреть, как построен сервис, и обучать ML на новых примерах.
Приоритеты мы выстраиваем по критичности ассетов. Есть сервисы, для которых даже один открытый порт – ЧП. А есть инфраструктурные зоны, где временная открытость допустима. Поэтому везде стоят разные SLA: где-то сканер должен уложиться в 15 минут, где-то – в час. Это позволяет не терять скорость и одновременно не топить людей в отчетах на десятки тысяч строк.
В итоге у нас получается не просто список дыр, а живой рейтинг рисков: что требует немедленной реакции, что можно закрыть в плановом порядке, а что стоит передать в мониторинг. Все это экономит часы анализа и позволяет тратить внимание на то, что действительно может привести к инциденту.
Итоги и выводы
За время работы над nmon мы убедились: периметр – это живой организм. Его нельзя проверить раз и навсегда, потому что каждый день он меняется, растет и стареет. Новые сервисы рождаются, старые забываются, правила в файрволах сбиваются, кто-то временно открывает доступ для теста – и вот уже наружу торчит то, что никогда не должно было быть доступно.
Сканер – не волшебная палочка, но это ваш лучший друг в этой среде. Он не заменяет SOC, не закрывает уязвимости, но дает понимание, где вы находитесь и что вообще происходит за границей вашего периметра. А машинное обучение – не магия, а способ не утонуть в потоке данных. Оно помогает увидеть закономерности и направить внимание туда, где риск действительно высок.
Мы поняли, что сила не в одном инструменте, а в сочетании подходов: распределенный сканер, ML для фильтрации, коммерческие решения для глубины. Вместе они дают ту самую наблюдаемость, без которой невозможно говорить о безопасности крупной компании.
И самое важное – осознанность. Любая автоматизация, любой ML имеют смысл только тогда, когда вы понимаете, зачем их внедряете.
Когда мы только начинали, идея собственного сканера казалась чем-то избыточным. Сегодня трудно представить, как жить без него. В каждом релизе, в каждом изменении инфраструктуры он напоминает о простом факте: безопасность не измеряется количеством патчей, а скоростью, с которой ты замечаешь новое. Nmon не сделал нас неуязвимыми, но дал нам возможность видеть и реагировать быстрее, чем проблема успевает перерасти в инцидент.
Редакция благодарит организаторов OFFZONE 2025 за содействие в подготовке материала.