Перейти до вмісту

Бездротові мережі та IoT

Ноутбук показує повну шкалу Wi-Fi, а сторінка вантажиться хвилину. У сусідній кімнаті той самий роутер роздає втричі менше, хоча відстань збільшилася на два метри. Датчик температури в теплиці, що має пропрацювати п’ять років від двох батарейок, не може тримати TCP-з’єднання, бо на нього піде уся енергія. Кабельна Ethernet-мережа з модуля 4 такої поведінки не має, і пояснити її можна лише знаючи, чим радіо принципово інше.

Для Інтернету речей це не окрема тема. Майже всі його рішення, від вибору радіотехнології до формату повідомлення в два байти, виростають з того, що енергії й пам’яті мало, а радіо ненадійне. Коли це тримаєш у голові, протоколи цього модуля перестають виглядати набором абревіатур.

Передумови. Ethernet і CSMA/CD (модуль 4), IPv4 і фрагментація (модуль 6), IPv6 (модуль 10), UDP і TCP (модуль 11). Для розділу про безпеку корисний модуль 15.

У кабелі між двома пристроями є провід, і сигнал іде лише ним. У радіо середовище спільне: усі, хто налаштований на ту саму частоту поруч, користуються тим самим «проводом» одночасно, і це тягне за собою наслідки, яких Ethernet не знає.

Півдуплекс і спільний ефір. Радіомодуль, як правило, не може одночасно передавати й слухати на тій самій частоті: власний передавач заглушає все, що надходить. Тому виявити колізію під час передачі, як робив класичний Ethernet (CSMA/CD), неможливо. Колізія стає відома лише тоді, коли у відповідь не прийшло підтвердження.

Загасання. Потужність сигналу спадає з відстанню: у вільному просторі у квадраті, а в приміщенні швидше. Вимірюють її в децибелах (dB): кожні 3 dB означають приблизно дворазову зміну потужності, а кожні 10 dB — десятикратну. Потужність сигналу на приймачі пишуть у dBm, і це від’ємні числа: ближче до нуля означає сильніше. Приблизно −50 dBm — сильний сигнал, близько −70 dBm — на межі пристойної роботи, нижче −80 dBm — зв’язок нестабільний.

Чому стіна гірша за відстань. Подвоєння відстані у вільному просторі коштує близько 6 dB. Одна цегляна чи бетонна стіна з арматурою легко забирає ще кілька або й десять-двадцять dB, залежно від матеріалу. Вища частота крізь перешкоди проходить гірше: 5 GHz слабший за 2,4 GHz після тієї самої стіни, хоча дає більше каналів і швидкості. «Через дві стіни» легко виходить слабше, ніж «через двадцять метрів коридору».

Перешкоди. Діапазон 2,4 GHz вільний від ліцензій, тож у ньому, крім Wi-Fi, працюють Bluetooth, Zigbee, бездротові миші й мікрохвильові печі. Чужий сигнал на тій самій частоті перетворюється на шум, і приймач не відрізняє його від власної колізії.

Швидкість підлаштовується. Чим гірший сигнал, тим простішу модуляцію обирають передавач і приймач, щоб кадр ще можна було розібрати. Ефект тут неочевидний: повільний клієнт займає ефір довше за швидкого. Щоб передати ті самі дані, йому потрібно більше часу, і весь цей час ефір недоступний для інших. Один далекий телефон здатен помітно сповільнити решту клієнтів тієї самої точки доступу.

Wi-Fi, за стандартом IEEE 802.11, розв’язує проблему колізій способом CSMA/CA (Carrier Sense Multiple Access with Collision Avoidance).

  1. Станція слухає ефір. Якщо він вільний певний короткий інтервал, вона може передавати.

  2. Якщо ефір зайнятий, станція чекає його звільнення, а потім ще випадковий час (backoff). Випадковість потрібна, щоб дві станції, які чекали одну й ту саму передачу, не кинулися в ефір в один момент.

  3. Отримувач підтверджує кожен кадр короткою відповіддю ACK. Якщо ACK не прийшов, відправник вважає кадр втраченим, збільшує вікно випадкового очікування й повторює.

Підтвердження на канальному рівні, незвичне для Ethernet, пояснюється ненадійністю радіо: кадри тут губляться постійно, і краще повторити кадр за мілісекунди на місці, ніж чекати таймера TCP.

Слухати ефір перед передачею корисно лише тоді, коли відправник чує тих, хто може зіпсувати його передачу. У радіо це не гарантовано.

Прихований вузол: станції A і B в зоні дії точки доступу, але поза зоною дії одна одної, тому їхні кадри накладаються на точці доступузона дії Aзона дії Bколізія тутABAPточка доступуне чують одна однуRTS/CTS: CTS від точки доступу чують обидві
A і B обидві бачать точку доступу, але одна одну не чують. Кожна вважає ефір вільним, передає, і на точці доступу кадри накладаються.

