MQTT Güvenliği

MQTT SSL Certificate Verify Failed Hatası: Python İstemcilerini Düzeltme

Python MQTT istemciniz 8883 portuna bağlanırken "[SSL: CERTIFICATE_VERIFY_FAILED]" hatası mı alıyor? Doğrulamayı devre dışı bırakmadan, tam nedeni bulup her platformda doğru şekilde nasıl düzelteceğinizi burada bulabilirsiniz.

8883 portunda reddedilen bir sertifika zincirini gösteren Python terminaliyle SSL certificate verify failed MQTT hatası illüstrasyonu
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

"ssl certificate verify failed" MQTT hatası, Python'un TLS handshake sırasında broker'ın sertifikasını reddettiği anlamına gelir. Bu, görevini yapan bir güvenlik özelliğidir ve çözüm neredeyse hiçbir zaman onu kapatmak değildir. Bu rehber, çalıştığı bilinen bir referans olarak 8883 portunda broker.connectmq.com'u kullanarak hata mesajından tam nedeni nasıl okuyacağınızı ve bunu paho-mqtt ile Windows, macOS, Linux ve Docker'da nasıl doğru şekilde düzelteceğinizi gösterir.

Hata Mesajını Okumak

Tam istisna genellikle şöyle görünür:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed:
unable to get local issuer certificate (_ssl.c:1000)

Önemli olan iki noktadan sonraki kısımdır. Yaygın varyantlar farklı nedenlere işaret eder:

Mesaj ayrıntısı Anlamı En olası çözüm
unable to get local issuer certificate Python zinciri imzalayan kök CA'yı bulamıyor CA paketini onarın veya sağlayın
self-signed certificate in certificate chain Bir şey, güvenilmeyen özel bir CA tarafından imzalanmış sertifika sundu Proxy veya antivirüs denetimi ya da yapılandırmadığınız özel bir broker CA'sı
Hostname mismatch, certificate is not valid for '...' Bağlandığınız ad sertifikada yok IP yerine doğru hostname ile bağlanın
certificate has expired Saat yanlış veya sunucu sertifikasının süresi dolmuş Sistem saatini düzeltin veya sunucu sertifikasını yenileyin

Adım 1: Python'un Broker'ı Doğrulayabildiğini Teyit Edin

Bu kısa betik, paho-mqtt'nin varsayılan olarak kullandığı ayarların aynısını kullanarak TLS'i MQTT olmadan test eder:

import socket
import ssl

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

ctx = ssl.create_default_context()
print("OpenSSL:", ssl.OPENSSL_VERSION)
print("Default verify paths:", ssl.get_default_verify_paths())

with socket.create_connection((HOST, PORT), timeout=10) as sock:
    with ctx.wrap_socket(sock, server_hostname=HOST) as tls:
        cert = tls.getpeercert()
        print("Connected with", tls.version())
        print("Issuer:", dict(x[0] for x in cert["issuer"]))
        print("Valid until:", cert["notAfter"])

Bu betik aynı hatayla başarısız olursa sorun Python ortamının güven deposunda, saatte veya ağdadır. Başarılı olup MQTT kodunuz başarısız oluyorsa sorun MQTT istemcisinin nasıl yapılandırıldığındadır: yanlış bir ca_certs yolu, IP ile bağlanma veya özel sertifikalı bir broker.

Adım 2: Doğru Bir paho-mqtt TLS Kurulumu Kullanın

paho-mqtt 2.x ile, ConnectMQ dahil herkesçe güvenilen sertifikaya sahip herhangi bir broker'a karşı çalışan temel kurulum şudur:

import ssl
import time
import certifi
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
TOPIC = "connectmq/demo/a8d2/verify-test"

def on_connect(client, userdata, flags, reason_code, properties):
    print("CONNACK:", reason_code)
    client.subscribe(TOPIC)
    client.publish(TOPIC, "certificate verified")

def on_message(client, userdata, msg):
    print("Received:", msg.payload.decode())

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="py-verify-a8d2")
client.on_connect = on_connect
client.on_message = on_message

# certifi, işletim sistemi deposundan bağımsız olarak Mozilla'nın CA paketini içerir
client.tls_set(ca_certs=certifi.where(), cert_reqs=ssl.CERT_REQUIRED)

# Özel ConnectMQ broker:
# client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")

client.connect(BROKER, 8883, keepalive=60)
client.loop_start()
time.sleep(3)
client.loop_stop()
client.disconnect()

Bağımlılıkları pip install "paho-mqtt>=2.0" certifi ile kurun. certifi.where() vermek, davranışı her işletim sisteminde aynı hale getirir; bu da çoğu zaman en hızlı kalıcı çözümdür. CA listeleri zamanla değiştiği için certifi'yi güncel tutun.

