MQTT Güvenliği

MQTT TLS 1.3: Handshake, Cipher Suite'ler ve Performans

TLS 1.3'ün MQTT bağlantılarını nasıl değiştirdiğini öğrenin: daha az tur, daha küçük ve güçlü bir cipher suite kümesi ve mikrodenetleyiciler için farklı ödünleşimler. Python, Node.js, Mosquitto ve OpenSSL örnekleri içerir.

Cihaz ile broker arasında iki turlu TLS 1.2 handshake'ini tek turlu TLS 1.3 handshake'iyle karşılaştıran MQTT TLS 1.3 çizimi
Bunu kendi MQTT broker’ınızda çalıştırınFree planla özel, yönetilen bir MQTT broker alın ve hazır kod örnekleriyle başlayın.
Ücretsiz deneyin Kod örnekleri Kart gerekmez

MQTT TLS 1.3 handshake'i kısaltır, zayıf kriptografiyi kaldırır ve cipher suite seçimini sadeleştirir; ancak pille çalışan cihazlarda asıl maliyet başka yerlerden gelir. Bu yazıda MQTT bağlantıları açısından TLS 1.2 ile 1.3 arasında gerçekte neyin değiştiğini, hangi cipher suite'lere izin vermeniz gerektiğini, bağlantınızın neyi müzakere ettiğini nasıl ölçeceğinizi ve Python, Node.js ve Mosquitto istemcilerini nasıl mantıklı biçimde yapılandıracağınızı anlatıyoruz.

TLS Sürümü MQTT İçin Neden Önemli?

MQTT uzun ömürlü bir TCP bağlantısı üzerinde çalışır. Cihaz bir kez bağlanır, TLS handshake'ini yapar ve ardından saatlerce, hatta günlerce küçük mesajlar alışverişi yapar. Bu, sürekli açık cihazlar için handshake maliyetinin nadiren ödendiği, ancak birkaç dakikada bir uyanan pilli sensörler gibi uyuyup yeniden bağlanan cihazlar için çok sık ödendiği anlamına gelir. Bu cihazlarda enerji tüketimine handshake turları ve açık anahtar işlemlerine harcanan CPU süresi hâkimdir; dolayısıyla TLS sürümü ve cipher suite seçimi büyük önem taşır.

MQTT bağlantılarını güvenli hâle getirmekte yeniyseniz önce MQTT TLS yapılandırması rehberimizle başlayın, ince ayar detayları için buraya geri dönün.

Bir Bakışta TLS 1.2 ve TLS 1.3

Özellik TLS 1.2 TLS 1.3
Tam handshake tur sayısı Uygulama verisinden önce 2 Uygulama verisinden önce 1
Devam ettirilen handshake 1 tur (session ID veya ticket) 1 tur (PSK), isteğe bağlı 0-RTT
Anahtar değişimi RSA veya (EC)DHE Yalnızca (EC)DHE, her zaman forward secrecy
Cipher suite'ler Çoğu zayıf veya eskimiş onlarca suite Beş tanımlı, üçü yaygın kullanılan
Handshake'te sertifikanın şifrelenmesi Hayır Evet
CBC modu, RC4, SHA-1, statik RSA İzinli (yapılandırmaya bağlı) Kaldırıldı

Yüksek gecikmeli bir hücresel bağlantıdaki istemci için her bağlantıda bir tur kazanmak fark edilir bir iyileşmedir. Yerel ağdaki bir cihaz içinse bu kazanç, kriptografik işlem yüküne kıyasla küçüktür.

Handshake Maliyeti Gerçekte Nereden Gelir?

Bir mikrodenetleyicide tam handshake'e üç işlem hâkimdir:

  1. Anahtar değişimi: genellikle X25519 veya P-256 eğrisi üzerinde bir ECDHE hesaplaması. Bu, her iki TLS sürümünde de gerçekleşir.
  2. Sertifika doğrulama: sunucu zincirindeki imzaların kontrol edilmesi. RSA imza doğrulaması ucuzdur; ECDSA doğrulaması istemcide daha maliyetlidir ama ECDSA sertifikaları daha küçüktür.
  3. Ağ turları: her biri radyoyu uyanık tutar.

TLS 1.3 tur sayısını azaltır ama açık anahtar işlemlerini ortadan kaldırmaz. Sık yeniden bağlanan cihazlar için en büyük kazanç genellikle oturum devamıdır (session resumption); bu yöntem sertifika doğrulamasını atlar ve TLS 1.3'ün anahtar değişimli PSK modunda forward secrecy'yi korumaya devam eder. Buna güvenmeden önce hem TLS yığınınızın hem de broker'ınızın bunu desteklediğini kontrol edin.

Donanım hızlandırma da önemlidir. ESP32 ailesi, RSA ve ECC'de kullanılan AES, SHA ve büyük sayı aritmetiğini mbedTLS üzerinden hızlandırır; bu da her iki TLS sürümünü bu çiplerde pratik kılar. Hızlandırma içermeyen daha küçük mikrodenetleyiciler, saf yazılımda hızlı çalışan ChaCha20-Poly1305'ten fayda görebilir.

MQTT TLS 1.3 Cipher Suite'leri

TLS 1.3, cipher suite'i (simetrik şifreleme ve hash) anahtar değişimi ve imza algoritmalarından ayırır. Pratikte karşılaşacağınız suite'ler şunlardır:

  • TLS_AES_128_GCM_SHA256: uygulanması zorunludur, AES donanımıyla hızlıdır, iyi bir varsayılandır.
  • TLS_AES_256_GCM_SHA384: daha büyük anahtar, biraz daha yavaş, çoğunlukla politika gereği tercih edilir.
  • TLS_CHACHA20_POLY1305_SHA256: AES hızlandırması olmayan CPU'larda mükemmeldir.

Üçü de kimlik doğrulamalı şifreleme (authenticated encryption) sağlar ve güçlü kabul edilir. Bunları kısıtlamanız nadiren gerekir. TLS 1.3 için tanımlanan diğer iki suite (CCM varyantları) çoğunlukla kısıtlı ortamlarda görülür.

TLS 1.2'yi hâlâ desteklemeniz gerekiyorsa yalnızca forward secrecy sağlayan AEAD suite'lerine izin verin:

ECDHE-ECDSA-AES128-GCM-SHA256
ECDHE-RSA-AES128-GCM-SHA256
ECDHE-ECDSA-CHACHA20-POLY1305
ECDHE-RSA-CHACHA20-POLY1305
ECDHE-ECDSA-AES256-GCM-SHA384
ECDHE-RSA-AES256-GCM-SHA384

CBC, RC4, 3DES, NULL, EXPORT içeren suite'lerden ve statik RSA anahtar değişimi kullananlardan (ECDHE olmadan AES ile başlayan adlar) kaçının.

Bağlantınızın Neyi Müzakere Ettiğini Ölçmek

Bir broker'ın hangi sürümü desteklediğini asla varsaymayın; ölçün. OpenSSL her sürümü zorlayıp sonucu raporlayabilir:

# Negotiate the best version both sides support
openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -brief </dev/null

# Force TLS 1.3
openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -tls1_3 -brief </dev/null

# Force TLS 1.2
openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -tls1_2 -brief </dev/null

Protocol version ve Ciphersuite satırları sonucu gösterir. Aynı testleri değerlendirdiğiniz her broker'a karşı çalıştırın ve broker ya da kütüphane güncellemelerinden sonra tekrarlayın; desteklenen sürümler zamanla değişebilir.

Handshake sürelerini bir betikten ölçmek için şu Python parçası bağlantı ve handshake gecikmesini ölçer:

import socket
import ssl
import time

HOST, PORT = "broker.connectmq.com", 8883

def handshake(version: ssl.TLSVersion) -> None:
    ctx = ssl.create_default_context()
    ctx.minimum_version = version
    ctx.maximum_version = version
    start = time.perf_counter()
    try:
        with socket.create_connection((HOST, PORT), timeout=10) as sock:
            with ctx.wrap_socket(sock, server_hostname=HOST) as tls:
                elapsed = (time.perf_counter() - start) * 1000
                print(f"{tls.version()}  {tls.cipher()[0]}  {elapsed:.1f} ms")
    except ssl.SSLError as exc:
        print(f"{version.name} not negotiated: {exc.reason}")

for v in (ssl.TLSVersion.TLSv1_2, ssl.TLSVersion.TLSv1_3):
    for _ in range(3):
        handshake(v)

