Новаком
IOT

OTA-обновления прошивок IoT: архитектура, протоколы и подводные камни

Как устроены OTA-обновления для IoT-устройств: A/B-схема, delta-обновления, Secure Boot, MCUboot, Mender, hawkBit. Архитектура, протоколы, чеклист для продакшена.

Н
Новаком
2026-05-22 · 13 минут чтения

Устройство без OTA — это бомба замедленного действия

Вы выпустили 10 000 умных датчиков. Через три месяца обнаружилась критическая уязвимость в TLS-библиотеке. Без OTA у вас два варианта: отозвать все устройства (убыток) или оставить уязвимость (риск). С OTA — один push, и все 10 000 устройств обновлены за ночь.

OTA (Over-The-Air) — это не просто «загрузить файл по Wi-Fi». Это система, которая должна гарантировать: обновление дойдёт, установится корректно, не превратит устройство в кирпич и не будет подменено атакующим. Каждое из этих требований — отдельная инженерная задача.

Анатомия OTA-обновления

Процесс обновления выглядит просто, но каждый шаг содержит ловушки:

┌──────────┐    1. Проверка    ┌──────────┐
│Устройство│───────────────────▶│OTA-сервер│
│          │◀───────────────────│          │
│          │ 2. Метаданные      │          │
│          │    (версия, размер,│          │
│          │     хеш, подпись)  │          │
│          │                    │          │
│          │ 3. Скачивание      │          │
│          │◀───────────────────│          │
│          │    (по частям)     │          │
│          │                    │          │
│          │ 4. Верификация     │          │
│          │    (подпись, хеш)  │          │
│          │                    │          │
│          │ 5. Установка       │          │
│          │    (запись в flash) │          │
│          │                    │          │
│          │ 6. Перезагрузка    │          │
│          │    + валидация     │          │
│          │                    │          │
│          │ 7. Отчёт           │          │
│          │───────────────────▶│          │
└──────────┘                    └──────────┘

Шаг 1–2: Проверка и метаданные

Устройство периодически (или по push) спрашивает сервер: «есть новая версия?». Сервер отвечает манифестом: версия, размер, SHA-256 хеш, цифровая подпись, совместимость (hardware revision, текущая версия).

Критичные моменты:

  • Канал проверки должен быть защищён (TLS). Иначе MITM подменит манифест
  • Версионирование: Semantic Versioning (MAJOR.MINOR.PATCH) + hardware compatibility tag
  • Rollout policy: не обновлять все устройства сразу — сначала 1%, потом 10%, потом 100%

Шаг 3: Скачивание

Для устройств с Wi-Fi/Ethernet — HTTPS. Для LPWAN (LoRaWAN, NB-IoT) — фрагментация и возобновление:

ТранспортТипичный размер прошивкиВремя скачиванияОсобенности
Wi-Fi1–16 МБСекундыБез ограничений
LTE/NB-IoT100 КБ – 1 МБМинутыТрафик платный
LoRaWAN10–100 КБЧасы–дниDuty cycle, фрагментация (FUOTA)
BLE100 КБ – 1 МБМинутыЧерез смартфон (DFU)

Для LoRaWAN существует стандарт FUOTA (Firmware Update Over The Air), но он сложен: multicast, фрагментация, CRC на каждый блок, часы на обновление.

Шаг 4: Верификация

Перед установкой устройство обязано проверить:

  1. Целостность: SHA-256 хеш скачанного файла совпадает с манифестом
  2. Подлинность: цифровая подпись прошивки валидна (Ed25519 или ECDSA-P256)
  3. Совместимость: прошивка предназначена для этого hardware revision

Публичный ключ для проверки подписи хранится в bootloader или Secure Element — не в самой прошивке (иначе вредоносная прошивка подменит ключ).

Шаг 5–6: Установка и перезагрузка

Здесь решается главный вопрос: что делать, если обновление прервалось (пропало питание, ошибка записи)?

Стратегии обновления

1. A/B (Dual-bank)

Самая надёжная схема. Flash разделён на два слота: A (активный) и B (обновление).

Flash layout:
┌──────────────┐
│  Bootloader  │  (не обновляется, проверяет подпись)
├──────────────┤
│  Slot A      │  ← текущая прошивка (работает)
│  (active)    │
├──────────────┤
│  Slot B      │  ← новая прошивка (скачивается сюда)
│  (update)    │
├──────────────┤
│  Settings    │  (NVS, конфигурация)
└──────────────┘

Процесс:

  1. Новая прошивка записывается в Slot B, пока старая работает из Slot A
  2. Bootloader переключается на Slot B и перезагружает
  3. Новая прошивка стартует и проводит self-test
  4. Если self-test пройден — подтверждает обновление (confirm)
  5. Если self-test провален или нет confirm за N секунд — автоматический откат на Slot A
ПлюсыМинусы
Атомарное обновлениеНужен двойной объём Flash
Автоматический откатДороже для MCU с малой Flash
Обновление без простоя
Прерывание безопасно

2. In-place (Single-bank)

Прошивка обновляется «на месте» — поверх текущей.

