Приветствую вас, уважаемыее!
Сегодня я хотел начать рассказ об одном интересном продукте представляемой мной на хабре компании Tibbo. Продукт этот может оказаться полезен широкому кругу IT-профессионалов, включая системных администраторов, специалистов по информационной безопасности, и, наконец, простых разработчиков, которым нет-нет, да и приходится программировать общение с устройствами и другой низкоуровневый ввод/вывод.
Разговор пойдёт про программируемый терминал/сниффер IO Ninja (здесь и далее я буду опускать слово «эмулятор» и говорить просто «терминал»). Подозреваю, что само определение «терминал/сниффер» может выглядеть достаточно непривычно, если не сказать странно. Поэтому начнём с истории возникновения IO Ninja.
Мотивация и история возникновения
Самым первым продуктом нашей компании был встраиваемый модуль (embedded module) EM100 для преобразования последовательного интерфейса Serial RS232 в Ethernet 10BASE-T (сейчас его аналогом являются модуль EM1206).
На этом устройстве были опробованы и обкатаны протоколы взаимодействия между прошивкой (на модулях) и драйверами виртуальных портов, а также конфигурационными утилитами (на PC).
Как вы понимаете, в нашем несовершенном мире ни одна программа не работает сразу после написания, и нам предстояли долгие месяцы отладки коммуникационных протоколов. В нашем конкретном случае отладки преобразователя Serial-to-Ethernet это выливалось в необходимость параллельного использования следующих утилит:
- Serial терминал;
- TCP терминал;
- UDP терминал;
- Serial монитор;
- Ethernet сниффер.
Помимо этого, для отладки наших протоколов также было нужно:
- Слушать и принимать входящие TCP соединения;
- Отправлять широковещательные (broadcast) UDP пакеты;
- Принимать ответы на них со множественных узлов;
- Отправлять и уметь отображать в шестнадцатеричном виде бинарные данные.
С мониторами для Ethernet и Serial затруднений не возникло – даже бесплатные продукты типа Wireshark (который тогда ещё назывался Ethereal) полностью удовлетворяли наши запросы. А вот с терминалами мы натолкнулись на проблемы.
Как и мониторов, терминалов существует великое множество. Но есть нюанс: большинство из них сильно хромает в части отправки и отображения бинарных данных. Eсли такая возможность и предоставляется, то в крайне неудобном виде – полноценного шестнадцатеричного просмотровщика входящих пакетов и редактора исходящих (с возможностью выделения, копирования, вставки и т.д.) не нашлось ни в одном из опробованных нами терминалов. Помимо этого, плохо дело обстоит также в части приёма TCP соединений и совсем полный мрак – c поддержкой работы с широковещательными UDP пакетами.
Именно после безуспешного поиска и родилась идея создать универсальную утилиту для отладки коммуникационных протоколов, которая умела бы делать всё вышеперечисленное и делала бы это хорошо. Да ещё – мечтать так мечтать! – была бы программируемой и позволяла с лёгкостью дописывать анализаторы наших собственных протоколов и тестовые скрипты (такие как, например, ждать команды и отправлять динамически генерируемые по определённым правилам ответы на них).
Мечты о программируемости, конечно, длительное время оставались просто мечтами. А вот утилитка для посылки и отображения бинарных данных, при этом с поддержкой приёма TCP соединений и широковещательной UDP рассылки была сляпана достаточно быстро. Называлась она бесхитростно – SockTerm – и выглядела вот так:
Помимо поддержки отсутствующих в стандартных терминалах режимов работы с сокетами, данная утилита продемонстрировала чрезвычайное удобство реализованного в ней подхода к логгированию, а именно шестнадцатеричной «простыни» с приклеиванием новых пакетов к предыдущим.
Работа над утилитой продолжалась в свободное от основных проектов и задач время в течение пары лет. Модуль логгирования был постепенно доработан, расширен и в итоге реорганизован в виде полноценного движка (о его возможностях будет более подробно рассказано далее). Данный движок был вполне пригоден для использования как в терминалах, так и в снифферах – что и было с энтузиазмом воплощено в жизнь. Результатом стало появление первой версии IO Ninja.
Эта утилита позволяла работать со всеми интересующими нас транспортами (Serial, TCP, UDP) как в режиме сниффера для пассивного прослушивания, так и в режиме терминала для направленной передачи и приёма данных. Множественные режимы работы были реализованы в виде плагинов (написанных, как и сама IO Ninja, на С++), что в теории позволяло нам с достаточной лёгкостью допиливать поддержку новых режимов, а в перспективе вообще опубликовать SDK и дать клиентам возможность делать это самим. Однако на практике последнее так и не было воплощено – нам не давали покоя те самые мечты о программируемости, а плагины на C++ – в данном случае не самая лучшая архитектура.
Что нам нужно было вместо этого, так это сделать ниндзю скриптованной. Но вот незадача – в языках без указателей и адресной арифметики работа с бинарными данными (а это неотъемлемая часть любого анализатора протоколов) превращается в кошмар типа «вытащить байт по индексу N, сдвинуть на 8 бит влево, сложить с байтом по индексу N + 1 и т.д.». А скриптовых языков с указателями в природе не существует. Точнее, не существовало раньше – мы исправили это досадное недоразумение, создав язык Jancy.
Данная статья не ставит себе целью рассказать о всех возможностях языка Jancy (хотя, если уважаемыее проявят интерес, соответствующие статьи обязательно появятся). Сейчас же речь идёт лишь о том, что в наших руках – после долгой череды полуживых прототипов (а затем и прототипа вполне себе жизнеспособного и использованного при создании второй, скриптованной версии IO Ninja – её скриншот вы видите ниже) оказался язык с безопасными указателями и адресной арифметикой.
При этом данный язык спроектирован настолько бинарно совместимым с C/C++, что возможен прямой вызов между Jancy и С++, а это приводит, во-первых, к высокой эффективность взаимодействия между скриптом и хостовым C++ приложением, а во-вторых, к лёгкости создания на C/C++ библиотек для использования из Jancy-скриптов. Помимо ABI (бинарной) совместимости, Jancy также обладает высокой степенью совместимости на уровне исходных кодов, что позволяет копировать и использовать (зачастую вообще без каких-либо модификаций) код на языке C, взятый из общедоступных источников.
В 2014 году была закончена работа над созданием и выпуском третьей версии IO Ninja, основанной на языке Jancy. О ней и пойдёт речь далее.
Если выделить самые значимые особенности новой IO Ninja, то это будут:
- Программируемость;
- Движок логгирования;
- Строитель пакетов;
- Универсальный редиректор;
- Объединение всех видов утилит для отладки коммуникаций в одном продукте.
О том, во что нинзю можно превратить с помощью программируемости, будет рассказано в последующих частях статьи; в этой же давайте посмотрим, что доступно «из коробки».
Движок логгирования
Движок логгирования ещё со времён непрограммируемой первой версии IO Ninja предлагал то, что не было доступно в других терминалах и снифферах. Выделяется этот движок прежде всего самим подходом к отображению данных лога.
Вместо пары окон «главный список» и «детали записи» (как в большинстве мониторов и просмотровщиков журналов) движок IO Ninja предлагает лог в виде «бесконечной простыни» с перемежением текстовых сообщений и бинарных данных – нечто вроде неограниченно растущей вниз гетерогенной HTML страницы. Кстати, именно в связи с неограниченным ростом лога и потребовалась разработка собственного движка – в противном случае можно было бы прикрутить что-нибудь типа Gecko или WebKit-а.
При этом, несмотря на фактическую неограниченность размера лога (реально он ограничен лишь свободным пространством на диске), движок IO Ninja предоставляет «гладкую» прокрутку, при этом без прямой зависимости объёма потребляемой памяти от размера лога.
Одной из причин ухода от стандартных терминалов было отсутствие удобных средств для работы с бинарными данными, поэтому совсем неудивительно, что логгирующий движок IO Ninja буквально «заточен» под эту задачу.
Бинарные данные можно отображать в шестнадцатеричном или текстовом виде, с настраиваемой шириной строки и табуляции и в любой из UTF-кодировок (включая вариации с обратным порядком следования байтов). Пакеты одного типа (например, входящие) опционально склеиваются друг с другом. Склеивание можно сконфигурировать на «всегда», «никогда» и «если интервал не превышает некий порог». Места склеивания подсвечиваются (опять-таки, опционально) цветом – шашечками.
Лог IO Ninja также поддерживает схлопывание/разворачивание записей, что может быть необходимо для переключения между кратким и полным описанием и используется, например, в сетевом сниффере:
Строитель пакетов
Говоря о поддержке работы с бинарными данными, нельзя не упомянуть о средствах IO Ninja для подготовки исходящих пакетов.
Для простейших случаев в IO Ninja есть текстовый редактор пакетов. Данный редактор понимает все общеизвестные escape-последовательности (n e x01 u2661 и т.д.), поэтому внедрить парочку спецсимволов – не проблема. А если требуется составить пакет, целиком состоящий из спецсимволов? Добро пожаловать в строитель пакетов IO Ninja!
Строитель пакетов является одной из сильнейших сторон IO Ninja, доступных «из коробки». Помимо современного шестнадцатеричного редактора с поддержкой всех UTF-кодировок, редактирования нибблов (полубайтов), ограничений на размер пакета сверху и снизу, удобной подсветкой выделения, а также всех других возможностей, которые можно ожидать от хорошего редактора (insert, overwrite, copy, paste, undo, redo) – в IO Ninja присутствует инструмент для создания пакетов по шаблону.
Помните, мы говорили про высокую степень совместимости между Jancy и C? Подготовка бинарных пакетов – это одно из мест, где пожинаются плоды этой совместимости.
Фаза 1: найти исходники реализации нужного нам протокола на C в общедоступных источниках;
Фаза 2: скопировать описания структур пакетов в IO Ninja и, возможно, чуть-чуть подретушировать (в конце концов, Jancy и C это разные языки);
Фаза 3: ???
Фаза 4: ПРОФИТ! Можно заполнять поля пакета из редактора свойств (property grid)!
Вместо заключения
На этом закончим вводный обзор, а в следующей части статьи продемонстрируем несколько реальных сценариев из жизни нашей компании, в которых IO Ninja помогал решать определённые практические задачи лучше аналогов.
Тем временем вы можете скачать и попробовать последнюю версию IO Ninja для Windows или Linux на страничке tibbo.com/ioninja/downloads. Там же доступна для скачивания и сопутствующая IDE, основанная на NetBeans (впрочем, подробнее об этом в другой раз).
Автор: vovkos