Назад | Перейти на главную страницу

Как я могу фильтровать тактовые импульсы реплики MongoDB с помощью tcpdump?

Иногда при устранении неполадок, связанных с работоспособностью набора реплик, я хотел бы специально отфильтровать контрольные пакеты, отслеживать их выход и последующий ответ (или его отсутствие) без всего шума других данных, которые проходят между наборы.

К сожалению, эти пакеты имеют такую ​​же структуру, как и обычные команды / запросы и ответы. Хотя Wireshark имеет диссекторы, которые позволяют мне проникать в проводной протокол MongoDB, я не могу использовать эту технику для tcpdump для фильтрации пакетов в источнике.

Итак, вопрос в том, как отфильтровать тактовые импульсы набора реплик MongoDB в tcpdump?

Опираясь на этот документсначала нам нужно решить, какова наша идентифицирующая черта, чтобы фильтр работал успешно и улавливал только сердцебиение. Затем нам нужно получить шестнадцатеричное представление этого идентификатора. Начиная с самого исходящего пульса (который по сути является просто запросом / командой), это команда администратора и содержит следующую строку:

replSetHeartBeat = 0x7265706c536574486561727446265174 (16 bytes)

Теперь, когда у нас есть идентифицирующая строка, нам нужно выяснить, где заглянуть внутрь TCP. Смещение рассчитывается так:

32 байта для TCP позволяют Проводной протокол MongoDB, а потом:

  • 4 байта - длина сообщения
  • 4 байта - идентификатор запроса
  • 4 байта - ответ на
  • 4 байта - код операции
  • 4 байта - флаги
  • 11 байт - название коллекции (в данном случае всегда одно и то же, но в целом может отличаться)
  • 4 байта - numtoskip
  • 4 байта - numtoreturn
  • 4 байта - длина документа
  • 1 байт - тип

Следовательно, общее смещение составляет: (32 + 4 + 4 + 4 + 4 + 4 + 11 + 4 + 4 + 4 + 1) = 76 байтов.

Следовательно, вы можете подумать, что требуется что-то вроде этого:

sudo tcpdump -i eth0 'tcp[76:16] = 0x7265706c536574486561727446265174'

К сожалению, tcpdump допускает только до 4-х байтовых совпадений за раз, поэтому вам действительно нужно разбить его на блоки 4 x 4 байта и использовать логическое И для объединения совпадений:

sudo tcpdump -i eth0 '(tcp[76:4] = 0x7265706c) and (tcp[80:4] = 0x53657448) and (tcp[84:4] = 0x65617274) and (tcp[88:4] = 0x62656174)'

Это покрывает исходящую часть сердцебиения, но как насчет ответа?

К счастью, ответ на биение намного легче сопоставить - мы ищем часть документа rs: true, и это переводится следующим образом, легко умещаясь в 4 байта:

rs : true = 0x72730001 (4 bytes)

Вычисляя смещение аналогичным образом (единственная реальная разница - это 8-байтовый идентификатор курсора, а не 11-байтовое имя коллекции), мы получаем смещение 73 байта, и это дает нам этот фильтр:

sudo tcpdump -i eth0 'tcp[73:4] = 0x72730001'

Наконец, давайте соберем все это вместе и добавим некоторые из моих предпочтительных параметров tcpdump. В итоге получаем такую ​​команду:

sudo tcpdump -Xs0 -nnpi eth0 -w heartbeats.pcap '((tcp[76:4] = 0x7265706c) and (tcp[80:4] = 0x53657448) and (tcp[84:4] = 0x65617274) and (tcp[88:4] = 0x62656174)) or tcp[73:4] = 0x72730001'

(Успешно протестировано с использованием MongoDB 2.4.4 в Mac OS X и Linux)

Конечно, это также можно применить в более общем плане, вам просто нужно разработать соответствующие критерии сопоставления, смещения и совпадения байтов.

Для справки, вы можете использовать те же критерии, но с немного другим синтаксисом, чтобы протестировать этот тип фильтрации в Wireshark. Эквивалентные фильтры Wireshark для вышеуказанных критериев:

tcp[76:16]==72:65:70:6c:53:65:74:48:65:61:72:74:62:65:61:74
tcp[73:4]==72:73:00:01