Home Research Царь всея Сети: исследование концепции распределенного анализатора трафика

Царь всея Сети: исследование концепции распределенного анализатора трафика

by Denis Makrushin
1.3K views

 

Хакер № 13/10 (144)

 

Нестандартный подход к задачам классическим может привести к рождению инновационной идеи. Привычный инструмент (например, сниффер), который позволяет нам решать какую-либо задачу (анализ траффика), при взгляде на него с другой позиции дает шанс разработчику получить на выходе нечто принципиально новое. Рассмотрим формулу «сниффер+распределение» и докажем, что ее результат – не просто «распределенный сниффер».

Ниша сетевых анализаторов плотно занята продуктами с самым разнообразным функционалом и вряд ли очередной самодельный сниффер будет выделяться своей оригинальностью. Среди бесплатных аналогов, пожалуй, флагманом является мультиплатформенный Wireshark: продвинутые фильтры по протоколам, гибкие средства автоматизации анализа протоколов и восстановления TCP-потоков, средства фильтрации и поиска пакетов по множеству параметров и формирования статистических данных и прочие функции делают этот сетевой анализатор на голову выше своих бесплатных конкурентов. Среди платных ему не уступает, а в ряде случаев, превосходит платный продукт CommView.

Выбор конкретного инструмента прежде всего зависит от задачи, которая с помощью него решается. Wireshark для обеспечения своей работоспособности использует библиотеку PCAP (Packet Capture), что в ряде случаев может не дать нужного результата. Например, при изучении сетевой активности вредоносного программного обеспечения, установленного в систему на уровне драйвера. В данном случае на помощь исследователю может прийти CommView, который устанавливает в систему собственный NDIS-драйвер, что позволяет ему работать с пакетами на самом низком уровне.

 

Различие между ведущими сетевыми анализаторами спрятано в их архитектуре

Новому продукту в этой сфере трудно удержаться на плаву, когда повсеместно распространенные конкуренты обладают столь широким функционалом и постоянно обновляются. Вряд ли разработчику удастся привнести кардинальные изменения в индустрию сетевых анализаторов, если его идеи будут ограничены рамками идей других коллег. Чтобы твой продукт заметили необходимо, как минимум, со своим программным обеспечением привнести что-либо инновационное, то, что до тебя либо еще не придумали, либо не реализовали.

 

Конвертация мысли в инновацию

Нестандартные идеи и подходы рождаются с нестандартными взглядами на привычные вещи. Вдоволь наигравшись сниффером, вдоль и поперек изучив сетевую активность операционной системы, перехватив всевозможные собственные или несобственные пароли наталкиваешься на мысль, а ведь неплохо было бы, если таким же образом можно было использовать этот инструмент на хосте, находящимся в другом сегменте сети или в локальной сети, находящейся за тысячи километров, отделенной от внешнего мира маршрутизатором и доступной только через Интернет. 

С позиции системного администратора такая возможность удаленного сетевого анализа траффика своих серверов полностью абстрагировала бы его от их местоположения. Единожды расставив некий модуль на ключевые компьютеры в сегментах сети, которые требуют пристального наблюдения, он будет получать актуальную информацию и сможет в реальном времени проанализировать траффик, который циркулирует в этих сегментах.

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

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

Позиция разработчика этого программного обеспечения помимо оригинальной идеи содержит еще ряд неочевидных «полезностей», которые мы будем выявлять по мере исследования концепции распределенного сниффера.

 

Распределение + сниффер =

На выходе этой простой формулы может получиться трудно предсказуемый результат. 

Во-первых, все зависит от того какой сетевой анализатор траффика будет распределяться: 

– имеет ли он дружественный интерфейс пользователя; 

– на каком уровне работает с пакетами (использует библиотеку PCAP или собственный драйвер);

– поддерживает ли плагины (модульная архитектура);

– моно или мультиплатформенный;

– количество поддерживаемых декодировщиков протоколов;

– прочие возможности, от наличия которых зависит интерес пользователей к снифферу.