Her Platform İçin Çözümler

macOS

python.org'dan alınan Python yükleyicileri kendi OpenSSL'lerini içerir ve macOS Keychain'i kullanmaz. Birlikte gelen betiği çalıştırana kadar hiç CA sertifikaları yoktur; bu da unable to get local issuer certificate hatasını üretir. Yükleyicinin sertifika betiğini çalıştırarak düzeltin:

/Applications/Python\ 3.12/Install\ Certificates.command

Sürüm numarasını kurulumunuzla eşleşecek şekilde ayarlayın. Homebrew Python, Homebrew'un CA paketini kullanır ve genellikle kutudan çıktığı gibi çalışır; çalışmazsa brew reinstall ca-certificates komutunu çalıştırın. certifi.where() değerini açıkça kullanmak her iki durumda da sorunu önler.

Windows

Windows'ta Python sertifikaları Windows sertifika deposundan yükler. Hatalar genellikle iki nedenden birinden kaynaklanır:

  • Güncelleme almamış bir makinede güncel olmayan bir kök deposu; bu durumda daha yeni bir kök eksiktir. Windows güncellemelerini yükleyin veya certifi kullanın.
  • Antivirüs veya kurumsal bir proxy tarafından yapılan TLS denetimi; bu self-signed certificate in certificate chain hatasını üretir. Adım 1 betiğinin yazdırdığı issuer'ı kontrol edin; bir güvenlik ürününün adını içeriyorsa o ürün bağlantının arasına giriyordur.

Linux

Python, OpenSSL'in varsayılan yollarını kullanır; bunlar genellikle Debian ve Ubuntu'da /etc/ssl/certs/ca-certificates.crt, Red Hat tabanlı sistemlerde ise /etc/pki/tls/certs/ca-bundle.crt dosyasıdır. Paket eksik veya eskiyse:

# Debian / Ubuntu / Raspberry Pi OS
sudo apt update && sudo apt install --reinstall ca-certificates
sudo update-ca-certificates

# Fedora / RHEL
sudo dnf reinstall ca-certificates

Docker ve Slim İmajlar

python:3.12-slim gibi imajlar genellikle CA sertifikalarını içerir, ancak alpine ve distroless varyantları içermeyebilir. Paketi açıkça ekleyin:

FROM python:3.12-alpine
RUN apk add --no-cache ca-certificates

Ya da imaja certifi kurun ve kodda ona başvurun. OpenSSL'i SSL_CERT_FILE ortam değişkeniyle bir pakete de yönlendirebilirsiniz.

Hostname Uyuşmazlığı Varyantı

Hostname mismatch, client.connect("203.0.113.10", 8883) çağırdığınızda veya sertifikada bulunmayan dahili bir takma ad kullandığınızda ortaya çıkar. TLS, istediğiniz adın sertifikanın Subject Alternative Names listesinde yer aldığını kontrol eder. Broker'ın gerçek hostname'iyle bağlanın. ConnectMQ için bu broker.connectmq.com adresidir. Test için belirli bir IP'yi zorlamanız gerekiyorsa IP ile bağlanmak yerine onu hosts dosyanıza ekleyin.

Özel veya Kendinden İmzalı Broker'lar

Özel bir CA ile kendi broker'ınızı çalıştırıyorsanız, herkese açık CA paketi ona asla güvenmez. Özel CA'yı client.tls_set(ca_certs="my-ca.crt") ile açıkça verin ve broker sertifikasının SAN alanında doğru hostname'i içerdiğinden emin olun. Süreç ve bakım yükü MQTT için kendinden imzalı sertifikalar yazısında açıklanır.

Zinciri OpenSSL ile İncelemek

Python çıktısı yeterli olmadığında OpenSSL, sunucunun gönderdiği tam zinciri ve doğrulamanın nerede durduğunu gösterir:

openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -showcerts </dev/null

Certificate chain bölümünü yukarıdan okuyun: 0 numaralı kayıt broker sertifikasıdır, sonraki kayıtlar ara sertifikalardır ve her i: (issuer) satırı bir sonraki kaydın s: (subject) satırıyla eşleşmelidir. Son Verify return code, OpenSSL'in kendi güven deposunun zinciri kabul edip etmediğini söyler. OpenSSL 0 (ok) deyip Python başarısız oluyorsa Python, OpenSSL'den farklı bir güven deposu kullanıyordur; Adım 1'deki gibi ssl.get_default_verify_paths() çıktısını yazdırmak bunu genellikle ortaya çıkarır. 0 numaralı kaydın issuer'ı antivirüs veya güvenlik duvarı üreticinizin adını içeriyorsa gerçek broker sertifikasına değil, TLS denetimine bakıyorsunuzdur.

