Русский
Русский
English
Статистика
Реклама

Tcpdump

Я смотрел свой трафик он все знал про меня (Mac os catalina)

28.09.2020 20:13:28 | Автор: admin
человек с бумажным пакетом на головечеловек с бумажным пакетом на голове

Сегодня после обновления catalina с 15.6 на 15.7, просела скорость интернета что то сильно грузило мою сеть я решил посмотреть сетевую активность.

запустил tcpdump на пару часов:

sudo tcpdump -k NP > ~/log 

И первое что бросилось мне в глаза:

16:43:42.919443 () ARP, Request who-has 192.168.1.51 tell 192.168.1.1, length 2816:43:42.927716 () ARP, Request who-has 192.168.1.52 tell 192.168.1.1, length 2816:43:42.934112 () ARP, Request who-has 192.168.1.53 tell 192.168.1.1, length 2816:43:42.942328 () ARP, Request who-has 192.168.1.54 tell 192.168.1.1, length 2816:43:43.021971 () ARP, Request who-has 192.168.1.55 tell 192.168.1.1, length 28

зачем ему вся моя локальная сеть? Он ее сканирует без конца каждую минуту 192.168.1./255, ладно допустим это служба сетевого обозревателя.

(shadowserver.org) - некоммерческая организация по обеспечению безопасности

16:43:33.518282 () IP scan-05l.shadowserver.org.33567 > 192.168.1.150.rsync: Flags [S], seq 1527048226, win 65535, options [mss 536], length 0

Еще одна стучалка (scanner-12.ch1.censys-scanner.com -> censys.io):

16:44:16.254073 () IP scanner-12.ch1.censys-scanner.com.62651 > 192.168.1.150.8843: Flags [S], seq 1454862354, win 1024, options [mss 1460], length 0

Ладно окей вроде ничего особенного аналитика сканирование локальной сети ну обычное дело но что тогда вот это:

16:15:56.603292 () IP 45.129.33.152.51777 > 192.168.1.150.jpegmpeg: Flags [S], seq 2349838714, win 1024, options [mss 536], length 0

Если перейти по этому ip адресу http://45.129.33.152 можно увидеть это:

Текстовые файлы содержать миллионы ip адресов с портами.Текстовые файлы содержать миллионы ip адресов с портами.

Содержание файла temp:

