Pico W MQTT TLS, hobi düzeyindeki bir bağlantıyı güvenebileceğiniz bir bağlantıya dönüştüren şeydir: trafik şifrelenir ve kart, parola göndermeden önce gerçekten sizin broker'ınızla konuştuğunu doğrular. Bu rehber çalışan bir MicroPython MQTT programını alıp tam sertifika doğrulamasıyla 8883 portuna taşıyor; ihtiyaç duyduğunuz firmware sürümlerini, yüklenecek kök sertifikayı, saatin neden önemli olduğunu, RP2040 üzerinde el sıkışmanın ne kadar sürdüğünü ve büyük olasılıkla karşılaşacağınız hataları nasıl gidereceğinizi ele alıyor.
Mikrodenetleyicide TLS Neden Önemli?
1883 portundaki düz MQTT, CONNECT paketindeki kullanıcı adı ve parola dahil her şeyi açık metin olarak gönderir. Aynı Wi-Fi ağındaki, internet servis sağlayıcısındaki veya broker'a giden yol üzerindeki herkes ölçümlerinizi okuyabilir ve kimlik bilgilerinizi yeniden kullanabilir. TLS iki sorunu aynı anda çözer:
- Şifreleme. Payload'lar ve kimlik bilgileri iletim sırasında okunamaz.
- Sunucu kimlik doğrulaması. Cihaz broker'ın sertifika zincirini kontrol eder; böylece sahte bir erişim noktası veya DNS ele geçirme saldırısı broker'ı taklit edip kimlik bilgilerini toplayamaz.
İkinci madde, çoğu eğitimin atladığı noktadır. Sertifikayı doğrulamadan TLS'i açmak, pasif dinleyicilere karşı şifreleme sağlar ama aktif bir saldırgana karşı hiçbir koruma sunmaz. Bu rehber işi doğru şekilde yapıyor. Daha geniş bir bakış için MQTT güvenliği en iyi uygulamaları yazımıza göz atın.
Daha önce bir Pico W'yi MQTT'ye bağlamadıysanız, önce düz Raspberry Pi Pico W MQTT eğitimi ile başlayın ve o çalıştıktan sonra buraya dönün.
Firmware ve Kütüphane Sürümleri
MicroPython'daki TLS desteği son birkaç sürümde değişti ve eski örneklerin çoğu yazıldığı haliyle artık çalışmıyor.
| Bileşen | Ne kullanılmalı | Neden |
|---|---|---|
| MicroPython firmware | RPI_PICO_W için güncel bir sürüm (1.23 veya daha yeni) |
load_verify_locations içeren ssl.SSLContext ve doğru hostname işleme sağlar |
umqtt.simple |
mip ile micropython-lib'den güncel sürüm |
Yeni sürümler ssl argümanında bir SSLContext kabul eder |
| Kök sertifika | DER formatında ISRG Root X1 | Let's Encrypt sertifikalarının güven çapası |
Eski örnekler ssl=True ile birlikte bir ssl_params sözlüğü geçirir. Beklenmeyen anahtar kelime argümanlarıyla ilgili bir TypeError ya da AttributeError: 'bool' object has no attribute 'wrap_socket' görüyorsanız, eski bir örneği yeni bir kütüphaneyle (veya tam tersi) karıştırıyorsunuz demektir. Hem firmware'i hem kütüphaneyi güncelleyin ve aşağıdaki context tabanlı kodu kullanın.
Ne çalıştırdığınızı REPL'den kontrol edin:
import sys, os
print(sys.version)
print(os.uname().machine)
Adım 1: Doğru Kök Sertifikayı Edinin
broker.connectmq.com adresindeki genel broker dahil ConnectMQ broker'ları, Let's Encrypt tarafından verilen sertifikaları kullanır. Zinciri kendiniz doğrulayabilirsiniz:
openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -showcerts </dev/null \
| grep -E "s:|i:"
Çıktı sunucu sertifikasını, Let's Encrypt ara sertifikasını ve en sonda ISRG Root X1 yayıncısını listeler. Pico W'nin güvenmesi gereken kök budur. Sunucu sertifikası yerine köke güvenmek önemlidir: Let's Encrypt sertifikaları birkaç ayda bir yenilenir ve ara sertifikalar zaman zaman değişir, ancak kök yıllarca geçerli kalır.
Kökü MicroPython'un doğrudan yükleyebildiği DER formatında indirin:
curl -o isrgrootx1.der https://letsencrypt.org/certs/isrgrootx1.der
# veya elinizdeki bir PEM kopyasını dönüştürün
openssl x509 -in isrgrootx1.pem -outform DER -out isrgrootx1.der
Dosyayı Thonny'nin dosya görünümüyle veya şu komutla karta kopyalayın:
mpremote cp isrgrootx1.der :isrgrootx1.der
Adım 2: Saati Ayarlayın
Pico W'de pille desteklenen bir saat yoktur. Her açılışta gerçek zamanlı saati geçmişteki varsayılan bir tarihten başlar. Firmware derlemesine bağlı olarak sertifika geçerlilik süreleri bu saate göre kontrol edilebilir ve kendini yıllar öncesinde sanan bir cihaz, geçen ay verilmiş bir sertifikayı henüz geçerli değil diye reddeder. Kontrol uygulanmasa bile doğru saat günlük kaydı ve zaman damgaları için faydalıdır; bu yüzden Wi-Fi bağlanır bağlanmaz saati NTP ile ayarlayın:
import ntptime
ntptime.host = "pool.ntp.org"
ntptime.settime() # sets the RTC to UTC
ntptime.settime(), NTP isteği zaman aşımına uğradığında OSError fırlatabilir; programın çökmesine izin vermek yerine birkaç kez yeniden deneyin.
Adım 3: Eksiksiz Pico W MQTT TLS Programı
Bunu main.py olarak kaydedin. Genel test broker'ı için kimlik bilgileri boş kalabilir ve benzersiz herhangi bir client ID çalışır. Üretim için portalda oluşturulan değerleri girin.
# main.py - Pico W MQTT over TLS with certificate verification
import time
import gc
import ssl
import network
import machine
import ntptime
import ubinascii
from umqtt.simple import MQTTClient
WIFI_SSID = "YOUR_WIFI_SSID"
WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"
BROKER = "broker.connectmq.com"
PORT = 8883
# Public test broker: anonymous, any unique client ID.
# Production: use the values from the broker portal.
MQTT_USER = None # "YOUR_USERNAME"
MQTT_PASSWORD = None # "YOUR_PASSWORD"
CLIENT_ID = "pico-tls-" + ubinascii.hexlify(machine.unique_id()).decode() # or "YOUR_CLIENT_ID"
TOPIC = "connectmq/demo/tl5v8n/pico1/temperature"
CA_FILE = "isrgrootx1.der"
sensor = machine.ADC(4)
def connect_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
wlan.connect(WIFI_SSID, WIFI_PASSWORD)
for _ in range(40):
if wlan.isconnected():
break
time.sleep(0.5)
if not wlan.isconnected():
raise OSError("Wi-Fi failed, status %d" % wlan.status())
print("Wi-Fi:", wlan.ifconfig()[0])
def sync_time():
for attempt in range(5):
try:
ntptime.settime()
print("Time set:", time.gmtime())
return
except OSError:
time.sleep(2)
print("Warning: NTP failed, clock may be wrong")
def make_ssl_context():
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ctx.verify_mode = ssl.CERT_REQUIRED
with open(CA_FILE, "rb") as f:
ctx.load_verify_locations(cadata=f.read())
return ctx
def connect_mqtt(ctx):
gc.collect()
print("Free RAM before TLS:", gc.mem_free())
client = MQTTClient(
CLIENT_ID, BROKER, port=PORT,
user=MQTT_USER, password=MQTT_PASSWORD,
keepalive=60, ssl=ctx,
)
start = time.ticks_ms()
client.connect()
print("TLS + MQTT connect took", time.ticks_diff(time.ticks_ms(), start), "ms")
print("Free RAM after TLS:", gc.mem_free())
return client
def read_temperature():
v = sensor.read_u16() * 3.3 / 65535
return round(27 - (v - 0.706) / 0.001721, 2)
def main():
connect_wifi()
sync_time()
ctx = make_ssl_context()
client = connect_mqtt(ctx)
while True:
payload = '{"value": %s, "unit": "C"}' % read_temperature()
client.publish(TOPIC, payload, qos=1)
print("Published", payload)
time.sleep(30) # publishing every 30 s keeps the 60 s keepalive satisfied
while True:
try:
main()
except OSError as e:
print("Error:", e, "- reconnecting in 10 s")
time.sleep(10)
umqtt.simple, soketi context ile sarar ve broker adını sunucu hostname'i olarak iletir. mbedTLS'in sertifikanın broker.connectmq.com için verildiğini kontrol edebilmesini sağlayan budur; ayrıca pek çok TLS sunucusunun doğru sertifikayı seçmek için ihtiyaç duyduğu SNI bilgisini de gönderir.
Çıktıyı bilgisayarınızdan, yine TLS üzerinden izleyin:
mosquitto_sub -h broker.connectmq.com -p 8883 --cafile isrgrootx1.pem \
-i laptop-tl5v8n -v -t "connectmq/demo/tl5v8n/#"
RP2040'ta El Sıkışma Süresi ve Bellek
RP2040'ta donanımsal kriptografi hızlandırması yoktur; bu nedenle mbedTLS tüm işi Cortex-M0+ çekirdeklerinde yazılımla yapar. TLS el sıkışmasının, neredeyse anlık olan düz TCP bağlantısına kıyasla belirgin biçimde fark edilir olmasını, çoğu zaman bir saniye veya daha uzun sürmesini bekleyin. Program kendi ağınızdaki kesin değeri yazdırır; bu değeri kaydetmeye değer, çünkü müzakere edilen anahtar değişimine, sertifika zincirinin uzunluğuna ve Wi-Fi gecikmesine bağlıdır.
Bunun pratikteki anlamı:
- Bir kez bağlanın, bağlı kalın. Şebeke elektriğiyle çalışırken uzun ömürlü tek bir TLS oturumu tutun ve onun üzerinden çok sayıda mesaj gönderin. El sıkışma maliyeti yalnızca yeniden bağlanırken ödenir.
- Derin uyku tasarımlarında dikkatli olun. Uyanan, bağlanan, yayınlayan ve uyuyan pilli bir cihaz her döngüde el sıkışmanın tamamını öder; bu da zaman ve enerji demektir. Pico W pilli MQTT rehberimiz bu durum için daha uzun aralıkları ve toplu gönderimi ele alıyor.
- Önce belleği boşaltın. Bir TLS oturumu tamponlar için onlarca kilobayt RAM gerektirir. Bağlanmadan önce
gc.collect()çağırın, el sıkışmadan önce büyük nesneler oluşturmaktan kaçının ve öncesinde ve sonrasında yazdırılan boş bellek değerlerini karşılaştırın. - Pico 2 W'yi değerlendirin. RP2350 daha hızlı Cortex-M33 çekirdekleri kullanır; bu da el sıkışmayı kısaltır ve daha fazla pay bırakır. Bkz. Pico W ve Pico 2 W karşılaştırması.
Pico W TLS Hatalarını Giderme
| Hata veya belirti | Olası neden | Çözüm |
|---|---|---|
OSError: (-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED') |
Yanlış veya eksik kök sertifika ya da yanlış hostname | ISRG Root X1'i yükleyin, IP yerine hostname ile bağlanın |
| Doğrulama yalnızca açılıştan sonra başarısız oluyor | Saat ayarlanmamış | Bağlanmadan önce ntptime.settime() çalıştırın |
OSError: [Errno 12] ENOMEM |
TLS tamponları için yeterli bitişik RAM yok | Bağlanmadan önce gc.collect(), tamponları ve global değişkenleri azaltın |
MQTTClient(... ssl_params=...) üzerinde TypeError |
Yeni umqtt.simple ile eski örnek |
ssl= olarak bir SSLContext geçirin |
| 1883'te bağlantı çalışıyor ama 8883'te zaman aşımı | Ağ 8883'ü engelliyor | Aynı ağdaki bir dizüstü bilgisayardan test edin; farklı bir ağ kullanın veya BT ekibinden giden 8883 trafiğine izin vermesini isteyin |
MQTTException: 5 |
Yetkisiz | Portaldaki kullanıcı adını, parolayı ve tam client ID'yi kontrol edin |
| El sıkışma çok uzun sürüyor | Zayıf Wi-Fi sinyali veya RAM baskısı | wlan.status("rssi") ile RSSI'yi ve boş belleği kontrol edin |
CERT_NONE hakkında bir not: ctx.verify_mode = ssl.CERT_NONE ayarı hataları ortadan kaldırır; pek çok forum cevabında bu yüzden karşınıza çıkar. Ancak sunucu kimlik doğrulamasını da kaldırır. Yalnızca tek seferlik bir teşhis için kullanın, sahada çalışan kodda asla kullanmayın.
Kendi Özel Broker'ınıza Geçiş
Genel broker 8883 portunda anonim TLS bağlantılarını kabul eder; bu kodu test etmek için mükemmeldir. Gerçek cihazlar için ConnectMQ üzerinde özel bir broker oluşturun ve oluşturulan kimlik bilgilerini programın başındaki üç ayara kopyalayın. Broker client ID'leri verilen kimlik bilgilerine bağlar; bu yüzden portaldaki client ID'yi birebir kullanın. Sertifika Let's Encrypt'ten geldiği için aynı isrgrootx1.der dosyası hem genel hem de özel broker'ınızda çalışır ve broker tarafındaki sertifika yenilemeleri cihazda herhangi bir değişiklik gerektirmez.
Tam yönetilen bir MQTT hizmeti ayrıca tekrarlanan başarısız oturum açma denemelerinden sonra IP adreslerini engeller ve plan bazında kotalar uygular; bu da sizin tarafınızda hiçbir iş gerektirmeden broker'ınızı hatalı davranan veya ele geçirilmiş istemcilerden korur. Broker'ları bulutta çalıştırma hakkında daha fazlası için bulut MQTT broker rehberimize, diğer Raspberry Pi projeleri için de Raspberry Pi MQTT eğitimi yazımıza bakın.
Pico W'nizi ConnectMQ ile Güvence Altına Alın
app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz bir Serverless broker oluşturun, kullanıcı adını, parolayı ve client ID'yi main.py dosyasına kopyalayın; Pico W'niz 8883 portunda doğrulanmış TLS üzerinden yayın yapmaya başlar. Portaldaki canlı topic gezgini gelen mesajları gösterir; böylece güvenli yolu uçtan uca doğrulayabilirsiniz.
Sık Sorulan Sorular
Pico W'nin ConnectMQ için hangi sertifikaya ihtiyacı var?
DER formatında ISRG Root X1, yani Let's Encrypt kök sertifikası. Köke güvenmek, broker'daki rutin sertifika yenilemelerinin cihazın güncellenmesini gerektirmemesi anlamına gelir.
Pico W'm neden geçerli bir sertifikayı reddediyor?
En yaygın nedenler hiç ayarlanmamış bir saat (bu durumda sertifika henüz geçerli değilmiş gibi görünür), hostname yerine IP adresiyle bağlanmak veya yanlış kök sertifikayı yüklemektir.
Pico W'de TLS el sıkışması ne kadar sürer?
RP2040 tüm kriptografiyi yazılımla yaptığı için kriptografi donanımı olan çiplere göre belirgin şekilde daha yavaştır. Yukarıda gösterildiği gibi connect() çağrısının etrafında time.ticks_ms() ile ölçün ve her mesaj için yeniden bağlanmak yerine bağlantıları açık tutun.
Pico W'de istemci sertifikası kullanabilir miyim?
MicroPython'un SSLContext sınıfı, istemci sertifikaları için load_cert_chain desteği sunar. Broker cihazların kimliğini portalda verilen kullanıcı adı, parola ve client ID ile doğrular; bu yüzden standart kurulum, bu kimlik bilgileriyle sunucusu doğrulanmış bir TLS bağlantısıdır.