Özellikle certifi ile karşılaştırmak için python -c "import certifi; print(certifi.where())" komutunun yazdırdığı yolla -CAfile ekleyin. certifi ile başarı ve onsuz başarısızlık, sorunun işletim sistemi deposunda olduğunu doğrular.

Yapılmaması Gerekenler

Arama sonuçları sıklıkla şu satırları önerir:

client.tls_set(cert_reqs=ssl.CERT_NONE)
client.tls_insecure_set(True)

Bunlar sunucu kimlik doğrulamasını devre dışı bırakarak hatayı ortadan kaldırır. Kimlik bilgileriniz bu durumda, bir saldırgan dahil, yanıt veren herhangi bir sunucuya gider. Kullanacaksanız bile yalnızca bir laboratuvar broker'ına karşı birkaç dakikalık yerel hata ayıklama için kullanın; asla commit edilen kodda değil. MQTT güvenliği en iyi uygulamaları yazısı, broker'ın kimlik doğrulamasının neden şifreleme kadar önemli olduğunu açıklar.

Hızlı Çözüm Kontrol Listesi

  1. certificate verify failed sonrasındaki ayrıntıyı okuyun.
  2. Adım 1 betiğini aynı ortamda çalıştırın.
  3. ca_certs olarak certifi.where() kullanın veya işletim sistemi deposunu onarın.
  4. IP ile değil hostname ile bağlanın.
  5. Saat sorunları için date -u çıktısını kontrol edin.
  6. Proxy'leri tespit etmek için sertifikanın issuer'ına bakın.
  7. Özel broker'lar için kendi CA dosyanızı sağlayın.

Handshake düzeltildikten sonra hâlâ takılıyorsanız MQTT TLS handshake hatalarını düzeltme rehberimiz portları, SNI'ı ve protokol sürümlerini ele alır; Python MQTT TLS eğitimi ise eksiksiz üretim desenlerini gösterir.

Herkese Açık Sertifikalar Neden Zaman Kazandırır?

Sertifika doğrulama hatalarının çoğu, broker herkesçe güvenilen bir CA'dan alınmış bir sertifika kullandığında ve onu otomatik olarak yenilediğinde ortadan kalkar. ConnectMQ böyle çalışır: 8883 ve 8084 portlarında Let's Encrypt sertifikasına sahip barındırılan bir MQTT broker; böylece standart Python kurulumları onu ek dosya olmadan doğrular. Özel kimlik bilgilerine geçmeden önce bu makaledeki her testi ücretsiz herkese açık MQTT broker üzerinde yeniden üretebilirsiniz.

ConnectMQ ile Başlayın

app.connectmq.com adresinden kaydolun, kredi kartı gerektirmeyen ücretsiz Serverless planı seçin, bir broker oluşturun ve yukarıdaki paho-mqtt örneğini oluşturulan kullanıcı adı, parola ve client ID ile çalıştırın.

Sık Sorulan Sorular

Aynı kod neden Linux'ta çalışıp macOS'ta başarısız oluyor?

python.org macOS derlemesi, "Install Certificates.command" çalıştırılana kadar CA sertifikaları olmadan gelir. Linux Python ise genellikle zaten kurulu olan sistem paketini kullanır.

İşletim sistemi deposu yerine certifi kullanmak güvenli mi?

Evet. certifi, Mozilla'nın özenle seçilmiş kök listesini paketler. Yalnızca pip ile güncel tutun ve özel veya kurumsal CA'ları içermeyeceğini unutmayın.

Bu hata broker'ın ele geçirildiği anlamına mı gelir?

Nadiren. Eksik CA paketleri, yanlış hostname'ler, saat sorunları ve TLS denetimi çok daha yaygındır. Emin olmak için issuer adını kontrol edin.

ConnectMQ sertifika dosyasına ihtiyacım var mı?

Hayır. ConnectMQ herkesçe güvenilen bir Let's Encrypt sertifikası kullanır; bu nedenle certifi veya işletim sistemi deposu gibi standart bir CA paketi yeterlidir.

İ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

MQTT Erişim Kontrol Listeleri (ACL): Kavramlar ve Tasarım

MQTT erişim kontrol listelerinin ne olduğu, Mosquitto gibi broker'ların topic düzeyinde okuma ve yazma kurallarını nasıl ifade ettiği, reddedilen işlemlerin nasıl davrandığı ve yetkilendirmenin basit kalması için topic namespace'lerinin nasıl tasarlanacağı.

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.