Birkaç kez çalıştırın; hızlı bir bağlantıda ağ dalgalanması (jitter) genellikle sürümler arasındaki farktan daha büyüktür.

İstemcileri Yapılandırmak

En güvenli istemci politikası "TLS 1.2 ve üstüne izin ver, en yenisini tercih et" yaklaşımıdır; böylece istemci ve sunucu ortak olan en iyi sürümü seçebilir.

Python (paho-mqtt 2.x)

import ssl
import paho.mqtt.client as mqtt

ctx = ssl.create_default_context()           # zinciri ve hostname'i doğrular
ctx.minimum_version = ssl.TLSVersion.TLSv1_2  # daha eski sürümleri reddeder

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="py-tls13-c71e")
client.tls_set_context(ctx)
# client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.connect("broker.connectmq.com", 8883)
client.loop_start()
client.publish("connectmq/demo/c71e/tls", "negotiated securely", qos=1).wait_for_publish()
client.loop_stop()
client.disconnect()

Python'daki set_ciphers() yalnızca TLS 1.2 ve öncesini etkiler; TLS 1.3 suite'leri zaten sağlam olan OpenSSL varsayılanlarıyla yönetilir.

Node.js (MQTT.js v5)

const mqtt = require("mqtt");

const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
  clientId: "node-tls13-c71e",
  protocolVersion: 5,
  minVersion: "TLSv1.2", // Node'un tls.connect fonksiyonuna aktarılır
});

client.on("connect", () => {
  const sock = client.stream;
  console.log("TLS:", sock.getProtocol(), sock.getCipher().name);
  client.end();
});

Kendi Barındırdığınız Broker Olarak Mosquitto

Kendi Mosquitto broker'ınızı çalıştırıyorsanız sunucu tarafını siz kontrol edersiniz:

listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
cafile /etc/mosquitto/certs/chain.pem
tls_version tlsv1.2
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ciphers_tls1.3 TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384

Mosquitto'da tls_version, listener'ın kabul ettiği minimum sürümü belirler. Sunucuyu yalnızca TLS 1.3 ile sınırlamak cazip gelebilir, ancak bu hâlâ yalnızca TLS 1.2 destekleyen eski firmware'leri ve gömülü TLS yığınlarını dışarıda bırakır.

Kısıtlı Cihazlar İçin Pratik Öneriler

  1. Bağlantıları açık tutun. Günde bir handshake, dakikada bir yapılan handshake'in herhangi bir optimizasyonundan daha ucuzdur.
  2. Oturum devamını kullanın: uyuması gereken cihazlarda, yığınınız destekliyorsa.
  3. Donanım kriptografisini etkinleştirin: SDK yapılandırmanızda.
  4. Yığınınızın TLS 1.3 durumunu kontrol edin. ESP-IDF'in kullandığı güncel mbedTLS sürümleri bir yapılandırma seçeneği olarak TLS 1.3 desteğiyle derlenebilir; eski SDK'lar yalnızca TLS 1.2 sunar, bu da yukarıda listelenen suite'lerle hâlâ güvenlidir.
  5. Firmware'de tek bir sürümü sabit kodlamayın. Sunucular değiştiğinde cihazların çalışmaya devam etmesi için müzakereye izin verin.
  6. Komutlar için 0-RTT'den kaçının. Early data yeniden oynatılabilir (replay); bu, aktüatör komutları için tehlikelidir.

ESP32 sertifika sabitleme rehberi gömülü TLS'nin sertifika tarafını ele alır; MQTT TLS handshake hatalarını düzeltme yazısı ise sürüm müzakeresi ters gittiğinde yardımcı olur.

Güvenlik Politikası Kontrol Listesi

Bir MQTT projesinin TLS politikasını yazarken bu listeyi kullanın:

  1. Minimum protokol sürümü: istemcilerde TLS 1.2; TLS 1.3'e izin verilir ve tercih edilir.
  2. TLS 1.2 suite'leri: yalnızca AES-GCM veya ChaCha20-Poly1305 ile ECDHE anahtar değişimi.
  3. TLS 1.3 suite'leri: politika AES-256 gerektirmedikçe kütüphane varsayılanları.
  4. Sertifika doğrulama ve hostname kontrolü: her zaman açık.
  5. Yeniden bağlanma stratejisi: mesaj başına bağlantı değil, backoff ile uzun ömürlü bağlantılar.
  6. Oturum devamı: uyuyan cihazlar için, yığının desteklediği yerlerde etkin.
  7. Gözden geçirme: her broker, kütüphane veya firmware güncellemesinden sonra OpenSSL sürüm testlerini yeniden çalıştırın.

