Весь диапазон IPv4 адресов — это 4-миллиарда IP-адресов. Это кажется огромной цифрой, но весь IPv4 интернет можно полностью просканировать на предмет одного TCP-порта за 40 минут, например найти все веб-серверы в мире или все открытые SSH-порты. При этом достаточно одного сервера и гигабитного канала. Это полезно для исследований, например если вы собираете статистику по используемым технологиям в мире, или оцениваете процент уязвимых сервисов, открытых наружу.
Программа zmap (не путать с nmap) позволяет сканировать огромные диапазоны сетей намного быстрее любого сканера из-за особой архитектуры. В статье мы рассмотрим пример как собрать список всех веб-серверов в мире с помощью zmap. Имея список хостов с открытым HTTP портом, уже можно использовать более интеллектуальный сканер, передавая ему точный список целей.
Чем плох nmap
Для сканирования небольших подсетей традиционно используется Nmap — популярный мультитул с открытым кодом и массой пентестерских плюшек внутри. Он хорошо подходит для сканирования небольших диапазонов и выборочных хостов. У nmap есть собственный движок для написания пользовательских скриптов на языке lua (Nmap Script Engine) и много крутых готовых скриптов. Но nmap плохо подходит для сканирования больших сетей, вроде миллионов или даже миллиардов адресов. Такие задачи займут несколько дней или даже недель. Дело в том, что nmap использует сетевую подсистему операционной системы и на каждый запрос открывается полноценный сокет. Без этого не обойтись для полноценного TCP-подключения, когда нужно пообщаться с сервисом, например сделать GET-запрос на веб-сервер. Но это сильно снижает производительность, когда требуется быстрое SYN-сканирование, где стоит задача только узнать открыт ли порт.
Zmap и Masscan
Нам больше подойдут асинхронные сканеры Zmap и Masscan: оба работают значительно быстрее, используют драйвер PF_RING (сокет, значительно ускоряющий захват пакетов) и рандомизируют адреса, чтобы избежать убойного DoS'a. В отличие от Nmap, они не используют системный TCP/IP: первый генерирует голые Ethernet-фреймы, второй использует самописный TCP-стек.
Masscan считается самым быстрым сканером интернета, способным пройтись по всему IPv4 диапазону за шесть минут, но только при нескольких параллельно подключенных физических адаптерах, с одного генерируется исходящий трафик с SYN-пакетам, а на другой приходят ответы. В условиях одиночного подключения доработанный Zmap оказался почти в полтора раза быстрее. Эти рекорды, разумеется, ставились на топовом железе на каналах 10 Гбит/c, и повторить их самостоятельно будет сложно и дорого. На куда более доступном гигабитном подключении Zmap тоже работает быстрее чем Masscan за счёт более эффективного использования ресурсов канала и CPU и справляется примерно за 45-50 минут.
Упрощенная схема работы Zmap и Masscan. Отдельно работает генератор исходящего трафика и обработчик входящих ответов
Если не вдаваться в технические подробности, Zmap и Masscan используют две сущности: генератор исходящего трафика содержащего SYN-запросы и отдельно обработчик входящих ответов. Производительность здесь ограничена только шириной канала и производительностью сетевого интерфейса, а именно лимитом PPS (packets per second). Поэтому процесс сканирования можно разделить на несколько интерфейсов или даже несколько физических хостов, если существует возможность подменять Source IP на адрес обработчика входящих пакетов.
Подготовка к сканированию
Нужно иметь в виду, что сканер сильно нагружает систему и особенно сетевые интерфейсы, утилизируя весь доступный канал. Если начать сканирование без предупреждения хостера, это будет выглядеть как DDoS и вас скорее всего очень быстро отключат от сети. Также нужно быть готовым, что сканирование всего интернета спровоцирует ответную реакцию — на вас начнут жаловаться. То есть хостеру придет пачка автоматических писем с жалобами «вы нас сканируете».
Так что перед началом своего проекта лучше подготовиться:
- Сообщите хостеру о своих планах — поддерживайте связь с администратором сети чтобы иметь возможность оперативно реагировать на проблемы (или чьё-то недовольство по поводу забитого канала). Убедитесь, что сканирование не будет перегружать локальную сеть или маршрутизаторы провайдера. Начинайте только после получения явного согласия от хостера.
- Установите PTR-запись — ваши действия наверняка спровоцируют автоматические системы обнаружения сканирования, на эти логи посмотрят системные администраторы. Попытайтесь сделать то, что они увидят, максимально понятным. Например, установите информативную PTR запись для IP-адреса, с которого будет происходить сканирование, что-то вроде:
scanner-for-educational-project.ivan-ivanov.com
- Добавьте пояснения в User-Agent — если вы сканируете веб и выполняете какие-то HTTP-запросы, установите дополнительные объяснения в User-Agent, четко объясните цель и объем сканирования. Там же можно добавить ссылку на страницу, объясняющую цели проекта.
- Рандомизируйте адреса — по возможности не сканируйте сети подряд, это выглядит как явный вредоносный паттерн поведения. Используйте случайный порядок целевых адресов.
NAT, фильтры и фаероволы
Важно понимать, что zmap генерирует одновременно миллионы TCP-запросов. Если между интернетом и сканирующим сервером будет установлен роутер с NAT, фаерволл с connection tracking, DDoS-защита или любая другая система со stateful фаерволом, пытающаяся отслеживать подключения, она сломается из-за того, что не сможет переварить столько подключений. Поэтому запускать zmap находясь NAT-ом, например за домашним WiFi-роутером, нельзя.
Пробуем Zmap
Установите Zmap (инструкция)
Протестируйте на чём-нибудь простом, посмотрим соседние веб-сервера с habr.com:
$ zmap -p 80 178.248.237.0/24 -B 100M -o habr.txt
Опции:
- -p 80 — порт TCP 80, то есть ищем только HTTP серверы
- 178.248.237.0/24 — целевой диапазон адресов. Если его не указать, будет просканирован весь интернет
- -B 100M — максимальная ширина канала, которую использует zmap. Если эту опцию не указать, будет утилизирован весь доступный канал
- -o habr.txt — записать результаты в текстовый файл. В него попадет адреса которые ответили на запрос, то есть на которых есть HTTP-сервер
Сканирование 254 адресов с помощью zmap заняло несколько секунд
Форматы вывода zmap
По умолчанию zmap просто складывает найденные адреса в текстовый файл отделяя их переносом строки. Но также может писать результаты в формате json и xml. Опция --output-fields позволяет указать дополнительные поля, которые будет добавлены в вывод.
Попробуем для примера более расширенный формат вывода в json, с указанием порта, на которым пришел ответный запрос и TTL пакета:
$ zmap -p80 --output-module=json --output-fields=ttl,sport,dport,saddr 178.248.237.68 -o habr.com.json
# Посмотрим результат
$ cat habr.com.json
{ "ttl": 58, "sport": 80, "dport": 51309, "saddr": "178.248.237.68" }
Сканируем весь интернет!
Я попробовал запустить сканирование на VPS, и через несколько минут меня забанили с требованием проверить сервер на наличие вирусов. Это вполне логично, ведь такое сканирование выглядит как DDoS со стороны хостера. Но после обсуждения моей задачи с поддержкой, мне предложили взять выделенный сервер и сканировать на нем.
Так выглядит сканирование на интерфейсе 200Mbit/s, прогнозируемое время около шести часов:
Даже с каналом в 100 Mbit/s весь интернет можно просканировать за ночь.
Что делать с этим дальше
Теперь мы можем сказать сколько мире адресов слушают порт 80 и собрать их список. Его можно направить в L7-сканер чтобы проанализировать на application layer на предмет уязвимостей.
Например, получить HTML Title всех веб-серверов в мире с помощью nmap. На вход nmap передаем файл полученный от zmap в обычном формате:
$ nmap -sV -p 80 -v -n --script http-title -iL habr.txt