Broker testleri

Wireshark ile MQTT hata ayıklama: her paketi okuyun

MQTT trafiğini Wireshark'ta yakalayıp çözümleyin: CONNECT, PUBLISH ve CONNACK filtreleri, 8883 portunda key log ile TLS şifre çözme ve tshark tarifleri.

Güncellendi · 9 dk okuma

Wireshark ile MQTT hata ayıklama: her paketi okuyun

Loglar bir istemcinin ne gönderdiğini düşündüğünü söyler. Paket yakalama ise hatta gerçekte neyin geçtiğini gösterir. Wireshark yerleşik, eksiksiz bir MQTT dissector'ı ile gelir: CONNECT flag'lerini, topic adlarını, QoS'u, packet identifier'ları, MQTT 5 property'lerini ve reason code'ları çözümler. Böylece kayıp bir mesajın hiç publish edilmediğini mi, hiç onaylanmadığını mı yoksa hiç teslim edilmediğini mi saniyeler içinde görürsünüz.

Bu rehber MQTT trafiğini yakalamayı, her gün kullanacağınız görüntüleme filtrelerini, 8883 portunda TLS şifresini çözmeyi ve grafik arayüzü olmayan sunucular için birkaç tshark komutunu anlatıyor.

Doğru trafiği yakalayın

Wireshark'ı istemcinin çalıştığı makinede (ya da kontrol ediyorsanız broker'da) başlatın ve trafiğin geçtiği arayüzü seçin: uzak broker'lar için Wi-Fi veya Ethernet adaptörünüz, localhost üzerindeki bir broker için loopback arayüzü.

Dosyanın küçük kalması için bir capture filtresi kullanın. Capture filtreleri BPF sözdizimini kullanır ve yakalamayı başlatmadan önce ayarlanır:

Capture filtreleri
tcp port 1883                        # şifresiz MQTT
tcp port 1883 or tcp port 8883       # şifresiz ve TLS
host broker.connectmq.com            # broker'a giden ve gelen her şey

Ardından analiz etmek istediğiniz trafiği üretin — örneğin benzersiz bir topic üzerinde bir subscriber ve bir publisher:

Test trafiği üretin
mosquitto_sub -h broker.connectmq.com -p 1883 -t 'testmqtt/wireshark/#' -q 1 -v &
mosquitto_pub -h broker.connectmq.com -p 1883 -t 'testmqtt/wireshark/hello' -q 1 -m 'ping'

Bir sunucuda yakalama yapıyorsanız tcpdump -w genellikle daha pratiktir; dosyayı sonra Wireshark'ta açarsınız. tcpdump ile MQTT yakalama yazısına bakın.

İhtiyacınız olan görüntüleme filtreleri

Görüntüleme filtreleri yakalamadan sonra uygulanır ve Wireshark alan adlarını kullanır. MQTT dissector'ının başlıca alanları:

AmaçGörüntüleme filtresi
Tüm MQTT paketlerimqtt
Yalnızca CONNECT / CONNACKmqtt.msgtype == 1 || mqtt.msgtype == 2
Yalnızca PUBLISHmqtt.msgtype == 3
Bir topic veya topic önekimqtt.topic contains "testmqtt/wireshark"
Bir istemcinin CONNECT'imqtt.clientid == "sensor-01"
Reddedilen bağlantılarmqtt.conack.val != 0
Retained publish'lermqtt.retain == 1
QoS 1 ve 2 PUBLISH'lermqtt.msgtype == 3 && mqtt.qos > 0
Keep-alive trafiğimqtt.msgtype == 12 || mqtt.msgtype == 13
Sıfırlanan bağlantılartcp.flags.reset == 1
TCP yeniden iletimleritcp.analysis.retransmission

mqtt.msgtype sayısal değerleri MQTT kontrol paketi tipleridir:

DeğerPaketDeğerPaket
1CONNECT8SUBSCRIBE
2CONNACK9SUBACK
3PUBLISH10UNSUBSCRIBE
4PUBACK11UNSUBACK
5PUBREC12PINGREQ
6PUBREL13PINGRESP
7PUBCOMP14DISCONNECT

Tip 15 AUTH'tur (yalnızca MQTT 5). Bu alanların arkasındaki bayt düzeyindeki yapı için MQTT paket yapısı yazısına bakın.

CONNECT ve CONNACK okumak

