ioninjaПриветствую вас, уважаемые хабровчане!

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

Разговор пойдёт про программируемый терминал/сниффер IO Ninja (здесь и далее я буду опускать слово «эмулятор» и говорить просто «терминал»). Подозреваю, что само определение «терминал/сниффер» может выглядеть достаточно непривычно, если не сказать странно. Поэтому начнём с истории возникновения IO Ninja.




Мотивация и история возникновения


ioninjaСамым первым продуктом нашей компании был встраиваемый модуль (embedded module) EM100 для преобразования последовательного интерфейса Serial RS232 в Ethernet 10BASE-T (сейчас его аналогом являются модуль EM1206).

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

Как вы понимаете, в нашем несовершенном мире ни одна программа не работает сразу после написания, и нам предстояли долгие месяцы отладки коммуникационных протоколов. В нашем конкретном случае отладки преобразователя Serial-to-Ethernet это выливалось в необходимость параллельного использования следующих утилит:
  • Serial терминал;
  • TCP терминал;
  • UDP терминал;
  • Serial монитор;
  • Ethernet сниффер.

Помимо этого, для отладки наших протоколов также было нужно:
  • Слушать и принимать входящие TCP соединения;
  • Отправлять широковещательные (broadcast) UDP пакеты;
  • Принимать ответы на них со множественных узлов;
  • Отправлять и уметь отображать в шестнадцатеричном виде бинарные данные.

С мониторами для Ethernet и Serial затруднений не возникло – даже бесплатные продукты типа Wireshark (который тогда ещё назывался Ethereal) полностью удовлетворяли наши запросы. А вот с терминалами мы натолкнулись на проблемы.

Как и мониторов, терминалов существует великое множество. Но есть нюанс: большинство из них сильно хромает в части отправки и отображения бинарных данных. Eсли такая возможность и предоставляется, то в крайне неудобном виде – полноценного шестнадцатеричного просмотровщика входящих пакетов и редактора исходящих (с возможностью выделения, копирования, вставки и т.д.) не нашлось ни в одном из опробованных нами терминалов. Помимо этого, плохо дело обстоит также в части приёма TCP соединений и совсем полный мрак – c поддержкой работы с широковещательными UDP пакетами.

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

Мечты о программируемости, конечно, длительное время оставались просто мечтами. А вот утилитка для посылки и отображения бинарных данных, при этом с поддержкой приёма TCP соединений и широковещательной UDP рассылки была сляпана достаточно быстро. Называлась она бесхитростно – SockTerm – и выглядела вот так:

sockterm

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

Работа над утилитой продолжалась в свободное от основных проектов и задач время в течение пары лет. Модуль логгирования был постепенно доработан, расширен и в итоге реорганизован в виде полноценного движка (о его возможностях будет более подробно рассказано далее). Данный движок был вполне пригоден для использования как в терминалах, так и в снифферах – что и было с энтузиазмом воплощено в жизнь. Результатом стало появление первой версии IO Ninja.

ioninja-1.8.6

Эта утилита позволяла работать со всеми интересующими нас транспортами (Serial, TCP, UDP) как в режиме сниффера для пассивного прослушивания, так и в режиме терминала для направленной передачи и приёма данных. Множественные режимы работы были реализованы в виде плагинов (написанных, как и сама IO Ninja, на С++), что в теории позволяло нам с достаточной лёгкостью допиливать поддержку новых режимов, а в перспективе вообще опубликовать SDK и дать клиентам возможность делать это самим. Однако на практике последнее так и не было воплощено – нам не давали покоя те самые мечты о программируемости, а плагины на C++ – в данном случае не самая лучшая архитектура.

Что нам нужно было вместо этого, так это сделать ниндзю скриптованной. Но вот незадача – в языках без указателей и адресной арифметики работа с бинарными данными (а это неотъемлемая часть любого анализатора протоколов) превращается в кошмар типа «вытащить байт по индексу N, сдвинуть на 8 бит влево, сложить с байтом по индексу N + 1 и т.д.». А скриптовых языков с указателями в природе не существует. Точнее, не существовало раньше – мы исправили это досадное недоразумение, создав язык Jancy.

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

ioninja-2.3.5

При этом данный язык спроектирован настолько бинарно совместимым с C/C++, что возможен прямой вызов между Jancy и С++, а это приводит, во-первых, к высокой эффективность взаимодействия между скриптом и хостовым C++ приложением, а во-вторых, к лёгкости создания на C/C++ библиотек для использования из Jancy-скриптов. Помимо ABI (бинарной) совместимости, Jancy также обладает высокой степенью совместимости на уровне исходных кодов, что позволяет копировать и использовать (зачастую вообще без каких-либо модификаций) код на языке C, взятый из общедоступных источников.

В 2014 году была закончена работа над созданием и выпуском третьей версии IO Ninja, основанной на языке Jancy. О ней и пойдёт речь далее.

Если выделить самые значимые особенности новой IO Ninja, то это будут:
  • Программируемость;
  • Движок логгирования;
  • Строитель пакетов;
  • Универсальный редиректор;
  • Объединение всех видов утилит для отладки коммуникаций в одном продукте.

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

Движок логгирования


Движок логгирования ещё со времён непрограммируемой первой версии IO Ninja предлагал то, что не было доступно в других терминалах и снифферах. Выделяется этот движок прежде всего самим подходом к отображению данных лога.

log

Вместо пары окон «главный список» и «детали записи» (как в большинстве мониторов и просмотровщиков журналов) движок IO Ninja предлагает лог в виде «бесконечной простыни» с перемежением текстовых сообщений и бинарных данных – нечто вроде неограниченно растущей вниз гетерогенной HTML страницы. Кстати, именно в связи с неограниченным ростом лога и потребовалась разработка собственного движка – в противном случае можно было бы прикрутить что-нибудь типа Gecko или WebKit-а.

