Cihazlarda MQTT kimlik bilgilerini korumak, cihazınızın broker'a ulaşmak için kullandığı kullanıcı adı ve şifrenin firmware imajlarından, dökümü alınmış flash çiplerinden, hata ayıklama portlarından veya günlük dosyalarından okunamamasını sağlamak demektir. Bu rehber ESP32 ve Linux cihazlardaki pratik seçenekleri karşılaştırıyor, her biri için yapılandırmayı gösteriyor ve sahada kimlik bilgilerini en sık sızdıran hataları listeliyor.
Sade Bir Dille Tehdit Modeli
Bir depolama yöntemi seçmeden önce kime karşı savunma yaptığınızı netleştirin:
| Saldırgan | Erişim | Ne denediği |
|---|---|---|
| Firmware dosyanıza sahip biri | Bir indirme sayfasından veya destek kaydından gelen .bin |
İmajda metin araması yapmak |
| Bir cihaza sahip biri | Fiziksel erişim, bir USB-seri adaptör | UART üzerinden flash dökümü almak, JTAG bağlamak |
| Cihazdaki bir zararlı yazılım veya hata | Cihazda çalışan kod | Dosyaları veya belleği okumak |
| Ağdaki biri | Paket yakalama | Şifreyi CONNECT'ten okumak |
Ağ saldırganı, her ConnectMQ broker'ının Let's Encrypt sertifikasıyla desteklediği 8883 portundaki (WebSocket için 8084) TLS ile ele alınır; MQTT kullanıcı adı şifre doğrulama yazısı, kimlik bilgilerinin neden asla 1883 portu üzerinden taşınmaması gerektiğini açıklar. Bu yazı diğer üçüne odaklanıyor: sırrın cihazda beklemedeyken korunması.
Sıfırıncı Kural: Kimlik Bilgilerinin Firmware'de Yeri Yoktur
Kaynak koddaki bir #define MQTT_PASSWORD "...", firmware ikili dosyasına, Git geçmişinize, CI günlüklerine ve imajın her kopyasına düşer. Tipik bir hobi projesinde strings firmware.bin | grep -i pass çalıştırmak çoğu zaman şifreyi saniyeler içinde bulur. Firmware her cihaz için aynı olmalıdır; kimlik bilgileri ise cihaz başına benzersiz olmalıdır. Bunları ayrı tutun ve kimlik bilgilerini güvenli IoT cihaz provizyonu sırasında depolamaya yazın.
ESP32'deki Seçenekler
Düz NVS (Temel Seviye, Güvenli Değil)
Non-Volatile Storage kütüphanesi (veya Arduino Preferences sarmalayıcısı) anahtar-değer çiftlerini bir flash bölümünde saklar. Kimlik bilgilerini firmware'den ayırır, bu zaten bir iyileştirmedir, ancak veri şifrelenmeden saklanır. Flash çipini okuyabilen herkes şifreyi okuyabilir.
NVS Şifreleme ve Flash Şifreleme
ESP-IDF, NVS bölümlerini şifreleyebilir. Klasik yöntemde NVS şifreleme anahtarları ayrılmış bir nvs_keys bölümünde bulunur ve bu bölüm, anahtarı yazılımın geri okuyamadığı eFuse'larda saklanan flash şifreleme ile korunur. ESP32-S3 ve ESP32-C3 gibi daha yeni çipler, nvs_keys bölümü olmadan NVS anahtarlarını bir eFuse anahtarından türeten HMAC tabanlı bir yöntemi de destekler.
Şifrelenmiş bir anahtar bölümü içeren bölüm tablosu:
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, , 0x6000,
nvs_keys, data, nvs_keys, , 0x1000, encrypted
phy_init, data, phy, , 0x1000,
factory, app, factory, , 1M,
İlgili sdkconfig seçenekleri:
CONFIG_SECURE_FLASH_ENC_ENABLED=y
CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE=y
CONFIG_NVS_ENCRYPTION=y
CONFIG_SECURE_BOOT=y
CONFIG_SECURE_BOOT_V2_ENABLED=y
Release modu önemlidir: geliştirme modu düz metin imajları yeniden flaşlamanın yollarını açık bırakır, bu da sevk edilen ünitelerde amacı boşa çıkarır. Secure Boot, imzalamadığınız firmware'i çalıştırmayı reddederek şifrelemeyi tamamlar; böylece bir saldırgan şifresi çözülmüş kimlik bilgilerini okuyup yazdıran bir kod flaşlayamaz. Her ikisi de eFuse'ları geri dönüşsüz biçimde yakar; bu yüzden önce yedek kartlarda test edin ve Espressif flash şifreleme dokümantasyonunu adım adım izleyin.
ESP32 üzerinde Arduino kullanan bir sketch'te kimlik bilgilerini okumak, NVS şifreli olsun ya da olmasın aynı görünür; asıl mesele de budur: koruma API'nin altındadır.
#include <Preferences.h>
struct MqttCreds { String user, pass, clientId; };
bool loadCreds(MqttCreds &c) {
Preferences prefs;
if (!prefs.begin("mqtt", true)) return false; // salt okunur
c.user = prefs.getString("user", "");
c.pass = prefs.getString("pass", "");
c.clientId = prefs.getString("cid", "");
prefs.end();
return c.user.length() && c.pass.length() && c.clientId.length();
}
void logCreds(const MqttCreds &c) {
// Kimliği günlüğe yaz, şifreyi asla
Serial.printf("MQTT user=%s clientId=%s pass=<%u bytes>\n",
c.user.c_str(), c.clientId.c_str(), c.pass.length());
}
Secure Element'ler
Microchip'in ATECC608'i gibi bir secure element, anahtarları saklayan ve özel anahtarları asla dışarı vermeden kriptografik işlemler gerçekleştiren ayrı bir çiptir. En güçlü olduğu alan, karşılıklı TLS için özel anahtarın çipten hiç çıkmadığı sertifika tabanlı kimliktir. Şifre ile kimlik doğrulamada da bir secure element, flash'taki şifre bloğunu şifrelemek için kullanılan anahtarı tutarak fiziksel çıkarmayı zorlaştırabilir. Malzeme maliyeti, kart alanı ve sürücü entegrasyonu ekler; bu yüzden en çok yüksek değerli veriye veya regülasyon baskısına sahip ürünlerde görülür.
Linux Cihazlardaki Seçenekler
Linux çalıştıran ağ geçitleri ve uç bilgisayarlar daha zengin araçlara sahiptir.
Dosya İzinleri (Temel Seviye)
Kimlik bilgilerini uygulama dizininin dışında, yalnızca servis hesabının okuyabildiği bir dosyada saklayın:
sudo install -d -m 0700 -o mqttsvc -g mqttsvc /etc/mqtt-agent
sudo install -m 0600 -o mqttsvc -g mqttsvc credentials.env /etc/mqtt-agent/credentials.env
Bu, diğer kullanıcılara ve servislere karşı korur, SD kartı çıkaran birine karşı değil. Fiziksel koruma için tam disk şifrelemeyle birleştirin.
TPM ile systemd Şifreli Kimlik Bilgileri
systemd ve TPM 2.0 çipine sahip sistemlerde systemd-creds, bir sırrı yalnızca o makinede ve yalnızca onu tanımlayan servis için çözülebilecek şekilde şifreler:
# Şifreyi bu makinenin TPM'ine bağlı olarak şifrele
echo -n 'YOUR_PASSWORD' | sudo systemd-creds encrypt --with-key=tpm2 \
--name=mqtt-password - /etc/credstore.encrypted/mqtt-password
# /etc/systemd/system/mqtt-agent.service
[Unit]
Description=MQTT telemetry agent
After=network-online.target
Wants=network-online.target
[Service]
User=mqttsvc
LoadCredentialEncrypted=mqtt-password:/etc/credstore.encrypted/mqtt-password
Environment=MQTT_USERNAME=YOUR_USERNAME MQTT_CLIENT_ID=YOUR_CLIENT_ID
ExecStart=/usr/bin/python3 /opt/mqtt-agent/agent.py
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Servis, şifresi çözülmüş sırrı özel, bellek içi bir dizinden okur:
import os
import ssl
import paho.mqtt.client as mqtt
cred_dir = os.environ["CREDENTIALS_DIRECTORY"]
with open(os.path.join(cred_dir, "mqtt-password")) as f:
password = f.read().strip()
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=os.environ["MQTT_CLIENT_ID"],
protocol=mqtt.MQTTv5)
client.username_pw_set(os.environ["MQTT_USERNAME"], password)
client.tls_set(cert_reqs=ssl.CERT_REQUIRED)
client.connect("YOUR_BROKER_HOST", 8883, keepalive=60)
client.loop_forever()
Kopyalanmış bir disk imajı başka bir makinede işe yaramaz, çünkü TPM kimlik bilgisinin mührünü açmaz.
Depolama Seçeneklerinin Karşılaştırması
| Yöntem | Platform | Firmware sızıntılarına karşı korur | Flash dökümüne karşı korur | Efor |
|---|---|---|---|---|
| Firmware'e sabit kodlanmış | Herhangi | Hayır | Hayır | Yok |
| Düz NVS / yapılandırma dosyası | ESP32 / Linux | Evet | Hayır | Düşük |
| NVS şifreleme ve flash şifreleme, Secure Boot | ESP32 | Evet | Evet | Orta, geri dönüşsüz eFuse'lar |
| Secure element | ESP32, Linux | Evet | Evet, anahtarlar için en güçlü | Yüksek |
| Dosya izinleri ve disk şifreleme | Linux | Evet | Kısmen | Düşük ila orta |
| TPM ile systemd-creds | Linux | Evet | Evet | Orta |
Bellekte, Yedeklerde ve Güncellemelerde Kimlik Bilgileri
Şifrelenmiş depolama kimlik bilgisini beklemedeyken korur, ancak CONNECT paketini oluşturmak için yine de RAM'de şifresinin çözülmesi gerekir. Birkaç alışkanlık, yolun geri kalanındaki maruziyeti azaltır:
- Tek bir yerde tutun. Kimlik bilgisini global metinlere, yapılandırma yapılarına ve tanılama nesnelerine kopyalamak yerine MQTT modülüne ait tek bir arabelleğe bir kez yükleyin.
- Tanılamanın dışında tutun. Çekirdek dökümleri, çökme raporları ve uzaktan günlük yüklemeleri kimlik bilgisi deposunu asla içermemelidir. Linux'ta kimlik bilgisi dosyasını yedekleme setlerinin ve destek paketlerinin dışında tutun.
- Bulut üzerinden gidip gelmesine izin vermeyin. Cihazın ayarlarını backend'inize yükleyen bir yapılandırma senkronizasyon özelliği, kimlik bilgisi alanlarını tamamen atlamalıdır.
- Güncellemeleri atomik olarak yazın. Yenileme sırasında yeni bir kimlik bilgisi geldiğinde onu ikinci bir yuvaya yazın ve yalnızca başarılı bir bağlantıdan sonra geçiş yapın; böylece bir elektrik kesintisi cihazı yarım yazılmış bir şifreyle bırakamaz.
- Hizmetten çıkarırken silin. NVS namespace'ini veya kimlik bilgisi dosyasını fabrika ayarlarına sıfırlama ve hizmetten çıkarma prosedürlerinin bir parçası olarak silin.
Kimlik Bilgilerini Sızdıran Hatalar
Şifreyi hata ayıklama günlüklerine veya çökme dökümlerine yazdırmak.
Şifreyi HTML'de maskelenmiş olsa bile "kolaylık olsun diye" bir cihaz web sayfasında göstermek.
Şifreyi retained bir MQTT mesajında saklamak veya paylaşılan bir topic'e göndermek.
Üretim ünitelerinde UART indirme modunu ve JTAG'i etkin bırakmak.
Tüm filo için tek bir kimlik bilgisi kullanmak; böylece tek bir çıkarma her şeyi tehlikeye atar.
Hiç yenilememek; böylece yıllar önce sızan bir kimlik bilgisi hâlâ çalışır.
madde özellikle vurgulanmayı hak ediyor. ConnectMQ'da her client ID kendisine verilen kimlik bilgilerine bağlıdır; bu yüzden her cihaza kendi setini verin. Böylece çıkarılan bir şifre yalnızca bir cihazı açığa çıkarır, siz de onu MQTT kimlik bilgilerinin nasıl yenileneceğini anlatan süreçle iptal edip değiştirebilirsiniz. Tenant izolasyonu, ele geçirilmiş bir cihazın kimlik bilgilerinin bile yalnızca kendi broker'ınıza ulaşması anlamına gelir; tekrarlanan başarısız girişlerden sonra IP engelleme de başka şifreleri tahmin etmeye çalışan saldırganları yavaşlatır. Daha geniş kontrol seti MQTT güvenliği en iyi uygulamaları yazısında ele alınıyor.
ConnectMQ ile Başlayın
Cihazdaki korumalı depolamayı, TLS ve kimlik bilgisi verme işlerini sizin için üstlenen bir tam yönetilen MQTT servisi ile birleştirin. app.connectmq.com adresinde kredi kartı gerekmeden ücretsiz bir Serverless broker oluşturun ve ESP32 veya Linux kimlik bilgisi depolamanızı gerçek bir TLS uç noktasına karşı test edin. Donanım tarafında yeniyseniz ESP32 MQTT eğitimi iyi bir başlangıç noktasıdır; bulut MQTT broker rehberi de barındırma seçeneklerini açıklar.
Sık Sorulan Sorular
ESP32 Preferences kütüphanesi MQTT şifreleri için güvenli mi?
Yalnızca NVS şifreleme ve flash şifreleme etkinse. Bunlar olmadan Preferences veriyi flash'ta düz metin olarak saklar; fiziksel erişimi olan herkes bunun dökümünü alabilir.
MQTT kimlik bilgileri için bir secure element'e ihtiyacım var mı?
Her zaman değil. Flash şifreleme ve Secure Boot ile şifrelenmiş depolama birçok ürün için yeterlidir; secure element en çok sertifika tabanlı kimlik veya yüksek değerli kurulumlar için değerlidir.
Bir Linux ağ geçidi MQTT şifresini nerede saklamalı?
En azından servis hesabına ait 0600 izinli bir dosyada. TPM mevcut olduğunda systemd şifreli kimlik bilgileri sırrı o makineye bağlar.
TLS, cihazda saklanan kimlik bilgilerini korur mu?
Hayır. TLS kimlik bilgilerini iletim sırasında korur. Depolama koruması, cihazın kendisinde ihtiyaç duyduğunuz ayrı bir katmandır.