[?1h=[?25l[H[J[mtop - 21:17:26 up 31 days,  6:44,  1 use[m[39;49m[m[39;49m[KTasks:[m[39;49m[1m 144 [m[39;49mtotal,[m[39;49m[1m   1 [m[39;49mrunning,[m[39;49m[1m 143 [m[39;49msleep[m[39;49m[m[39;49m[K%Cpu(s):[m[39;49m[1m  0.8 [m[39;49mus,[m[39;49m[1m  0.0 [m[39;49msy,[m[39;49m[1m  0.0 [m[39;49mni,[m[39;49m[1m 92.0[m[39;49m[m[39;49m[KKiB Mem :[m[39;49m[1m 32681700 [m[39;49mtotal,[m[39;49m[1m 18410244 [m[39;49mfree,[m[39;49m[m[39;49m[KKiB Swap:[m[39;49m[1m 16449532 [m[39;49mtotal,[m[39;49m[1m 16449288 [m[39;49mfree,[m[39;49m[m[39;49m[K[K[7m  PID USER      PR  NI    VIRT    RES [m[39;49m[K[m    1 root      20   0  191072   3924 [m[39;49m[K[m    2 root      20   0       0      0 [m[39;49m[K[m    3 root      20   0       0      0 [m[39;49m[K[m    5 root       0 -20       0      0 [m[39;49m[K[m    7 root      rt   0       0      0 [m[39;49m[K[m    8 root      20   0       0      0 [m[39;49m[K[m    9 root      20   0       0      0 [m[39;49m[K[m   10 root      rt   0       0      0 [m[39;49m[K[m   11 root      rt   0       0      0 [m[39;49m[K[m   12 root      rt   0       0      0 [m[39;49m[K[m   13 root      20   0       0      0 [m[39;49m[K[m   15 root       0 -20       0      0 [m[39;49m[K[m   16 root      rt   0       0      0 [m[39;49m[K[H[mtop - 21:17:29 up 31 days,  6:44,  1 use[m[39;49m[m[39;49m[K%Cpu(s):[m[39;49m[1m  0.0 [m[39;49mus,[m[39;49m[1m  0.0 [m[39;49msy,[m[39;49m[1m  0.0 [m[39;49mni,[m[39;49m[1m100.0[m[39;49m[m[39;49m[KKiB Mem :[m[39;49m[1m 32681700 [m[39;49mtotal,[m[39;49m[1m 18409876 [m[39;49mfree,[m[39;49m[m[39;49m[K[K

Ну и напоследок пачка неизвестных запросов:

16:16:07.022910 () IP 059148253194.ctinets.com.58703 > 192.168.1.150.4244: Flags [S], seq 2829545743, win 1024, options [mss 536], length 016:15:57.133836 () IP 45.129.33.2.55914 > 192.168.1.150.39686: Flags [S], seq 700814637, win 1024, options [mss 536], length 016:15:56.603292 () IP 45.129.33.152.51777 > 192.168.1.150.jpegmpeg: Flags [S], seq 2349838714, win 1024, options [mss 536], length 016:16:15.083755 () IP 45.129.33.154.55846 > 192.168.1.150.7063: Flags [S], seq 4079154719, win 1024, options [mss 536], length 016:15:43.251305 () IP 192.168.1.150.60314 > one.one.one.one.domain: 3798+ PTR? 237.171.154.149.in-addr.arpa. (46)16:16:24.386628 () IP 45.141.84.30.50763 > 192.168.1.150.12158: Flags [S], seq 572523718, win 1024, options [mss 536], length 016:16:44.817035 () IP 92.63.197.66.58219 > 192.168.1.150.15077: Flags [S], seq 4012437618, win 1024, options [mss 536], length 016:15:43.172042 () IP 45.129.33.46.51641 > 192.168.1.150.bnetgame: Flags [S], seq 362771723, win 1024, options [mss 536], length 016:17:02.120063 () IP 45.129.33.23.42275 > 192.168.1.150.11556: Flags [S], seq 3354007029, win 1024, options [mss 536], length 016:16:00.589816 () IP 45.129.33.3.56005 > 192.168.1.150.40688: Flags [S], seq 2710391040, win 1024, options [mss 536], length 0

Если я блокирую эти домены и ip адреса в файле host то в следующем дампе будут те же подсети ip но с другими конечными адресами, и у доменов меняется поддомен.

Мак не понимает маску в файле host *.example.com

Как смотреть пакеты которые передаются и какие процессы или демоны вызывают эти соединения я пока не понял (обладаю маком несколько дней) но уже весело!

Подробнее..

Прерывается голос, слышу эхо Проблема качества связи ip телефонии. Как можно решить самостоятельно?

07.04.2021 08:12:05 | Автор: admin
Источник: ЯндексКартинкиИсточник: ЯндексКартинки

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

Некоторые провайдеры, конечно подсказывают, что можно предпринять со своей стороны, в чем может быть проблема. Снимут дамп, сделают анализ и дадут рекомендации. Но таких крайне мало. Из памяти, пожалуй вспомню оператора Мобилон. Привет техподдержке, если читаете!

А что происходит, если провайдер не дал рекомендаций, не указал на причину?

Несомненно, у вас начнет закрадываться мысль о смене провайдера. Но решит ли это проблему? Если причина на нашей стороне, то очевидно, что проблема не решится, и качество будет также неудовлетворительным с новым провайдером. А переход, дело не простое и затратное. За такой исход событий руководство компании спасибо нам не скажет.

Можно еще обратиться к какой-нибудь аутсорсинговой фирме, которая имеет кейсы в решении подобных проблем. Но это дополнительные затраты. Да и нет никаких гарантий, что потраченные средства в итоге оправдают себя.

Что же еще можно предпринять? Казалось бы, вариантов больше не осталось...

Но может быть, все таки, разобраться самому? Возможно, это не так сложно?

Да, дорогие друзья!
Отвечу я вам. Всё гораздо проще, чем кажется на первый взгляд!

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

Для диагностики нам понадобится научиться снимать дамп сети (sniffer) с роутера и маршрутизатор Mikrotik. А также, настроить очереди (QoS) на роутере.

Для упрощения схемы, я поделил весь процесс на этапы:

  1. Настроить и запустить sniffer

  2. Воспроизвести проблемный вызов

  3. Проанализировать sniffer в Wireshark

  4. Настроить на роутере выделенную полосу (QoS) для телефонии

  5. Протестировать связь

1. Настройка и запуск packet sniffer

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

Настраиваем на Микротике packet sniffer: Tools->Packet Sniffer

На вкладке General оставляем значения по умолчанию.

Открываем настройку Packet SnifferОткрываем настройку Packet Sniffer

Вкладка Streaming: галочки Streaming Enabled и Filter Stream, в поле Server пишем адрес, куда будем отправлять данные, собираемые сниффером.

Прописываем адрес хоста куда слать снифферПрописываем адрес хоста куда слать сниффер

Я отправляю на свой ПК в той же сети, поэтому прописываю его локальный адрес. Но можно слать и на удаленный сервер, тогда прописываем его внешний ip.

Вкладка Filter: здесь необходимо в поле IP Address прописать ip адрес провайдера телефонии.

Желательно уточнить у самого провайдера адреса серверов, с каким сервером осуществляется обмен сигнальными сообщениями, а с каким - RTP.

Если не получилось выяснить адреса провайдера, то можно прописать просто 0.0.0.0/0

Но тогда в дампе будет очень много лишней информации, что затруднит анализ.

Я пообщался с техподдержкой своего провайдера, они порекомендовали прописать всю подсеть.

Прописываем адрес провайдера ip телефонииПрописываем адрес провайдера ip телефонии

Нажимаем Apply и Start. Внизу окна появится статус: running

Packet Sniffer запущенPacket Sniffer запущен

Сниффер на роутере запущен, теперь необходимо поймать пакеты.

На том ПК или сервере, адрес которого указали в поле Server, нужно запустить tcpdump.

На Windows:

а) нужно скачать утилиту tcpdump

Скачиваем с официального сайта версию не для коммерческого использования.

tcpdump.exe можно запустить даже с флэшки

Для этого запускаем cmd от имени администратора и проваливаемся в директорию с файлом tcpdump.exe

Запускаем tcpdump на WindowsЗапускаем tcpdump на Windows

Вводим команду tcpdump -D

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

Выводим список доступных интерфейсовВыводим список доступных интерфейсов

Запускаем дамп в онлайн режиме, чтобы найти интерфейс, который нам нужно слушать.

Например: tcpdump -i 1 -v -n host 192.168.88.1

где 1 - это номер интерфейса, а host - адрес роутера.

У меня пакеты летят на интерфейсе под 4, его и буду слушать.

Запускаем tcpdump onlineЗапускаем tcpdump online

Далее запускаем команду для отлова сниффера с Микротика:

tcpdump host 192.168.88.1 -i 4 -C50 -n -v -w name_sniffer.pcap

где i - номер интерфейса, С50 - ограничение размера записываемого файла до 50Мб, n - отображать IP адреса вместо имени хостов, v - уровень отображения получаемой информации (1-й уровень), w - записывать данные в файл.

Запустили tcpdump для отлова Packet SnifferЗапустили tcpdump для отлова Packet Sniffer

На Linux :

Необходимо установить утилиту tcpdump. Обычно она присутствует в стандартном репозитории.

Более подробно про установку можно посмотреть, например, здесь.

Запускаем команду:

tcpdump host 192.168.88.1 -i any -C50 -n -v -w /var/tmp/name_sniffer.pcap

После запуска tcpdump вы должны увидеть отсчет улавливаемых пакетов (на Linux), в поле Got. Если отсчет не идет, значит что-то сделали неверно, перепроверьте.

Запустили tcpdump для отлова Packet SnifferЗапустили tcpdump для отлова Packet Sniffer

2. Фиксируем проблемный звонок

Теперь, когда у нас tcpdump ловит сниффер с Микротика, нужно зафиксировать проблемный звонок.

Если проблема плавающая, тогда следуют попросить сотрудников, чтобы записали время и номер телефона, когда возникнет деградация голоса.

У меня получилось зафиксировать такой пример самостоятельно с одним из сотрудников:

Как мы слышим на записи, голос идет с прерываниями.

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

3. Останавливаем sniffer и анализируем его в Wireshark

Проблемный вызов необходимо проанализировать. Останавливаем tcpdump (Ctrl+C) и sniffer на Микротике (нажать Stop). Создастся файл name_sniffer.pcap.

Устанавливаем программу Wireshark. Скачать ее можно бесплатно с официального сайта. А на Линуксе можно установить из стандартного репозитория.

Открываем pcap файл в Wireshark и переходим в Телефония->Вызовы VoIP

Открываем pcap файл для анализаОткрываем pcap файл для анализа

В новом окне отобразятся все вызовы, которые попали в дамп. У меня такой один.

VoIP вызов в дампеVoIP вызов в дампе

Для удобства поиска вызовов (когда их в дампе много) установите галочку Время дня.

Выберите вызов и откройте Последовательность потоков, чтобы увидеть движение запросов по вашему звонку.

Дамп движения запросов звонка (последовательность потоков)Дамп движения запросов звонка (последовательность потоков)

Здесь мы увидим, с каким сервером провайдера идет обмен сигнальными сообщениями, а с каким сервером осуществляется передача голосовых пакетов (RTP).

В случае, когда не проходит вызов или наблюдается односторонняя слышимость, мы можем с помощью дампа последовательности потоков увидеть, где кроется проблема.

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

Далее нас интересуют RTCP пакеты.

Из всего перехваченного сниффером трафика нужно отфильтровать только RTCP пакеты.

Прописываем фильтр:

(rtcp.ssrc.fraction>10)||(rtcp.ssrc.jitter>35)

- отобразить RTCP со значением потерь пакетов больше 10 или RTCP со значением джиттера больше 35.

Выбираем сообщение и разворачиваем RTCP -> Source 1 -> SSRC Contents

Анализ RTCP по звонкуАнализ RTCP по звонку

Здесь видим, что потеряно 50 пакетов из 256 и уровень джиттера 166 (хотя нормальный уровень это 30-70).

Так можно полистать по всем найденным сообщениям и убедиться, что деградация качества голоса возникает из-за потери голосовых пакетов на нашем интернет канале.

По каким причинам это может происходить?

  1. Забивается линия выделенная вам от интернет провайдера.
    Например, у нас 3Mб/с на "внешку". Устройства в локальной сети потребляют все 3Mб/с, но если просто сёрфить в браузере, то мы не заметим нехватку канала. Так как в этом случае, используется транспортный протокол TCP. А телефония использует UDP, которому свойственно теряться в процессе передачи, если весь ваш выделенный канал занят.

  2. Устройства подключены по воздуху (Wi-Fi).
    В таком случае будет высокий показатель джиттера.

  3. У провайдера на линии есть радиоканал.

  4. Проблема с вашим маршрутизатором.

  5. Проблемы на линии интернет провайдера

В этой статье, более подробно, рассмотрена причина под пунктом 1.

По остальным скажу кратко.

Пункт 2 - если на устройствах есть функция джиттер-буфер, то нужно установить режим Fixed. Если нет такой опции, то подключить устройство витой парой.

Пункт 3 и 5 - обратиться к интернет провайдеру, предоставив наши дампы, подтверждающие проблему.

Пункт 4 - диагностировать или заменить роутер.

Но в первую очередь, рекомендую всегда сначала проработать пункт 1.

4. Настраиваем выделенную полосу для ip телефонии

Необходимо в вашей локальной сети обеспечить для ip телефонии отдельную полосу пропускания (QoS), чтобы трафик других устройств не мешал.

Для начала, измерьте фактическую скорость интернета на "внешку".

Я измеряю через speedtest.net

Можно еще с помощью 2ip.ru или утилитой iperf

На speedtest.net я выбираю Change Server город отличный от моего, чтобы исключить вероятность замера скорости в пиринге.

Настраиваю speedtest.net для замера скоростиНастраиваю speedtest.net для замера скоростиВыбираю Change ServerВыбираю Change ServerРезультаты измерения скорости интернетаРезультаты измерения скорости интернета

У меня на загрузку скорость 11Мб/с, на отдачу 14Мб/с. Хотя по договору должно быть 15М в обе стороны. Поэтому и рекомендую измерять, какая у вас скорость по факту, а не по бумагам. Это поможет корректно настроить очереди на роутере.

Для настройки очередей открываем на Микротике Queues

QueuesQueues

Cоздаем правила в разделе Simple Queues.

На вкладке General задаем ограничение по скорости для всей локальной сети.

Я устанавливаю максимальные значения лимита меньше на 2М, чем полученные при замере.

Почему 2М? Беру с запасом, так как скорость может быть не постоянной и в моменте меняться как в большую, так и в меньшую сторону.

Настройки на вкладке GeneralНастройки на вкладке General

В Advanced выставить Queue Type распределение по pcq (это делается для того, чтобы устройства не мешали друг другу и равномерно использовали трафик).

Настройки на вкладке AdvancedНастройки на вкладке Advanced

Сохраняем это правило и создаем еще одно, для SIP.

Прописываем ip адрес (можно всю подсеть) провайдера ip телефонии.

Максимальные лимиты устанавливаем, как заявлено по договору интернет провайдера.

Настройки General для SIPНастройки General для SIP

В Advanced устанавливаем Limit At. Это позволит для телефонии оставлять 1Мб/с в любом случае, даже если идет максимальная нагрузка на канал другими устройствами.

Вкладка Advanced при настройке QoS для SIPВкладка Advanced при настройке QoS для SIP

Сохраняем и устанавливаем правило SIP на верхнюю позицию.

Порядок QoS правилПорядок QoS правил

ВНИМАНИЕ!

  1. Чтобы очереди (QoS) начали работать, необходимо деактивировать правило Fasttrack в IP -> Firewall -> Filter Rules.

  2. Учитывайте порядок настроенных правил. Обработка осуществляется сверху вниз. Поэтому обязательно правило SIP поднимаем на самый верх.

Пояснение по настроенным QoS:

  • весь трафик, который идет на ip адреса отличные от адреса voip провайдера, ограничивается 12Мб/с на загрузку и 9Мб/с на отдачу

  • весь остаток от этого до 15Мб/с оставляем для телефонии

  • и на тот случай, что если даже трафик проскочит выше лимитов, для телефонии отведен 1Мб/с принудительно

Далее проверяем ходит ли вообще трафик в настроенных QoS.

Нужно открыть настройки очереди и перейти на вкладку Traffic.

График трафика local QoSГрафик трафика local QoSГрафик трафика sip QoSГрафик трафика sip QoS

На вкладке Statistic можно увидеть, количество дропнутых пакетов и распределенных по pcq.

Статистика local QoSСтатистика local QoS

Также можно проверить, как отрабатывают очереди, с помощью утилиты iperf.

5. Тестируем связь

Теперь, когда QoS настроены, нужно протестировать связь.

Ставим дамп и делаем несколько тестовых звонков.

Я сделал несколько вызовов сотрудникам, и мы вместе убедились, что теперь прерываний не наблюдалось.

Вот пример одного из звонков.

В дампе этого вызова потерь пакетов не наблюдается.

Дамп звонка после настройки QoSДамп звонка после настройки QoSДамп звонка после настройки QoSДамп звонка после настройки QoS

Единственное, можно заметить, что уровень джиттера выше нормы.

Это обусловлено подключением voip устройства через Wi-Fi. И, так как устройство позволяет настроить джиттер-буфер, качество голоса не страдает.

Вы можете также и сами наглядно всё это увидеть в моих дампах. Скачать можно здесь:
дамп звонка до настройки QoS
дамп звонка после настройки QoS

Итог:

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

В некоторых организациях в локальной сети может находиться большое количество устройств с разными категориями. Например, помимо ip телефонии еще ip камеры, которые также используют udp протокол для передачи данных. Следовательно для ip камер тоже необходимо выделять QoS.

Вам не обязательно настраивать очереди точно также, как у меня. Главное, что я хотел показать, это логику решения проблемы с качеством голоса.

Более подробно про QoS можно изучить еще в этой статье.

Подробнее..

Анализ сетевого трафика и базовый траблшутиг (бесплатный видео курс)

08.04.2021 10:11:09 | Автор: admin

Прошло уже почти два года с момента публикации моего последнего курса и наконец я опять в деле! Как и прежде, весь контент на ресурсе NetSkills предназначен для подготовки начинающих инженеров. Этот курс не стал исключением и посвящен основам анализа трафика и базовому траблшутингу с помощью таких популярнейших инструментов как tcpdump и wireshark! Одна из важнейших тем, которая совершенно точно пригодится любому сетевику, админу или даже безопаснику. Я бы рекомендовал приступать к этому курсу только после окончания Курса молодого бойца, т.к. данный материал предполагает, что вы понимаете базовые принципы работы компьютерных сетей. В этом же курсе мы погрузимся в детальное изучение работы стэка TCP/IP - тема, которую многие старательно избегают. Однако, по завершению курса вы получите знания и навыки, которые выведут ваше понимание сетей на принципиально новый уровень. Вы поймете саму суть работы сетей и что важнее - научитесь видеть проблемы в ее работе.

Повторюсь, мы будем анализировать трафик с помощью утилит tcpdump и wireshark, которые уже давно являются стандартом в мире анализа и траблшутинга. Вы просто обязаны уметь ими пользоваться! При этом большинство использует их от силы на 10% от возможностей (если вообще используют). Я же постараюсь научить вас это делать, как профессионалы.

Содержание

  1. Три главных способа сбора сетевого трафика

    Обсудим, что такое вообще сбор, как он осуществляется и какие преимущества и недостатки у этих способов.

  2. Основы tcpdump

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

  3. Фреймы, пакеты, сегменты

    Возможно кому-то покажется, что это тема здесь лишняя, но это заблуждение. Невозможно нормально анализировать трафик, и уж тем более траблшутить, если вы не понимаете основы. Я постараюсь рассказать о самом главном и показать, как это работает в реальной жизни.

  4. Основы Wireshark

    Запустим Wireshark и обсудим основы сбора трафика. Поупражняемся с интерфейсами, профилями и т.д.

  5. Исследование сети

    Попробуем применить полученные навыки в реальном кейсе - а именно исследование сети по дампу трафика. Вы удивитесь, сколько всего можно узнать об инфраструктуре, всего лишь по одному дампу.

  6. Основы фильтрации

    Более плотно поработаем с фильтрацией, колонками, протоколами, полями и т.д. Т.е. научимся выделять нужную информацию в большом объеме данных. Это очень важный навык в работе с Wireshark.

  7. Основы TCP

    Опять перейдем к фундаментальным вещам - основам TCP. Уже на примере дампа реального трафика рассмотрим как работает 3 way tcp handshake - важнейший механизм в сетевом взаимодействии.

  8. RTT & Window Size

    Параметры, которые во многом определяют надежность и стабильность сети. Здесь вы на практике поймете, почему широкий канал это не всегда быстрый канал и почему так важно время отклика для онлайн игр.

  9. Визуализация данных

    Да, wireshark умеет и это. Причем в некоторых кейсах это очень помогает в решении проблем.

  10. Реальные кейсы

    Ну и под конец мы рассмотрим несколько типовых проблем в сети и научимся их решать с помощью Wireshark.

Видео курс

Данный курс, как и Курс молодого бойца, бесплатно опубликован на ютуб-канале:

Смотрите, оставляйте комментарии, принимается любая конструктивная критика.

Спасибо за внимание!

Подробнее..

Перевод Инструмент для отслеживания DNS-запросов dnspeep

07.05.2021 18:23:01 | Автор: admin

Недавно я создала небольшой инструмент под названием dnspeep, который позволяет понять, какие DNS-запросы отправляет ваш компьютер и какие ответы он получает. Всего мой код занял 250 строк на Rust. В этой статье я расскажу о коде, объясню, для чего он нужен, почему в нём возникла необходимость, а также расскажу о некоторых проблемах, с которыми я столкнулась при его написании. И, конечно, вы сами сможете попробовать код в действии.


Что нужно для начала работы с кодом

Чтобы было удобнее работать с кодом, я подготовила несколько бинарных файлов.

Команды для Linux (x86):

wget https://github.com/jvns/dnspeep/releases/download/v0.1.0/dnspeep-linux.tar.gztar -xf dnspeep-linux.tar.gzsudo ./dnspeep

Команды для Mac:

wget https://github.com/jvns/dnspeep/releases/download/v0.1.0/dnspeep-macos.tar.gztar -xf dnspeep-macos.tar.gzsudo ./dnspeep

Коду необходим доступ ко всем отправляемым компьютером пакетам DNS, поэтому его необходимо запускать от имени root. По этой же причине утилиту tcpdump также нужно запускать от имени root: код использует libpcap ту же библиотеку, что и tcpdump. Если вам по какой-либо причине не захочется загружать бинарные файлы и запускать их от имени root, вы можете воспользоваться моим исходным кодом и создать на его основе собственный.

Что получается в результате

Каждая строка представляет собой DNS-запрос и соответствующий запросу ответ.

$ sudo dnspeepquery   name                 server IP      responseA       firefox.com          192.168.1.1    A: 44.235.246.155, A: 44.236.72.93, A: 44.236.48.31AAAA    firefox.com          192.168.1.1    NOERRORA       bolt.dropbox.com     192.168.1.1    CNAME: bolt.v.dropbox.com, A: 162.125.19.131

Эти запросы отражают мои визиты на сайт neopets.com в браузере, а запрос bolt.dropbox.com возник потому, что у меня запущен агент Dropbox, и, как я полагаю, время от времени он заходит на свой сайт для синхронизации.

Зачем создавать ещё один инструмент DNS?

Я считаю, что в таком инструменте есть смысл, так как с его помощью можно лучше представить, как работает DNS без этого инструмента довольно сложно понять, как ведёт себя DNS на компьютере.

Ваш браузер (и другие компьютерные программы) постоянно отправляет DNS-запросы. Если знать, какие запросы отправляет компьютер и какие ответы он получает, можно получить более реальную картину "жизни" компьютера.

Написанный мною код я также использую как инструмент отладки. На вопросы типа: "А не связана ли моя проблема с DNS?" ответить иногда бывает довольно сложно. Пользователи, не зная всей информации, зачастую, чтобы найти проблему, используют метод проб и ошибок или просто строят догадки, хотя, казалось бы, стоит просто проанализировать ответы на получаемые компьютером DNS-запросы, и проблема будет решена.

Можно увидеть, какое программное обеспечение "тайно" выходит в Интернет

Мне нравится в этом инструменте, что он даёт представление о том, какие программы моего компьютера пользуются Интернетом! Например, я обнаружила, что какая-то утилита на моём компьютере время от времени по непонятной причине отправляет запросы на ping.manjaro.org, вероятно, чтобы проверить, подключён ли мой компьютер к Интернету.

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

Если вы раньше не работали с tcpdump, поначалу может быть непонятно, что делает эта утилита

Рассказывая людям об отправляемых с компьютера DNS-запросах, я почти всегда хочу добавить: "Всю информацию можно получить через tcpdump!" Что делает утилита tcpdump? Она осуществляет разбор пакетов DNS! Например, вот как выглядит DNS-запрос incoming.telemetry.mozilla.org.:

11:36:38.973512 wlp3s0 Out IP 192.168.1.181.42281 > 192.168.1.1.53: 56271+ A? incoming.telemetry.mozilla.org. (48)11:36:38.996060 wlp3s0 In  IP 192.168.1.1.53 > 192.168.1.181.42281: 56271 3/0/0 CNAME telemetry-incoming.r53-2.services.mozilla.com., CNAME prod.data-ingestion.prod.dataops.mozgcp.net., A 35.244.247.133 (180)

Сначала эта информация может показаться "тёмным лесом", но её при некоторых навыках можно научиться читать. Давайте для примера разберём такой запрос:

192.168.1.181.42281 > 192.168.1.1.53: 56271+ A? incoming.telemetry.mozilla.org. (48)
  • A? означает DNS-запрос типа A;

  • incoming.telemetry.mozilla.org. это имя объекта, к которому осуществляется запрос;

  • 56271 это идентификатор DNS-запроса;

  • 192.168.1.181.42281 исходный IP/порт;

  • 192.168.1.1.53 IP/порт назначения;

  • (48) длина DNS-пакета.

Ответ выглядит следующим образом:

56271 3/0/0 CNAME telemetry-incoming.r53-2.services.mozilla.com., CNAME prod.data-ingestion.prod.dataops.mozgcp.net., A 35.244.247.133 (180)
  • 3/0/0 количество записей в ответе: 3 ответа, 0 полномочий, 0 дополнительно. Исходя из моего опыта, tcpdump выводит только количество ответов на запрос.

  • CNAME telemetry-incoming.r53-2.services.mozilla.com, CNAME prod.data-ingestion.prod.dataops.mozgcp.net. и A 35.244.247.133 это те самые три ответа

  • 56271 идентификатор ответов, соответствующий идентификатору запроса. По этому идентификатору можно понять, что это ответ на запрос из предыдущей строки.

С таким форматом, конечно, работать довольно сложно, ведь человеку нужно просто посмотреть на трафик DNS, к чему все эти нагромождения? И вот ему приходится вручную сопоставлять запросы и ответы, к тому же не всегда находящиеся на соседних строках. Здесь в дело вступают компьютерные возможности!

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

Проблемы, с которыми я столкнулась при написании кода

При написании кода я столкнулась с рядом проблем.

  • Мне пришлось несколько изменить библиотеку pcap, чтобы заставить её правильно работать с Tokio на Mac OS вот эти изменения. Это была одна из тех ошибок, на поиск которой ушло много часов, а всё исправление уложилось в одну строку.

  • Разные дистрибутивы Linux, по всей видимости, используют разные версии libpcap.so, поэтому мне не удалось воспользоваться непосредственно бинарным файлом, динамически компонующим libpcap (у других пользователей возникала такая же проблема, например здесь). Поэтому компилировать библиотеки libpcap в инструмент на Linux мне пришлось статически. Я до сих пор не понимаю, как такое правильно организовать на Rust, но я добилась, чего хотела, и всё заработало я скопировала файл libpcap.a в каталог target/release/deps, а затем просто запустила cargo build.

  • Используемая мною библиотека dns_parser поддерживает не все типы DNS-запросов, а только некоторые самые распространённые. Возможно, для разбора DNS-пакетов можно было использовать другую библиотеку, но я не нашла подходящей.

  • Поскольку интерфейс библиотеки pcap выдает набор "голых" байтов (в том числе для данных Ethernet-фреймов), мне пришлось написать код, который определял, сколько байтов нужно отсечь от начала строки, чтобы получить IP-заголовок пакета. Но я уверена, что в моей задаче ещё остались "подводные камни".

Кстати, вы даже не представляете, каких сложностей мне стоило подобрать название для своей утилиты ведь инструментов для работы с DNS великое множество, и у каждого своё название (dnsspy! dnssnoop! dnssniff! dnswatch!) Сначала я хотела включить в название слово spy (шпион) или его синонимы, а затем остановилась на показавшемся мне забавным названии, которое о чудо! ещё никто не занял для собственного DNS-инструмента.

У моей утилиты есть один недостаток: она не сообщает, какой именно процесс отправил DNS-запрос, но выход есть используйте инструмент dnssnoop. Этот инструмент работает с данными eBPF. Судя по описанию, он должен работать нормально, но я его ещё не пробовала.

В моём коде наверняка ещё много ошибок

Мне удалось его протестировать только на Linux и Mac, и я уже знаю как минимум об одной ошибке (из-за того, что поддерживаются не все DNS-запросы). Если найдёте ошибку, пожалуйста, сообщите мне!

Сами по себе ошибки не опасны интерфейс libpcap доступен только для чтения, самое худшее, что может случиться, он получит какие-то непонятные данные и выдаст ошибку или аварийно завершит работу.

Мне нравится составлять небольшие учебные материалы

В последнее время я получаю огромное удовольствие от написания небольших учебных материалов по DNS. Вот ссылки на мои предыдущие статьи:

  • Простой способ составления DNS-запросов;

  • Рассказывается, что происходит внутри компьютера при отправке DNS-запроса;

  • Ссылка на dnspeep.

Ранее в своих постах я просто объясняла, как работают существующие инструменты (например dig или tcpdump), а если и писала собственные инструменты, то довольно редко. Но сейчас для меня очевидно, что выходные данные этих инструментов довольно туманны, их сложно понять, поэтому мне захотелось создать более дружественные варианты просмотра такой информации, чтобы не только гуру tcpdump, но любые другие пользователи могли понять, какие DNS-запросы отправляет их компьютер.

А если вы хотите не только понимать, что происходит с запросами и ответами DNS на вашем компьютере, но и писать собственные протоколы для своих приложений, обратите внимание на профессии C++ разработчик или Java-разработчик, позволяющие с нуля освоить эти языки или прокачать своё владение ими. Приходите опытные менторы и эксперты своего дела с удовольствием поделяться с вами своими знаниями.

Узнайте, как прокачаться и в других специальностях или освоить их с нуля:

Другие профессии и курсы
Подробнее..

Как Иван ошибку в бэкенде локализовывал

09.09.2020 12:15:30 | Автор: admin
В комментариях к одной из моих статей про базовые команды Linux shell для тестировщиков справедливо заметили, что в ней не было указано применение команд в процессе тестирования. Я подумал, что лучше поздно, чем никогда, поэтому решил рассказать историю Backend QA-инженера Вани, который столкнулся с неожиданным поведением сервиса и попытался разобраться, где именно случилась ошибка.



Что тестировал Ваня


Ваня знал, что ему предстоит тестировать связку nginx + сервис.
Здесь я сразу сделаю ремарку: такая связка была выбрана для этой статьи просто потому, что она нагляднее всего может продемонстрировать применение различных утилит при дебаге проблемы и потому, что её очень просто сконфигурировать и поднять. В реальных условиях это может быть либо просто сервис, либо цепочка сервисов, которые делают запросы друг другу.

В качестве сервиса выступает дефолтный HTTP сервер Python SimpleHTTPServer, который в ответ на запрос без параметров выводит содержимое текущей директории:

[root@ivan test_dir_srv]# ls -ltotal 0-rw-r--r-- 1 root root 0 Aug 25 11:23 test_file[root@ivan test_dir_srv]# python3 -m http.server --bind 127.0.0.1 8000Serving HTTP on 127.0.0.1 port 8000 (http://personeltest.ru/away/127.0.0.1:8000/) ...

Nginx же сконфигурирован следующим образом:

upstream test {server 127.0.0.1:8000;}server {listen    80;location / {proxy_pass http://test;}}

Ване нужно было протестировать один-единственный тест-кейс: проверить, что запрос на / работает. Он проверил, и всё работало:

MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Directory listing for /</title></head><body><h1>Directory listing for /</h1><hr><ul><li><a href="test_file">test_file</a></li></ul><hr></body></html>

Но затем в один момент на тестовом стенде разработчики что-то обновили, и Ваня получил ошибку:

MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78<html><head><title>502 Bad Gateway</title></head><body bgcolor="white"><center><h1>502 Bad Gateway</h1></center><hr><center>nginx/1.14.2</center></body></html>

Он решил не скидывать эту непонятную ошибку разработчикам, а получить доступ по ssh на сервер и разобраться, в чём там дело. Знаний в области такого рода дебага проблем у него было мало, но он очень хотел научиться, поэтому вооружился поисковиками, логикой и пошёл локализовывать баг.

Первая мысль Вани: логи


Действительно, если случилась ошибка, то нужно просто найти её в лог-файле. Но сначала нужно найти сам лог-файл. Ваня полез в Google и узнал, что часто логи лежат в директории /var/log. Действительно, там нашлась директория nginx:

[root@ivan ~]# ls /var/log/nginx/access.log access.log-20200831 error.log error.log-20200831

Иван посмотрел последние строчки error лога и понял, в чём дело: разработчики ошиблись в конфигурации nginx, в порт upstream закралась опечатка.

[root@ivan ~]# tail /var/log/nginx/error.log2020/08/31 04:36:21 [error] 15050#15050: *90452 connect() failed (111: Connection refused) while connecting to upstream, client: 31.170.95.221, server: , request: "GET / HTTP/1.0", upstream: "http://127.0.0.1:8009/", host: "12.34.56.78"

Какой можно сделать из этого вывод? Логи лучший друг тестировщиков и разработчиков при локализации ошибок. Если есть какое-то неожиданное поведение сервиса, а в логах при этом ничего нет, то это повод вернуть задачу в разработку с просьбой добавить логов. Ведь если б nginx не писал в лог о неудачной попытке достучаться до апстрима, то, согласитесь, искать проблему было бы сложнее?

В тот момент Ваня задумался: А что, если бы в nginx логи лежали в другой директории? Как бы я их нашёл? Через пару лет у Вани будет больше опыта работы с сервисами в Linux, и он будет знать, что путь к лог-файлу часто передают сервису аргументом командной строки, либо он содержится в файле конфигурации, путь к которому также часто передают сервису аргументом командной строки. Ну и в идеале путь к лог-файлу должен быть прописан в документации сервиса.

Кстати, через файл конфигурации можно найти путь к лог-файлу и в nginx:

[root@ivan ~]# ps ax | grep nginx | grep masterroot   19899 0.0 0.0 57392 2872 ?    Ss  2019  0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf[root@ivan ~]# grep "log" /etc/nginx/nginx.conferror_log /var/log/nginx/error.log warn;log_format main '$remote_addr - $remote_user [$time_local] "$request" 'access_log /var/log/nginx/access.log main;

А что если в логах ничего нет?


В свободное время Ваня решил подумать, а как бы он справился с задачей, если бы nginx не писал ничего в лог. Ваня знал, что сервис слушает порт 8000, поэтому решил посмотреть трафик на этом порту на сервере. С этим ему помогла утилита tcpdump. При правильной конфигурации он видел запрос и ответ:

Дамп трафика на порту 8000
[root@ivan ~]# tcpdump -nn -i lo -A port 8000tcpdump: verbose output suppressed, use -v or -vv for full protocol decodelistening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes09:10:42.114284 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [S], seq 3390176024, win 43690, options [mss 65495,sackOK,TS val 830366494 ecr 0,nop,wscale 8], length 0E..<..@.@..............@.............0.........1~c.........09:10:42.114293 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [S.], seq 4147196208, ack 3390176025, win 43690, options [mss 65495,sackOK,TS val 830366494 ecr 830366494,nop,wscale 8], length 0E..<..@.@.<..........@...110.........0.........1~c.1~c.....09:10:42.114302 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 1, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0E..4..@.@..............@.....111.....(.....1~c.1~c.09:10:42.114329 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [P.], seq 1:88, ack 1, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 87E.....@.@..b...........@.....111...........1~c.1~c.GET / HTTP/1.0Host: testConnection: closeUser-Agent: curl/7.64.1Accept: */*09:10:42.114333 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [.], ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0E..4R/@.@............@...111...p.....(.....1~c.1~c.09:10:42.115062 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [P.], seq 1:155, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 154E...R0@.@............@...111...p...........1~c.1~c.HTTP/1.0 200 OKServer: SimpleHTTP/0.6 Python/3.7.2Date: Mon, 07 Sep 2020 13:10:42 GMTContent-type: text/html; charset=utf-8Content-Length: 34009:10:42.115072 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 155, win 175, options [nop,nop,TS val 830366494 ecr 830366494], length 0E..4.@.@..............@...p.11......(.....1~c.1~c.09:10:42.115094 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [P.], seq 155:495, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 340E...R1@.@..<.........@...11....p.....|.....1~c.1~c.<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><title>Directory listing for /</title></head><body><h1>Directory listing for /</h1><hr><ul><li><a href="test_file">test_file</a></li></ul><hr></body></html>09:10:42.115098 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [.], ack 495, win 180, options [nop,nop,TS val 830366494 ecr 830366494], length 0E..4.@.@..............@...p.13......(.....1~c.1~c.09:10:42.115128 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [F.], seq 495, ack 88, win 171, options [nop,nop,TS val 830366494 ecr 830366494], length 0E..4R2@.@............@...13....p.....(.....1~c.1~c.09:10:42.115264 IP 127.0.0.1.33296 > 127.0.0.1.8000: Flags [F.], seq 88, ack 496, win 180, options [nop,nop,TS val 830366495 ecr 830366494], length 0E..4..@.@..............@...p.13 .....(.....1~c.1~c.09:10:42.115271 IP 127.0.0.1.8000 > 127.0.0.1.33296: Flags [.], ack 89, win 171, options [nop,nop,TS val 830366495 ecr 830366495], length 0E..4R3@.@............@...13 ...q.....(.....1~c.1~c.^C12 packets captured24 packets received by filter0 packets dropped by kernel


При неправильной конфигурации (с портом 8009 в апстриме nginx) на порту 8000 никакого трафика не было. Ваня обрадовался: теперь даже если разработчики забыли реализовать запись в лог при сетевых ошибках, всё равно можно хотя бы узнать, идёт ли трафик на нужный хост или порт.

Какой вывод можно сделать из этой истории? Даже если логов нет, в Linux есть утилиты, которые могут помочь с локализацией проблем.

А если не сеть?


Всё хорошо работало, но однажды Ваня снова получил ошибку, на этот раз другую:

MacBook-Pro-Ivan:~ ivantester$ curl http://12.34.56.78<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"><html><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8"><title>Error response</title></head><body><h1>Error response</h1><p>Error code: 404</p><p>Message: File not found.</p><p>Error code explanation: HTTPStatus.NOT_FOUND - Nothing matches the given URI.</p></body></html>

Ваня снова зашёл на сервер, но в этот раз проблема не была связана с сетью. В логе сервиса тоже было написано File not found, и Ваня решил разобраться, почему внезапно появилась такая ошибка. Он знает, что есть процесс python3 -m http.server, но не знает, содержимое какой директории выводит этот сервис (или, другими словами, какая у этого процесса current working directory). Он узнаёт это с помощью команды lsof:

[root@ivan ~]# ps aux | grep python | grep "http.server"root   20638 0.0 0.3 270144 13552 pts/2  S+  08:29  0:00 python3 -m http.server[root@ivan ~]# lsof -p 20638 | grep cwdpython3 20638 root cwd  DIR   253,1   4096 1843551 /root/test_dir_srv2

Также это можно сделать с помощью команды pwdx или с помощью директории proc:

[root@ivan ~]# pwdx 2063820638: /root/test_dir_srv2[root@ivan ~]# ls -l /proc/20638/cwdlrwxrwxrwx 1 root root 0 Aug 31 08:37 /proc/20638/cwd -> /root/test_dir_srv2

Такая директория действительно есть на сервере, и в ней лежит файл с именем test_file. В чём же дело? Иван погуглил и нашёл утилиту strace, с помощью которой можно смотреть, какие системные вызовы выполняет процесс (про strace, кстати, есть хорошая статья на Хабре, и даже не одна). Можно либо запускать новый процесс через strace, либо подключаться этой утилитой к уже запущенному процессу. Ване подходил второй вариант:

Вывод утилиты strace
[root@ivan ~]# strace -ff -p 20638strace: Process 20638 attachedrestart_syscall(<... resuming interrupted poll ...>) = 0poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 1 ([{fd=4, revents=POLLIN}])accept4(4, {sa_family=AF_INET, sin_port=htons(57530), sin_addr=inet_addr("127.0.0.1")}, [16], SOCK_CLOEXEC) = 5clone(child_stack=0x7f2beeb28fb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f2beeb299d0, tls=0x7f2beeb29700, child_tidptr=0x7f2beeb299d0) = 21062futex(0x11204d0, FUTEX_WAIT_PRIVATE, 0, NULLstrace: Process 21062 attached<unfinished ...>[pid 21062] set_robust_list(0x7f2beeb299e0, 24) = 0[pid 21062] futex(0x11204d0, FUTEX_WAKE_PRIVATE, 1) = 1[pid 20638] <... futex resumed> )    = 0[pid 20638] futex(0x921c9c, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 27, {1598879772, 978949000}, ffffffff <unfinished ...>[pid 21062] futex(0x921c9c, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x921c98, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1[pid 20638] <... futex resumed> )    = 0[pid 20638] futex(0x921cc8, FUTEX_WAIT_PRIVATE, 2, NULL <unfinished ...>[pid 21062] futex(0x921cc8, FUTEX_WAKE_PRIVATE, 1) = 1[pid 20638] <... futex resumed> )    = 0[pid 20638] futex(0x921cc8, FUTEX_WAKE_PRIVATE, 1) = 0[pid 20638] poll([{fd=4, events=POLLIN}], 1, 500 <unfinished ...>[pid 21062] recvfrom(5, "GET / HTTP/1.1\r\nConnection: upgr"..., 8192, 0, NULL, NULL) = 153[pid 21062] stat("/root/test_dir_srv/", 0x7f2beeb27350) = -1 ENOENT (No such file or directory)[pid 21062] open("/root/test_dir_srv/", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)[pid 21062] write(2, "127.0.0.1 - - [31/Aug/2020 09:16"..., 70) = 70[pid 21062] write(2, "127.0.0.1 - - [31/Aug/2020 09:16"..., 60) = 60[pid 21062] sendto(5, "HTTP/1.0 404 File not found\r\nSer"..., 184, 0, NULL, 0) = 184[pid 21062] sendto(5, "<!DOCTYPE HTML PUBLIC \"-//W3C//D"..., 469, 0, NULL, 0) = 469[pid 21062] shutdown(5, SHUT_WR)    = 0[pid 21062] close(5)          = 0[pid 21062] madvise(0x7f2bee329000, 8368128, MADV_DONTNEED) = 0[pid 21062] exit(0)           = ?[pid 21062] +++ exited with 0 +++<... poll resumed> )          = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500)  = 0 (Timeout)poll([{fd=4, events=POLLIN}], 1, 500^Cstrace: Process 20638 detached<detached ...>


Обычно вывод strace довольно объёмный (а может быть и очень большим), поэтому удобнее сразу перенаправлять его в файл и потом уже искать в нём нужные системные вызовы. В данном же случае можно сразу обнаружить, что сервис пытается открыть директорию /root/test_dir_srv/ кто-то переименовал её и не перезапустил после этого сервис, поэтому он возвращает 404.

Если сразу понятно, какие именно системные вызовы нужно посмотреть, можно использовать опцию -e:

[root@ivan ~]# strace -ff -e trace=open,stat -p 20638strace: Process 20638 attachedstrace: Process 21396 attached[pid 21396] stat("/root/test_dir_srv/", 0x7f2beeb27350) = -1 ENOENT (No such file or directory)[pid 21396] open("/root/test_dir_srv/", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)[pid 21396] +++ exited with 0 +++^Cstrace: Process 20638 detached

Вывод: иногда можно немножко залезть под капот процессу, а помогает с этим strace. Так как эта утилита выводит все системные вызовы, которые использует процесс, то с её помощью также можно находить и сетевые проблемы (например, к какому хосту/порту пытается подключиться процесс), что делает её довольно универсальным инструментом дебага. Также существует похожая утилита ltrace.

Есть ли что-то ещё?


Ваня на этом не остановился и узнал, что есть GNU Project Debugger GDB. С его помощью можно залезть в процесс и даже немного модифицировать его. И Ваня решил попробовать обнаружить последнюю ошибку с помощью GDB. Он предположил, что раз сервис выводит содержимое директории, то можно попробовать поставить breakpoint на функции open() и посмотреть, что будет:
Вывод утилиты gdb
[root@ivan ~]# gdb -p 23998GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-119.el7Copyright (C) 2013 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.  Type "show copying"and "show warranty" for details.This GDB was configured as "x86_64-redhat-linux-gnu".For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Attaching to process 23998 <здесь много сообщений о загрузке символов и отсутствии debugging symbols...>...0x00007f2284c0b20d in poll () at ../sysdeps/unix/syscall-template.S:8181T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)Missing separate debuginfos, use: debuginfo-install keyutils-libs-1.5.8-3.el7.x86_64 krb5-libs-1.15.1-34.el7.x86_64 libcom_err-1.42.9-13.el7.x86_64 libgcc-4.8.5-36.el7.x86_64 libselinux-2.5-14.1.el7.x86_64 openssl-libs-1.0.2k-16.el7.x86_64 pcre-8.32-17.el7.x86_64 zlib-1.2.7-18.el7.x86_64(gdb) set follow-fork-mode child(gdb) b openBreakpoint 1 at 0x7f2284c06d20: open. (2 locations)(gdb) cContinuing.[New Thread 0x7f227a165700 (LWP 24030)][Switching to Thread 0x7f227a165700 (LWP 24030)]Breakpoint 1, open64 () at ../sysdeps/unix/syscall-template.S:8181T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)(gdb) n83T_PSEUDO_END (SYSCALL_SYMBOL)(gdb) n_io_FileIO___init___impl (opener=<optimized out>, closefd=<optimized out>, mode=<optimized out>, nameobj=0x7f227a68f6f0, self=0x7f227a68f6c0) at ./Modules/_io/fileio.c:381381                Py_END_ALLOW_THREADS(gdb) n379                self->fd = open(name, flags, 0666);(gdb) n381                Py_END_ALLOW_THREADS(gdb) print name$1 = 0x7f227a687c90 "/root/test_dir_srv/"(gdb) qA debugging session is active.Inferior 1 [process 23998] will be detached.Quit anyway? (y or n) yDetaching from program: /usr/local/bin/python3.7, process 23998[Inferior 1 (process 23998) detached]


После команды c (continue) Ваня в другой консоли запустил curl, попал в дебаггере в точку останова и стал выполнять эту программу (то есть сервис) по шагам. Как только он нашёл в коде open по какому-то пути name, он вывел значение этой переменной и увидел /root/test_dir_srv/.
GDB это мощный инструмент, и здесь описан простейший вариант его использования. Иногда он может помочь в воспроизведении каких-либо сложных кейсов (например, можно приостановить процесс в нужный момент и воспроизвести состояние гонки), также он помогает с чтением core dump файлов.

А что если Docker?


В один момент DevOps решили, что сервис теперь будет деплоиться Docker-контейнером, и нужно было провести ретест всех кейсов, которые нашёл Ваня. Ваня без проблем нагуглил следующее:

  1. Использовать tcpdump, strace и gdb можно и внутри контейнера, но нужно иметь ввиду Linux capabilities (есть статья, которая объясняет, почему strace не работал в контейнере без --cap-add=SYS_PTRACE).
  2. Можно использовать опцию --pid.

Но ему стало интересно, можно ли посмотреть весь трафик, идущий в контейнер (или из контейнера), прям с хоста. У tcpdump есть возможность выводить трафик какого-либо интерфейса (опция -i), каждому контейнеру соответствует один виртуальный интерфейс veth (это можно увидеть, например, через ifconfig или ip a), но как понять, какому контейнеру какой интерфейс соответствует? Если контейнер не использует host networking, то внутри него будет сетевой интерфейс eth0, через который он может общаться по сети с другими контейнерами и хостом. Остаётся лишь найти, ifindex какого интерфейса на хосте совпадает с iflink интерфейса eth0 контейнера (что это означает можно почитать здесь).

[root@ivan ~]# for f in `ls /sys/class/net/veth*/ifindex`; do echo $f; cat $f; done | grep -B 1 `docker exec test_service_container cat /sys/class/net/eth0/iflink` | head -1/sys/class/net/veth6c18dba/ifindex

Теперь можно запускать tcpdump для интерфейса veth6c18dba:

tcpdump -i veth6c18dba

Но есть способ проще: можно найти IP-адрес контейнера в его сети и слушать трафик на нём:

[root@ivan ~]# docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' test_service_container172.17.0.10[root@ivan ~]# tcpdump -i any host 172.17.0.10

Вывод: дебаг в Docker-контейнере это не страшно. Утилиты в нём работают, а для чтения логов можно использовать docker logs.

Выводы


Как ответственный инженер, Ваня решил кратко законспектировать новую для себя информацию во внутренней базе знаний. Вот что он написал:

  • Логи лучший друг человека. Если встречается неожиданное поведение сервиса и при этом он не пишет ничего в лог это повод попросить разработчиков добавить логов.
  • Иногда бывает, что локализовать ошибку надо, даже если в логах ничего нет. К счастью, в Linux есть много утилит, которые помогают с этим.
  • С дебагом любых сетевых коммуникаций помогает tcpdump. Он помогает видеть, какой трафик откуда и куда идёт на сервере.
  • Заглянуть внутрь процесса помогают утилиты strace, ltrace и gdb.
  • Всё это можно использовать, если сервис работает в Docker-контейнере.
  • Много информации о процессе есть в директориях /proc/PID. Например, в /proc/PID/fd находятся симлинки на все открытые процессом файлы.
  • Также помочь получить различную информацию о системе, файлах или процессах могут утилиты ps, ls, stat, lsof, ss, du, top, free, ip, ldconfig, ldd и прочие.

Надеюсь, вам была полезна эта история, и хотя бы однажды она поможет вам понять, в чём дело, когда вы будете что-то дебажить в Linux. Если Ваня что-то упустил, делитесь этим в комментариях!
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru