- PVSM.RU - https://www.pvsm.ru -

TcpDumper: DIY устройство для исследования сети Ethernet

TcpDumper: DIY устройство для исследования сети Ethernet - 1

Привет! Решил представить тут небольшое и дешёвое устройство, которое на данный момент умеет:
1. Пинговать заданный IP
2. Смотреть пакеты с помощью tcpdump
3. Сканировать сеть через ARP

А главное, всё это работает полностью автономно на Raspberry PI 2 без GUI и потребляет всего 50 Мб ОЗУ!
В статье будет: описание самого устройства и идеи; описание различных приколов и багов в процессе разработки; инструкция как сделать такое самому; и вопрос знатокам, нужно ли это вообще кому-нибудь :)

Как я к этому пришел

В процессе разработки коммутатора на работе я столкнулся с тем, что было бы прикольно иметь небольшое настольное устройство для, например, генерации пакетов с заданными QoS метками; пакетов с таким-то VLAN'ом, или просто для просмотра "идут пакеты или нет".

Постепенно в голове начали формироваться следующие требования к устройству:
1. Дешевизна (забегая вперед, это устройство получилось в районе 20$)
2. Наличие собственного экрана (3.5 дюйма SPI экран с резистивным тач-скрином)
3. Наличие линукса на борту
4. И один или несколько портов Ethernet.

Я долго искал одноплатники с двумя портами Ethernet, но находил только дорогие, заточенные под создание собственного маршрутизатора. В итоге остановился на Raspberry pi 2B, потому что во-первых, она была в наличии, а во-вторых, не возникнет проблем с подключением экрана (думал он). Плюс, при желании добавить один порт можно просто купить дешевый переходник USB - Ethernet, открывая кучу возможностей.

Описание возможностей

Итак, что имеем сейчас в получившемся устройстве (подчеркиваю, это только proof-of-concept):

  • Можно пингануть другое устройство в сети.

  • Можно посмотреть пакеты, приходящие на интерфейс.

  • Можно узнать какие девайсы есть в сети. При этом устройство посылает arp-запросы на маску /24 (да, она захардкожена. PoC же), и слушает ответы, генерируя список соответствия IP-адреса MAC-адресу.

  • И можно посмотреть информацию о своём интерфейсе (на данный момент это просто вывод "ip address show dev eth0".

Гифки (~10 мб)
TcpDumper: DIY устройство для исследования сети Ethernet - 2
TcpDumper: DIY устройство для исследования сети Ethernet - 3
TcpDumper: DIY устройство для исследования сети Ethernet - 4
TcpDumper: DIY устройство для исследования сети Ethernet - 5

Как это было сделано

А теперь, к вопросу как это все сделать без GUI.

Компоненты

Их всего два. Raspberry pi 2b можно взять на авито примерно за 10 долларов; экранчик брал как в спойлере, с учетом доставки и прочего получаются те же 10$.

Фото
Экран

Экран
Малинка

Малинка

Образ ОС

В качестве ОС я выбрал Raspbian lite (32х битную), без десктопного окружения, потому что зачем, когда у нас есть терминал :) Да и вторая малинка с трудом тянет полноценную графическую систему.

Подключение экрана

Итак, экран начал подключать по инструкции здесь [1]. Там всё просто, клонируем репу, запускаем ./LCD35-show, наслаждаемся. Но не тут-то было, т.к. далее стоял вопрос как откалибровать его. Не помню как именно, но тернистыми путями вышел на библиотеку [2], в которой было всё что нужно для калибровки.

Написание собственно программы

Существует шикарная библиотека для быстрого написания интерфейсов на плюсах Dear ImGui. Однако существует менее известная библиотека ImTui [3], которая позволяет использовать ImGui для написания приложений в терминале с использованием ncurses.

Про автора:

Автор ImTui -- ggerganov -- какой-то монстр: он сделал мегапопулярную библиотеку для LLM llama.cpp [4], порт Whisper [5] на С++, ImTui... А о его активности можно слагать легенды:

TcpDumper: DIY устройство для исследования сети Ethernet - 8

Склонировав репу ImTui и попробовав запустить, я столкнулся со следующим: не регистрирует нажатия. Потыкавшись с линуксовыми инпутами, я решил проблему просто: линкуем себе в приложение libts, лезем в исходник imtui и добавляем обработку:

// imtui-impl-ncurses.cpp
#include "tslib.h"
...
static struct tsdev* ts;
...
ImTui::TScreen * ImTui_ImplNcurses_Init() {
    ...
    ts = ts_setup(nullptr, 1);
}