Bir CONNECT paketi seçin ve MQ Telemetry Transport Protocol bölümünü açın. Şunları göreceksiniz:

  • Protokol adı ve sürümü — sürüm 4 (3.1.1) veya 5 ile MQTT. Broker sürümü kabul etmezse unacceptable protocol version hatasıyla yanıt verir.
  • Connect flag'leri — clean session / clean start, will flag, will QoS, will retain ve username ile password'ün olup olmadığı.
  • Keep alive — istemcinin söz verdiği saniye cinsinden aralık.
  • Client ID ve şifresiz 1883 portunda açık metin olarak username ve password.
  • MQTT 5 property'leri — session expiry interval, receive maximum ve maximum packet size gibi.

Ardından gelen CONNACK sonucu taşır. MQTT 3.1.1'de bu bir return code'dur (0 kabul edildi demektir); MQTT 5'te ise 0x86 Bad User Name or Password veya 0x87 Not authorized gibi bir reason code'dur ve bazen bir reason string içerir. Herhangi bir değeri reason code aracında arayabilirsiniz. Alan alan dökümü MQTT CONNECT paketi yazısında.

Hiç CONNACK yoksa ve broker bunun yerine bir TCP RST veya FIN gönderiyorsa, broker bağlantıyı MQTT aşamasına gelmeden reddetmiştir — çoğunlukla şifresiz MQTT alan bir TLS listener'ı, bozuk bir paket ya da bir bağlantı limiti.

Bir mesajı uçtan uca takip etmek

Bir mesajın nerede kaybolduğunu kanıtlamak için onu yakalama boyunca takip edin:

  1. mqtt.topic contains "testmqtt/wireshark" filtresini uygulayıp publisher'ın PUBLISH paketini bulun. QoS 1 veya 2 ise Message Identifier değerini not edin.
  2. PUBACK'i (QoS 1) ya da PUBREC / PUBREL / PUBCOMP dizisini (QoS 2) görmek için mqtt.msgid == <id> filtresini uygulayın. PUBACK yoksa broker mesajı hiç kabul etmemiştir — ACL'leri ve payload boyutunu kontrol edin.
  3. Subscriber tarafında da yakalama yaptıysanız broker'ın teslim ettiği PUBLISH'i arayın. Packet identifier farklıdır, çünkü her atlamanın kendine ait bir identifier'ı vardır.

"Displayed packets" seçeneğiyle Statistics → Flow Graph, alışverişi bir sıralama diyagramı olarak çizer — eksik bir onayı yakalamanın en hızlı yolu budur.

TLS üzerinden MQTT'nin şifresini çözmek (port 8883)

8883 portunda, Wireshark oturum anahtarlarına sahip olana kadar yalnızca TLS kayıtları görürsünüz. Bu anahtarları almanın standart yolu, birçok TLS kütüphanesinin yazabildiği bir key log dosyasıdır.

Python (paho-mqtt 2.x) — SSL context'inde keylog_filename ayarlayın:

tls_keylog.py
import ssl
import paho.mqtt.client as mqtt

ctx = ssl.create_default_context()
ctx.keylog_filename = "/tmp/mqtt-tls-keys.log"   # Python 3.8+

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
client.tls_set_context(ctx)
client.connect("broker.connectmq.com", 8883)
client.loop_start()
client.publish("testmqtt/wireshark/tls", "hello over TLS", qos=1).wait_for_publish()
client.loop_stop()
client.disconnect()

Node.js (MQTT.js) — kodu değiştirmeden yerleşik flag'i kullanın:

Node.js key log
node --tls-keylog=/tmp/mqtt-tls-keys.log publish.js

Tarayıcılar ve curl SSLKEYLOGFILE ortam değişkenini dikkate alır. Ardından Wireshark'ta Edit → Preferences → Protocols → TLS menüsünü açın ve (Pre)-Master-Secret log filename alanına key log dosyasının yolunu yazın. 8883'teki TLS kayıtları, TLS 1.2'de de 1.3'te de çözümlenmiş MQTT paketlerine dönüşür.

TLS handshake'in kendisi başarısız oluyorsa şifre çözmeye gerek yoktur: alert kaydı (örneğin Unknown CA veya Handshake Failure) açıkça görünür. TLS handshake failed yazısına bakın.

Standart dışı portlar ve WebSockets