Задача не состоит в написании конкурентноспособного сетевого анализатора трафика (в журнале неоднократно публиковались материалы о написании сниффера с использованием разных инструментов и подходов, поэтому советую поднять подшивку или ознакомиться с содержимым ссылок, приложенных к статье). По этой причине предлагаю абстрагироваться от программной составляющей сниффера и сконцентрироваться на процессе его распределения, тем самым поддерживая основную идею и увеличивая значимость полученного концепта.

Структура распределенного сетевого анализатора трафика

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

И, наконец, в-третьих, формирование отчета на стороне серверной части и его предоставление в удобочитаемом виде реципиенту в нашем лице также может осуществляться произвольным образом, на усмотрение программиста.

Совокупность вышеперечисленных факторов позволяет разработчику системы подойти к ее проектированию с разных позиций и в разной степени акцентировать внимание на разработке той или иной части.

 

Анализируй это

К распределению сетевого анализатора будем подходить с точки зрения спектра технологий Windows Communication Foundation (детальный обзор WCF ты можешь найти в позапрошлом выпуске журнала в статье «WTF WCF?! Windows Communication Foundation: искусство скоростного создания сложных транзакционных систем»), которые любезно предоставляет .NET Framework. По этой причине после непродолжительных поисков в Сети у меня на руках оказались исходные коды простого сниффера, написанного на C#.

Чтобы понять, с какой стороны подойти к наращиванию нужного нам функционала, необходимо в общих чертах ознакомиться с устройством «подопытного» приложения.

Процесс перехвата сетевых пакетов

Имеющийся в наличии сниффер разбирает пакеты наиболее распространенных протоколов: 

• TCP;

• UDP;

• IP;

• DNS.

Напомню, что протоколы типа HTTP, SMTP, FTP и прочие инкапсулируются в TCP, который, в свою очередь, инкапсулируется в IP, поэтому, если у тебя вдруг появится желание «допилить» имеющийся сниффер, рекомендую начать с парсинга популярных высокоуровневых сетевых протоколов.

Процесс перехвата пакетов осуществляется с помощью так называемого сырого сокета (raw socket), то есть манипулирует пакетами непосредственно на уровне их непосредственного «конструирования». Сокет привязывается к IP-адресу и затем вызывается метод IOControl со специальным кодом управления «ReceiveAll», который указывает сокету на то, что все входящие и исходящие пакеты должны быть перехвачены.


//создание raw-сокета
mainSocket = new Socket(
AddressFamily.InterNetwork,
SocketType.Raw, ProtocolType.IP);
//привязка созданного сокета к выбранному IP-адресу
mainSocket.Bind(newIPEndPoint(
IPAddress.Parse(cmbInterfaces.Text),0));
/*включение IP-заголовка в данные
и перевод сокета в режим приема всех пакетов*/
mainSocket.SetSocketOption(
SocketOptionLevel.IP,
SocketOptionName.HeaderIncluded,
true);
mainSocket.IOControl(
IOControlCode.ReceiveAll,
byTrue, //входные данные, необходимые для операции
byOut);//выходные данные, возвращенные операцией
//непосредственно асинхронный перехват пакетов
mainSocket.BeginReceive(byteData, 0,
byteData.Length, SocketFlags.None,
newAsyncCallback(OnReceive), null);

Процедуры парсинга заголовков протоколов описаны в соответствующих классах: IPHeader, DNSHeader, TCPHeader. В качестве примера рассмотрим структуру класса IPHeader.

Структура полей IP-заголовка


public classIPHeader
{
/*список членов, каждый из которых отвечает за
конкретное поле заголовка IP-пакета*/

/*конструктор класса, в качестве параметров
использует массив принятых байтов*/
public IPHeader(byte[] byBuffer, int nReceived)
{

}
}

 

Аналогичным образом происходит разбор заголовков TCP и UDP: их содержимое читается с той позиции, в который заканчивается содержимое IP-заголовка. Разобравшись со структурой одного из предоставленных классов без в практически полной аналогии можно написать парсер какого-либо специфичного протокола, имея на руках устройство его заголовка (как правило, описывается в спецификации протокола – документ RFC).

