[О блоге] [наверх] [пред] [2022-09-06 22:11:45+03:00] [9fe4474ce530fe5e8793160fb9218b36f68bd491]
Темы: [bsd][ipv6]

Написал утилиту для мониторинга 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
    
    *** kmeaw [2022-09-07 01:16]:
    >Всегда использовал 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
    
    *** kmeaw [2022-09-07 01:16]:
    >Всегда использовал 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
    
    *** kmeaw [2022-09-07 16:09]:
    >Может быть и у FreeBSD есть подобный режим?
    
    Быстрый grep вроде бы говорит что это Linux-specific штука. Но iftop
    поверх gif-туннелей работает: IPv4 трафик показывает, сообщает о нулевом
    MAC-адресе. А вот IPv6 игнорирует.
    
    Сегодня я на самом деле уже увидел что с патчем из
    https://lists.beasts.org/pipermail/iftop-users/2021-February/000503.html
    всё работает, на первый взгляд, как надо -- как минимум, IPv6 появился в
    выводе.