Архітектура захищених систем: як я створив клієнт-серверний захист для десктопної телеметрії на STM32, Python

💡 Усі статті, обговорення, новини про Python — в одному місці. Приєднуйтесь до Python спільноти!

Мене звати Олександр, я self-taught інженер та засновник Hopeok Code Studio. Моя основна спеціалізація — розробка embedded-систем на базі мікроконтролерів STM32 та створення комплексного софту для взаємодії з апаратним забезпеченням. Цей матеріал буде корисним розробникам заліза, IoT-інженерам та програмістам, які створюють комерційні продукти і шукають надійні архітектурні рішення для захисту своєї інтелектуальної власності від реверс-інжинірингу.

Світ розробки апаратних та програмних рішень має одну неприємну особливість: щойно ваш продукт стає затребуваним, його намагаються скопіювати. Тут я поділюся власним досвідом побудови екосистеми безпеки без розкриття вихідних кодів, фокусуючись виключно на логіці та архітектурі, які я застосував у своєму останньому проєкті — Hopeok Telemetry Hub.

Проблема: Чому класичний захист не працює?

Працюючи над високошвидкісними логерами даних (зокрема на базі STM32G474RE), я зрозумів, що захистити лише прошивку через Readout Protection (RDP) — це лише половина справи. Клієнтська частина, яка працює на ПК (візуалізація, калібрування, аналітика), залишається вразливою. Десктопний додаток на Python досить легко декомпілювати, а локальні ліцензійні перевірки — просто вирізати.

Мені була потрібна архітектура, де мікроконтролер, десктопний софт та віддалений сервер працюють як нерозривний ланцюг. Якщо вилучити або підмінити хоча б одну ланку — система має блокуватися.

Апаратний рівень: Збір даних та UID

Основою системи є плата з мікроконтролером STM32 (у проєкті залучені серії F103, F407 та G474). Завдання контролера — збирати дані з 8 DC каналів (INA226), тахометра, тензодатчиків та модулів PZEM, а потім передавати їх на ПК.

Щоб не перевантажувати систему звичайним текстовим виводом, я відмовився від JSON чи класичних рядків. Дані формуються у жорсткий бінарний пакет фіксованої довжини з маркерами початку та кінця і передаються через DMA зі швидкістю 921600 baud.

Але найважливіша функція мікроконтролера в контексті безпеки — це передача свого унікального 96-бітного ідентифікатора (UID). Цей ідентифікатор вшивається на заводі-виробнику, його неможливо змінити, і саме він стає апаратним «якорем» для нашої ліцензії.

Десктопний клієнт: Розділення потоків та авторизація

Десктопний клієнт написаний на Python (PyQt6). Головним архітектурним викликом тут стала багатопотоковість. Читання UART-порту на таких швидкостях у головному потоці миттєво «заморожує» графічний інтерфейс.

Тому логіку було повністю розділено:

  1. Фоновий потік: Безперервно читає буфер послідовного порту, шукає бінарні маркери, розпаковує байти у фізичні величини і формує готові словники даних.
  2. Головний потік (UI): Лише отримує сигнали з готовими даними і оновлює екран з частотою 20 Гц.

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

  • При запуску програма зчитує HWID комп’ютера.
  • Користувач вводить ключ доступу у вікні авторизації.
  • Програма формує зашифрований запит на сервер, передаючи ключ та HWID.
  • Сервер перевіряє базу. Якщо все добре — він не просто каже «ОК», а повертає частину конфігураційних даних, без яких локальні математичні розрахунки сенсорів просто не працюватимуть (софт виводитиме сміття замість реальних метрик).
  • Після завантаження інтерфейсу клієнт зчитує UID мікроконтролера і робить фінальну звірку.

Серверний бекенд: Активний захист від Brute Force

Серверна частина реалізована на PHP + MySQL. Вона генерує ключі та керує клієнтською базою. Але головне її завдання — активна кібербезпека.

Я реалізував модуль, який логує кожен неуспішний запит. Якщо з однієї IP-адреси надходить серія помилкових запитів (невірний ключ, спроба підміни HWID), сервер автоматично додає цей IP у чорний список. Будь-які подальші запити відкидаються на рівні сервера ще до етапу підключення до бази даних (повертається помилка доступу). Це робить автоматизовані атаки на API економічно та технічно недоцільними.

Фінальний рівень: Компіляція через Nuitka

Навіть із серверною перевіркою, залишати Python-скрипти у вигляді .pyc архівів (як це робить PyInstaller) — небезпечно. Їх легко розпакувати і відновити початковий код.

Щоб захистити інтелектуальну власність студії, я використав Nuitka. Це інструмент, який транслює Python-код у C-код, а потім компілює його через C-компілятор у справжній машинний бінарний файл (.exe).

Я використовую таку конфігурацію збірки (можливо, комусь стане в пригоді): nuitka --standalone --onefile --plugin-enable=pyqt6 --windows-disable-console --include-data-dir=assets=assets main.py

На виході ми отримуємо монолітний файл без Python-байтокоду. Відновити алгоритми парсингу чи логіку ліцензування з такого файлу вимагає тижнів роботи в дизасемблерах, що відлякує абсолютну більшість зломщиків.

Висновок

Створення цієї екосистеми дозволило обкатати в реальних умовах надійну архітектуру захисту. Каркас клієнта (авторизація з прив’язкою до HWID), серверна валідація та блокування за IP можуть бути масштабовані не лише на embedded-сферу, а й на захист будь-якого десктопного чи IoT ПЗ.

Щоб продемонструвати, як це працює на практиці, я виклав скомпільовану версію на GitHub. Ви можете завантажити бінарник і на власні очі побачити реалізацію вікна активації, ліцензійної угоди (EULA) та реакцію системи. Відновлювати вкрадений код завжди складніше, ніж інвестувати час у правильну архітектуру безпеки з самого початку.

👉 Подивитися практичну реалізацію (бінарний реліз): github.com/...​odkf/Hopeok_Telemetry_Hub

👍ПодобаєтьсяСподобалось2
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Дякую за увагу до матеріалу! Буду радий відповісти на ваші запитання щодо архітектури чи технологічного стека

Підписатись на коментарі