Mosquitto TLS устанавливает лимит размера автозагрузки

Я реализовал незащищенного брокера от комаров, который фантастически работает, периодически отправляя большие объемы данных (~200 КБ раз в минуту) через порт 1883.

Поскольку я реализовал TLS, брокер, по-видимому, автоматически отклоняет данные>128 КБ через порт 8883, несмотря на установку message_size_limit = 0,

вот мой mosquitto.conf:

listener 1883 localhost

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

И вот мой сценарий, который используется для тестирования брокера, который отлично работает без TLS более 1883

client = mqtt.Client("test")
client.tls_set(certfile="./mqtt/cert.pem", keyfile="./mqtt/key.pem")
client.connect("example.com", 8883)

#publish file as zip
with open("./mqtt/20180319171000.gz", 'rb') as f:
    byte_array = f.read()
    m.update(byte_array)
    file_hash = m.hexdigest()
    payload_json = {'byte_array': byte_array, 'md5': file_hash}
    client.publish("topic", pickle.dumps(payload_json), 0)
time.sleep(1)
client.disconnect()

Есть ли ограничение на размер полезной нагрузки с TLS или что-то не так с моими настройками / сценарием?

2 ответа

Проблема здесь в том, что цикл клиента MQTT не запускается.

Когда полезная нагрузка больше, чем может поместиться в одном TCP-пакете, вызов необходимо поставить в очередь остальную часть сообщения, которое затем разбивается на несколько пакетов и отправляется через клиентский цикл.

Правильный ответ — не увеличивать период проверки активности. Есть 2 способа решить эту проблему с помощью библиотеки python Paho.

Во-первых, вы можете использовать класс Publish вместо класса Client. Сюда входит одна функция, которая обрабатывает все фоновые задачи, необходимые для доставки всего сообщения.

      import paho.mqtt.publish as publish

tls_opt = {
  'certfile':"./mqtt/cert.pem", 
  'keyfile':"./mqtt/key.pem"
}

with open("./mqtt/20180319171000.gz", 'rb') as f:
    byte_array = f.read()
    m.update(byte_array)
    file_hash = m.hexdigest()
    payload_json = {'byte_array': byte_array, 'md5': file_hash}
    publish.single("topic", payload=pickle.dumps(payload_json), qos=0, hostname="example.com", port=8883, tls=tls_opt)

Во-вторых, запустить сетевой цикл следующим образом:

      client = mqtt.Client("test")
client.tls_set(certfile="./mqtt/cert.pem", keyfile="./mqtt/key.pem")
client.connect("example.com", 8883)
client.loop_start()

#publish file as zip
with open("./mqtt/20180319171000.gz", 'rb') as f:
    byte_array = f.read()
    m.update(byte_array)
    file_hash = m.hexdigest()
    payload_json = {'byte_array': byte_array, 'md5': file_hash}
    client.publish("topic", pickle.dumps(payload_json), 0)
time.sleep(1)
client.loop_stop()
client.disconnect()

Старый вопрос, но у меня возникла та же проблема с большими сообщениями (>500 КБ). Мое решение состояло в том, чтобы увеличить время проверки активности на клиенте с (по умолчанию) 60 до 300 секунд.

Это, вероятно, связано с тем, что время ожидания для шифрования TLS для больших сообщений занимает больше времени, чем поддержка активности.

Изменить: добавлен код python для подключения:

      client.connect(
    host="example.com",
    port=8883,
    keepalive=300)

Обновление: я нашел этот вопрос в поисках ответов на проблему, похожую на мою, а именно: публикация MQTT не удалась для больших (>500 КБ) полезных лодов при использовании MQTT TLS. Как указывает @hardillb в своем ответе, OP отсутствует client.loop_start(). Однако это не решает мою проблему.

не должно влиять, но это не так. Увеличение значения определенно устраняет проблему. Моя теория заключается в том, что брокер прерывает соединение по тайм-ауту, потому что он пытается отправить PING клиенту, но клиент отказывается отвечать, потому что он занят попыткой зашифровать сообщение. Впрочем, это всего лишь теория.

Я создал тестовый код, чтобы проиллюстрировать проблему. Я также включил «последнюю волю», чтобы проверить, потеряно ли соединение без надлежащего разъединения (), и это, кажется, соответствует моей теории. Использование слишком малого значения определенно активирует последнюю волю к брокеру, указывая на «тайм-аут».

Увеличение не активирует «последнюю волю» у брокера.

Вот мой код, который я использовал для тестирования различных значений и размеров полезной нагрузки.

      import paho.mqtt.client as mqtt_client
import time
from datetime import datetime

password = 'somepassword'
user = 'someuser'
address = 'somebroker.no'
connected = False

def on_connect(client, userdata, flags, rc):
    global connected
    connected = True
    print("Connected!")

def on_disconnect(client, userdata, rc):
   global connected
   connected = False
   print("Disconnected!")

client = mqtt_client.Client()
client.username_pw_set(user, password)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
client.tls_set()

client.will_set(topic='tls_test/connected', payload='False', qos=0, retain=True)

client.connect(host=address, port=8883, keepalive=100)
client.loop_start()

while not connected:
    time.sleep(1)

topic = 'tls_test/abc'
payload = 'a'*1000000

start = time.time()
print('Start: {}'.format(datetime.fromtimestamp(start).strftime('%H:%M:%S')))

result = client.publish(topic='tls_test/connected', payload='True', qos=0, retain=True)
result = client.publish(topic=topic, payload=payload)

if result.rc != 0:
    print("MQTT Publish failed: {}".format(result.rc))
    exit()

client.loop_stop()
client.disconnect()

stop = time.time()
print('Stop:  {}, delta: {} sec'.format(datetime.fromtimestamp(stop).strftime('%H:%M:%S'), stop-start))

Используя приведенный выше код ( keepalive=100), он отправляет 1000000 байт и имеет значение Trueна брокера после окончания. Данные успешно переданы, вывод консоли:

      python3 .\mqtt_tls.py
Connected!
Start: 10:51:16
Disconnected!
Stop:  10:53:01, delta: 105.57992386817932 sec

Уменьшение активности ( keepalive=10), передача не удалась и tls_test/connectedимеет значение Falseна брокера после окончания. Передача данных не удалась, и вывод консоли:

      python3 .\mqtt_tls.py
Connected!
Start: 11:08:23
Disconnected!
Disconnected!
Stop:  11:08:43, delta: 19.537118196487427 sec

Хвост /var/log/mosquitto/mosquitto.logна брокере выдает следующее сообщение об ошибке:

      1612346903: New client connected from x.x.x.x as xxx (c1, k10, u'someuser').
1612346930: Socket error on client xxx, disconnecting.

Мой вывод таков: keepalive влияет на большие полезные нагрузки при использовании TLS

Другие вопросы по тегам