tcpdump, neredeyse her Linux sunucusunda, router'da ve gateway'de zaten kurulu olan — ya da bir paket uzaklıkta bulunan — paket yakalama aracıdır. MQTT'yi anlamaz ama buna ihtiyacı da yoktur: 1883 veya 8883 portundaki TCP konuşmasını yakalamak; kimin bağlandığını, bağlantıyı kimin kapattığını ve yolda paket kaybolup kaybolmadığını kanıtlamaya yeter. MQTT ayrıntılarına ihtiyaç duyduğunuzda aynı dosyayı Wireshark'ta açarsınız.
Bu rehber MQTT için bir tcpdump tarif koleksiyonudur: temel yakalamalar, MQTT paket tiplerini yakalayan BPF filtreleri, Docker ve Kubernetes'te yakalama, uzun süre çalışan ring buffer'lar ve yakaladıklarınızı nasıl analiz edeceğiniz.
Temel MQTT yakalaması
# Segment başına bir satır (şifresiz MQTT ve TLS)
sudo tcpdump -i any -nn 'tcp port 1883 or tcp port 8883'
# Bunun yerine Wireshark için dosyaya yazın
sudo tcpdump -i any -nn -w mqtt.pcap 'tcp port 1883 or tcp port 8883'
# Yalnızca tek bir cihazla olan trafik
sudo tcpdump -i any -nn 'host 192.168.1.50 and tcp port 1883'En sık kullanacağınız seçenekler:
| Seçenek | Anlamı |
|---|---|
-i any / -i eth0 | Yakalama yapılacak arayüz (tcpdump -D listeler) |
-nn | Host ve port adlarını çözümleme — daha hızlı ve net |
-w file.pcap | Paketleri yazdırmak yerine dosyaya yaz |
-r file.pcap | Bir yakalama dosyasını oku |
-A / -X | Payload'ı ASCII / hex ve ASCII olarak göster |
-c 200 | 200 paketten sonra dur |
-U | Her paketi hemen yaz (bir pipe'a yazarken gerekli) |
-tttt | Her satırda tam tarih ve saat |
Hemen faydalı bir şey görmek için başka bir terminalden bir test topic'ine publish edin ve payload'ı ASCII olarak izleyin:
sudo tcpdump -i any -nn -A 'tcp port 1883' &
mosquitto_pub -h broker.connectmq.com -p 1883 -t 'testmqtt/tcpdump/hello' -m 'hello from tcpdump'PUBLISH segmentinin içinde testmqtt/tcpdump/hello topic'ini ve payload'ı açık metin olarak görürsünüz. 8883 portunda ise yalnızca şifreli baytlar görünür — TLS'in amacı da budur.
Nerede yakalamalı
Yakalamayı yaptığınız yer neyi kanıtlayabileceğinizi belirler. İstemcide yapılan bir yakalama cihazın gerçekte ne gönderdiğini ve neyin geri geldiğini gösterir; uygulamanın hiç fark etmediği yeniden iletimler de buna dahildir. Broker host'unda yapılan bir yakalama ise NAT, load balancer ve proxy'ler işini yaptıktan sonra gerçekte neyin ulaştığını gösterir. İkisi uyuşmuyorsa sorun aradadır.
İnatçı bir sorunda iki tarafta aynı anda -tttt zaman damgalarıyla yakalama yapıp karşılaştırın. İstemcinin gönderdiği bir PUBLISH broker tarafında hiç görünmüyorsa ağ yoluna bakın; broker onu alıyor ama subscriber hiç almıyorsa bunun yerine broker'ın ACL'lerine, kuyruklarına ve loglarına bakın.
tcpdump çıktısını okumak
Tipik bir MQTT bağlantısı şöyle görünür (adresler kısaltılmıştır):
10:15:02.114 IP 10.0.0.12.52144 > 203.0.113.10.1883: Flags [S], seq 1902...
10:15:02.139 IP 203.0.113.10.1883 > 10.0.0.12.52144: Flags [S.], seq 4471..., ack 1902...
10:15:02.139 IP 10.0.0.12.52144 > 203.0.113.10.1883: Flags [.], ack 1
10:15:02.140 IP 10.0.0.12.52144 > 203.0.113.10.1883: Flags [P.], length 35 <- CONNECT
10:15:02.166 IP 203.0.113.10.1883 > 10.0.0.12.52144: Flags [P.], length 4 <- CONNACK
10:15:02.167 IP 10.0.0.12.52144 > 203.0.113.10.1883: Flags [P.], length 42 <- PUBLISH
10:15:02.168 IP 10.0.0.12.52144 > 203.0.113.10.1883: Flags [P.], length 2 <- DISCONNECT
10:15:02.168 IP 10.0.0.12.52144 > 203.0.113.10.1883: Flags [F.], ...Teşhisin büyük kısmını TCP flag'leri taşır:
[S]var ama[S.]yanıtı yok — SYN hiç yanıt almadı: firewall, yönlendirme veya yanlış IP. MQTT ağ sorunlarını teşhis etmek yazısına bakın.[S]'e[R.]ile yanıt — host ayakta ama portta dinleyen yok (Connection refused).[F.]— düzenli bir kapanış. İlk FIN'i gönderen taraf oturumu bitirmeye karar veren taraftır.[R]— ani bir reset. Ne istemci ne de broker olan bir adresten geliyorsa aradaki bir cihaz bağlantıyı öldürmüştür.- Aynı
[P.]segmentinin bir gecikmeden sonra tekrarlanması — yeniden iletim, yani yolda kayıp.
MQTT paket tipine göre filtrelemek
Her MQTT paketinin ilk baytı, üst dört bitinde paketin tipini kodlar. Bir BPF ifadesi TCP payload'ının başındaki bu baytı okuyabilir; böylece tcpdump yalnızca belirli paket tiplerini tutar:
| Tip | İlk bayt (0xf0 ile maskelenmiş) |
|---|---|
| CONNECT | 0x10 |
| CONNACK | 0x20 |
| PUBLISH | 0x30 |
| SUBSCRIBE | 0x80 |
| PINGREQ / PINGRESP | 0xc0 / 0xd0 |
| DISCONNECT | 0xe0 |
sudo tcpdump -i any -nn -A \
'tcp port 1883 and tcp[tcpflags] & tcp-push != 0 and
((tcp[((tcp[12:1] & 0xf0) >> 2):1] & 0xf0) = 0x10 or
(tcp[((tcp[12:1] & 0xf0) >> 2):1] & 0xf0) = 0x20)'(tcp[12:1] & 0xf0) >> 2 TCP başlığının uzunluğudur; dolayısıyla ifade payload'ın ilk baytını okur. tcp-push koşulu boş ACK segmentlerini atlar. Akılda tutulması gereken iki sınır var: yalnızca her segmentteki ilk MQTT paketini görür (birkaç küçük paket aynı segmenti paylaşabilir) ve tcp[] offset'leri yalnızca IPv4'te çalışır. Bu bir çözücü değil, yakalamayı daraltmak için bir filtredir — kesin yanıtlar için Wireshark'ın mqtt.msgtype filtresini kullanın.
Bağlantı kopmalarını ve yeniden bağlanmaları yakalamak
İki kısa filtre, production'daki en yaygın soruyu yanıtlar — "bu istemci neden sürekli bağlantıyı koparıyor?":
# Her yeni bağlantı denemesi (ACK'siz SYN)
sudo tcpdump -i any -nn 'tcp port 1883 and tcp[tcpflags] == tcp-syn'
# Her kapanış veya reset, zaman damgalarıyla
sudo tcpdump -i any -nn -tttt 'tcp port 1883 and tcp[tcpflags] & (tcp-fin|tcp-rst) != 0'İkisini birlikte okuyun:
- İstemcinin son paketinden yaklaşık bir buçuk keep-alive aralığı sonra broker'dan gelen bir FIN, istemcinin PINGREQ göndermeyi bıraktığı anlamına gelir — MQTT keep alive yazısına bakın.
- Uzun bir boşta kalma süresinden sonra, çoğu zaman her seferinde aynı aralıkta gelen bir RST, NAT veya firewall zaman aşımına işaret eder — MQTT NAT zaman aşımı yazısına bakın.
- Bir kesintiden sonra birçok cihazdan saniyede yüzlerce SYN gelmesi bir yeniden bağlanma fırtınasıdır.
- Aynı client ID ile başka bir adresten yeni bir SYN geldikten hemen sonra broker'dan gelen bir FIN, oturumun devralındığını gösterir. Her test istemcisine client ID üreticisi ile ayrı bir ID verin.
Uzun süreli yakalamalar
Aralıklı sorunlar, diski doldurmadan saatlerce çalışan yakalamalar gerektirir. tcpdump dosyaları kendisi döndürebilir:
# Her biri ~100 MB olan 10 dosya, en eskisinin üzerine yazılır
sudo tcpdump -i any -nn -w /var/tmp/mqtt.pcap -C 100 -W 10 'tcp port 1883 or tcp port 8883'
# Saat başına bir dosya, zamana göre adlandırılmış
sudo tcpdump -i any -nn -G 3600 -w '/var/tmp/mqtt-%Y%m%d-%H%M.pcap' 'tcp port 1883'Bunu tmux içinde veya geçici bir systemd unit'i olarak başlatın, sorunun yaşandığı zamanı not edin ve yalnızca ilgili dosyayı alın.
Container'lar, Kubernetes ve uzak host'lar
Bir broker container'ında genellikle tcpdump bulunmaz. Bunun yerine onun ağ namespace'ini ödünç alın:
docker run --rm --net container:mosquitto nicolaka/netshoot \
tcpdump -i any -nn -U -w - 'tcp port 1883' > broker.pcapkubectl debug -it mosquitto-0 --image=nicolaka/netshoot --target=mosquitto -- \
tcpdump -i any -nn 'tcp port 1883'Debug container'ının yakalama yapma iznine (root ve NET_RAW capability'si) ihtiyacı vardır; kısıtlayıcı pod güvenlik politikaları bunu engelleyebilir. Port eşlemeleri ve bridge ağlarının kendi tuzakları vardır; bunlar Docker'da MQTT ağ sorunları yazısında ele alınıyor.
Uzak bir sunucuyu Wireshark'ta canlı izlemek için yakalamayı SSH üzerinden aktarın (uzak kullanıcının tcpdump için parolasız sudo yetkisi olmalıdır):
ssh admin@gateway.example "sudo tcpdump -i any -nn -U -w - 'tcp port 1883'" | wireshark -k -i -ESP32 gibi mikrodenetleyiciler tcpdump çalıştıramaz. Yakalamayı gateway'de, Wi-Fi router'ında (OpenWrt'nin bir tcpdump paketi vardır) veya yansıtılmış bir switch portunda, cihazın IP adresine göre filtreleyerek yapın.
Yakalamayı analiz etmek
tcpdump kaydedilmiş bir dosya üzerinde ilk geçişi yapabilir:
# Kaç bağlantı denemesi var ve nereden geliyor?
tcpdump -r mqtt.pcap -nn 'tcp[tcpflags] == tcp-syn' | awk '{print $3}' | cut -d. -f1-4 | sort | uniq -c | sort -rn
# Belirli bir zaman civarındaki açık metin payload'ları okuyun
tcpdump -r mqtt.pcap -nn -tttt -A | less
# MQTT çözümlemesi için tshark'a devredin
tshark -r mqtt.pcap -Y mqtt -T fields -e frame.time -e ip.src -e mqtt.msgtype -e mqtt.topicSaymanın ötesindeki her şey için dosyayı Wireshark'ta açın: her MQTT paketini çözümler ve bir key log ile TLS şifresini çözebilir. Tüm iş akışı Wireshark ile MQTT hata ayıklama yazısında.
Bir düzeltmeyi yakalama ile doğrulayın
Bir yakalama, ağ düzeltmeleri için en iyi regresyon testidir. Keep-alive'ı, bir firewall zaman aşımını veya bir load balancer ayarını değiştirdikten sonra, bir istemci bağlı kalırken bağlantı kopması filtresini eski hata aralığından daha uzun süre çalıştırın — örneğin online MQTT istemcisinde testmqtt/tcpdump/# topic'ine abone bir subscriber ile. Bu süre içinde hiç FIN veya RST görünmüyorsa düzeltme işe yarıyor demektir.
Yakalama sırasında bir test subscriber'ını bağlı tutun
tcpdump, "bağlantı bazen kopuyor" cümlesini zaman damgalarına, flag'lere ve IP adreslerine dönüştürür. Dar kapsamlı yakalayın, bağlantıyı kimin kapattığını flag'lerin söylemesine izin verin ve MQTT paketlerinin kendisini okumanız gerektiğinde Wireshark'a geçin.
Sıkça sorulan sorular
MQTT yakalamak için tcpdump komutu nedir?
sudo tcpdump -i any -nn -w mqtt.pcap 'tcp port 1883 or tcp port 8883' komutu tüm arayüzlerde şifresiz ve TLS MQTT trafiğini Wireshark'ta açabileceğiniz bir dosyaya yakalar. Şifresiz MQTT payload'larını doğrudan terminalde görmek için -w'yi kaldırıp -A ekleyin.
tcpdump MQTT paketlerini çözümleyebilir mi?
Hayır. tcpdump TCP segmentlerini, flag'leri ve ham baytları gösterir ama MQTT çözücüsü yoktur. tcpdump ile yakalayın, ardından pcap dosyasını Wireshark'ta açın ya da CONNECT, PUBLISH ve diğer MQTT paketlerini görmek için tshark -r dosya.pcap -Y mqtt çalıştırın.
Docker içindeki bir broker için tcpdump nasıl çalıştırılır?
Bir araç container'ını broker'ın ağ namespace'ine bağlayın, örneğin docker run --rm --net container:mosquitto nicolaka/netshoot tcpdump -i any -nn port 1883. Bu container, broker container'ına hiçbir şey kurmadan onun trafiğini birebir görür.