Flash layout:
┌──────────────┐
│  Bootloader  │
├──────────────┤
│  Firmware    │  ← стирается, записывается новая версия
├──────────────┤
│  Staging     │  (временный буфер, может быть во внешней Flash)
├──────────────┤
│  Settings    │
└──────────────┘

Процесс:

  1. Новая прошивка скачивается во временный буфер (внешняя Flash, RAM)
  2. Bootloader стирает основной раздел и записывает новую прошивку
  3. Если прервалось — кирпич (если нет recovery)
ПлюсыМинусы
Экономия FlashНет отката
Подходит для MCU с 64–128 КБПрерывание = кирпич
Простой при обновлении

3. Delta (дифференциальное)

Передаётся не полная прошивка, а разница между текущей и новой версией.

ПараметрFull imageDelta
Размер передачи (типичный)200 КБ20–50 КБ
Экономия трафика70–90%
Сложность на устройствеНизкаяВысокая (применение патча)
Требования к RAMНизкиеНужен буфер для патча
РискНизкийВерсионная зависимость

Delta критичен для LPWAN-устройств (LoRaWAN, NB-IoT), где трафик ограничен или платный. Алгоритмы: bsdiff, detools, SUIT CBOR.

Проблема: delta-обновление зависит от точной текущей версии. Если устройство пропустило промежуточную версию — delta не применится. Нужен fallback на full image.

Безопасный загрузчик (Secure Boot)

Bootloader — единственный компонент, которому устройство доверяет безусловно. Он проверяет подпись прошивки перед запуском. Если подпись невалидна — прошивка не запускается.

Цепочка доверия

ROM bootloader (неизменяемый, в кремнии)
    │ проверяет подпись
    ▼
Bootloader (MCUboot / ESP Secure Boot)
    │ проверяет подпись
    ▼
Firmware (ваша прошивка)

Каждый уровень проверяет следующий. Компрометация ROM bootloader невозможна (он в silicon). Компрометация bootloader требует физического доступа к Flash (и отключённого Flash Encryption).

MCUboot

MCUboot — стандартный загрузчик для Zephyr, Mynewt, Mbed OS, Apache NuttX. Поддерживает:

ФункцияОписание
Secure BootПроверка подписи (RSA-2048, ECDSA-P256, Ed25519)
A/B swapАтомарное переключение слотов
RevertАвтоматический откат при неудачном обновлении
Encrypted imagesШифрование прошивки в Flash
Serial recoveryВосстановление через UART при полном сбое
Hardware keysПоддержка Secure Element для хранения ключей

MCUboot занимает 16–32 КБ Flash — приемлемо для большинства MCU.

ESP32 Secure Boot

Espressif предлагает собственную реализацию:

  • Secure Boot V2: RSA-3072 или ECDSA-256, ключ в eFuse (one-time programmable)
  • Flash Encryption: AES-256, уникальный ключ на каждый чип
  • Anti-rollback: счётчик версий в eFuse — нельзя откатить на старую прошивку

Особенность: после активации Secure Boot отключить его невозможно — eFuse пережигается навсегда.

OTA-серверы и платформы

Self-hosted

ПлатформаПротоколMCU поддержкаОсобенности
Eclipse hawkBitHTTP/HTTPS (DDI API)Любой с HTTPJava, open-source, enterprise-grade
MenderHTTPS (REST API)Yocto, DebianA/B, delta, dashboard, open-source
RAUCHTTPS + hawkBitYocto, DebianТолько Linux-устройства
SWUpdateHTTP/HTTPS + hawkBitLinux, bare-metalГибкий, scriptable
GoliothCoAP/DTLSZephyr, ESP-IDFCloud-native, MCU-first

Облачные

ПлатформаПротоколСтоимостьОсобенности
AWS IoT Device ManagementMQTT + S3$0.05/устройство/месJobs API, fleet management
Azure IoT HubMQTT + Blob Storage$0.05–0.15/устройство/месDevice Twins, ADU
GoliothCoAP$0.03/устройство/месZephyr-нативный, LightDB
MemfaultHTTPS$0.10/устройство/месOTA + мониторинг + crash analytics
ParticleПроприетарный$0.04/устройство/месПолная платформа (hardware + cloud)

Минимальный self-hosted OTA

Для прототипа или малой серии можно обойтись без специализированной платформы:

  1. S3/MinIO — хранилище прошивок с версионированием
  2. JSON-манифест — файл с текущей версией, URL, SHA-256, подписью
  3. HTTPS-сервер (nginx) — отдача манифеста и бинарника
  4. Скрипт на устройстве — периодическая проверка манифеста, скачивание, верификация

Этого достаточно для сотен устройств. Для тысяч — нужен hawkBit или Mender с rollout-политиками.

Протоколы доставки

Для MCU (bare-metal, RTOS)

ПротоколOverheadПодходит дляБезопасность
HTTPSВысокий (TLS handshake)Wi-Fi, LTETLS 1.3
CoAP/DTLSНизкийLPWAN, constrainedDTLS 1.2
MQTT + файлСреднийУже есть MQTT-соединениеTLS
LwM2M (Object 5)НизкийСтандартизированный OTADTLS
BLE DFUНизкийЧерез смартфонBLE encryption
SUIT (RFC 9019)МинимальныйIETF стандарт для IoT OTACOSE подпись

