Написал утилиту для мониторинга IP/TCP трафика -- dmon

Что: 9fe4474ce530fe5e8793160fb9218b36f68bd491

Когда: 2022-09-06 22:11:45+03:00

Темы: bsd ipv6 netperf perl

Написал утилиту для мониторинга IP/TCP трафика -- dmon

http://www.git.stargrave.org/?p=dmon.git;a=commitdiff;h=589005ba759ab606ed18b6c6a20a4df76cbaf399
Снова, в очередной раз, как всегда, не нашёл, казалось бы простейшей
утилиты: хочу в real-time в консоли видеть какой сейчас трафик идёт
между какими IP. Просто увидеть, что сейчас вот такой-то хост активно
что-то качает. Из портов перепробовал с десяток утилит, которые мне
выдавал поисковик на эту тему. Часть или не работает под консолью
(строит графики для web-интерфейса), или не собирается (к чёрту
разбираться почему, хочу быстро и прямо сейчас!), или мониторят только
интерфейсы, без конкретики по адресам. А остальная, работающая часть,
просто не поддерживает IPv6.

Ведь нужно же просто узнавать информацию по переданным IP или TCP
пакетам и красиво агрегировать для показа пользователю. И самая сложная
часть это именно отображение. Пришлось написать самому подобное. Для
сбора информации использую DTrace. Банально взял примеры из
man dtrace_ip и man dtrace_tcp, где показано отображение отправленных и
принятых пакетов. Попробовал в самом DTrace сделать и агрегацию и
отображение, но это дело не простое и имеет очень ограниченную гибкость.
А раз я же ещё и захочу на лету генерировать DTrace скрипты, чтобы можно
было "слушать" на разных сетевых интерфейс��х (мне интересен трафик
только на некоторых), то надо брать в руки Perl.

DTrace скрипт для каждого IP или TCP пакета генерирует вывод: src, dst,
[<>], size. В случае IP адресов src/dst это просто адреса, а в случае
TCP ещё и порты добавлены. И каждую секунду он выводит "T", сигнализируя
что пользователю можно показать обновлённую информацию. Все размеры по
src/dst суммируются, сортируются по убыванию и показывается только топ
значений. Плюс шапка таблицы содержит суммарное кол-во переданных
пакетов и их размер.

Вывод для IP трафика:

         1.25 K / 2.38 K                           85.65 KiB / 2.29 MiB
    ------------------------------------------------------------------------
    2a03:e2c0:2663:2::2         >  2a02:810c:WWWW:XXXX:YYYY:3f    208.91 KiB
    2a03:e2c0:2663:2::2         >  2600:1700:XXXX:YYYY:WWWW:85     48.52 KiB
    2a03:e2c0:2663:1::1         >        2409:8060:XXXX:YYY::2      1.11 KiB

Вывод для TCP:

        21.96 K / 14.08 K                          37.90 MiB / 16.28 MiB
    ------------------------------------------------------------------------
    [2a03:e2c0:2663:2::1]:2049  <    [2a03:e2c0:2663:2::3]:657      2.31 MiB
    [91.211.5.21]:80            >       [200.XXX.YYY.ZZ]:43751    299.53 KiB
    [2a03:e2c0:2663:2::1]:2049  >    [2a03:e2c0:2663:2::3]:657     39.41 KiB
    [91.211.5.21]:443           >        [185.XXX.YYY.Z]:27054      1.69 KiB
    [91.211.5.21]:22            >        [61.XXX.YYY.ZZ]:57762        900 iB

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

На гигабитной скорости оно конечно не дешёвое: сам DTrace жрёт треть
ядра, а Perl 28%, да и drop-ы случаются. Но это же миллионы пакетов за
секунды, где каждый "генерирует" текстовую строчку, которую Perl ещё и
парсит. Но мою задачу это решает более чем полностью и более чем удобно.

оставить комментарий

комментарий 0:

From: kmeaw
Date: 2022-09-06 22:16:42Z

Всегда использовал iftop [-P] для решения этой задачи. Он не подошёл,
потому что считает трафик с помощью захвата через pcap?

комментарий 1:

From: Sergey Matveev
Date: 2022-09-07 05:16:15Z


>Всегда использовал iftop [-P] для решения этой задачи. Он не подошёл,
>потому что считает трафик с помощью захвата через pcap?

Это первое что я попробовал, да и точно помню что видел его не раз. Но
он не показывает мне ничего на интерфейсе где нет IPv4 адреса:

    # iftop -i gif_tb
    interface: gif_tb
    Unable to get IP address for interface: gif_tb
    ioctl(SIOCGIFADDR): Can't assign requested address
    MAC address is: 00:00:00:00:00:00

Это gif-туннель до туннельного брокера, где только IPv6 ходит.

комментарий 2:

From: Sergey Matveev
Date: 2022-09-07 05:25:04Z


>Всегда использовал iftop [-P] для решения этой задачи.

Да и на gif-интерфейсе с IPv4 он тоже IPv6 не показывает трафик.

комментарий 3:

From: kmeaw
Date: 2022-09-07 13:09:48Z

В Linux есть специальный режим cooked-mode capture (SLL), в котором ядро
само формирует заголовки канального уровня. Это позволяет, например,
работать tcpdump -i any и захватывать трафик одновременно со всех
интерфейсов, вне записимости от того, как у них устроен L2. Это
позволяет iftop работать одинаково как на настоящих интерфейсах, так и
на tun, получая нули вместо MAC-адресов.

Может быть и у FreeBSD есть подобный режим?

комментарий 4:

From: Sergey Matveev
Date: 2022-09-07 13:29:36Z


>Может быть и у FreeBSD есть подобный режим?

Быстрый grep вроде бы говорит что это Linux-specific штука. Но iftop
поверх gif-туннелей работает: IPv4 трафик показывает, сообщает о нулевом
MAC-адресе. А вот IPv6 игнорирует.

Сегодня я на самом деле уже увидел что с патчем из
https://lists.beasts.org/pipermail/iftop-users/2021-February/000503.html
всё работает, на первый взгляд, как надо -- как минимум, IPv6 появился в
выводе.

Сгенерирован: SGBlog 0.34.0