שליטה ב-ESP8266 בלי העברת פורט: נתיב MQTT יוצא
broker נגיש מהאינטרנט מאפשר לשלוט במכשיר ביתי דרך חיבור שהוא עצמו פתח. מה זה משנה לזיכרון TLS, לנושאים ולחזרה.
המכשיר יושב מאחורי ראוטר ביתי בלי העברת פורט ובלי כתובת ציבורית, ובכל זאת עליו לקבל תצורה בתוך שניות. הטריק אינו חור בחומת האש. זהו חיבור שהמכשיר פותח החוצה אל broker שהוא יכול להגיע אליו, וזה מעביר את ההודעות בחזרה באותו נתיב שכבר נבנה. כל תכונה שאנשים אוהבים בתכנון הזה, וכל מלכודת בו, נובעות מאותו היפוך.
מה באמת עובר דרך ה-NAT
כשהמכשיר פותח חיבור TCP אל ה-broker, הראוטר הביתי יוצר מיפוי ושומר עליו חי כל עוד הזרימה קיימת. תשובות באותה זרימה חוזרות למכשיר מפני שהמיפוי כבר קיים. ה-broker אינו יוזם דבר כלפי הבית, ולכן אין מקטע נכנס לא מבוקש שהראוטר צריך לדחות. זה כל הטיעון הרשתי, ולכן הגישה עובדת ברשתות שאינך שולט בהן.
המכשיר חייב לשמור את החיבור חי או להקים אותו מחדש, וזה הופך לשאלת האמינות לאחר שהארכיטקטורה נקבעת.
ה-broker מנתב נושאים, הוא לא משמש פרוקסי ל-HTTP
MQTT מגדיר חילופי פרסום ומנוי: המכשיר נרשם כמנוי למסנן נושאים שמותר לו לקרוא, ובקר מורשה מפרסם לנושא תואם. ה-broker מתאים פרסומים למנויים ומעביר עותקים. הוא לא יודע מהי בקשת דפדפן, והוא לא יעביר HTTP GET לשרת האינטרנט של המכשיר. אם הקושחה הקיימת מדברת רק HTTP, תכנון ה-broker דורש שינוי ביישום או רכיב תרגום מכוון.
גם שמות נושאים אינם הרשאה. רוב ה-broker תומכים ברשימות בקרת גישה לכל לקוח, ויש להגביל מכשירים לעצי הפרסום והמנוי שלהם במקום לחלוק מרחב שמות גלובלי אחד.
משאבי המכשיר קובעים את צורת ה-TLS
ל-ESP8266 יש RAM מוגבל, ולחיצת היד של TLS היא הדבר היקר ביותר שהוא עושה. ליבת Arduino מספקת את BearSSL בדיוק בגלל המגבלה הזו, והבחירה בין אימות CA לבין נעיצת טביעת אצבע משנה גם את טביעת הזיכרון וגם את מה שתוקף עם אישור תקף לשם אחר יכול לעשות. אימות ה-CA של ה-broker הוא האפשרות החזקה יותר כשהערמה מאפשרת. גם גודל המטען חשוב: לקוח ה-MQTT מחזיק חוצץ, והודעות גדולות ממנו נחתכות בשקט אלא אם החוצץ מוגדל בכוונה.
Keepalive וזמני הקצבה של השקע הם חלק מאותו תקציב, כי לקוח שלעולם לא מבחין בחיבור מת מפסיק לקבל פקודות בלי לדווח על שגיאה.
סמנטיקת ההודעות שנושכת
הודעה שמורה נשמרת אצל ה-broker ונמסרת למנויים תואמים מאוחרים יותר, מה שמצוין למצב הנוכחי ומסוכן לפקודות חד-פעמיות: מכשיר שמתחבר מחדש עלול לקבל את פקודת האתמול כאילו היא חדשה. QoS 1 מבטיח מסירה לפחות פעם אחת, ולכן כפילויות הן נורמליות והיישום חייב להיות בטוח לחזרה, באופן אידיאלי עם מזהה או חותמת זמן שהוא יכול לדחות. הצוואה האחרונה נותנת אות מצב כשהמכשיר נופל, אבל רק אם החיבור באמת נכשל ולא נתלה.
התנהגות סשן נקי קובעת אם ה-broker שומר על המנויים שלך בזמן שאתה נעדר, וטעות בכך היא הסיבה לכך שכמה מכשירים מפספסים את ההודעה הראשונה אחרי כל התחברות מחדש.
TLS מגן על הקטע עד ה-broker. זה אינו הצפנת מטען מקצה לקצה מול מפעיל ה-broker, שיכול לקרוא כל מה שאתה מפרסם דרכו.
הגבל את מחזור החיים ובדוק אותו בנתונים לא מזיקים
תכנן התחברות מחדש עם נסיגה במקום לולאת ניסיונות צפופה, הירשם מחדש במפורש אם הסשן אינו מתמשך, ורשום את תוצאת החיבור כדי שמכשיר שקט לא מקוון ישאיר ראיות. בדוק את נתיב ההתחברות מחדש עם מטענים לדוגמה שאינם עושים דבר, כי הבדיקה הייצורית הראשונה של ערוץ פקודות לא צריכה להיות פקודה אמיתית. אחר כך אמת מה עושה הודעה שמורה מיושנת בהתחברות מחדש, והחלט אם ההתנהגות הזו מקובלת לכל נושא.
כשעושים זאת כך, התכנון מסיר דרישת רשת נכנסת אחת ומשאיר את תוכנת המכשיר, את מדיניות ה-broker ואת סמנטיקת ההודעות כעבודה גלויה במקום הנחות נסתרות.