Ноя 122017
 

MQTT – это легковесный протокол сообщений, предназначенный для общения между устройствами (machine-to-machine) интернета вещей. Он используется для отслеживания перемещения транспортных средств, домашней автоматизации и сбора данных.

Mosquitto – это популярный MQTT-сервер (или брокер). Он прост в установке и настройке и активно поддерживается сообществом.

Данное руководство поможет установить Mosquitto, получить для него сертификат SSL от сервиса Let’s Encrypt и настроить безопасное взаимодействие устройств по MQTT.

Требования

1: Установка Mosquitto

В репозитории Ubuntu 16.04 можно найти сравнительно недавнюю версию Mosquitto. Чтобы установить Mosquitto, введите:

sudo apt-get install mosquitto mosquitto-clients

По умолчанию сервис Mosquitto запускается сразу после установки. Проверьте стандартные настройки. Для этого нужно подписаться на тему с помощью одного из клиентов Mosquitto.

Темы – это метки, которые присваиваются опубликованным заметкам. Они расположены в виде иерархии (например, sensors/outside/temp или sensors/outside/humidity). Упорядочивание тем полностью зависит от ваших потребностей.

Откройте ещё одну сессию терминала, в результате у вас должно быть два терминала. Запустите в новом терминале команду mosquitto_sub, чтобы подписаться:

mosquitto_sub -h localhost -t test

Флаг –h указывает имя хоста сервера MQTT, -t – тему. После запуска команды на экране не появится вывода, поскольку команда mosquitto_sub ждет получения сообщений. Вернитесь в первый терминал и опубликуйте сообщение:

mosquitto_pub -h localhost -t test -m "hello world"

Команда mosquitto_pub использует те же опции, что и mosquitto_sub, однако в этот раз используется дополнительный флаг –m (он позволяет ввести текст сообщения). Нажмите Enter, и вы увидите в другом терминале MQTT-сообщение hello world.

Введите во втором терминале CTRL+C, чтобы остановить mosquitto_sub, но не прерывайте подключения к серверу (оно понадобится позже).

Теперь нужно защитить трафик с помощью SSL-сертификата. Используйте Certbot, новый клиент Let’s Encrypt.

2: Установка Certbot

Let’s Encrypt – это новый сервис, предоставляющий бесплатные SSL-сертификаты при помощи автоматического API. Для взаимодействия с API существует несколько клиентов. Официальный клиент можно найти в репозитории Ubuntu, но он немного устарел и не предоставляет всех необходимых функций.

Вместо него мы используем официальный клиент из PPA Ubuntu, где можно найти более новые версии программ.

Добавьте репозиторий:

sudo add-apt-repository ppa:certbot/certbot

Нажмите Enter, чтобы продолжить. После этого обновите индекс пакетов.

sudo apt-get update

Установите Certbot:

sudo apt-get install certbot

3: Запуск Certbot

Чтобы подтвердить права на домен, Certbot должен пройти криптографический тест интерфейса Let’s Encrypt. Для этого используются порты 80 (HTTP) и/или 443 (HTTPS). В руководстве используется только порт 80. Разблокируйте его в брандмауэре.

sudo ufw allow http
Rule added

Теперь можно запустить Certbot, чтобы получить сертификат. Используйте опцию –standalone, чтобы Certbot самостоятельно обрабатывал тестовый запрос HTTP. Опция —standalone-supported-challenges http-01 ограничивает взаимодействие с интерфейсом портом 80. Опция -d позволяет указать домен, для которого предназначен сертификат, а certonly извлекает сертификат.

sudo certbot certonly --standalone --standalone-supported-challenges http-01 -d mqtt.example.com

После запуска команды будет предложено указать адрес электронной почты и принять условия предоставления услуг. На экране появится сообщение, указывающее, где хранятся сертификаты.

4: Автоматическое обновление сертификата

Сертификаты Let’s Encrypt действительны в течение 90 дней. По истечении этого срока пользователь должен обновить сертификат. Вы можете настроить автоматическое обновление сертификатов.

Чтобы ежедневно запускать команду для проверки и обновления сертификата, используйте cron. Откройте crontab в редакторе:

sudo crontab -e

Выберите текстовый редактор. На экране появится crontab по умолчанию. Вставьте следующую строку в конец файла:

. . .
15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"

Часть строки «15 3 * * *» значит, что команду нужно запускать в 3:15 утра каждый день. Команда renew будет проверять все существующие сертификаты и обновлять их по мере необходимости (если до окончания срока действия остается меньше 30 дней). Флаг –noninteractive запускает процесс в немом режиме.

Флаг —post-hook «systemctl restart mosquitto» перезапустит Mosquitto, чтобы загрузить новый сертификат (только если сертификат был обновлен). Опции post-hook нет ни в одном клиенте Let’s Encrypt, кроме Certbot. Без неё вам пришлось бы самостоятельно перезапускать Mosquitto каждый день.

5: Настройка пароля MQTT

Теперь настройте пароль для Mosquitto.

Mosquitto предоставляет утилиту mosquitto_passwd для генерирования файла паролей. Эта команда предложит ввести пароль для указанного пользователя и поместит результат в /etc/mosquitto/passwd.

sudo mosquitto_passwd -c /etc/mosquitto/passwd 8host

Откройте конфигурационный файл Mosquitto и добавьте информацию о новом файле паролей:

sudo nano /etc/mosquitto/conf.d/default.conf

На экране появится пустой файл. Введите:

allow_anonymous false
password_file /etc/mosquitto/passwd

Строка allow_anonymous false блокирует доступ анонимных пользователей. Строка password_file указывает путь к файлу паролей. Сохраните и закройте файл.

Перезапустите Mosquitto:

sudo systemctl restart mosquitto

Теперь нужно протестировать новые настройки. Попробуйте опубликовать сообщение без пароля:

mosquitto_pub -h localhost -t "test" -m "hello world"

Сервер должен отклонить сообщение:

Connection Refused: not authorised.
Error: The connection was refused.

Перейдите во второй терминал и подпишитесь на тему test.

mosquitto_sub -h localhost -t test -u "8host" -P "password"

Оставьте этот терминал открытым до конца руководства, чтобы периодически отправлять в него тестовые сообщения.

Вернитесь в первый терминал и опубликуйте сообщение:

mosquitto_pub -h localhost -t "test" -m "hello world" -u "8host" -P "password"

Сообщение появится во втором терминале. Если это так, то настройка пароля Mosquitto прошла успешно.

Пока что пароли передаются в незашифрованном виде. Чтобы исправить это, нужно настроить Mosquitto для поддержки SSL-шифрования.

6: Настройка поддержки SSL

Чтобы настроить шифрование, нужно изменить права на сертификаты Let’s Encrypt.

Процесс mosquitto запускается не через root, а через пользователя mosquitto из соображений безопасности. Но для чтения сертификатов SSL нужны права root.

Чтобы не изменять владельца файлов, добавьте сертификаты в группу mosquitto:

sudo chgrp -R mosquitto /etc/letsencrypt/archive/mqtt.example.com/

Команда chgrp -R обновит группу указанного каталога и всех файлов в нём. Однако Certbot, обновляя сертификаты, будет создавать новые файлы, которые будут принадлежать root, а при перезапуске Mosquitto будет возникать ошибка.

Чтобы исправить это, нужно установить SGID на каталог сертификатов. SGID – это параметр прав доступа, который передаёт права root другой группе (в данном случае mosquitto).

sudo chmod g+s /etc/letsencrypt/archive/mqtt.example.com/

Убедитесь, что изменения вступили в силу:

sudo ls -al /etc/letsencrypt/archive/mqtt.example.com/

В каталоге должен быть установлен бит SGID.

drwxr-sr-x 2 root mosquitto 4096 Oct 5 17:48 .

В привилегиях (последовательности drwxr-sr-x) есть символ s. Каталог должен принадлежать группе mosquitto.

Попробуйте также запросить права группы mosquitto на сертификаты.

-rw-r--r-- 1 root mosquitto 1809 Oct 1 16:42 cert1.pem

Если все установлено верно, можно обновить конфигурации Mosquitto. Откройте конфигурационный файл:

sudo nano /etc/mosquitto/conf.d/default.conf

Добавьте в него:

. . .
listener 1883 localhost
listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem

Теперь файл содержит два отдельных блока listener. Первый, listener 1883 localhost, обновляет прослушиватель MQTT
на порте 1883 (это стандартный нешифрованный порт MQTT). Часть строки localhost привязывает этот порт к интерфейсу локального хоста, потому к нему не будет внешнего доступа (в любом случае, внешние запросы заблокировал бы брандмауэр).

Строка listener 8883 настраивает зашифрованный прослушиватель на порт 8883. Это стандартный порт MQTT + SSL (также называется MQTTS). Следующие три строки, certfile, cafile и keyfile указывают Mosquitto путь к файлам сертификата Let’s Encrypt.

Сохраните и закройте файл. Перезапустите Mosquitto:

sudo systemctl restart mosquitto

Откройте порт 8883 в брандмауэре.

sudo ufw allow 8883
Rule added

Создайте ещё одно тестовое сообщение с помощью mosquitto_pub, добавив несколько опций для SSL:

mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --capath /etc/ssl/certs/ -u "8host" -P "password"

Обратите внимание: вместо localhost используется полное имя хоста. Поскольку сертификат SSL предназначен для домена (в данном случае для mqtt.example.com), при попытке подключиться к localhost вы получите ошибку: имя хоста не совпадает с именем хоста сертификата (несмотря на то, что оба они указывают на один сервер Mosquitto).

Опция —capath /etc/ssl/certs/ включает SSL для mosquitto_pub и сообщает, где найти root-сертификаты. Путь зависит от операционной системы. Команда mosquitto_pub проверяет подпись сертификата сервера Mosquitto. Команды mosquitto_pub и mosquitto_sub не смогут создать SSL-соединение без этой опции (или её аналога, —cafile) даже с помощью стандартного порта 8883.

Если настройка выполнена правильно, во втором терминале появится сообщение «hello again». MQTT-сервер полностью готов к работе.

7: Поддержка веб-сокетов (опционально)

Для взаимодействия с JavaScript в браузерах в протокол MQTT была добавлена поддержка стандартных веб-сокетов.

Чтобы включить эту функцию, нужно добавить ещё один блок listener в настройки Mosqiutto:

sudo nano /etc/mosquitto/conf.d/default.conf

Добавьте в конец файла:

. . .
listener 8083
protocol websockets
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem

Этот блок почти такой же, как предыдущие, он отличается толлько номером порта и строкой protocol websockets. У MQTT нет стандартного порта для поддержки веб-сокетов, обычно для этого используется 8083.

Сохраните и закройте файл. Перезапустите сервер:

sudo systemctl restart mosquitto

Откройте этот порт в брандмауэре:

sudo ufw allow 8083

Чтобы протестировать эту настройку, используйте открытый MQTT-клиент для браузера (например, mqtt-admin). Откройте mqtt-admin в браузере.

На экране появится окно настроек.

Заполните предложенные поля:

  • Protocol: wss (что значит websocket secure).
  • Host: домен сервера Mosquitto.
  • Port: 8083.
  • User: имя пользователя Mosquitto (в данном случае 8host).
  • Password: пароль.
  • ClientId: можно оставить по умолчанию (mqtt-admin).

Нажмите Save Settings, после чего mqtt-admin подключится к серверу Mosquitto. В следующем окне укажите:

  • Topic: test
  • Payload: введите любое сообщение

Нажмите Publish. Сообщение должно появиться в терминале mosquitto_sub.

Заключение

Сервер MQTT установлен, защищен паролем и готов к работе. SSL-сертификат Let’s Encrypt шифрует трафик и автоматически обновляется. Теперь у вас есть надёжная платформа для обмена сообщениями.

С протоколом MQTT хорошо работают следующие программы:

  • OwnTracks – открытое приложение геолокации, которое можно установить на телефон. Полученные данные можно переносить на карту, на их основе можно создавать предупреждения и настроить запуск компонентов интернета вещей.
  • Node-RED – графический веб-интерфейс для настройки интернета вещей. Инструмент позволяет перенаправлять вывод одной ноды на ввод другой, фильтровать данные, применять разные протоколы и базы данных и многое другое.
  • ESP8266 – недорогой wifi микроконтроллер с поддержкой MQTT. С его помощью вы можете следить за температурой, атмосферным давлением и т.п.
Понравилось? Поделитесь:

:

Sorry, the comment form is closed at this time.