Politikayı kısa ve yazılı tutmak denetimleri kolaylaştırır ve devre dışı bırakılmış bir sertifika kontrolü gibi tek seferlik "geçici" istisnaların üretime ulaşmasını engeller.

Sunucu İnce Ayarını Yönetilen Bir Broker'a Bırakın

Kendi barındırdığınız bir broker'da protokol kullanımdan kaldırmalarını, cipher önerilerini ve sertifika yenilemelerini kendiniz takip etmeniz gerekir. Yönetilen bir MQTT broker sunucu tarafını sizin yerinize üstlenir. ConnectMQ, Let's Encrypt sertifikasıyla 8883 portunda TLS ve 8084 portunda güvenli WebSocket sunar; böylece yalnızca yukarıdaki istemci politikasına ihtiyacınız kalır: sertifikayı doğrulayın, TLS 1.2 ve üstüne izin verin ve en iyi seçeneği müzakereye bırakın. Bu yazıdaki ölçümleri kendi ağınızdan çalıştırmak için herkese açık MQTT test broker'ını kullanın.

ConnectMQ ile Başlayın

app.connectmq.com adresinden ConnectMQ'ya kaydolun, kredi kartı gerektirmeyen ücretsiz Serverless planını seçin ve bir broker oluşturun. Yukarıdaki Python veya Node.js örneklerini oluşturulan kimlik bilgilerinizle bu broker'a yönlendirin ve bağlantınızın neyi müzakere ettiğini kontrol edin.

Sık Sorulan Sorular

TLS 1.2 MQTT için hâlâ güvenli mi?

Evet, AES-GCM veya ChaCha20-Poly1305 gibi AEAD şifreleriyle birlikte ECDHE anahtar değişimiyle sınırlandırıldığında güvenlidir. İstemcilerin mümkün olduğunda kullanabilmesi için yanında TLS 1.3'e de izin verin.

TLS 1.3 MQTT mesaj ek yükünü azaltır mı?

Kayda değer ölçüde hayır. Kayıt başına ek yük benzerdir; asıl kazanımlar daha kısa bir handshake, daha güçlü varsayılanlar ve şifrelenmiş sertifikalardır.

IoT cihazları hangi TLS 1.3 cipher suite'ini kullanmalı?

AES hızlandırmalı donanımda TLS_AES_128_GCM_SHA256, hızlandırması olmayan CPU'larda TLS_CHACHA20_POLY1305_SHA256. İkisi de güçlüdür.

MQTT ile 0-RTT early data kullanmalı mıyım?

Genellikle hayır. Early data bir saldırgan tarafından yeniden oynatılabilir ve bağlantılar uzun ömürlü olduğu için MQTT istemcileri bundan çok az kazanç elde eder.

İlgili yazılar

MQTT Kimlik Bilgileri Kesintisiz Nasıl Yenilenir?

Bir filo genelinde MQTT kullanıcı adı ve şifrelerini yenilemek için adım adım çift kimlik bilgisi stratejisi: yeni kimlik bilgisini hazırlayın, geri dönüş seçeneğiyle geçiş yapın, doğrulayın ve ancak ondan sonra eskisini iptal edin.

6 dk okuma

MQTT Kimlik Bilgilerini Gömülü Cihazlarda Güvenle Saklamak

ESP32 ve Linux cihazlarda MQTT kullanıcı adı ve şifrelerini korumanın yollarına pratik bir karşılaştırma; şifrelenmiş NVS ve flash şifrelemeden secure element'lere ve TPM destekli systemd kimlik bilgilerine kadar.

6 dk okuma

Tüm yazılar →

Özel MQTT broker’ınız birkaç tık uzağınızda

Hesabınızı oluşturun, broker kimlik bilgilerinizi alın ve ilk cihazınızı bağlayın — kurulacak, yamalanacak ya da ölçeklendirilecek sunucu yok.