Wireshark yalnızca kayıtlı portlarında MQTT olduğunu varsayar. Broker'ınız örneğin 11883'te dinliyorsa bir pakete sağ tıklayın, Decode As… seçin ve bu TCP portunu MQTT'ye eşleyin.

WebSockets üzerinden MQTT'de (8083 / 8084) Wireshark HTTP upgrade isteğini ve WebSocket frame'lerini gösterir; MQTT paketleri binary frame'lerin içindedir. Tarayıcı uygulamalarında bu frame'leri doğrudan tarayıcıda okumak genellikle daha hızlıdır — Chrome DevTools ile MQTT hata ayıklama yazısına bakın.

tshark tarifleri

tshark, Wireshark'ın komut satırı ikizidir ve aynı filtreleri kullanır:

tshark tarifleri
# Canlı: zaman, paket tipi, topic ve payload yazdır
tshark -i any -f "tcp port 1883" -Y mqtt \
  -T fields -e frame.time_relative -e mqtt.msgtype -e mqtt.topic -e mqtt.msg

# Dosyadan: topic başına PUBLISH sayısı
tshark -r mqtt.pcap -Y "mqtt.msgtype == 3" -T fields -e mqtt.topic | sort | uniq -c | sort -rn

# Keep-alive ping'leri arasındaki boşluklar (keep-alive sınırına yakın değerlere bakın)
tshark -r mqtt.pcap -Y "mqtt.msgtype == 12" -T fields -e frame.time_delta_displayed

Sonuncusu keep-alive zaman aşımları için kullanışlıdır: boşluklar keep-alive değerinin 1,5 katını aşarsa broker'ın istemcinin bağlantısını kesme hakkı vardır.

Belirtiye göre neye bakmalı

BelirtiYakalama ne gösterir
İstemci "bağlanamıyor"CONNECT'in ardından sıfırdan farklı kodlu bir CONNACK ya da CONNACK olmadan RST
QoS 1'de kaybolan mesajlarPUBACK'siz PUBLISH, yeniden bağlandıktan sonra bir kopya (DUP flag'i set)
Rastgele bağlantı kopmalarıPINGREQ'lerde boşluklar, TCP yeniden iletimleri, ardından bir taraftan FIN veya RST
Büyük mesajlar kayboluyorBüyük bir PUBLISH'in ardından broker bağlantıyı kapatıyor — maximum packet size ile karşılaştırın ve boyutları paket boyutu hesaplayıcı ile kontrol edin
Subscriber hiçbir şey almıyor0x80 hata kodlu SUBACK ya da eşleşmeyen bir topic filter

Bir durumu hızla yeniden üretmek için yakalamayı çalıştırırken online MQTT istemcisinden publish edin ve paketlerin gerçek zamanlı gelişini izleyin.

Wireshark tahminin yerine kanıt koyar. Dar kapsamlı yakalayın, paket tipine ve topic'e göre filtreleyin, TLS şifresini yalnızca gerektiğinde çözün ve çalışan bir oturumun yakalamasını saklayın — bozuk bir yakalamayı sağlam bir yakalamayla karşılaştırmak çoğu zaman en hızlı teşhistir.

Sıkça sorulan sorular

MQTT için Wireshark görüntüleme filtresi nedir?

Çözümlenmiş tüm MQTT paketlerini görmek için 'mqtt' kullanın. PUBLISH için mqtt.msgtype == 3, bir topic için mqtt.topic contains "sensors" veya bir istemcinin CONNECT paketi için mqtt.clientid == "sensor-01" gibi alanlarla daraltın.

Wireshark 8883 portunda neden MQTT yerine TLS gösteriyor?

MQTT paketleri şifrelidir. Wireshark onları ancak TLS oturum anahtarlarını verirseniz çözebilir: istemcinin bir key log dosyası yazmasını sağlayın (SSLKEYLOGFILE, Python'da keylog_filename, Node'da --tls-keylog) ve Wireshark'ın TLS tercihlerinde bu dosyayı gösterin.

MQTT trafiğim neden düz TCP verisi olarak görünüyor?

Wireshark MQTT'yi otomatik olarak yalnızca standart 1883 portunda (ve şifre çözüldükten sonra 8883'te) çözümler. Diğer portlar için bir pakete sağ tıklayın, Decode As seçin ve TCP portunu MQTT'ye atayın.