Станції A і B стоять по різні боки від точки доступу. Обидві досягають її, але між собою занадто далеко. A не чує B, тож бачить вільний ефір і передає; B робить те саме. Точка доступу отримує обидва кадри одночасно й не розбирає жодного. Для відправників це виглядає як відсутність ACK.

Проти цього існує необов’язковий обмін RTS/CTS: станція спершу надсилає короткий запит на передачу (Request To Send), точка доступу відповідає дозволом (Clear To Send), а цей дозвіл чують усі станції в її зоні, навіть ті, що не чують відправника, і мовчать на вказаний час. Обмін коштує ефірного часу, тож зазвичай його вмикають лише для великих кадрів або для мереж, де прихованих вузлів багато.

Wi-Fi працює в кількох діапазонах: 2,4 GHz, 5 GHz і, у Wi-Fi 6E та новіших, 6 GHz. Кожен поділений на канали, зазвичай шириною 20 MHz, які можна об’єднувати для швидкості.

У діапазоні 2,4 GHz смуга вузька, тому канали частково перекриваються, і три неперекривні канали (1, 6 і 11) є усталеним вибором. Якщо в під’їзді п’ять мереж сидять на каналах 1, 2, 4, 7 і 9, вони заважають одна одній сильніше, ніж коли б усі п’ять стояли на одному каналі: на одному вони хоча б чують одна одну й ділять ефір за CSMA/CA, а на сусідніх сприймають чужі передачі як шум.

У 5 GHz каналів значно більше, а дальність через перешкоди менша. Компроміс звичний: 2,4 GHz дістає далі й крізь стіни, 5 GHz швидший поруч із точкою доступу.

Як клієнт приєднується

Section titled “Як клієнт приєднується”
  1. Точка доступу періодично розсилає маячки (beacon) з назвою мережі (SSID) і підтримуваними можливостями. Клієнт може й сам запитати (probe request).
  2. Клієнт проходить автентифікацію й асоціацію: «я хочу в цю мережу».
  3. Якщо мережа захищена, виконується чотирикроковий обмін (4-way handshake), у якому з пароля (або індивідуальних облікових даних) і випадкових чисел обох сторін виводяться ключі шифрування сеансу.
  4. Далі клієнт отримує IP-адресу через DHCP (модуль 9), і з цього місця все працює як у звичайній мережі.

SSID не ідентифікує точку доступу: багато точок із тим самим SSID утворюють одну мережу, і клієнт переходить між ними (роумінг) за власними правилами.

Найчастіше заважає зайнятість каналу: у багатоквартирному будинку десятки точок доступу ділять кілька каналів, і кожна з них спершу слухає ефір, а вже потім передає. Ефірний час забирають і повільні клієнти, про яких ішлося вище. Буває й асиметрія потужності. Зв’язок двосторонній, а передавач телефона набагато слабший за передавач точки доступу, тож телефон може бачити мережу на повну шкалу, а точка доступу його ледве чує. Окрема історія з роумінгом: клієнт тримається за далеку точку доступу, аж поки сигнал зовсім не зникне, бо рішення про перехід приймає він сам. Тому в мережах із кількома точками доступу сусідам призначають різні канали й налаштовують зони дії так, щоб вони перекривалися лише частково.

Без шифрування будь-хто в зоні дії може читати ваші кадри, бо ефір спільний. WPA2 із паролем (WPA2-PSK) шифрує кадри за AES. Слабкість у тому, що, зафіксувавши чотирикроковий обмін, зловмисник може вгадувати пароль офлайн, скільки вистачить обчислювальної потужності. Слабкий пароль тому тримається недовго.

WPA3-Personal замінює обмін паролем на SAE (Simultaneous Authentication of Equals): кожна спроба вгадати потребує участі точки доступу, тож офлайн-підбір за перехопленим обміном не працює. WPA3 також вимагає захисту службових кадрів (PMF) і шифрує трафік у відкритих мережах (Enhanced Open). Для підприємств є режим з індивідуальними обліковими даними (802.1X): кожен користувач має власні дані, і відкликати їх можна окремо.

Стільникова мережа (4G/LTE, 5G) будується з сот: базова станція покриває ділянку, а абонент під час руху переходить від однієї станції до іншої без розриву зв’язку (handover). На відміну від Wi-Fi, користувач не ділить ефір випадково: базова станція розподіляє радіоресурс між абонентами сама, за розкладом, тож немає ні CSMA, ні прихованих вузлів. Автентифікацію виконує SIM-картка, а мережевий оператор тримає ядро мережі, яке видає IP-адреси (часто за CGNAT, модуль 9) й виходить в інтернет.

Для IoT оператори пропонують окремі профілі: LTE-M і NB-IoT. Вони жертвують швидкістю заради енергоощадності й покриття в підвалах. Власні шлюзи не потрібні, бо покриття вже є, зате кожному пристрою потрібна SIM-картка й абонентська плата.

Обмеження, з яких виростає IoT

Section titled “Обмеження, з яких виростає IoT”

Типовий мікроконтролер для датчика має лише десятки або сотні кілобайтів пам’яті. Живиться він від батарейки, яку не збираються міняти роками. Радіомодуль у режимі передачі споживає найбільше з усього, що є в пристрої; тому найважливіший прийом для довгого життя на одній батареї такий: спати майже весь час, прокидатися на мілісекунди, щось передати й знову засинати.

Майже всі відмінності IoT-протоколів від «великого» інтернету випливають із цих обмежень:

Обмеження Наслідок
Батарея пристрій майже завжди спить, тому не може бути сервером, який слухає; з’єднання з ним ініціює він сам, або воно відкрите короткими вікнами
Пам’ять малі кадри, стиснуті заголовки, прості протоколи без великих буферів і довгих станів
Радіо низька швидкість заради далекості, обмеження на частку часу в ефірі, втрати є нормою

В IoT через це трапляються речі, незвичні для Ethernet: дозволена частка часу в ефірі, кадри по кілька десятків байтів, протокол поверх UDP замість TCP, стиснення заголовків IPv6 до кількох байтів.

Бездротові технології для речей

Section titled “Бездротові технології для речей”

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

Технологія Дальність Швидкість Споживання Де живе
Wi-Fi десятки метрів висока велике побут, офіс
BLE від метрів до десятків метрів невисока мале носимі пристрої, маячки
802.15.4 (Thread, Zigbee) десятки метрів, мережа розширює 250 kbit/s мале розумний дім, mesh
LoRaWAN кілометри дуже низька дуже мале датчики на відкритій місцевості
LTE-M, NB-IoT покриття оператора низька середнє трекери, лічильники

Low-Power Wide-Area Network, мережа з малим споживанням на великі відстані, пропонує зворотний обмін: кілометри дальності коштують швидкості й частоти повідомлень. LoRa — спосіб модуляції, у якому сигнал «розмазано» за частотою (chirp spread spectrum), тому приймач витягує його з-під рівня шуму. Протокол мережі поверх цієї модуляції називається LoRaWAN.

Архітектура LoRaWAN: датчики передають радіо до кількох шлюзів, шлюзи пересилають кадри IP-мережею до мережевого сервера, той віддає дані застосункудатчикишлюзимережевий серверсервер застосункумережевий сервердедуплікація, ADR, лічильникисервер застосункурадіо LoRaзвичайний IPОдин кадр можуть почути кілька шлюзів; сервер лишає одну копію.
Кадр пристрою чують одразу кілька шлюзів. Шлюзи нічого не розшифровують, а лише пересилають кадр звичайною IP-мережею на мережевий сервер, який лишає одну копію.

Архітектура проста: пристрій → шлюз → мережевий сервер → сервер застосунку. Пристрій не приєднується до шлюзу, як клієнт Wi-Fi до точки доступу: він передає в ефір, а будь-який шлюз, що почув кадр, пересилає його мережевому серверу за IP. Шлюзи тому прості й взаємозамінні. Мережевий сервер прибирає дублікати, перевіряє лічильники кадрів, керує швидкістю пристроїв (ADR, adaptive data rate) і передає корисне навантаження застосунку. Мережевий ключ сеансу в пристрої захищає кадри між пристроєм і мережевим сервером, а окремий ключ застосунку шифрує корисні дані аж до сервера застосунку, тож оператор мережі їх не читає.

Швидкість у LoRaWAN обирають через коефіцієнт розсіювання (spreading factor, SF7–SF12). Більший SF дає більшу дальність і меншу швидкість, а кадр залишається в ефірі довше: для малого повідомлення на SF12 це порядку секунди. Тому і потрібні правила частки часу в ефірі: в Європейському діапазоні 868 MHz передавати дозволено порядку одного відсотка часу для більшості піддіапазонів. Типове повідомлення займає кілька байтів і йде раз на кілька хвилин.

Пристрої LoRaWAN класу A спершу передають, а потім коротко слухають два вікна, чи немає відповіді. Поза цими вікнами мережа пристрою нічого надіслати не може. Для датчика, який живе від батареї, це розумна ціна.

Bluetooth Low Energy працює в діапазоні 2,4 GHz і розрахований на короткі обміни з мінімальним споживанням. Пристрій оголошує про себе короткими кадрами на трьох каналах (advertising). Інший пристрій може лише слухати такі оголошення, як робить маячок, або приєднатися, і тоді обидва обмінюються даними в заздалегідь узгоджені моменти. Дані в BLE подаються як набір характеристик у профілі GATT, а не як потік байтів, тож застосунок читає й записує значення за ідентифікаторами. Зазвичай BLE з’єднує датчик із телефоном, а телефон уже виводить дані в інтернет.

IEEE 802.15.4 задає канальний і фізичний рівні для малопотужних мереж. Кадр тут має максимум 127 байтів, швидкість у 2,4 GHz — 250 kbit/s. Але IPv6 вимагає, щоб канал передавав пакети щонайменше 1280 байтів, тож 127 байтів кадру для нього замало. Цю прогалину закриває 6LoWPAN: шар адаптації, що стискає заголовки IPv6 (повна адреса перетворюється на кілька байтів, якщо вона виводиться з адреси канального рівня) і при потребі фрагментує пакет. Завдяки цьому кожен датчик отримує справжню IPv6-адресу й досяжний звичайними засобами.

Thread будує поверх 6LoWPAN сіткову мережу (mesh): пристрої пересилають пакети одне одному, а мережа сама перебудовує маршрути, коли вузол зникає. Вузли, які мають живлення від розетки, стають маршрутизаторами, а ті, що живляться від батарейки й сплять, лише під’єднуються до сусіда. З великим інтернетом мережу Thread поєднує прикордонний маршрутизатор (border router): він з’єднує її з Wi-Fi чи Ethernet і пересилає IPv6-пакети. Тому NAT для IoT-пристроїв у Thread не потрібен.

Zigbee також використовує 802.15.4, але має власний стек вище. Він не IP-сумісний, тому потребує шлюзу, що перекладає між Zigbee та IP.

Matter, стандарт застосунків розумного дому від Connectivity Standards Alliance, нової радіотехнології не вводить. Він описує, як пристрої різних виробників (лампа, замок, термостат) виявляють одне одного й спілкуються, а транспортом служать IP-мережі: Wi-Fi, Ethernet і Thread. Початкове підключення пристрою часто виконують через BLE. Мета в тому, щоб лампа від однієї компанії працювала з додатком іншої без хмарного сервера посередника.

Опитування «а що там із датчиком?» не підходить для пристроїв, які сплять. MQTT перевертає модель: пристрій сам надсилає повідомлення тоді, коли є що сказати, а хто зацікавлений, той підписується.

MQTT: датчики публікують у топіки брокера, підписники отримують повідомлення за точним топіком або за шаблономвидавціброкерпідписникидатчик кухніhome/kitchen/tempдатчик залуhome/hall/temphome/kitchen/temphome/hall/temphome/hall/humiditycmd/lampпанельhome/+/tempархівhome/#лампаcmd/lampВидавець і підписник не знають адрес одне одного й не мусять працювати одночасно.
Датчики публікують у топіки, підписники оголошують, що їм цікаво. Брокер посередині доставляє, а видавець і підписник не знають одне про одного.

У центрі системи стоїть брокер (broker). Клієнти відкривають TCP-з’єднання з брокером (порт 1883, з TLS — 8883) і виконують одну з двох дій: публікують повідомлення в топік (topic) або підписуються на топіки. Топік — рядок із рівнями через /, наприклад home/kitchen/temp. Підписуватися можна з шаблонами:

  • + заміняє рівно один рівень: home/+/temp збігається з home/kitchen/temp і home/hall/temp, але не з home/hall/humidity.
  • # заміняє будь-яку кількість рівнів і ставиться лише в кінці: home/# охоплює все під home/.

Топіки, що починаються з $ (наприклад $SYS/... зі службовою статистикою брокера), під шаблон # на першому рівні не потрапляють.

Для кожного повідомлення обирають рівень гарантії доставки.

QoS Гарантія Обмін Ціна
0 не більше одного разу: надіслав і забув PUBLISH найдешевший; повідомлення може загубитися
1 щонайменше раз PUBLISH → PUBACK можливі дублікати, якщо підтвердження загубилося
2 рівно один раз PUBLISH → PUBREC → PUBREL → PUBCOMP найдорожчий: чотири повідомлення

Гарантія діє окремо на кожній ділянці: від видавця до брокера й від брокера до підписника. Підписник отримує повідомлення з нижчим із двох рівнів: якщо видавець надіслав із QoS 2, а підписався з QoS 0, отримає без гарантії. QoS стосується лише доставки між клієнтом і брокером, а не того, чи підписник обробив повідомлення.

Від звичайних втрат пакетів QoS не рятує, бо рятувати нема від чого: MQTT іде поверх TCP, а той сам перепосилає загублені сегменти, тож на каналі з великими втратами QoS 0 доставляє все, лише повільно. QoS працює там, де TCP безсилий: коли з’єднання рветься й відкривається нове (що було в дорозі, пропало разом зі старим) і коли підписника немає онлайн. Для клієнта зі сталою сесією брокер відкладає повідомлення QoS 1 і 2 до його повернення, а QoS 0 відкидає. Це видно в лабораторній B8.

Retained. Повідомлення, опубліковане з ознакою retain, брокер запам’ятовує як останнє значення топіка й одразу віддає кожному, хто підписується пізніше. Без цього щойно запущений інформаційний екран не знав би температури аж до наступного вимірювання.

Last will. Клієнт під час підключення повідомляє брокеру «якщо я зникну без прощання, опублікуй це». Коли з’єднання обривається без коректного DISCONNECT (зникло живлення, пропала мережа, вичерпався keep-alive), брокер публікує це повідомлення-заповіт сам. Так «пристрій поза мережею» стає подією, а не відсутністю подій. Зазвичай заповіт поєднують із retain: пристрій при підключенні публікує в home/sensor7/status значення online, а заповіт замінює його на offline, тож статус завжди актуальний.

Persistent session. Якщо клієнт підключається зі збереженням сесії (clean session = false у MQTT 3.1.1; clean start = false у версії 5), брокер пам’ятає його підписки й накопичує повідомлення QoS 1 і 2, поки клієнт офлайн. Після повернення клієнт їх отримує. Для пристрою, який спить і прокидається раз на годину, без цього команди губилися б.

MQTT 5.0 не змінила основної ідеї, але закрила болючі місця. Брокер тепер пояснює у відповідях причину відмови замість голого коду. Час життя сесії задається числом секунд, тож «зберегти сесію назавжди» більше не єдина опція. Повідомленню можна призначити термін придатності: команда «відчинити двері» не має дійти до пристрою через добу. Також з’явилися властивості повідомлення (тип вмісту, топік для відповіді), завдяки яким запит-відповідь виражається без вигаданих домовленостей. Дві популярні версії досі співіснують: брокер зазвичай підтримує обидві, і вибирає клієнт під час CONNECT.

CoAP (Constrained Application Protocol, RFC 7252) задумано як HTTP для обмежених пристроїв: ті самі ідеї — ресурси за адресами, методи GET, POST, PUT, DELETE, коди відповіді — але компактно й поверх UDP. Заголовок займає чотири байти. Порт за замовчуванням 5683, із DTLS — 5684. Оскільки UDP не гарантує доставки, надійність CoAP забезпечує сам:

  • Confirmable (CON) — отримувач відповідає ACK, відправник повторює передачу, поки підтвердження не прийде.
  • Non-confirmable (NON) — без підтвердження, для даних, втрату яких переживають, наприклад періодичних показів.

Observe (RFC 7641) дає CoAP те, що MQTT має від народження: клієнт надсилає GET із прапорцем спостереження й потім отримує нові відповіді щоразу, коли ресурс змінюється. Без постійного опитування.

Обмін CoAP виглядає як крихітна версія HTTP. Клієнт запитує температуру, сервер відповідає підтвердженням із даними в тому самому пакеті:

Клієнт Датчик
| CON [MID 0x7d34] GET /temp -------> |
| <------- ACK [MID 0x7d34] 2.05 "21.5" |

Ідентифікатор повідомлення (MID) зв’язує запит із підтвердженням. Код 2.05 Content відповідає HTTP 200, а 4.04 Not Found — 404: формат коду інший, але зміст упізнається одразу. Якщо відповідь не готова, сервер спершу надсилає порожнє ACK, щоб клієнт припинив повтори, а саму відповідь шле окремим повідомленням пізніше. Пристрої, що спілкуються за CoAP, зазвичай отримують адресу в локальній мережі, тому до них достукуються через прикордонний маршрутизатор або перекладач CoAP у HTTP, що стоїть на шлюзі.

MQTT і CoAP відповідають на схожі питання по-різному. MQTT тримається на брокері й TCP. Це зручно, коли споживачів багато і є постійне з’єднання, але пристрою, який засинає, TCP незручний. CoAP працює поверх UDP за моделлю «клієнт—сервер» напряму. Він легший і добре перетворюється на HTTP через проксі, проте потребує, щоб ресурс пристрою був досяжний, а це важко, коли пристрій спить або стоїть за NAT.

