На мысль сделать карманный инструмент для анализа WiFi сетей меня подтолкнула эта статья.
Спасибо им за идею. Мне как раз было нечем заняться.
На данный момент весь задуманный функционал работает. Все исходники, полностью готовые для сборки, выложены здесь. Там же инструкция по сборке и пр. В данной заметке я не буду дублировать информацию, выложенную на github. Расскажу только то, что считаю нужным описать отдельно.
Мое мнение по поводу «универсального инструмента» и причина выбора ESP32
Я не претендую на истину. Она у каждого своя. Постараюсь обосновать свой выбор «железа».
Предложенный в статье вариант использования сочетание Linux (изначально Raspberry Pi) + «периферии» в виде контроллер (STM32) + CC1110 (ядро 8051) и план впихнуть туда все что только можно (125kHz, NFC, 433mHz, USB, iButton, bluetooth, ?) показался не подходящим для меня. Впрочем, этот проект похоже так останется частным и закрытым (flipper-zero github «This organization has no public repositories.») и пошел в сторону не слишком распространенного железа.
Возможно я не прав, и в дальнейшем авторы выложат исходники ПО в открытый доступ. Но если нет, то я бы такую железку без исходников не купил бы.
Мои требования к «инструменту»
Коробочка должна быть маленькая (чем меньше, тем лучше).
Поэтому:
- Встроенный аккумулятор не нужен. При токе > 100 mA при работе с Wifi, встроенный аккумулятор либо будет большой, либо его хватает не на долго. Поэтому пусть «коробочка» питается от стандартного power bank. Все равно power bank в кармане/машине валяется у меня всегда.
- Держать внутри «коробочки» Linux с инструментами, написанными за много лет на всех языках при наличии мелкого экрана и скудного набора управляющих кнопок смысла нет. Результаты можно смотреть/обрабатывать и на нормальном ноутбуке с полноценной клавиатурой и экраном.
- Компоненты должны быть легкодоступными и широко известными (доступный SDK, много примеров и документации).
В результате, для меня, выбор был очевиден — ESP32.
Под все задачи, заявленные в статье, которая подтолкнула меня к действиям, возможностей ESP32 вполне хватает. Хотя максимум что я хочу еще сделать это:
- Поиграться с Bluetooth.
- Поиграться с 433mHz диапазоном с простейшим hardware (только амплитудная модуляция, чего достаточно для практически надобностей).
Ложка дегтя в ESP32
- SDK (IDF) ESP32 несколько коряв.
- Часть функционала (стек WiFi, например) идет без исходников в виде собранных статических библиотек.
- Не поддерживается диапазон 5gHz и есть некоторые ограничения и корявости по работе с WiFi.
Но цена/размеры вполне компенсируют эти недостатки.
Основной функционал ПО
Коротко опишу функционал и своем мнение о…
Управление настройками и выгрузка файлов с SD
Все внешнее управление сделано через простейшую Web страницу, запускаемую в отдельном пункте меню. ESP32 запускается в режиме WiFi AP и выдает страницу по фиксированному IP адресу.
Режим работы с Beacon пакетами
Режим сканирования списков AP. Собственно, это умеет делать любой смартфон. Ну и в этом режиме сохранятся список AP.Beacon spammer. ESP32 стартует как AP со скрытым SSID и случайным MAC и начинает слать [beacon frame] по заранее созданному списку SSID (созданному вручную или полученному ранее при сканировании списка AP)
Режим sniffing пакeтов WiFi
Разработчики Espressif добавили возможность прикладному ПО получать через callback функцию все WiFi пакеты «пролетающие в воздухе». На самом деле не все, поскольку можно установить режим только для одного фиксированного канала.
На обработку вызова callback функции накладываются очень жесткие временные ограничения. Если для режима простого сбора статистики это проблем не вызывает, то для режима записи PCAP файла на SD карту пришлось повозится, организуя запись через очередь в памяти и семафоры. С учетом особенности, что процесс, вызывающий callback крутится на одном ядре, а процесс, выполняющий запись на SD в другом.
При «зашумленном эфире» некоторые пакеты теряются (в очереди нет места и они отбрасываются), но при типичном «эфире» квартиры вечером (5..7 AP в пределах видимости) запись в PCAP успевает выполнятся без потерь пакетов.
Дополнительно, для мониторинга и записи PCAP есть режим фильтрации по списку MAC в заголовках пакетов.
Например, можно отследить появление человека в клубе/кафешке, до того, как он вообще вошел или появился в поле зрения. Мало кто отключает WiFi и автоматические соединение с известными AP. (Я теперь отключаю..)
Просматривать записанный трафик в Wireshark познавательно и интересно для понимания карт это все работает.
Режим работы с deauth пакетами
По умолчанию, посылка этих пакетов запрещена в библиотеке libnet80211.a, которая идет без исходников. Но это несложно купировать, подправив пару байтиков. Вначале я сомневался, а стоит ли выкладывать patch. Но походив по разным местам с включенным режимом сканирования источников посылки [deauthentication frame], подумал: «какого черта». Тем более, что в esp8266 посылка этих пакетов не закрыта и сборки на github под esp8266 есть.
В очень многих местах (не буду говорить где) используется подавление нежелательных AP через этот метод. И это не «хулиганы»…
А я еще удивлялся, что это у меня раздача интернета с телефона местами не работает…
Режим отслеживание количества и RSSI таких пакетов очень полезен что бы понять «где не любят левые AP».
Режим router
Эта функция, наверное, самая интересная из всех для исследования.
ESP32 поддерживает одновременную работу в режиме STA + SoftAP. Поэтому на нем можно реализовать классический NAT router.
Для поддержки сетевого стека Espressif использует fork (практически без изменений) библиотеки lwip.
Hо, по умолчанию, в стандартной сборке, в библиотеке esp-lwip между netif интерфейсами ‘ap’(SoftAP) и ‘st’ (STA) не предусмотрен проброс.
Можно конечно сделать и без NAT, но возникает проблема с одновременным подключение двух и более STA к интерфейсу ‘ap’ и синхронизации IP адресов от сетевого интерфейса ‘st’ к ‘ap’. Так что сложности не стоят того и проще через NAT.
Тем более, что существует fork esp-lwip от martin-ger в котором добавленa простая реализация NAT для IP4.
Хотя у меня руки чесались ее переделать чисто косметически (по моему, проще было без fork проекта, а через LWIPHOOK функции, определяемых при сборке), но лень победила и вариант от martin-ger используется как есть.
В режиме router просматривается входящий и исходящий IP4 трафик.
В частности, из него извлекается для показа на экранчике и сбора статистики в файл:
- Имя устройства, которое подключилось к SoftAP ESP32 (DHCP пакеты)
- URL из DNS запросов (UDP port 53) от подключенного к SoftAP ESP32 устройства.
Дополнительно можно включить запись трафика в PCAP файл.
Данный режим весьма полезен, например, для того что бы понять, например, что ваш телефон шлет в сеть и куда при этом ходит.
Можно придумать и другие способы использования этого режима с учетом возможности полностью управлять программно входящим и исходящим трафиком SoftAP ESP32 на уровне сетевого интерфейса: Ehernet заголовок (destMAC[6]+srcMAC[6]+type[2]) + payload (IP4, IP6, DCHP, и прочее type).
В принципе, ESP32 вполне нормально справляется с функцией WiFi->WiFi роутера, пропуская через себя без особых задержек обычный трафик. Субъективно, задержки в телефоне, подключенном через router на ESP32 не заметны.
К сожалению, в API Espressif нет возможности установить фильтр по MAC подключаемым к SoftAP EPS32. В место этого предлагается говорить «до свидание» (esp_wifi_deauth_sta) уже подключенным STA, которые «не желательны».
Фильтрация по MAC для подключаемых STA пришлось сделать чрез вызов esp_wifi_deauth_sta()
В заключение
Хотя ничего нового в рамках работы с ESP32 я не придумал, но возможно кому то результат (исходники) будет интересен.
Хотел бы отметить, что код писал исключительно в познавательных целях. Для «взлома» и пр. он специально делался не очень удобным.
Печатную плату не делал, поскольку на то, что бы спаять проводом готовые платки ушло часа 1.5-2.
Да и если делать, то нужно не из готовых плат собирать, а из отдельных компонент. Тогда габариты будут еще меньше.
Главная›Программирование ESP8266›ESP8266 Урок 14. Wi-Fi. Режим STA (Станция)
 
 
 