Добавляя новые декодировщики протоколов можно составить конкуренцию большинству имеющихся решений. Наращиванием функционала программы в виде плагинов (соответственно, после проектирования интерфейса их подключения) обеспечивается ее расширяемость и гибкость, а там уже и пользовательский интерфейс в виде плагина не за горами…

 

Распределяй и властвуй

И вот, допустим, у нас на операционном столе пациент, представляющий собой полнофункциональный сетевой анализатор трафика, который ждет хардкорного имплантирования свежей идеи в виде распределения.

Определяем область имплантирования. Для этого найдем место, где собранные данные фиксируются и отправляются на вывод в пользовательский интерфейс:

 


/*вспомогательная функция, которая возвращает информацию,
содержащуюся в заголовке IP-пакета*/
private TreeNode MakeIPTreeNode(IPHeader ipHeader)
{
//инициализация узла – записи в общем дереве
TreeNode ipNode = new TreeNode();
//формирование записи

return ipNode;
}

 

Далее в пошаговом режиме исполнения приложения определяем положение инструкции вывода сформированных данных в область пользовательского интерфейса:


AddTreeNode addTreeNode = new AddTreeNode(OnAddTreeNode);

Режим пошагового исполнения программы позволяет определить инструкцию вывода полученных данных

Именно в это место производим вставку «имплантанта» в виде распределяющего кода. Для этого нам потребует вспомнить архитектуру клиент-серверного приложения на основе технологии .NET Remoting. Сэмпл простейшей «распределенки» ищи на диске – именно его мы сейчас соответствующим образом адаптируем к нашему снифферу.

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

 


/*создание и регистрация клиентского канала
с помощью конфигурационного файла*/
RemotingConfiguration.Configure("Client.exe.txt");
//создание объекта удаленного класса
Test test = new Test();
//обновление общего спула логов
test.SendLog(rootNode);

 

В свою очередь, метод удаленного класса SendLog() должен добавлять к содержимому общего отчета, находящегося на стороне сервера, данные типа rootNode. Для наглядности примера предположим, что общий отчет хранится в строковой переменной Result, тогда обновление отчета происходи следующим образом:

 


public void SendLog(string SensorLog)
{
//добавления лога сенсора в общий отчет
Result = Result + SensorLog;
}

 

Используя этот же класс на своей стороне, сервер в реально времени может просматривать общий отчет, хранящийся в переменной Result, форматируя ее вывод произвольным образом.

 


//вывод отчета на стороне сервера
test.Show()

 

где Show() – метод удаленного класса, который осуществляет вывод переменной Result в удобочитаемой форме.

Метод Show() представляет собой некую абстракцию: он может быть банальным выводом результата в консоль сервера с помощью пары инструкций, может являться выводом в специфичное хранилище логов (например, база данных) из которого впоследствии формируется вывод данных, отсортированных строго по определенным критериям и предоставленный пользователям твоего веб-сервиса. 

 

Есть идея? Значит делай!

До полноценного инновационного продукта предстоит осуществить еще несколько шагов: написать полнофункциональный и конкурентноспособный сетевой анализатор траффика, распределить его в соответствии с тем подходом, который описан в статье, реализовать в виде онлайн-сервиса удобную серверную часть, которая в реальном времени обрабатывает непрерывный поток отчетов с сенсоров и представляет статистику пакетов в надлежащем виде. Однако, уже имея за спиной нестандартную мысль, воплощенную в оригинальную и яркую идею, любые шаги к инновации меркнут на фоне ожидаемых результатов. Как гласит слоган одной крупной компании: “Просто возьми и сделай!”.

 

The "Xakep" magazine

1 comment

c0n Difesa May 3, 2011 - 07:08

Отредактированная версия статьи на официальном веб-ресурсе журнала “Хакер”: http://www.xakep.ru/post/55569/default.asp

Reply

Leave a Comment

You may also like