Жодна з цих технологій не доставляє дані до застосунку сама. Між датчиком і хмарою зазвичай стоїть шлюз. Датчик температури в теплиці розмовляє з ним по BLE, LoRa чи 802.15.4, бо на TCP/IP у нього немає ні пам’яті, ні енергії. Шлюз — звичайний Linux-пристрій: він приймає кадри датчиків і публікує їх як MQTT-повідомлення до брокера, локального чи хмарного. Підписники, від панелі до бази даних, працюють уже в звичайній IP-мережі.

Шлюз стоїть на межі: з одного боку дешева радіотехнологія з крихітними кадрами, з іншого звичайний IP. Шлюз часто виконує й корисну роботу: агрегує вимірювання, відкидає очевидно хибні значення, накопичує дані, коли зникає зв’язок із хмарою, і виконує локальні правила («якщо температура вища за поріг, увімкни вентилятор»), які мають працювати й без інтернету.

MQTT-з’єднання довгоживуче, а NAT із модуля 9 забуває потоки, що мовчать, коли спливає таймаут запису в таблиці відстеження з’єднань. Якщо пристрій мовчить довше, клієнт і брокер ще вважають з’єднання живим, але пакети вже нікуди не потраплять. Для цього в MQTT є keep-alive: клієнт при підключенні каже, як часто він обіцяє подавати голос, і коли передавати нічого, шле крихітний PINGREQ. Брокер, не почувши клієнта півтора періоду, вважає з’єднання обірваним і, якщо задано, публікує заповіт. У мобільних мережах за CGNAT таймаути часто короткі, тож період keep-alive доводиться скорочувати, а кожен зайвий обмін коштує енергії. Розробнику прошивки й мережевому інженерові доводиться про це домовлятися.

Схема топіків — частина проєкту так само, як схема бази даних, і виправляти її пізніше боляче. Рівні йдуть від загального до конкретного (site/building/room/device/measurement), щоб шаблони + і # добирали потрібні зрізи. Початкового слеша не ставлять: він створює порожній перший рівень. Команди й дані розділяють у різних гілках (cmd/lamp і state/lamp), інакше пристрій побачить серед команд власні дані. Ідентифікатор пристрою кладуть у топік, а не в тіло повідомлення, щоб права на брокері можна було задавати за топіками: sensor7 дозволяють писати лише у свою гілку й читати лише свої команди.

Мільйони пристроїв потрапили в ботнети з банальних причин, і причини ці повторюються.

  • Типові паролі. Камери й роутери з однаковим admin/admin на всіх екземплярах. Ботнет Mirai збирав пристрої саме так: перебором невеликого списку типових облікових даних на відкритих Telnet-портах.
  • Відкриті брокери. MQTT-брокер, що слухає весь інтернет без автентифікації, дозволяє кому завгодно підписатися на # і побачити все, що передають пристрої, а також подавати їм команди. Пошукові системи на кшталт Shodan індексують такі брокери.
  • Відсутність оновлень. Пристрій, який нема як оновити, стає вразливим назавжди. Механізм оновлення прошивки «по повітрю» з перевіркою підпису закладають у проєкт із першого дня.
  • Відкритий текст. MQTT і CoAP без TLS/DTLS передають усе читабельно, включно з паролем у CONNECT (нижче це видно в tcpdump).
  • Спільні секрети. Один ключ на всю партію: витік із одного пристрою відкриває всі.

З TLS на слабких пристроях окремий клопіт. Рукостискання потребує оперативної пам’яті під буфери, часу й енергії на криптографію, правильного годинника для перевірки терміну сертифікатів, а кадри LoRaWAN та 802.15.4 надто малі для сертифікатів. На практиці застосовують криптографію на еліптичних кривих замість RSA, відновлення сесії TLS замість нового рукостискання, попередньо розподілені ключі (PSK), DTLS для CoAP і шифрування на рівні мережевого протоколу (у LoRaWAN) замість TLS. Принцип той самий, що в модулі 15: ключ на пристрій, а не один на всіх, і можливість його відкликати.

Радіо без обладнання не показати, тому практичну частину зробимо з MQTT у просторах імен: один простір для брокера, другий для пристрою.

Terminal window
apt-get install -y mosquitto mosquitto-clients
ip netns add iot-br; ip netns add iot-dev
ip link add vb type veth peer name vd
ip link set vb netns iot-br; ip link set vd netns iot-dev
ip -n iot-br addr add 10.20.0.1/24 dev vb
ip -n iot-dev addr add 10.20.0.2/24 dev vd
for n in iot-br iot-dev; do ip -n $n link set lo up; done
ip -n iot-br link set vb up; ip -n iot-dev link set vd up

