2010-12-02 3 views
4

это мой первый вопрос здесь @stackoverflow.Функция libpcap setfilter() и потеря пакетов

Я пишу инструмент мониторинга для некоторых серверов производства VoIP, особенно инструмент для обнюхивания, который позволяет захватывать весь трафик (VoIP-вызовы), который соответствует заданному шаблону, используя библиотеку pcap в Perl.

Я не могу использовать плохие избирательные фильтры, например, «udp», а затем выполнить всю фильтрацию в коде моего приложения, потому что это будет связано с слишком большим объемом трафика, и ядро ​​не справится с сообщением о потере пакетов.

Что я делаю тогда, чтобы итеративно создавать более избирательный фильтр во время захвата. Вначале я фиксирую только (все) SIP-сигнальный трафик и IP-фрагменты (совпадение шаблонов должно выполняться на уровне приложения в любом случае), тогда, когда я нахожу некоторую информацию о RTP в SIP-пакетах, я добавляю предложения или предложения к фактическую строку фильтра с конкретными IP и PORT и повторно установить фильтр с помощью setfilter().

Так что в основном что-то вроде этого:

  1. Начальный фильтр "(УДП и порт 5060) или (УДП и ф [6: 2]! & 0x1FFF = 0)" -> захватывает все SIP трафика и IP-фрагменты

  2. Изменено фильтр: -> Захватывает также RTP на: "(ОДП и порт 5060) или или (хост IP и порт PORT) (ОДП и ф [6 2] & 0x1FFF = 0!)" конкретный IP, PORT

  3. Обновлен фильтр: "(udp и порт 5060) или (udp и ip [6: 2] & 0x1fff! = 0) или (хост IP и порт PORT) или (хост IP2 и порт PORT2) "-> Захватывает второй поток RTP, а также

И так далее.

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

Но давайте обратимся к недостатку этого подхода.

Вызов setfilter() во время захвата включает в себя тот факт, что libpcap отбрасывает пакеты, полученные «при смене фильтра», как указано в комментариях кода для функции set_kernel_filter() в pcap-linux.c (проверены версии libpcap версии 0.9 и 1.1).

Итак, что происходит, когда я вызываю setfilter(), и некоторые пакеты поступают в IP-фрагментацию, я теряю некоторые фрагменты, и об этом не сообщается статистикой libpcap в конце: я заметил, что он копает в следы.

Теперь я понимаю причину, по которой это действие выполняется libpcap, но в моем случае мне определенно не нужно отказываться от пакета (я не хочу получать какой-то несвязанный трафик).

У вас есть идея по решению этой проблемы, которая не изменяет код libpcap?

ответ

1

Как насчет запуска нового процесса с использованием более конкретного фильтра. У вас может быть сразу два параллельных захвата pcap. Через некоторое время (или проверка того, что оба получили одни и те же пакеты), вы можете остановить оригинал.

+0

Привет, спасибо за ответ. Я думал о нерестационных процессах каждый раз, когда нужен «новый фильтр», но в итоге я получаю довольно много процессов, а также задачу слияния захватов в конце. Честно говоря, это было то, чего я бы избегал ..: P – Guido 2010-12-03 10:06:18

1

Вы можете просто захватить весь трафик RTP?

Из capture filters предложения для RTP трафика:

udp[1] & 1 != 1 && udp[3] & 1 != 1 && udp[8] & 0x80 == 0x80 && length < 250 

Как ссылка указует вы получите несколько ложных срабатывания, где DNS и, возможно, другие UDP пакеты случайна содержат байты заголовка, 0x80, используемые RTP пакетов, однако число должно быть незначительным и недостаточно, чтобы вызвать падение ядра.

+0

Привет, спасибо за ответ. К сожалению, на производственных серверах есть множество вызовов, и весь трафик RTP означает почти весь трафик, и это много. Хорошо знать об этом виде фильтра, хотя, может быть полезно в будущем. – Guido 2010-12-06 10:43:29

1

Круглое отверстие, квадратный штифт.

У вас есть инструмент, который не соответствует вашим потребностям.

Другой вариант - сделать фильтр первого уровня (как указано выше, который захватывает намного больше, чем нужно) и передать его в другой инструмент, который реализует более тонкий фильтр, который вы хотите (вплоть до случая для каждого вызова). Если этот фильтр первого уровня слишком много для ядра из-за интенсивного трафика RTP, вам может понадобиться сделать что-то еще, например, сохранить стабильные процессы для захвата отдельных вызовов (поэтому вы не меняете фильтр на «основной», процесс, просто поручая другим, как устанавливать фильтры.)

Да, это может означать слияние захватов, либо на лету (передайте их всем процессу «сохранить захват»), либо после факта.

Вы понимаете, что вы можете пропустить RTP-пакеты в любом случае, если вы не установите свои фильтры быстро. Не забывайте, что RTP-пакеты могут появиться для отправителя до того, как 200 OK (или сразу вместе), и они могут вернуться к ответчику перед ACK (или поверх него). Также не забудьте INVITE без SDP (предложение в 200 OK, ответ в ACK). Etc и т. Д. :-)

+0

Что касается медиапотоков, то это не большая проблема, если я пропускаю некоторые пакеты в начале и конце, при условии, что я получаю полный реальный поток посередине: этого должно быть достаточно, чтобы обнаружить * реальную потерю пакетов (т. Е. Когда пакет ядра не падает бывает). Я решил, что многопроцесс - это единственное решение. Несмотря на то, что я реализовал версию, исправляющую libpcap, и она работает достаточно хорошо, хотя и не всегда, к сожалению. – Guido 2010-12-20 10:16:17

Смежные вопросы