Broker testleri

MQTT TLS Bağlantısı Nasıl Test Edilir (openssl, mosquitto, kod)

8883 portunda MQTT over TLS testi: openssl s_client kontrolleri, sertifika zinciri, SNI ve hostname doğrulaması, mosquitto --cafile ve yaygın hata çözümleri.

Güncellendi · 9 dk okuma

MQTT TLS Bağlantısı Nasıl Test Edilir (openssl, mosquitto, kod)

Bir MQTT TLS bağlantısını test etmek için üç katmanı sırayla kontrol edin: önce openssl s_client ile TLS handshake'in kendisini, ardından mosquitto_sub veya mosquitto_pub ile gerçek bir MQTT oturumunu, son olarak da cihazlarınızın kullandığı istemci kütüphanesini. Her katman farklı nedenlerle başarısız olabilir; ayrı ayrı test etmek hangisinin bozuk olduğunu tam olarak gösterir.

Tüm örnekler 8883 portunda (MQTT over TLS) broker.connectmq.com kullanır. Host'u kendi broker'ınızla değiştirin.

1. adım: handshake'i openssl ile kontrol edin

openssl s_client TLS konuşur ama MQTT konuşmaz; istediğiniz de tam olarak budur: araya hiçbir MQTT kütüphanesi girmeden broker'ın gönderdiği sertifikayı ve makinenizin ona güvenip güvenmediğini gösterir.

Temel TLS kontrolü
openssl s_client -connect broker.connectmq.com:8883 \
  -servername broker.connectmq.com \
  -verify_hostname broker.connectmq.com \
  -showcerts </dev/null

Her seçeneğin görevi:

  • -servername SNI (Server Name Indication) gönderir. Birden fazla alan adı barındıran broker'lar ve load balancer'lar sertifikayı seçmek için bunu kullanır. SNI olmadan varsayılan bir sertifika ve hostname uyuşmazlığı alabilirsiniz.
  • -verify_hostname, openssl'in sertifikanın o ad için geçerli olup olmadığını kontrol etmesini sağlar — MQTT istemcinizin yaptığı kontrolün aynısı.
  • -showcerts, sunucunun gönderdiği tüm sertifikaları yazdırır; böylece ara sertifikanın dahil olup olmadığını görürsünüz.
  • </dev/null, girdi beklemek yerine bağlantıyı handshake'ten hemen sonra kapatır.

Çıktının sonunda şunu arayın:

Sağlıklı sonuç
Verify return code: 0 (ok)

Başka her sonuç, MQTT istemcinizde de göreceğiniz bir sorundur:

openssl sonucuAnlamı
Verify return code: 20 (unable to get local issuer certificate)CA (veya eksik bir ara sertifika) güven deponuzda yok
Verify return code: 18 (self-signed certificate)Sunucu sertifikası kendinden imzalı; CA'sını -CAfile ile verin
Verify return code: 19 (self-signed certificate in certificate chain)Zincir, güvenmediğiniz özel bir kök sertifikayla bitiyor
Verify return code: 10 (certificate has expired)Broker'daki sertifikayı yenileyin
Verify return code: 62 (hostname mismatch)Sertifika bağlandığınız adı içermiyor
wrong version numberBu port TLS değil, şifresiz MQTT (çoğunlukla 1883)
connect: Connection refused / zaman aşımıPort kapalı veya filtreleniyor — TLS sorunu değil

Özel CA kullanan bir broker için -CAfile ca.crt ekleyip komutu tekrar çalıştırın. Sonuç 0 (ok) olursa sertifikalarınız sorunsuzdur ve istemcinin yalnızca aynı CA dosyasına ihtiyacı vardır.

Sertifikayı hızlıca inceleyin

Subject, issuer, SAN ve geçerlilik süresi
openssl s_client -connect broker.connectmq.com:8883 \
  -servername broker.connectmq.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates -ext subjectAltName

subjectAltName alanının cihazlarınızın kullandığı hostname'i birebir içerdiğini kontrol edin. Modern istemciler sertifikanın Common Name alanını yok sayar; yalnızca CN içinde geçen bir ad sayılmaz. Süre dolmadan iki hafta önce başarısız olan bir CI kontrolü için sertifikayı openssl x509 -noout -checkend 1209600 komutuna yönlendirin.

Broker'ın hangi TLS sürümlerini kabul ettiğini test etmek için ilk komutu -tls1_2 veya -tls1_3 ile tekrarlayın. Yalnızca TLS 1.2 konuşan eski bir TLS yığınına sahip cihaz, broker'ın 1.2'yi açık tutmasına ihtiyaç duyar — bkz. MQTT için TLS 1.2 ve 1.3.

2. adım: TLS üzerinden gerçek bir MQTT oturumu

Başarılı bir handshake, arkasındaki MQTT listener'ının çalıştığını kanıtlamaz. 8883 üzerinden abone olun ve publish edin:

Terminal 1 — TLS üzerinden subscribe
mosquitto_sub -h broker.connectmq.com -p 8883 \
  --cafile /etc/ssl/certs/ca-certificates.crt \
  -u "$MQTT_USER" -P "$MQTT_PASS" \
  -t testmqtt/tls/check -v -d
Terminal 2 — TLS üzerinden publish
mosquitto_pub -h broker.connectmq.com -p 8883 \
  --cafile /etc/ssl/certs/ca-certificates.crt \
  -u "$MQTT_USER" -P "$MQTT_PASS" \
  -t testmqtt/tls/check -m "hello over tls"