bool ImTui_ImplNcurses_NewFrame() {
    struct ts_sample samp;
    int ret = ts_read(ts, &samp, 1);
    if (samp.pressure > 0) { // Если давление на экран больше ноля
        // и если данные от экрана "более-менее" норм
        if (samp.x > 0 && samp.x < 1000 && samp.y > 0 && samp.y < 1000) {
            // масштабируем и выдаем координаты нажатия
            mx = (double)samp.x * 30 / 240;
            my = (double)samp.y * 20 / 160;
            lbut = 1;
            hasInput = true;
        } else {
            lbut = 0;
        }
    } else {
        lbut = 0;
    }
    ...
}

Весь код лежит на гитхабе [6].
Был также момент с масштабированием. По умолчанию текст получался очень мелкий, было сложно что-то разглядеть. Однако драйвер к экрану не поддерживает масштабирование. Поэтому я просто задал разрешение экрана в 1.5 раза меньше, и текст увеличился. Это неидеальное решение, он получился немного размытым, надо бы больше поковырять этот момент.

Приколы в коде и баги

Для пинга и просмотра пакетов используются команды ping и tcpdump, вывод которых перенаправляется в pipe и отображается. При этом у tcpdump есть флаг -U, который, согласно ману, означает "вывод будет записан в stdout когда закончится очередной пакет". Но это не работало! Пакеты выводились пачкой раз в секунд 10. Зато опция -l "вывод записывается в stdout по окончанию очередной строки" работала! Хотя даже в man tcpdump говорится что опции идентичны.

Залез в исходники [7]. Флаг -l вызывает setvbuf(stdout, NULL, _IOLBF, 0) где _IOLBF и означает строковую буферизацию. Флаг -U вызывает в конце каждого пакета функцию pcap_dump_flush, которая является частью API libpcap. Лезем в код libpcap [8]. Находим:

int
pcap_dump_flush(pcap_dumper_t *p)
{
	if (fflush((FILE *)p) == EOF)
		return (-1);
	else
		return (0);
}

Fflush чистит все user-space буферы, но не чистит kernel-space. При этом размер pipe обычно 4 кибибайта, а средний пакет в выводе tcpdump ~ 100 байт. Вот и получалось что он печатал пачками по ~40 пакетов. Причина найдена, поэтому идем дальше.

Был прикол с тем, что если в .bashrc прописать что-то типа

if [[ $(tty) == /dev/tty1 ]]; then
    /root/TcpDumper/build/bin/TcpDumper
fi

То при открытии приложения будет чёрный экран. Я не знаю сколько бы я с этим бодался, но подсказала ChatGPT: для ncurses приложения необходима переменная среды TERM! Добавив в код выше export TERM=xterm-256color, все заработало.

С файлом .profile был ещё один мем. Когда я первый раз добавил запуск приложения сразу после запуска ОС, я по-глупости написал это вот так:

# файл /root/.profile
...
exec /root/TcpDumper/build/bin/TcpDumper

И сохранил. Решил проверить. Перезахожу по ssh. Меня встречает приложение, работает, всё хорошо. Жму Ctrl+C чтобы его закрыть и... сессия ssh закрывается. О нет. Ведь exec замещает процесс баша приложением в его аргументе, и назад в баш вернуться не было возможности. От пользователя pi пароль я забыл, команда вида ssh root@192.168.0.114 'echo privet > /root/.profile' завершается ошибкой...

Начал думать что делать. Точно, нужно просто достать sd-карточку и поменять на ней этот файл! Но есть проблема. Файловая система у малинок отформатирована в ext4, а винда такой формат не поддерживает. Другого устройства на линуксе дома нет.
Нашел под винду программу просмотра файлов с карточек ext2fsd, но она умеет их только читать, а не писать. Но у меня же есть WSL, подумал я, нашёл программу для проброса usb флешек в WSL -- usb-ipd [9]. Но она тоже отказалась монтировать флешку. Погуглив, нашел информацию [10]что нужно пересобрать ядро WSL с поддержкой нужных дров, но решил остановиться и... поспать. На завтра занёс её на работу, где проблема решилась за 10 секунд :) Можно ещё было залить на флешку образ линукса и загрузиться в live cd на ноуте, но тогда я почему-то отверг этот вариант (может просто флешки не было еще одной).

Ещё был баг, если зайти на малинку через ssh, и открыть сразу две копии приложения через openvt, то все начинает глючить. Не знаю зачем вам эта информация :)

Инструкция по программированию

Если вы не собираетесь повторять девайс, этот раздел можно пропустить, тут не будет ничего интересного.

