Конфиденциальность и защита данных в системах автоматизации HI
COURSE-16-M04-L07 — Конфиденциальность и защита данных в системах автоматизации HI
Введение в кибербезопасность IoT
В современных системах автоматизации, от умного дома до небольшого промышленного объекта, контроллер является цифровым сердцем системы. Он собирает, обрабатывает и передает данные, которые могут быть крайне чувствительными: графики присутствия людей, данные о потреблении ресурсов, статусы систем безопасности. Компрометация этих данных или самого контроллера может привести не только к нарушению конфиденциальности, но и к прямому физическому ущербу, финансовым и репутационным потерям.
Данный урок посвящен практическим методам защиты контроллера HI и всей экосистемы на его базе. Мы рассмотрим модель угроз, специфичную для нашей платформы, и пошагово разберем обязательные меры по обеспечению безопасности на уровне операционной системы, среды исполнения Node-RED, протоколов связи и логики сценариев.
Модель угроз для платформы HI
Для эффективной защиты необходимо понимать, откуда исходит угроза. Для типового объекта на базе контроллера HI можно выделить четыре основных вектора атак:
* Веб-интерфейс редактора Node-RED (порт 1880).
* Интерфейс Node-RED Dashboard (порт 1880/ui).
* MQTT-брокер (порт 1883/8883).
* База данных MySQL (порт 3306).
* Modbus RTU/TCP: Протокол не имеет встроенных средств аутентификации. Любой, кто подключен к шине RS-485 или к сети, может отправлять команды устройствам.
* Незащищенные API: Интеграция с облачными сервисами или устройствами по HTTP без шифрования (TLS) и аутентификации (API-ключи).
💡 Совет: При проектировании системы всегда исходите из принципа «нулевого доверия» (Zero Trust). Не доверяйте ни одному устройству или пользователю по умолчанию, даже если они находятся в локальной сети.
Практические меры защиты на уровне контроллера HI
Ниже приведен обязательный набор действий для обеспечения базового уровня безопасности контроллера. Эти шаги должны выполняться на каждом объекте перед сдачей в эксплуатацию.
1. Защита операционной системы (Debian Linux)
Контроллер HI работает под управлением Debian. Его защита — первый и самый важный рубеж обороны.
- Смена пароля по умолчанию: Сразу после первого входа в систему через SSH смените пароль пользователя `admin` (или другого стандартного пользователя). Используйте сложный пароль (минимум 12 символов, буквы, цифры, спецсимволы).
passwd
- Настройка межсетевого экрана: Используйте `ufw` (Uncomplicated Firewall) для ограничения доступа к портам контроллера извне.
# Установка (если не установлен)
sudo apt-get install ufw
# Запрещаем все входящие соединения по умолчанию
sudo ufw default deny incoming
# Разрешаем все исходящие
sudo ufw default allow outgoing
# Разрешаем доступ к SSH (порт 22) только из локальной сети
sudo ufw allow from 192.168.1.0/24 to any port 22
# Разрешаем доступ к Node-RED (порт 1880) только из локальной сети
sudo ufw allow from 192.168.1.0/24 to any port 1880
# Разрешаем доступ к защищенному MQTT (порт 8883)
sudo ufw allow 8883
# Включаем firewall
sudo ufw enable
- Установка `fail2ban`: Эта утилита автоматически блокирует IP-адреса, с которых производятся многократные неудачные попытки входа, защищая от атак перебором (brute-force).
sudo apt-get install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
2. Защита среды исполнения Node-RED
По умолчанию редактор Node-RED доступен любому пользователю в сети. Это необходимо исправить.
* Отредактируйте файл конфигурации `settings.js`, который обычно находится в директории `~/.node-red/`.
* Раскомментируйте и заполните секцию `adminAuth`. Для генерации хеша пароля используйте утилиту `node-red-admin hash-pw`.
// В файле settings.js
adminAuth: {
type: "credentials",
users: [{
username: "admin",
password: "$2a$08$zZWtXTajcPeGpt54WOKhAeVw.LgC5j7yC1Kx.o.d2prVpFAf/fI.S", // Замените на ваш хеш
permissions: "*"
}]
},
* Сгенерируйте самоподписанный сертификат или используйте сертификат от Let's Encrypt.
* Раскомментируйте и настройте секцию `https` в `settings.js`.
// В файле settings.js
https: {
key: require("fs").readFileSync('privkey.pem'),
cert: require("fs").readFileSync('fullchain.pem')
},
3. Защита протоколов связи
- MQTT: Никогда не используйте MQTT-брокер без аутентификации и шифрования.
* Шифрование (TLS): Включите опцию "Использовать TLS" и предоставьте сертификаты. Это переключит брокер на защищенный порт 8883.
- ⚠️ Modbus (RTU/TCP): Помните, что протокол Modbus не поддерживает шифрование или аутентификацию.
* Шлюз: Если требуется удаленный доступ к Modbus-устройствам, он должен осуществляться исключительно через контроллер HI, который выступает в роли защищенного шлюза, а не напрямую.
4. Безопасность на уровне потоков (Flows)
Даже при защищенной инфраструктуре, уязвимости в логике потоков могут привести к проблемам. Здесь мы применяем паттерны Академии HI.
- Валидация входных данных (Паттерн "Контракт сообщения"): Любые данные, приходящие извне (от MQTT, HTTP, Dashboard), должны проходить строгую проверку перед исполнением.
Пример: Управление реле через MQTT. Топик `commands/relay/1/set`, сообщение `{"value": true}`.
// Код в узле Function после MQTT In
// 1. Проверяем структуру сообщения
if (typeof msg.payload !== 'object' || typeof msg.payload.value !== 'boolean') {
node.error("Неверный формат команды: " + JSON.stringify(msg.payload), msg);
node.status({fill:"red", shape:"dot", text:"Invalid command"});
return null; // Прерываем поток
}
// 2. Проверяем права (если нужно)
// Например, проверяем, что команда пришла от доверенного источника
// if (msg.payload.source !== "trusted_app") { ... }
// 3. Если все в порядке, формируем команду для реле
let relayId = parseInt(msg.topic.split('/')[2]);
// ... дальнейшая логика
node.status({fill:"green", shape:"dot", text:"Command OK"});
return msg;
- Аудит и журналирование критичных действий: Все значимые события должны записываться в надежное хранилище (например, в базу данных MySQL на контроллере) для последующего анализа инцидентов.
Пример: Запись в лог факта открытия электронного замка.
// Код в узле Function перед отправкой команды на реле замка
let user = msg.payload.user || "unknown";
let action = "UNLOCK";
// Формируем SQL-запрос
msg.topic = `INSERT INTO audit_log (timestamp, actor, action, target) VALUES (NOW(), '${user}', '${action}', 'main_door');`;
// Отправляем на узел mysql
return msg;
Лабораторные работы
COURSE-16-M04-LAB13: Базовая защита контроллера HI
Задача: Установить пароль на редактор Node-RED и настроить базовые правила межсетевого экрана `ufw`. Оборудование: Контроллер HI, компьютер в той же сети. Порядок выполнения:- [5 баллов] Доступ к редактору Node-RED защищен паролем.
- [5 баллов] Межсетевой экран `ufw` активен и настроен на ограничение доступа к портам 22 и 1880.
COURSE-16-M04-LAB14: Создание безопасного потока с аудитом
Задача: Реализовать поток для управления реле (например, имитирующим замок) через MQTT с валидацией команды и записью всех действий в лог-файл. Оборудование: Контроллер HI с настроенным Node-RED. Flow Diagram (ASCII):[mqtt in] --> [function: Validate & Audit] --+--> [debug: Valid Command]
(commands/lock/set) |
+--> [file out: audit.log]
'--> [rpi gpio out: Lock Relay]
Порядок выполнения:
// Ожидаемый контракт: msg.payload = {"action": "OPEN", "user": "admin"}
const payload = msg.payload;
// 1. Валидация
if (typeof payload !== 'object' || (payload.action !== "OPEN" && payload.action !== "CLOSE")) {
node.error("Неверная команда для замка!", msg);
return null; // Прерываем поток
}
const user = payload.user || "unknown";
const timestamp = new Date().toISOString();
// 2. Формирование записи для аудита
const log_entry = `${timestamp} | USER: ${user} | ACTION: ${payload.action} | TARGET: Main Lock\n`;
// 3. Подготовка сообщения для разных выходов
// Выход 1: Команда на реле
const relay_msg = { payload: (payload.action === "OPEN") ? 1 : 0 };
// Выход 2: Запись в лог
const log_msg = { payload: log_entry };
// У узла Function должно быть 2 выхода
return [relay_msg, log_msg];
* Реле срабатывает только на корректные команды.
* В файле `audit.log` появляются записи о действиях.
* В логе отладки Node-RED появляются ошибки при неверных командах.
Рубрика оценивания:- [3 балла] Поток корректно принимает команды по MQTT.
- [4 балла] Реализована валидация входящего сообщения, некорректные команды отбрасываются.
- [3 балла] Все успешные действия записываются в лог-файл с указанием времени, пользователя и действия.
Тест для самопроверки (Квиз)
ID: `COURSE-16-M04-QUIZ`a) `firewalld`
b) `iptables`
c) `ufw`
d) `netstat`
a) Запускает Node-RED с правами администратора.
b) Генерирует хеш пароля для файла `settings.js`.
c) Устанавливает пароль на операционную систему.
d) Хеширует все потоки для безопасности.
a) Низкая скорость передачи данных.
b) Отсутствие встроенных механизмов аутентификации и шифрования.
c) Сложность настройки.
d) Ограничение на 32 устройства на шине.
a) Для шифрования сообщений между узлами.
b) Для стандартизации структуры `msg.payload` и валидации данных на входе.
c) Для автоматического подписания юридических контрактов.
d) Для сжатия данных перед отправкой по сети.
a) 1883
b) 8883
c) 502
d) 8080
a) Перезагрузить контроллер.
b) Отключить контроллер от сети.
c) Отредактировать `settings.js` и установить пароль для `adminAuth`.
d) Проверить логи на предмет взлома.
a) Для резервного копирования данных.
b) Для защиты от атак типа "отказ в обслуживании" (DoS).
c) Для автоматической блокировки IP-адресов после нескольких неудачных попыток входа.
d) Для шифрования файловой системы.
a) `mqtt out`
b) `http request`
c) `mysql`
d) `file out`
a) Собирать как можно больше данных "на всякий случай".
b) Хранить данные в открытом виде для легкого доступа.
c) Применять принцип минимизации данных: собирать и хранить только то, что абсолютно необходимо для работы функции.
d) Передавать все данные в облако для анализа.
a) `sudo ufw allow 22`
b) `sudo ufw allow from any to any port 22`
c) `sudo ufw allow from 192.168.1.0/24 to any port 22`
d) `sudo ufw deny 22`
(Ответы: 1-c, 2-b, 3-b, 4-b, 5-b, 6-c, 7-c, 8-c, 9-c, 10-c)Мини-runbook «Если что-то пошло не так»
📋 Симптом: Не могу зайти в редактор Node-RED после установки пароля.
- Возможная причина: Опечатка в пароле или синтаксическая ошибка в `settings.js`.
- Диагностика:
2. Проверьте лог Node-RED: `sudo journalctl -f -u nodered`. Ищите ошибки при запуске.
3. Если Node-RED не запускается, временно закомментируйте секцию `adminAuth` в `settings.js` и перезапустите сервис. Если запустился — ошибка была в этой секции.
4. Сгенерируйте хеш пароля заново и аккуратно вставьте его.
📋 Симптом: Команды по MQTT не проходят, хотя брокер и клиенты настроены.
- Возможная причина: Межсетевой экран `ufw` блокирует порт 1883 или 8883.
- Диагностика:
2. Убедитесь, что для нужного MQTT-порта (1883 для обычного, 8883 для TLS) есть правило `ALLOW`.
3. Если правила нет, добавьте его: `sudo ufw allow 1883`.
📋 Симптом: Поток, управляющий реле, не срабатывает на команду, хотя в логе `mqtt in` видно, что сообщение приходит.
- Возможная причина: Сработал узел валидации (`function`), который отбросил некорректное сообщение.
- Диагностика:
2. Отправьте команду еще раз и посмотрите, какое сообщение об ошибке выводит `node.error()`.
3. Сравните структуру отправляемого вами JSON с той, что ожидается в коде валидации. Скорее всего, есть несоответствие в именах полей или типах данных.