mosquitto istemcileri TLS'i yalnızca bir CA seçeneği verdiğinizde etkinleştirir. CA paketinizle --cafile (yukarıdaki yol Debian/Ubuntu içindir; Homebrew kullanan macOS'ta $(brew --prefix)/etc/ca-certificates/cert.pem altındadır), --capath /etc/ssl/certs veya mosquitto 2.x'te --tls-use-os-certs kullanın. Özel CA için --cafile seçeneğini kendi ca.crt dosyanıza yönlendirin. Karşılıklı TLS için --cert client.crt --key client.key ekleyin — bkz. istemci sertifikaları ve mTLS.

Başarısız olduğunda mosquitto pek konuşkan değildir: Error: A TLS error occurred. yazdırır, o kadar. 1. adıma dönün — nedenini openssl söyler. openssl başarılı olup mosquitto başarısız oluyorsa hostname'i karşılaştırın: -h bir IP adresi değil, sertifikadaki ad olmalıdır.

3. adım: istemci kodunuzdan test edin

Son olarak uygulamanızın kullandığı kütüphaneyle test edin. Sertifika deposu ve varsayılanlar dile göre değişir; mosquitto ile çalışan bir bağlantı burada yine de başarısız olabilir.

tls_check.py (paho-mqtt 2.x)
import os
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, reason_code, properties):
    print("CONNACK:", reason_code)
    client.publish("testmqtt/tls/check", "hello from python over tls", qos=1)

c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, protocol=mqtt.MQTTv5)
c.tls_set()  # sistem CA'ları, hostname doğrulaması açık; özel CA için ca_certs="ca.crt"
c.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
c.on_connect = on_connect
c.connect("broker.connectmq.com", 8883)
c.loop_forever()
tls-check.mjs (MQTT.js 5)
import mqtt from "mqtt";

const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
  username: process.env.MQTT_USER,
  password: process.env.MQTT_PASS,
  // ca: fs.readFileSync("ca.crt"),   // yalnızca özel CA için
  reconnectPeriod: 0,
});

client.on("connect", () => {
  console.log("connected over TLS");
  client.publish("testmqtt/tls/check", "hello from node over tls", () => client.end());
});
client.on("error", (err) => console.error(err.code, err.message));

Bunların ürettiği hatalar, insanların aradığı hatalardır:

KütüphaneHataOlağan neden
Python[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificateCA veya ara sertifika eksik
Pythoncertificate verify failed: Hostname mismatch, certificate is not valid for '...'IP ile veya yanlış adla bağlanılmış
Python[SSL: WRONG_VERSION_NUMBER] wrong version numberŞifresiz porta TLS istemcisi
Node.jsUNABLE_TO_VERIFY_LEAF_SIGNATURE — unable to verify the first certificateSunucu ara sertifikayı göndermiyor
Node.jsSELF_SIGNED_CERT_IN_CHAINÖzel CA ca seçeneğiyle verilmemiş
Node.jsERR_TLS_CERT_ALTNAME_INVALID — Hostname/IP does not match certificate's altnamesAd SAN listesinde yok

Çözümler tek tek certificate verify failed, TLS handshake hatası ve hostname mismatch yazılarında anlatılıyor. Kod üreticisi diğer diller için TLS'li bağlantı kod parçaları üretir.

Hızlı TLS test kontrol listesi

  1. -servername ve -verify_hostname ile openssl s_client, Verify return code: 0 (ok) döndürüyor.
  2. -showcerts, sunucu sertifikasını ve ara sertifikayı listeliyor.
  3. SAN, istemcilerin kullandığı hostname'i birebir içeriyor; sertifikanın süresi dolmak üzere değil.
  4. mosquitto_sub ve mosquitto_pub, doğrulama açıkken 8883 üzerinden mesaj alışverişi yapabiliyor.
  5. Uygulama kütüphaneniz varsayılan güven deposuyla (veya dağıttığınız özel CA ile) bağlanıyor.
  6. TLS zorunluysa şifresiz 1883 portu canlıda kapalı veya devre dışı.
  7. Eski TLS yığınlarına sahip cihazlar, izin verdiğiniz TLS sürümü ve cipher suite'lerle bağlanabiliyor.

Tarayıcıdan da bir kontrol mü istiyorsunuz? Online MQTT istemcisi, birçok kurulumda aynı sertifikayı kullanan 8084 portundaki güvenli WebSocket üzerinden bağlanır — bir cihazı debug etmeden önce broker'ın TLS tarafını doğrulamanın hızlı bir yolu.

TLS'i katman katman test etmek, belirsiz bir "TLS hatası"nı birkaç dakika içinde somut bir nedene dönüştürür. openssl komutunu ve süre kontrolünü betiklerinizde tutun; her sertifika yenilendiğinde veya bir load balancer değiştiğinde çalıştırın.

Sıkça sorulan sorular

Bir MQTT broker'ın TLS desteklediğini nasıl kontrol ederim?

openssl s_client -connect host:8883 -servername host komutunu çalıştırın. Handshake başarılı olursa sertifika zincirini ve 'Verify return code: 0 (ok)' satırını görürsünüz. 'wrong version number' hatası, portun TLS değil şifresiz MQTT konuştuğu anlamına gelir.

TLS neden tarayıcıda çalışıyor ama cihazımda başarısız oluyor?

Genellikle sunucu ara (intermediate) sertifikasını göndermiyordur. Tarayıcılar eksik ara sertifikaları kendileri indirebilir; openssl, mosquitto ve gömülü TLS yığınları indiremez. s_client -showcerts çıktısında ara sertifikanın listelendiğini kontrol edin ve broker'ın sertifika dosyasını düzeltin.

--insecure veya tls_insecure_set(True) kullanmak güvenli mi?

Yalnızca kendi makinenizde geçici bir teşhis olarak. Bu seçenekler hostname doğrulamasını kapatır ve bağlantıyı man-in-the-middle saldırılarına açık bırakır. Bunun yerine sertifikayı veya hostname'i düzeltin ve doğrulamayı açık tutun.