Ну вот, наконец-то, дошли мы до той темы, к которой стремились и ради чего начинался цикл уроков по контроллерам ESP8266 – это приём и передача данных при помощи возможностей ESP8266 по беспроводной сети Wi-Fi.
Я думаю, что все знают, что это за тип сети и для чего она применяется.
Напомню лишь, что Wi-Fi – это протокол передачи данных, осуществляемой без применения проводов, физического уровня.
Как именно передаются данные по сети и как они подготавливаются, как заворачиваются в протоколы различного уровня, мы также очень хорошо знаем. Кто не помнит, напомню – смотрите уроки 40, 41, 44, 45, 46, 47, 48, 49, 50, 51, 52 по программированию контроллеров AVR, а также аналогичные уроки по контроллерам STM32. В данных уроках мы очень подробно рассмотрели многие протоколы всех уровней модели OSI. Те же самые протоколы будут использоваться и здесь, причём нам особо не придётся их программировать вручную, но знать, как они устроены, для чего нужны, мы обязаны, чтобы избежать ошибок при передаче данных, а также, если они и возникнут, то оперативно их устранить. И рассмотренных нами протоколов нам не потребуется протокол физического уровня Ethernet, его заменит протокол Wi-Fi.
Мы пока подробно не будем изучать протокол Wi-Fi, так как с ним работает наш контроллер аппаратно, но режимы работы мы должны знать. И знакомится с их разновидностями мы будем постепенно.
А пока мы должны знать, что наш контроллер ESP8266 поддерживает три основных режима работы – станция (Station mode или кратко STA), программная точка доступа (SoftAP), а также смешанный – Station + SoftAP.
Самым простым из этих режимов является первый – режим станции.
Режим станции (STA) – это такой режим, в котором контроллер не создает собственную сеть, а подключается к любой существующей сети Wi-Fi, например, к существующей локальной сети или к другому устройству, работающему в режиме точки доступа (AP).
На данном уроке мы настроим режим станции и попробуем подключиться к существующей точке доступа, например к роутеру, который раздаёт Wi-Fi по дому. Роутер от просто точки доступа отличается тем, что трафик, идущий от станций, подключенных к нему, он транслирует во внешнюю сеть и наоборот.
Пока воспользуемся возможностями SDK, то есть не будем лезть глубоко в дебри аппаратной части. Всему своё время.
Схема у нас будет простейшая – отладочная плата, подключенная к USB компьютера
Весь процесс соединения с точкой доступа и вхождение в различные стадии соединения мы будем отслеживать с помощью терминальной программы с помощью UART.
Проект наш выполнен из проекта прошлого урока с именем OS_TIMER и назван WIFI_STA.
Откроем наш проект в Eclipse и в файле main.c подключим библиотеку для работы с UART
В функции user_init сконфигурируем UART
После небольшой задержки переведём строку в терминальной программе, чтобы отделить вывод следующих сообщений
Вызовем функцию SDK, с помощью которой установим режим работы устройства в качестве станции
Добавим функцию пока с пустым телом, которая будет вызываться через определённые промежутки времени по программному таймеру
А подобную функцию для обработки событий от программного таймера с именем timer_func_user удалим вместе с телом.
В функции user_init() в функции инициализации программного таймера, соответственно, изменим имя функции в параметре
os_timer_setfn(&os_timer01, (os_timer_func_t *)wifi_check_ip, NULL);
Также изменим третий параметр в вызове функции старта таймера. Теперь здесь будет ноль, так как запускать таймер мы будем однократно. Также увеличим период срабатывания
os_timer_arm(&os_timer01, 1000, 0);
Добавим локальную переменную структуры для настроек Wi-Fi соединения
Забьём нулями всю память, зарезервированную под переменную структуры
В файле user_config.h добавим логин и пароль для соединения с точкой доступа
У вас, соответственно, данные будут свои, я также ввожу временные данные, затем я их из соображений безопасности опять изменю.
В функции user_init() файла main.c занесём наши настройки в поля структуры
Применим данные настройки с помощью функции SDK
Мы должны помнить, что данные настройки применятся только на время действия нашей программы, в память FLASH они не пропишутся, для этого есть уже другая функция.
После запуска таймера вызовем функцию соединения с точкой доступа
Объявим и проинициализируем две глобальные переменные – одну для хранения состояния соединения с точкой доступа, а другую – пользовательскую
В функции wifi_check_ip добавим переменную структуры соединения сетевого уровня
Произведём деинициализацию таймера
Узнаем состояние соединения с точкой доступа
Если состояние будет указывать на то, что IP-адрес получен, а также сетевой адрес ненулевой, то проинициализируем и запустим таймер, только с интервалом в 2 секунды и вывеем соответствующее сообщение в терминальную программу. Также у наше условие будет иметь и противный случай
Начнём обрабатывать противный случай. В нем будет несколько условных конструкций.
Если пароль не совпал, то выведем соответствующее сообщение в терминальную программу и попытаемся соединиться повторно
Подобным образом поступим, если не будет найдена точка доступа
То же самое проделаем при неудачном соединении
В другом случае, не относящемся к вышеперечисленным установим переменной величину, соответствующую состоянию покоя
Не выходя из тела противного состояния верхнего уровня, проинициализируем наш таймер и запустим его, установив период в полсекунды
Соберём код, прошьём контроллер и через некоторое время в терминальной программе, если всё правильно, мы получим соответствующее сообщение об удачном соединении с точкой доступа
Теперь мы можем спокойно передавать и принимать данные, с точкой доступа мы соединены, и сетевой адрес получен, также давайте для того, чтобы каждые 2 секунды не было сообщения об удачном сетевом соединении, а было только однажды, немного переработаем ветку условия, где мы это выводим.
Если наша пользовательская переменная в нуле, то мы только тогда выводим сообщение, поэтому перенесём его вывод в данное условие, а также в этом же теле выставим нашу переменную в единицу
А в противном случае мы изменим состояние ножки, к которой подключен светодиод
Также в противном случае верхнего уровня мы обнулим пользовательский статус
Вот теперь, скорей всего, у нас вывод сообщения об удачном соединении будет только однажды, а именно в момент нашего соединения, а вернее не позже чем через 2 секунды после его установления.
Проверим это
Так и есть – сообщение теперь выводится только один раз, также, думаю, если произойдут какие-то проблемы с соединением, то потом после удачного соединения, у нас также сообщение выведется только один раз. А после вывода сообщения у нас только медленно мигает светодиод, что будет свидетельствовать о наличии соединения в данный момент нашей станции с точкой доступа.
Давайте проверим соединение с помощью пинга
Как видим, всё пингуется и пакеты проходят отлично. Только вот период великоват. Это всё потому, что наш контроллер находится в одном из режимов пониженного энергопотребления.
Давайте исправим данную ситуацию. Для этого в функции user_init() включим режим полноправной работы модуля
Теперь мы видим, что отклик происходит гораздо быстрее
Итак, на данном уроке мы научились конфигурировать беспроводное соединение в режиме станции, что позволило нам организовать стабильное соединение с точкой доступа, получив при этом сетевой адрес, что, как я думаю, уже немало.
Всем спасибо за внимание!
Исходный код
Модуль ESP NodeMCU можно купить здесь: Модуль ESP NodeMCU
Различные модули ЕSP8266 можно приобрести здесь Модули ЕSP8266
Переходник USB to TTL можно приобрести здесь ftdi ft232rl
Многофункциональный переходник CJMCU FT232H USB к JTAG UART FIFO SPI I2C можно приобрести здесь ftdi ft232rl
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК (нажмите на картинку)
Используемые источники:
- https://habr.com/post/493412/
- http://narodstream.ru/esp8266-urok-14-wi-fi-rezhim-sta-stanciya/