SUIT (Software Updates for Internet of Things) — новый стандарт IETF, специально разработанный для constrained IoT. Манифест в CBOR, подпись в COSE, минимальный overhead. Поддерживается в Zephyr.

Для Linux-устройств

ИнструментМеханизмDeltaRollback
MenderA/B full-imageДа (mender-binary-delta)Автоматический
RAUCA/B или in-placeЧерез casyncАвтоматический
SWUpdateScriptable handlersЧерез librsyncConfigurable
OSTree (libostree)Git-like content-addressableНативныйДа (reflog)
BalenaDocker containersДа (layer-based)Container rollback

OSTree заслуживает отдельного внимания: он работает как git для корневой файловой системы. Обновления — это коммиты, откат — checkout предыдущего коммита. Используется в Fedora IoT, Automotive Grade Linux, Endless OS.

Подводные камни

1. Питание прервалось во время записи Flash

Это самый частый сценарий отказа. Решения:

  • A/B-схема: запись идёт в неактивный слот, прерывание безопасно
  • Журналирование: bootloader ведёт лог состояния обновления
  • Атомарный swap: MCUboot переключает слоты одной записью в trailer

2. Устройство не подтвердило обновление

Новая прошивка загрузилась, но зависла до вызова boot_set_confirmed(). Bootloader ждёт N секунд (watchdog), не дождался — откат.

Обязательно: self-test в первые секунды после обновления. Проверить: сеть работает, датчики отвечают, конфигурация читается.

3. Устройство в поле без связи

Некоторые устройства выходят на связь раз в сутки (или реже). Обновление может занять дни. Нужна:

  • Возобновляемая загрузка (resume): скачать 40% сегодня, 60% завтра
  • Контроль целостности блоков: CRC на каждый фрагмент, не только на весь файл
  • Приоритизация трафика: OTA не должно блокировать передачу данных

4. Rollback-атака

Атакующий заставляет устройство откатиться на старую версию с известной уязвимостью. Защита:

  • Anti-rollback counter: монотонный счётчик в OTP/eFuse. Прошивка с версией ниже счётчика отклоняется
  • Минимальная версия в bootloader: bootloader знает минимально допустимую версию

5. Обновление bootloader

Обновлять bootloader — самая рискованная операция. Если новый bootloader не работает — устройство кирпич навсегда (bootloader проверяет сам себя, замкнутый круг).

Решения:

  • Не обновлять bootloader в поле (самый безопасный вариант)
  • Dual bootloader: два bootloader с переключением (как A/B для прошивки)
  • ROM-based recovery: recovery-код в неизменяемой ROM (если MCU поддерживает)

Чеклист OTA для продакшена

#ПроверкаПриоритет
1Подпись прошивки (Ed25519/ECDSA) проверяется bootloaderКритический
2A/B-схема с автоматическим откатомКритический
3TLS/DTLS для скачиванияКритический
4Anti-rollback (монотонный счётчик версий)Высокий
5Self-test после обновления (сеть, датчики, конфиг)Высокий
6Возобновляемая загрузка для нестабильных каналовВысокий
7Rollout policy (1% → 10% → 100%)Высокий
8Dashboard: версии всех устройств в реальном времениСредний
9Delta-обновления для LPWANСредний
10Шифрование прошивки в FlashСредний
11Bootloader НЕ обновляется в поле (или dual bootloader)Высокий
12Максимальный таймаут на обновление (аварийный откат)Высокий
13Логирование всех этапов обновленияСредний
14Оповещение при массовом откате (возможная проблема в релизе)Средний

Итого

OTA — не фича, а требование для любого IoT-устройства, подключённого к сети. Без OTA вы не закроете уязвимости, не исправите баги и не добавите функции после выпуска.

Три ключевых решения при проектировании OTA:

  1. A/B или in-place: если Flash позволяет — всегда A/B. Кирпич в поле обходится дороже, чем лишние 128 КБ Flash
  2. MCUboot или vendor-specific: MCUboot — портируемый, стандартный, с поддержкой Zephyr/NuttX. ESP Secure Boot — только для ESP32, но глубже интегрирован
  3. Self-hosted или облако: до 1 000 устройств — self-hosted (hawkBit, nginx + S3). Больше — Mender, Golioth или AWS IoT

Самая частая ошибка: «добавим OTA потом». OTA влияет на разметку Flash, bootloader, криптографию, сетевой стек — это архитектурное решение, которое закладывается на старте проекта, а не прикручивается сбоку.


Проектируете IoT-устройство и не уверены в архитектуре OTA? Мы делаем экспресс-аудит IoT-идеи за 25 000 ₽: архитектура, OTA-стратегия, безопасность, компоненты — за 5 рабочих дней. Или посмотрите наши услуги по IoT и embedded-разработке.

РАЗРАБОТКА

Нужна похожая задача?

Обсудим вашу задачу и предложим решение за 30 минут.

Обсудить проект