Сам себе IP-телефон. VoIP для программера
Салиев Александр aka Fagot
Xakep, номер #056, стр. 056-062-1
(salieff@mail.ru)
Страшное слово IP-телефония для многих связано с дорогими шлюзами известных фирм типа Cisco или Vocaltech, что придает этому понятию некий ореол таинственности и немеренной сложности. Но ведь H.323 это всего лишь протокол, положенный поверх TCP/IP, и работать с ним сможет программа, запущенная на обычном компьютере, и по идеологии своей особо не отличающаяся от собратьев, профилирующихся на протоколах HTTP или ICQ. Сегодня мы напишем простой снифер, который позволит выгребать всевозможную информацию из сигнализации H.323, независимо от того, снифит ли он промышленный VoIP шлюз Cisco или обычный NetMeeting в твоей локалке.
Страшный зверь ASN.1
В формировании пакетов H.323 задействованы 3 алгоритма бинарной сериализации, это TPKT3, Q.931, и ASN.1. Если с первыми двумя все просто, и работа с ними сводится к разбору линейных байтовых полей, то с ASN.1 (Abstractive Syntax Notation One) следует разъяснить ситуацию. Практически ASN.1 - это не пакетный протокол, а компилятор-декомпилятор логических структур, написанных на собственном языке. Сначала создается описание пакета с использованием примитивных типов вроде INTEGER, STRING и тому подобных, конструкций вроде массивов и других языковых заморочек, а также сложных типов SEQUENCE и CHOICE. Если сравнивать с конструкциями языка C, то SEQUENCE подобен структуре (struct), а CHOICE - объединению (union). После этого данное описание компилируется в байт-код, который вкладывается в поле IE:USER-USER пакета Q.931 (стоит обратить внимание, что в H.323 поле длины данного IE расширено до двух байт, когда в классическом ISDN’овском Q.931 поле длины любого IE - один байт, этот нюанс иногда вносит путаницу). Этот пакет, в свою очередь, вкладывается в оболочку TPKT3. Пакет готов для отсылки в сеть. Декодировка пакета происходит аналогичным образом, только в обратную сторону. Транспорт и методы передачи различных протоколов семейства H.323 я рассматривал в предыдущей статье "VoIP изнутри", замечу лишь, что уровень TPKT присутствует только в самостоятельных пакетах, идущих по транспорту с гарантированной доставкой (H.225 и нетуннелированный H.245 поверх TCP), а оболочка Q.931 создается только вокруг пакетов H.225. Схема упаковки TPKT-Q.931-ASN.1 представлена на рисунке.
Компилируем сигнализацию
В свое время я пытался написать компилятор ASN.1, ибо стандарты для него открыты, но после трех месяцев возни понял, что дело это неблагодарное, и надо искать готовый. Найдено их было превеликое множество, но все они, к сожалению, оказались коммерческими и стоили немалых денег. Я почти отчаялся, когда наткнулся на кроссплатформенную opensource библиотеку PWLIB, которая решила все мои проблемы. Утилита asnparser, которая входит в состав pwlib, это не просто asn-компилятор, а замечательное средство разработки, которое позволяет генерить из описаний ASN.1 классы для C++. Каждый такой класс имеет методы Encode() и Decode(), позволяющие компилировать бинарный asn-код, предварительно заполнив поля класса данными, и наоборот, декомпилировать бинарные asn-пакеты, заполняя поля класса данными, содержащимися в этом пакете.