Иногда при устранении неполадок, связанных с работоспособностью набора реплик, я хотел бы специально отфильтровать контрольные пакеты, отслеживать их выход и последующий ответ (или его отсутствие) без всего шума других данных, которые проходят между наборы.
К сожалению, эти пакеты имеют такую же структуру, как и обычные команды / запросы и ответы. Хотя Wireshark имеет диссекторы, которые позволяют мне проникать в проводной протокол MongoDB, я не могу использовать эту технику для tcpdump для фильтрации пакетов в источнике.
Итак, вопрос в том, как отфильтровать тактовые импульсы набора реплик MongoDB в tcpdump?
Опираясь на этот документсначала нам нужно решить, какова наша идентифицирующая черта, чтобы фильтр работал успешно и улавливал только сердцебиение. Затем нам нужно получить шестнадцатеричное представление этого идентификатора. Начиная с самого исходящего пульса (который по сути является просто запросом / командой), это команда администратора и содержит следующую строку:
replSetHeartBeat = 0x7265706c536574486561727446265174 (16 bytes)
Теперь, когда у нас есть идентифицирующая строка, нам нужно выяснить, где заглянуть внутрь TCP. Смещение рассчитывается так:
32 байта для TCP позволяют Проводной протокол MongoDB, а потом:
Следовательно, общее смещение составляет: (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