Дві ізольовані «машини» з’єднані парою veth. Тепер конфіг брокера. Кладемо його в /etc/mosquitto/: в Ubuntu 26.04 і новіших профіль AppArmor не дає mosquitto читати конфіг з інших місць (подробиці в B8). Mosquitto 2.x без listener слухає лише localhost, а без allow_anonymous true відмовляє клієнтам без пароля, тому обидва рядки пишемо явно.

Terminal window
cat > /etc/mosquitto/demo.conf <<'E'
listener 1883 10.20.0.1
allow_anonymous true
persistence false
E
ip netns exec iot-br mosquitto -c /etc/mosquitto/demo.conf -d
ip netns exec iot-br ss -ltnp | grep 1883
LISTEN 0 100 10.20.0.1:1883 0.0.0.0:* users:(("mosquitto",pid=1531,fd=4))

Підписка із шаблоном і публікація з «пристрою»:

Terminal window
ip netns exec iot-br mosquitto_sub -h 10.20.0.1 -t 'home/+/temp' -v -q 1 &
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -t home/kitchen/temp -m 21.5 -q 1
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -t home/hall/temp -m 19.0 -r
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -t home/hall/humidity -m 40
home/kitchen/temp 21.5
home/hall/temp 19.0

Вологість (home/hall/humidity) шаблон home/+/temp не пропустив. Ключ -r у другій публікації зробив повідомлення retained. Підписник, який з’явився пізніше, отримує його одразу:

Terminal window
timeout 2 ip netns exec iot-dev mosquitto_sub -h 10.20.0.1 -t 'home/#' -v
home/hall/temp 19.0

Лише home/hall/temp: ні температуру на кухні, ні вологість не публікували як retained. Тепер last will. Підписуємося на статуси, запускаємо «датчик» із заповітом і обриваємо його сигналом SIGKILL, без прощання:

Terminal window
ip netns exec iot-br mosquitto_sub -h 10.20.0.1 -t 'home/+/status' -v &
ip netns exec iot-dev mosquitto_sub -h 10.20.0.1 -t x -i sensor7 \
--will-topic home/sensor7/status --will-payload offline --will-qos 1 --will-retain &
kill -9 $!
home/sensor7/status offline

Брокер опублікував заповіт сам. Якщо той самий клієнт завершити звичайним SIGTERM, mosquitto_sub коректно відключиться, і заповіт не спрацює: так і має бути, бо це була не аварія.

Persistent session перевіряється двома запусками. Перший підписується з постійною сесією (-c, ідентифікатор клієнта -i обов’язковий) і виходить, далі хтось публікує, поки клієнта немає:

Terminal window
ip netns exec iot-dev mosquitto_sub -h 10.20.0.1 -t cmd/lamp -q 1 -c -i lamp1 -W 1
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -t cmd/lamp -m ON -q 1
ip netns exec iot-dev mosquitto_sub -h 10.20.0.1 -t cmd/lamp -q 1 -c -i lamp1 -W 2 -v
cmd/lamp ON

Команда ON дочекалася клієнта. Повторіть з новим ідентифікатором без -c, і повідомлення, опубліковане до підписки, не прийде.

Режим -d показує службові повідомлення протоколу, тобто різницю між QoS:

Terminal window
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -d -t home/k/t -m 5 -q 1
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -d -t home/k/t -m 5 -q 2
Client null sending PUBLISH (d0, q1, r0, m1, 'home/k/t', ... (1 bytes))
Client null received PUBACK (Mid: 1, RC:0)
...
Client null sending PUBLISH (d0, q2, r0, m1, 'home/k/t', ... (1 bytes))
Client null received PUBREC (Mid: 1)
Client null sending PUBREL (m1)
Client null received PUBCOMP (Mid: 1, RC:0)

QoS 1 — два повідомлення, QoS 2 — чотири, як у таблиці вище. Тепер те, що бачить спостерігач у мережі, якщо TLS немає:

