io ninjaДанная статья является продолжением предыдущей, вводной статьи, в которой речь шла о мотивации и истории создания терминала/сниффера IO Ninja, и было немного рассказано про встроенные возможности нашего продукта. Продолжим рассказ о том, что доступно «из коробки», но с более практическим уклоном.

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

Перенаправление TCP в Serial


tcp-to-serial link settingsПользователи Unix-подобных систем хорошо знакомы с возможностью перенаправления выхода одной программы на вход другой. Связывание сессий (Session Linking) в IO Ninja предоставляет похожий функционал. Различие заключается в том, что вместо однонаправленного каскада данных, как в случае Unix pipes, связываение двух сессий «закорачивает» выход одной на вход другой и наоборот (при этом в лог записываются все передаваемые данные). Тем самым появляется возможность использовать IO Ninja в качестве универсального посредника для перенаправления и/или прослушивания.

Допустим, к компьютеру через последовательный интерфейс (serial) подключено устройство. Открываем IO Ninja и запускаем сессию Serial. Открываем и конфигурируем последовательный порт (возможно, посылаем несколько тестовых команд устройству, дабы убедиться, что оно живо-здорово).

Далее запускаем сессию TCP Listener, выбираем интерфейс и TCP порт, на котором будем слушать. Связываем наши две сессии Serial и TCP Listener через диалог настроек и – вуаля! Теперь к нашему последовательному устройству можно подсоединяться по TCP с любого другого компьютера!

tcp-to-serial link

Поиск устройств в локальном сегменте с помощью UDP broadcast


Типовым методом автообнаружения устройств в сети является широковещательная UDP рассылка некоего эхо-запроса и последующий сбор ответных пакетов – так, в частности, работает автообнаружение у всех встраиваемых модулей, производимых нашей компанией. IO Ninja может быть использована в качестве широковещательного UDP терминала для общения в режиме «one-to-many».

Открываем UDP Socket, прописываем в качестве адреса 255.255.255.255 (или же subnet-broadcast типа 192.168.1.255), и рассылаем эхо-запрос. В результате мы видим список всех устройств в локальном сегменте. Далее, если это необходимо, мы можем продолжать общение с каким-то конкретным устройством.

device auto-discovery

Кстати, обратите внимание на кнопочку с компасом. При работе с UDP (и в особенности на стороне сервера) часто требуется запоминать адрес, с которого пришёл пакет, и отвечать именно туда – соединения-то нет! В принципе, ничто не мешает копировать адрес из лога и вставлять его в поле ввода “Remote address”. Но зачем делать руками то, что можно переложить на машину? Жмём компас, и получаем требуемую автоматизацию – UDP-сессия будет автоматически перенастраивать Remote address.

Сохранение части входного потока в файл


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

Стандартные терминалы часто буксуют на этой достаточно простой задаче, и связано это со следующими моментами:
  • Данные могут быть бинарными и содержать непечатаемые символы;
  • Данные могут быть «размазаны» между несколькими пакетами;
  • Нужен нам, как правило, не весь входной поток, а строго определённый блок (а значит, простым перенаправлением потока в файл проблема тоже решается не совсем чисто).

IO Ninja выгодно отличается наличием лога в виде «шестнадцатеричной простыни» со склеиванием входящих пакетов – это позволяет выполнить именно то, что нам надо.

ssh log save as file

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

midnight commander on tcp listener

Приём TCP соединений с помощью TCP Listener


Выше мы видели, как с помощью TCP Listener можно организовать перенаправление, чтобы можно было подсоединяться к последовательному устройству по TCP. Однако изначальным назначением плагина TCP Listener является не это, а работа в качестве server-side TCP терминала (в частности, для отладки клиентской стороны TCP соединения).

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

google chrome on tcp listener

Отметим, что в TCP Listener также имеется возможность выбора: принимать или нет новые входящие соединения, если соединение уже имеется в наличии. Данная опция может быть крайне полезной в ситуациях, когда клиент устанавливает множество вторичных соединений на один и тот же адрес (как, например, многие web-браузеры)

Прослушивание TCP соединений с помощью TCP Proxy


IO Ninja включает в себя плагин Network Sniffer – основанный на PCap сетевой сниффер для прослушивания сетевых соединений. Однако, в ряде случаев значительно удобнее использовать другой встроенный плагин, а именно TCP Proxy.

TCP Proxy – это комбинация TCP Connection и TCP Listener, которая позволяет организовать посредника для TCP соединений. Удобство данного подхода заключается в том, что он сразу даёт чистый лог потоков данных в реальном времени (вместо лога в виде пакетов, из которых потоки данных надо ещё потом восстановить). Помимо этого, данная модель работает и там, где прослушивание с помощью сниффера может быть затруднительно (с определёнными моделями сетевых свичей, Wi-Fi карточек и т.д.)

Создаём сессию TCP Proxy, конфигурируем серверную и клиентскую стороны и запускаем наш прокси-сервер. Любое подсоединение к данному серверу породит вторичное подсоединение с клиентской стороны нашего прокси, при этом все данные принятые на клиентской стороне, будет переданы на серверную и наоборот. В этом смысле TCP Proxy напоминает связывание сессий, но специально заточенное под TCP и вследствие этого более удобное.

ftp sniffing with tcp proxy

Отладка Windows Named Pipes


IO Ninja может быть использована в качестве инструмента для отладки достаточно распространённого подхода к IPC (Inter-Process Communication) в Windows – named pipes. В частности, так общаются некоторые наши Windows-драйвера с сопутствующими сервисами и приложениями.