Установка ОС

  1. Перейдите на https://www.raspberrypi.com/software [11], скачайте raspberry pi imager под вашу ОС

  2. В Imager: выберите вашу модель Raspberry, ОС - Raspberry pi OS lite, в настройках включите удаленный доступ (ssh).

  3. Установите выбранную ОС на sd-карточку.

Установка драйверов для дисплея и калибровка

  1. Установите необходимые пакеты: apt install libts-dev cmake

  2. Склонируйте репозиторий с драйвером дисплея: git clone https://github.com/goodtft/LCD-show.git

  3. cd LCD-show; ./LCD35-show

  4. Поменяйте (уменьшите) разрешение дисплея. Для этого в файле /boot/config.txt добавьте (если их нет) в конец следующие строки:
    framebuffer_width=240
    framebuffer_height=160

  5. reboot

  6. Далее, необходимо выставить следующие переменные среды для работы libts: export TSLIB_FBDEVICE=/dev/fb0;
    export TSLIB_TSDEVICE=/dev/input/event0

  7. Откалибруйте дисплей: ts_calibrate

Сборка программы

  1. Склонируйте репозиторий:
    cd ~;
    git clone https://github.com/Dima-Makarov/TcpDumper.git --recurse-submodules

  2. Можно собирать и запускать:
    cd TcpDumper;
    mkdir build;
    cmake -S . -B build;
    cmake --build build;
    build/bin/TcpDumper

  3. Для того, чтобы оно автоматически запускалось при старте малинки, добавьте следующие строки в ~/.profile:
    export TSLIB_FBDEVICE=/dev/fb0
    export TSLIB_TSDEVICE=/dev/input/event0
    if [[ $(tty) == /dev/tty1 ]]; then
    export TERM=xterm-256color
    openvt -f -c 1 /root/TcpDumper/build/bin/TcpDumper
    fi

  4. Также нужно сделать так, чтобы экран запускался с пользователем root. Для этого:
    nano /etc/systemd/system/getty@tty1.service.d/autologin.conf
    В строке после слова autologin измените слово pi на root
    Выйдите из редактора:
    reboot

  5. Готово!

Если появятся какие-то проблемы - смело пишите в лс, обещаю оперативно помочь.

Инструкция по сборке

Простите
Соедините детали как показано на видео

Соедините детали как показано на видео

Описание улучшений которые можно было бы реализовать

  1. Не зря я упомянул про адаптер USB-Ethernet в начале, ведь с ним можно сделать следующее: втыкаем его в usb, соединяем два сетевых интерфейса в bridge, и вуаля, получаем сниффер, который можем включить в разрыв между двумя устройствами и смотреть через tcpdump что они там шлют друг другу.

  2. На поздних "малинках" есть wi-fi, и с ним можно сделать много чего интересного, и всё из того же TUI интерфейса. Как минимум - переходник "медь-воздух", wi-fi сканер, you name it.

  3. Можно реализовать сценарии разных атак на сеть - arp spoof, mac spoof, проверить включен ли port-security на коммутаторе, попытавшись загадить ему mac-таблицу :), и прочее и прочее.

  4. Также, через wi-fi можно реализовать управление этим устройством со смартфона, и там уже воротить все что вздумается.

Вопросы знатокам

Мои вопросы: заинтересован ли кто-нибудь в подобном устройстве? Какие бы фичи вам были бы полезны? Удобный ли форм-фактор, на ваш взгляд? Добро пожаловать в комменты!

Скрытый текст

Стоп он реально не оставил ссылки на свой тг канал???

Автор: Duke_nukeum

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/raspberry-pi/410209

Ссылки в тексте:

[1] здесь: https://github.com/goodtft/LCD-show

[2] библиотеку: https://github.com/libts/tslib

[3] ImTui: https://github.com/ggerganov/imtui

[4] llama.cpp: https://github.com/ggerganov/llama.cpp

[5] Whisper: https://github.com/ggerganov/whisper.cpp

[6] гитхабе: https://github.com/Dima-Makarov/TcpDumper

[7] исходники: https://github.com/the-tcpdump-group/tcpdump

[8] код libpcap: https://github.com/the-tcpdump-group/libpcap

[9] usb-ipd: https://github.com/dorssel/usbipd-win

[10] информацию : https://github.com/dorssel/usbipd-win/wiki/WSL-support#building-your-own-usbip-enabled-wsl-2-kernel

[11] https://www.raspberrypi.com/software: https://www.raspberrypi.com/software/

[12] Источник: https://habr.com/ru/articles/879182/?utm_campaign=879182&utm_source=habrahabr&utm_medium=rss