При этом, несмотря на фактическую неограниченность размера лога (реально он ограничен лишь свободным пространством на диске), движок IO Ninja предоставляет «гладкую» прокрутку, при этом без прямой зависимости объёма потребляемой памяти от размера лога.

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

log settingsБинарные данные можно отображать в шестнадцатеричном или текстовом виде, с настраиваемой шириной строки и табуляции и в любой из UTF-кодировок (включая вариации с обратным порядком следования байтов). Пакеты одного типа (например, входящие) опционально склеиваются друг с другом. Склеивание можно сконфигурировать на «всегда», «никогда» и «если интервал не превышает некий порог». Места склеивания подсвечиваются (опять-таки, опционально) цветом – шашечками.

Лог IO Ninja также поддерживает схлопывание/разворачивание записей, что может быть необходимо для переключения между кратким и полным описанием и используется, например, в сетевом сниффере:

log

Строитель пакетов


Говоря о поддержке работы с бинарными данными, нельзя не упомянуть о средствах IO Ninja для подготовки исходящих пакетов.

Для простейших случаев в IO Ninja есть текстовый редактор пакетов. Данный редактор понимает все общеизвестные escape-последовательности (\n \e \x01 \u2661 и т.д.), поэтому внедрить парочку спецсимволов – не проблема. А если требуется составить пакет, целиком состоящий из спецсимволов? Добро пожаловать в строитель пакетов IO Ninja!

packet template editorСтроитель пакетов является одной из сильнейших сторон IO Ninja, доступных «из коробки». Помимо современного шестнадцатеричного редактора с поддержкой всех UTF-кодировок, редактирования нибблов (полубайтов), ограничений на размер пакета сверху и снизу, удобной подсветкой выделения, а также всех других возможностей, которые можно ожидать от хорошего редактора (insert, overwrite, copy, paste, undo, redo) – в IO Ninja присутствует инструмент для создания пакетов по шаблону.

Помните, мы говорили про высокую степень совместимости между Jancy и C? Подготовка бинарных пакетов – это одно из мест, где пожинаются плоды этой совместимости.

Фаза 1: найти исходники реализации нужного нам протокола на C в общедоступных источниках;

Фаза 2: скопировать описания структур пакетов в IO Ninja и, возможно, чуть-чуть подретушировать (в конце концов, Jancy и C это разные языки);

Фаза 3: ???

Фаза 4: ПРОФИТ! Можно заполнять поля пакета из редактора свойств (property grid)!

packet template editor

Вместо заключения


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

Тем временем вы можете скачать и попробовать последнюю версию IO Ninja для Windows или Linux на страничке tibbo.com/ioninja/downloads. Там же доступна для скачивания и сопутствующая IDE, основанная на NetBeans (впрочем, подробнее об этом в другой раз).

Вторая часть статьи: http://habrahabr.ru/company/tibbo/blog/255221/

Комментарии (4)


  1. norguhtar
    31.03.2015 11:56

    Ну вообще есть вот такая штука justniffer.sourceforge.net/
    Я в свое время использовал ее для поймать и посмотреть SOAP


  1. vovkos Автор
    31.03.2015 14:19

    Спасибо за ссылку. Данным сниффером я не пользовался, но по секции «Examples» достаточно понятно, что он из себя представляет. Отличия от нашего продукта следующие:

    1. justniffer — сниффер, основанный на pcap и заточенный под TCP. ioninja — проектировалась как универсальная отладочно-тестировочная утилита а-ля всё-в-одном (terminal, sniffer, serial, tcp, udp broadcast, generic files, windows named pipes и т.д.)
    2. justniffer — утилита командной строки, а ioninja — утилита с графическии интерфейсом. Нельзя сказать что один подход однозначно лучше или хуже: в одном случаев удобнее первое, в другом — второе. Но согласитесь, иногда удобный GUI проще в использовании, а иногда без GUI вообще не обойтись (hex-редактор?)
    3. justniffer — не предоставляет собственно «программируемости», вместо этого есть возможность скармливать выхлоп сниффера внешнему скрипту (или любой другой программе). ioninja — утилита со встроенным скриптовым языком (кстати, ожидаю вопросы «почему не питон, луа и т.д.» — тема интересная, с удовольствием поспорю ;)


    Возможно, что-то проглядел, но вообще разница между продуктами достаточно ощутимая.


  1. amarao
    31.03.2015 15:01
    +1

    Спасибо. В архиве (tar.gz) зачем-то пути закодированы с точкой в начале, то есть не

    ioninja-3.3.3/..., а ./ioninja-3.3.3/…

    Это не фатально, но странно.

    Плюс tar.gz не содержит инструкций по сборке (debian/*)

    Ну и главное, лицензия печальная. Почему не свободная? Было бы здорово быть во всех себя уважающих дистрибутивах, правда?


    1. vovkos Автор
      01.04.2015 05:48

      В архиве (tar.gz) зачем-то пути закодированы с точкой в начале

      Спасибо за замечание, поправил сборочные скрипты. В следующем релизе будет как надо.

      Плюс tar.gz не содержит инструкций по сборке (debian/*)

      А вот тут не совсем понял. В таре ведь лежат уже собранные бинарники плюс скрипты (которые собирать не надо). Что вы имеете в виду под инструкциями по сборке?

      Ну и главное, лицензия печальная. Почему не свободная? Было бы здорово быть во всех себя уважающих дистрибутивах, правда?

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

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