Для эмуляции серверной стороны вашего приложения (той, где вызывается ConnectNamedPipe), запустите Named Pipe Listener. Данный плагин позволяет принимать входящие named pipe-соединения, которые будут исходить от вашего клиентского приложения/сервиса.
После установления соединения вы можете общаться с клиентом, анализируя лог полученных запросов и отсылая ему ответные пакеты (созданные, например, в строителе пакетов).

Для эмуляции клиентской стороны (той, где вызывается CreateFile) используется плагин Generic File.

named pipe to tdevmon

Помимо отладки named pipes (или FIFOs в *nix), данный плагин также может быть использован для чтения и записи в драйверы нестандартных устройств.

Кратко коснёмся вопроса прослушивания named pipes. Предположим, имеется приложение или драйвер, использующие pipes для IPC. Если вы можете каким-то образом настраивать адрес named pipe на клиентской стороне, то появляется возможность прослушивания pipe-соединений с помощью посредника (аналогично TCP Proxy).
Как именно?
Пусть отлаживаемая система устанавливает pipe соединение на \\.\pipe\debuggee_pipe_server. Выбираем какое-нибудь незанятое имя pipe, например, \\.\pipe\my_pipe_proxy. Настраиваем клиентскую сторону отлаживаемой системы на этот наш \\.\pipe\my_pipe_proxy. В IO Ninja открываем пару Pipe Listener и Generic File, связываем их. В Pipe Listener прописываем \\.\pipe\my_pipe_proxy, жмём Listen. В Generic File прописываем \\.\pipe\debuggee_pipe_server, жмём Open. Посредник готов.


Со временем в будущих версиях IO Ninja будет также добавлено полноценное прослушивание named pipes без организации man-in-the-middle (в качестве первого приближения, скорее всего, через user-mode API hooking, а впоследствии – через file system filter).

Отправка «битых» фреймов для тестирования


Необходимость в отправке «битых» или иным образом специально сформированных Ethernet фреймов встречается не столь часто и может казаться относящейся, скорее, к разряду экзотики. Тем не менее данный функционал востребован в ряде вполне себе реальных сценариев. Например, в нашей практике это было необходимо во время отладки реализации TCP/IP стека у производимых нашей компанией встраиваемых модулей; другой реалистичной областью приложения могут быть задачи, стоящие перед специалистами по сетевой безопасности, разработчиками firewall-ов и т.д.

Открываем сессию Network Sniffer, выбираем интерфейс и фильтр захвата, запускаем захват. В строителе пакетов подготавливаем необходимый фрейм – например, можно воспользоваться встроенной библиотекой шаблонов пакетов TCP/IP, или же просто скопировать какой-то из захваченных фреймов в шестнадцатеричный редактор и подправить нужные поля.

inject frame with network sniffer

Нажимаем Send, и любовно составленный нами фрейм отправляется выполнять боевое задание!

Заключение


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

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

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


  1. Ivan_83
    09.04.2015 16:19
    +1

    Современные протоколы для обнаружения в сети используют мультикаст, вместо броадкаста.
    И про IPv6 поддержку у вас ни слова.


    1. vovkos Автор
      10.04.2015 04:44
      +1

      Несомненно, много чего ещё можно и нужно добавлять. Писали нинзю мы прежде всего под себя и свои собственные потребности. Так как наши встраиваемые модули в настоящий момент работают на IPv4 и не поддерживают мультикастовые группы, то и в нинзе эти вопросы остро пока не стояли (вообще я большой сторонник принципа «you ain't gonna need it»).

      На каком уровне вы ожидаете поддержку IPv6? Парсинг и отображение IPv6-адресов допилим в ближайших релизах. Насколько актуальны мультикасты в плагине UDP Socket?

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


      1. Ivan_83
        10.04.2015 08:02

        Я не ожидаю, просто обратил внимание что такого функционала нет.

        IPv6 — ещё же и сокеты создавать, подключатся, принимать соединения.
        Мультикаст — присоединение к группе, отправка сообщений, приём.


        1. vovkos Автор
          10.04.2015 09:30

          Да вроде бы кардинальных изменений в работе с сокетами быть не должно (AF_INET->AF_INET6, sockaddr_in->sockaddr_in6, ну и обработка парсинга и форматирования IPv6 адресов). С мультикастами тоже посылка и приём поменяться вроде не должны, а вот настройку присоединения к группе надо добавить.

          Впрочем, вполне мог что-то пропустить — практического опыта программирования ни IPv6, ни мультикастов у меня нет (но есть ощущение, что любые проблемы тут можно решить без глобальных переделок).

          В любом случае соглашусь, что поддержку IPv6 надо для приличия допилить.


          1. Ivan_83
            10.04.2015 17:04
            +1

            sockaddr -> sockaddr_storage, это портабельное решение с запасом на будущее.
            С парсингом кажется тоже особых проблем нет, как минимум с отображением: WSAAddressToStringW(), WSAStringToAddressW()
            С мультикастом всё просто, но в винде есть особенность: он принимается либо в зависимости от роутинга 224/4 либо от того куда прибинден сокет. В линуксе/бсд есть расширенное апи (в винде не смотрел, может тоже есть), оно позволяет явно задать интерфейс куда отправлять IGMP трафик, и соответственно с которым работать.

            www.netlab.linkpc.net/download/software/TCPterm
            Не достающее брать тут: www.netlab.linkpc.net/download/software/SDK
            Немного сокетной специфики тут: www.netlab.linkpc.net/download/software/SDK/SocketFunctions.h
            Осторожно: код вырвиглазный, и IPv6 там кажется не доделан, но адреса оно отображает :)


            1. vovkos Автор
              10.04.2015 19:36

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