Terminal window
ip netns exec iot-br tcpdump -nn -A -i vb 'tcp port 1883' &
ip netns exec iot-dev mosquitto_pub -h 10.20.0.1 -t home/kitchen/temp -m 21.5 -q 1 -u sensor -P s3cret
IP 10.20.0.2.54602 > 10.20.0.1.1883: Flags [P.], ... length 30
E..R3$@.@..W
...
....J.[..V1..>....?.o.....
E..~P2{.....MQTT...<....sensor..s3cret
...
IP 10.20.0.2.54602 > 10.20.0.1.1883: Flags [P.], ... length 27
...home/kitchen/temp..21.5

Ім’я користувача, пароль, топік і значення лежать у відкритому вигляді. Тому для будь-чого, що виходить за межі однієї лабораторної, брокер слухає на порту 8883 із TLS (модуль 15), а не на 1883.

Прибрати за собою: зупиніть mosquitto, mosquitto_sub та tcpdump, видаліть простори імен і /etc/mosquitto/demo.conf.

Terminal window
ip netns del iot-br; ip netns del iot-dev

Радіо дивляться через iw і nmcli. Нижче вивід довідковий, він залежить від карти й драйвера, а на машині без Wi-Fi-адаптера (зокрема у ВМ чи контейнері) його не отримати.

Terminal window
iw dev wlan0 link
nmcli -f SSID,CHAN,SIGNAL,SECURITY dev wifi list
Connected to aa:bb:cc:dd:ee:ff (on wlan0)
SSID: HomeNet
freq: 5180
signal: -58 dBm
rx bitrate: 433.3 MBit/s
SSID CHAN SIGNAL SECURITY
HomeNet 36 78 WPA2
Neighbour 1 41 WPA2 WPA3

Рядок signal у iw — рівень у dBm, про який ішлося вище. У виводі nmcli шкала від 0 до 100 умовна. Порівнювати її між різними пристроями не можна. Канали в списку покажуть, хто сусідить із вами в ефірі.

Типові помилки розуміння

Section titled “Типові помилки розуміння”

Повна шкала Wi-Fi означає швидкий інтернет. Шкала показує силу сигналу від точки доступу, а не швидкість, яку дає провайдер, і не завантаженість ефіру. Сильний сигнал у перевантаженому каналі, де сусіди й далекі клієнти з’їдають ефірний час, може працювати повільніше за слабший на вільному каналі.

Вищий діапазон завжди краще. 5 GHz дає швидкість і вільні канали, але гірше проходить крізь стіни. У дальній кімнаті 2,4 GHz часто виграє.

Wi-Fi не має колізій, бо ним керує точка доступу. Точка доступу не розподіляє ефір за розкладом: станції змагаються за нього за CSMA/CA, і прихований вузол, а також перешкоди, дають втрати, які Wi-Fi приховує повторними передачами.

MQTT QoS 2 означає, що повідомлення гарантовано оброблено. QoS описує доставку між клієнтом і брокером. Чи спрацював підписник і що він із ним зробив, протокол не знає. Обробку, коли вона важлива, підтверджують на рівні застосунку.

LoRaWAN — це «Wi-Fi на більшу відстань». Швидкість на кілька порядків менша, обмін зазвичай односторонній, а повідомлення обмежені розміром і частотою. Фото чи відео через LoRaWAN не передаєш.

Шифрування Wi-Fi захищає мій трафік до сервера. Воно діє лише на радіоділянці до точки доступу. Наскрізний захист дає лише TLS.

Пристрою IoT безпечно дати адресу й залишити порт відкритим, бо це лише датчик. Найчастіше такі пристрої й стають частиною ботнетів: у них немає ні нормального пароля, ні оновлень.

Перевір себе

1. Чому в Wi-Fi не можна застосувати CSMA/CD, як в Ethernet?
2. Станції A і B бачать точку доступу, але не чують одна одну. Що станеться, якщо обидві почнуть передавати?
3. Чому крізь дві стіни Wi-Fi часто слабший, ніж на вдвічі більшій відстані в коридорі?
4. Навіщо MQTT retained-повідомлення?
5. Датчик вказав last will `offline`. Коли брокер його опублікує?
6. Видавець публікує з QoS 2, а підписник підписався з QoS 0. З якою гарантією підписник отримає повідомлення?
7. Чому LoRaWAN-шлюз не потребує ключів шифрування вмісту кадру?
8. Чому 6LoWPAN потрібен, щоб IPv6 працював поверх IEEE 802.15.4?
9. Який із цих прийомів найкраще допомагає IoT-пристрою на батареї прожити роки?

B8. MQTT і IoT-шлюз — брокер Mosquitto, QoS 0/1/2 під втратами й TLS між пристроєм і брокером. Спирається на цей модуль і на модуль 15. Про мережу, яку збирають для кількох пристроїв у датацентрі, а не для датчиків, — у модулі 18.

  • Kurose, Ross, Computer Networking: A Top-Down Approach, розділ про бездротові й мобільні мережі
  • Tanenbaum, Feamster, Wetherall, Computer Networks, розділ про підшар MAC і бездротові LAN
  • IEEE 802.11 (Wi-Fi), IEEE 802.15.4
  • RFC 7252, The Constrained Application Protocol (CoAP); RFC 7641, Observing Resources in CoAP
  • OASIS, MQTT Version 3.1.1 і MQTT Version 5.0
  • LoRa Alliance, специфікація LoRaWAN
  • Документація Mosquitto, man mosquitto, man mosquitto.conf, man mosquitto_pub, man mosquitto_sub
  • man iw, man nmcli