Подключите Shelly к RabbitMQ через MQTT mTLS.
Краткое описание
[править]Это решение обеспечивает безопасное подключение IP-устройства Shelly к RabbitMQ через плагин MQTT с использованием взаимного TLS (mTLS), без паролей, с применением взаимной аутентификации на основе сертификатов. Один скрипт Bash устанавливает и настраивает RabbitMQ, генерирует частный центр сертификации (CA), сертификаты сервера и клиента, а затем отображает таблицу значений конфигурации. После завершения единственного ручного действия на Shelly — это загрузка ca.crt , client.crt и client.key , копирование этих значений в настройки MQTT и сохранение. Поддерживает выбор серий RabbitMQ ( --rmq-series 3.13|4.0|4.1 , по умолчанию 4.1) из репозиториев Ubuntu noble от Team RabbitMQ и принудительно использует только TLS 1.2. В версии 4.x идентификатор клиента MQTT (client_id) определяется на основе сертификата (SAN, URI), в то время как аутентифицированное имя пользователя (username) по-прежнему определяется на основе сертификата (CN); в версии 3.13 привязка SAN->client_id недоступна. Вы можете управлять хостом подключения (и CN/SAN сертификата сервера) с помощью --connect-dns / --connect-ip . Скрипт экспортирует сертификаты устройств в /etc/mqtt-cert
и по умолчанию также выдает сертификат монитора (-mon ) в /etc/mqtt-cert-monitor с архивами в /tmp/. Результат: зашифрованный MQTT с аутентификацией по сертификату и доступом к темам с минимальными привилегиями.
Ссылка на скрипт: здесь
Важно:
Этот скрипт предназначен только для разработки/тестирования, являясь примером того, что возможно. Используйте с осторожностью и не развертывайте в продакшене в неизмененном виде.
Архитектура
[править]СХЕМА
[Устройство Shelly] |
| MQTT через TLS (mTLS) - порт 8883 v [Слушатель RabbitMQ MQTT] ---> [обмен amq.topic] ---> [очереди/подписки] | |
| ‘-- ACL тем, ограниченные вашим префиксом MQTT |
«-- Пользовательский интерфейс управления (HTTPS, 15671)
- Транспорт: Shelly взаимодействует с RabbitMQ по порту 8883 (MQTTS). Требуется TLS; клиенты должны предоставить действительный сертификат (mTLS), принудительно используется только TLS 1.2.
- Идентификация: Сертификат устройства CN сопоставляется с пользователем RabbitMQ (в Shelly нет имени пользователя/пароля).
- Привязка идентификатора клиента: Принудительно осуществляется из SAN сертификата (URI) в RabbitMQ 4.x. Имя пользователя по-прежнему берется из CN; версия 3.13 не поддерживает SAN→client_id.
» * Авторизация: Списки контроля доступа к темам ограничены выбранным вами префиксом MQTT (плюс доступ только для чтения к shellies/command для совместимости).
- Арендаторство: MQTT не передает виртуальные хосты, поэтому соединения направляются на выделенный виртуальный хост (например, /shelly ) через mqtt.vhost .
- Управление: HTTPS-интерфейс на 15671.
- Порты без ограничений: По умолчанию отключено. Вы можете временно сохранить 1883/15672 с помощью --keep-plaintext во время миграции.
Краткая справка
[править]| Внимание! Решение | |
|---|---|
| Порт (данные) | 8883 / TCP (MQTTS с mTLS) |
| Порт (администратор) | 15671 / TCP (интерфейс управления HTTPS) |
| Идентификатор | CN сертификата -> пользователь RabbitMQ |
| Идентификатор клиента | Предоставляется пользователем в Shelly; в RabbitMQ 4.x он определяется из SAN сертификата (URI). В версии 3.13 привязка SAN -> client_id недоступна |
| Vhost | /shelly (устанавливается через mqtt.vhost) |
| Темы | Ограничено вашим префиксом MQTT (как в форме косой черты, так и в форме точки), а также shellies/command только для чтения (shellies.command) |
| Секреты на устройстве | Только ключ клиента (без паролей) |
| Открытый текст | По умолчанию отключено; можно включить с помощью --keep-plaintext |
| Версия TLS | Только TLS 1.2 |
Предварительные условия
[править]- Протестированная среда (на момент написания): Ubuntu 24.04 LTS (amd64), RabbitMQ 4.1 (установлен с помощью этого скрипта), прошивка Shelly 1.7.1.
- Установка: из репозиториев Team RabbitMQ, закрепленных в Ubuntu noble.
- Доступ: Оболочка на хосте с правами sudo; исходящий интернет для репозиториев apt.
- Адресация: Стабильный IP-адрес/DNS брокера (скрипт может автоматически определять, фиксированный лучше).
- Синхронизация времени: NTP включен (действительность сертификата зависит от правильного времени).
- Необязательно: mosquitto-clients для быстрого сквозного тестирования.
Что делает скрипт
[править]- Установка RabbitMQ (3.13 / 4.0 / 4.1) + соответствующий Erlang на Ubuntu 24.04 Использует репозитории apt Team RabbitMQ (рекомендуемый путь) для получения современного Erlang/RabbitMQ. https://www.rabbitmq.com/docs/install-debian
- Настройка через rabbitmq.conf (а не rabbitmq-env.conf) Настройки среды выполнения (слушатели, TLS, плагины) находятся в rabbitmq.conf; rabbitmq-env.conf предназначен только для переменных окружения. https://www.rabbitmq.com/docs/configure
- Включить плагины MQTT + управления Включает встроенную поддержку MQTT и управление/пользовательский интерфейс HTTPS, а также активирует rabbitmq_auth_mechanism_ssl. https://www.rabbitmq.com/docs/mqtt Включить флаг функции detailed_queues_endpoint (подробная информация о очередях только в пользовательском интерфейсе).
- Принудительное использование взаимного TLS (mTLS) для MQTT Устанавливает ssl_options.verify = verify_peer и ssl_options.fail_if_no_peer_cert = true, поэтому клиенты должны предоставлять действительный сертификат; принудительно использует только TLS 1.2. https://www.rabbitmq.com/docs/mqtt#tls
- Вход по сертификату без пароля (CN → пользователь) Включает mqtt.ssl_cert_login = true и ssl_cert_login_from = common_name. Сопоставленный пользователь должен существовать в RabbitMQ (пароль не требуется). https://www.rabbitmq.com/docs/mqtt#tls-certificate-authentication
- Привязка client_id MQTT к SAN сертификата (URI) В RabbitMQ 4.1 устанавливает
BASH
mqtt.ssl_cert_client_id_from = subject_alternative_name
таким образом, CONNECT client_id
должен совпадать с SAN сертификата (предотвращает подмену идентификатора).
Это привязывает client_id к сертификату SAN (URI) .
Имя пользователя по-прежнему берется из CN
- если вы хотите, чтобы
имя пользователя было из SAN
вместо этого, вам следует изменить ssl_cert_login_from=subject_alternative_name и ssl_cert_login_san_type=uri
в конфигурации.
- Выдача двух клиентских сертификатов (один и тот же CN, разные SAN) * устройство: SAN=URI:
- монитор: SAN=URI: -mon
- Профили сертификатов : CA RSA-4096; сервер/клиент RSA-2048; срок действия конечного сертификата ≈ 825 дней
Позволяет подписаться на сертификат монитора без отключения устройства (различные идентификаторы клиентов).
- Блокировка прослушивателей и портов * MQTTS: 8883
- Управление (HTTPS): 15671
- Обычный 1883/15672 отключен по умолчанию; опционально при миграции с помощью --keep-plaintext. https://www.rabbitmq.com/docs/networking
- Создание арендатора и разрешений * Направляет MQTT-сессии на /shelly (через mqtt.vhost). https://www.rabbitmq.com/docs/vhosts
- Применяет разрешения для темы, так что публикация/подписка ограничена вашим префиксом MQTT (плюс shellies/command только для чтения). https://www.rabbitmq.com/docs/man/rabbitmqctl.8#Access_control
- Удаляет пользователя guest по умолчанию.
- Если set_topic_permissions недоступен в вашем RabbitMQ, скрипт выдаст предупреждение и оставит более широкий доступ к теме до обновления.
- Вывод, используемый на Shelly Создает папку экспорта с файлами ca.crt, client.crt, client.key и выводит таблицу точных значений для копирования в настройки Shelly MQTT.
Реализация
[править]- Запуск скрипта
BASH
./shelly-rmq-mqtt/setup-mqtt-mtls.sh \ --admin-user admin \ --admin-pass 'Sh3lly-i0T!' \ -C 'Shelly-Group' \ --client-id 'test-device' \ --vhost /shelly \ --mqtt-prefix 1pm-mini
Приоритет хоста подключения (и CN сертификата):
--connect-dns > --connect-ip > --ip (автоматически определяется, если нет). Выбранное значение становится сертификатом сервера CN
и тем, на который должны набираться клиенты. Полезные флаги (при необходимости)
BASH
Идентификатор / Целевой адрес подключения (на который набираются клиенты; определяет CN/SAN сертификата) --connect-dns
- предпочтительно: клиенты набирают это имя
--connect-ip
- клиенты набирают этот IP-адрес (если нет DNS)
Идентификатор хоста (эта машина) -i | --ip | --server-ip
- переопределяет обнаруженный основной IP-адрес (используется в сводке и SAN)
MQTT / аренда / темы -V | --vhost
- по умолчанию /shelly
--mqtt-prefix
- область действия ACL для тем
Сертификаты / выходные данные --tls-dir
- по умолчанию /etc/rabbitmq-tls
--export-dir
- по умолчанию /etc/mqtt-cert
--monitor-export-dir
- по умолчанию /etc/mqtt-cert-monitor
--no-monitor-cert # пропустить -mon bundle --monitor-client-id
- по умолчанию
-mon --force-regen # ротация CA/сервера/клиента, даже если присутствует
Версионирование RabbitMQ --rmq-series 3.13|4.0|4.1 # по умолчанию 4.1
Аутентификация / пользователи --admin-user
- администратор по умолчанию
-p | --admin-pass
- автоматически генерируется по умолчанию, если опущено
-C | --client-cn
- Группа Shelly по умолчанию
--client-id
- по умолчанию =
Сеть (временная совместимость) --keep-plaintext # оставить открытыми порты 1883/15672 во время миграции
Ведение логов / диагностика -l | --log-level debug|info|warn|error -d | --debug # потоковые логи; без индикатора загрузки --debug-tls | --tls-debug # вывести диагностику сертификата (или DEBUG_TLS=1)
Скрипт будет запущен и будет проходить каждый шаг, отображая индикатор успеха и ошибку, если она возникнет.
Шаги скрипта
После завершения обратите внимание на сводную таблицу внизу:
- IP-адрес/порты брокера
- ID клиента и префикс MQTT
- Пути к ca.crt, client.crt, client.key (папка экспорта)
- Параметры конфигурации Shelly
- URL управления: https:// :15671 (или https:// :15671, если CN — IP-адрес)
- Имя пользователя и пароль администратора (пароль генерируется автоматически, если не указан параметр --admin-pass)
- Путь к файлу журнала: /tmp/rabbitmq-mqtt-setup.log
- Загрузка сертификатов в Shelly Откройте Веб-интерфейс Shelly → Настройки → Конфигурация TLS. Загрузите три файла из папки экспорта скрипта: * Сертификат CA: ca.crt
- Сертификат клиента: client.crt
- Закрытый ключ клиента: client.key. Загрузите каждый файл по отдельности: выберите файл, нажмите «Загрузить» и дождитесь всплывающего окна с подтверждением успешной загрузки. Повторите для всех трех файлов.
- Настройка Shelly MQTT Откройте веб-интерфейс Shelly → Настройки → MQTT. Настройте значения из скрипта:
ТЕКСТ
Включить: Выбрано TLS пользователя: Выбрано Использовать сертификат клиента: Включено Включить «Управление MQTT»: Включено Включить RPC через MQTT: Включено Уведомления о состоянии RPC через MQTT: Включено Общее обновление состояния через MQTT: Включено Сервер: Значение из скрипта Идентификатор клиента: Значение из скрипта Префикс MQTT: Значение из скрипта Имя пользователя / Пароль: Оставьте пустым
- Нажмите «Сохранить настройки» и перезагрузите устройство
После завершения настройки устройство должно выглядеть следующим образом:
Веб-интерфейс настройки MQTT Shelly
- После перезагрузки Shelly выполните команду мониторинга, которая отображается в сводке скрипта. Она автоматически генерируется на основе предоставленных вами значений и использует сертификат монитора (distinct client_id), поэтому устройство не будет отключено. Вы должны увидеть сообщения, поступающие от Shelly к RabbitMQ.
Готовность к выполнению команды мониторинга
Вы должны увидеть, как Shelly подключается и публикует сообщения.
Мониторинг сообщений Shelly в RabbitMQ
Вы также можете подтвердить успешное подключение в веб-интерфейсе Shelly: значок MQTT в правом верхнем углу показывает две стрелки при подключении. Если вы видите стрелки, устройство активно связано с RabbitMQ по протоколу MQTT/TLS.
Индикатор успешного подключения Shelly MQTT
Вы также можете увидеть индикатор в веб-интерфейсе RabbitMQ в разделе «Подключения».
Файл:RabbitMQ Web UI Connection info.png
Статус подключения в веб-интерфейсе RabbitMQ
Информация о подключении в веб-интерфейсе RabbitMQ
Скрипт также выводит сводку отладки сертификатов, помогая вам увидеть, какие сертификаты были сгенерированы, чтобы минимизировать возможные проблемы. Пожалуйста, имейте в виду, что вам необходимо использовать
--debug-tls флаг
.
Устранение неполадок
[править]- Синхронизация времени - Убедитесь, что часы брокера и Shelly установлены правильно (NTP). Искажение времени нарушает работу TLS.
- Загружены три файла - ca.crt, client.crt, client.key (каждый загружен отдельно, всплывающее окно об успешной загрузке).
- Идентификатор клиента против SAN - В RabbitMQ 4.1 идентификатор клиента MQTT должен совпадать с SAN (URI) сертификата. Если они различаются, соединение отклоняется. * В RabbitMQ 3.13 привязка client_id из SAN не поддерживается; используется только CN->username.
- CN user exists - Сертификат CN должен соответствовать существующему пользователю RabbitMQ (пароль не требуется при использовании mTLS).
- Ports - Используйте 8883 (MQTTS). Порты 1883/15672 отключены, если вы не запускали скрипт с параметром --keep-plaintext.
- Firewall - Если UFW активен, скрипт открывает порты 8883 и 15671; в противном случае он не изменяет правила брандмауэра.
- Prefix - Темы должны находиться в пределах вашего префикса MQTT, иначе ACL RabbitMQ заблокируют их.
- Совпадение ключа и сертификата: Если соединение не удается, запустите с параметром --debug-tls и проверьте строку «совпадение ключа и сертификата» как для сервера, так и для клиента.


