|
С/C++ - Самопальный снифер под Linux kas1e Xakep, номер #050, стр. 050-082-2 Теперь повторно зададимся вопросом, что же на самом деле должен делать снифер. Все зависит от того, чего ты хочешь. Снифер - это большой сборник различных способов обработки информации. Их собирание, декодирование/интерпретирование, вывод, анализ и т.д. В этой статье рассматриваются 2 вида сниферов: сетевой анализатор ethernet/arp/ip-пакетов и pop3-снифер, который собирает различную информацию (в свою очередь она может быть полезна разным пользователям). Во-первых, нам нужно читать ВСЕ данные, которые попадают на сетевуху. Т.е. не только ip, но и ethernet. Любые биты, летящие по сети. Для этого будем пользоваться SOCK_PACKET и PF_PACKET параметрами при открытии сокета. Почему именно они? Потому что в некоторых маннах на соответствующие функции встречается фраза: "для чтения всех данных с сетевой карты используйте SOCK_PACKET и PF_PACKET". Предвидя вопрос "а как же старый добрый SOCK_RAW?", спешу тебя разочаровать: SOCK_RAW позволит работать не ниже IP. Да, ты сможешь собрать полностью IP-пакет и отправить его, или, скажем, считать. Но читать все данные не выйдет, соответственно используем SOCK_PACKET. В принципе, самая простая часть - чтение. Поставили в цикле, и все. Самый неприятный момент - обработка принятых данных. Если это анализатор, то просматриваем все поля и выводим нужные. Если это снифер конкретных данных, то находим в буфере эти данные и выводим опять же в удобоваримом виде. Вообще, в целях фильтрации и упрощения работы существуют готовые библиотеки. Например, есть пакетный фильтр BFP (Berkley Packet Filter), который занимается обработкой данных на нижнем уровне и их фильтрацией на более высоком уровне. А есть библиотека libpcap, предоставляющая относительно универсальный способ доступа к фильтру и имеющая свой набор функций. Задумано очень грамотно (кросплатформенность и простота разработки), однако программа, которая делает то, что нужно, сочетая в себе маленький размер и быстроту работы, - приятнее. Написание снифера При работе с tcp/ip-стеком у нас довольно часто будет возникать необходимость работать с определенными полями определенных протоколов. Поэтому хотелось бы сделать некие структуры, содержащие смещения полей, к которым мы могли бы адресоваться, как хотели. Опять-таки, ориентируясь на данную статью, самое необходимое – это структура IP-заголовка. Еще для анализатора нам понадобится структура ARP-пакета (для ETHERNET-пакета проще работать непосредственно с буфером). Как ты помнишь из RFC, заголовок IP-пакета выглядит следующим образом: Как нам это представить в структуре? Самое наглое - залезть в инклуды и посмотреть, как сделано там. В данном случае это /usr/include/netinet/ip.h, но, например, ip_source и ip_dest поля у разработчиков описаны немного муторно, поэтому мы их добавим, как нужно нам. Итак, делаем структуру: struct my_ip |