צלילה עמוקה: כיצד אנו משתמשים בתיבות דואר מוצפנות של SQLite בטוחות קוונטיות עבור שירות הדוא"ל הממוקד בפרטיות והמאובטח שלנו

בניגוד לשירותי דוא"ל אחרים , אנו מבטיחים שרק לך תהיה גישה לתיבת הדואר שלך בכל עת.

הַקדָמָה

tldr; שירות המייל שלנו הוא 100% קוד פתוח וממוקד פרטיות באמצעות תיבות דואר SQLite מאובטחות ומוצפנות.

עד שהשקנו תמיכה ב-IMAP, השתמשנו ב-MongoDB לצרכי אחסון הנתונים המתמידים שלנו.

הטכנולוגיה הזו מדהימה ואנחנו עדיין משתמשים בה היום - אבל כדי לקבל הצפנה במצב מנוחה עם MongoDB אתה צריך להשתמש בספק שמציע MongoDB Enterprise, כגון Digital Ocean או Mongo Atlas - או לשלם עבור רישיון ארגוני (ו לאחר מכן צריך לעבוד עם חביון צוות המכירות).

הצוות שלנו ב העברת דוא"ל היה זקוק לפתרון אחסון ידידותי למפתחים, ניתן להרחבה, אמין ומוצפן עבור תיבות דואר IMAP. כמפתחי קוד פתוח, באמצעות טכנולוגיה אתה צריך לשלם דמי רישיון כדי לקבל את תכונת ההצפנה במנוחה הייתה נגד העקרונות שלנו – וכך התנסנו, חקרנו ופיתחנו פתרון חדש מאפס כדי לפתור את הצרכים הללו.

במקום להשתמש במסד נתונים משותף לאחסון תיבות הדואר שלך, אנו מאחסנים ומצפינים בנפרד את תיבות הדואר שלך עם הסיסמה שלך (שרק לך יש). שירות הדואר האלקטרוני שלנו כל כך מאובטח שאם תשכח את הסיסמה שלך, תאבד את תיבת הדואר שלך (וצריך להתאושש עם גיבויים לא מקוונים או להתחיל מחדש).

המשך לקרוא כשאנחנו צוללים לעומק למטה עם א השוואה בין ספקי שירותי דואר אלקטרוני, איך השירות שלנו עובד, מחסנית הטכנולוגיה שלנו, ועוד.

השוואה בין ספקי שירותי דואר אלקטרוני

אנחנו ספק שירותי הדואר האלקטרוני היחיד בקוד פתוח וממוקד פרטיות המאחסן תיבות דואר מוצפנות של SQLite בנפרד, מציע דומיינים, כינויים ומשתמשים ללא הגבלה, ויש לו תמיכה יוצאת ב-SMTP, IMAP ו-POP3:

בניגוד לספקי דוא"ל אחרים, אינך צריך לשלם עבור אחסון על בסיס דומיין או כינוי עם העבר דוא"ל. האחסון משותף על פני כל החשבון שלך - כך שאם יש לך מספר שמות דומיין מותאמים אישית וכינויים מרובים בכל אחד מהם, אז אנחנו הפתרון המושלם עבורך. שים לב שאתה עדיין יכול לאכוף מגבלות אחסון אם תרצה על בסיס לכל דומיין או כינוי.

קרא השוואת שירותי דואר אלקטרוני

איך זה עובד

  1. באמצעות לקוח הדוא"ל שלך כגון Apple Mail, Thunderbird, Gmail או Outlook - אתה מתחבר למאובטח שלנו IMAP שרתים המשתמשים בשם המשתמש והסיסמה שלך:

    • שם המשתמש שלך הוא הכינוי המלא שלך עם הדומיין שלך כגון hello@example.com.
    • הסיסמה שלך נוצרת באופן אקראי ומוצגת לך רק למשך 30 שניות כאשר אתה לוחץ צור סיסמה מ החשבון שלי דומיינים כינויים.
  2. לאחר החיבור, לקוח הדוא"ל שלך ישלח פקודות פרוטוקול IMAP לשרת ה-IMAP שלנו כדי לשמור על סנכרון תיבת הדואר שלך. זה כולל כתיבה ואחסון של טיוטות דוא"ל ופעולות אחרות שאתה עשוי לעשות (למשל, תווית דוא"ל כחשובה או סימון דוא"ל כדואר זבל/דואר זבל).

  3. שרתי חילופי דואר (הידועים בכינויים שרתי "MX") מקבלים דוא"ל נכנס חדש ומאחסנים אותו בתיבת הדואר שלך. כשזה יקרה לקוח הדואר האלקטרוני שלך יקבל הודעה ויסנכרן את תיבת הדואר שלך. שרתי חילופי הדואר שלנו יכולים להעביר את הדוא"ל שלך לנמען אחד או יותר (כולל webhooks), אחסן את הדוא"ל שלך עבורך באחסון ה-IMAP המוצפן שלך אצלנו, או שניהם!

    מעוניינים ללמוד עוד? לקרוא כיצד להגדיר העברת דוא"ל, כיצד פועל שירות החלפת הדואר שלנו, או הצג המדריכים שלנו.

  4. מאחורי הקלעים, עיצוב אחסון הדוא"ל המאובטח שלנו פועל בשתי דרכים כדי לשמור על תיבות הדואר שלך מוצפנות ונגישות רק לך:

    • כאשר דואר חדש מתקבל עבורך משולח, שרתי חילופי הדואר שלנו כותבים לתיבת דואר בודדת, זמנית ומוצפנת עבורך.

      sequenceDiagram
          autonumber
          actor Sender
          Sender->>MX: Inbound message received for your alias (e.g. you@yourdomain.com).
          MX->>SQLite: Message is stored in a temporary mailbox.
          Note over MX,SQLite: Forwards to other recipients and webhooks configured.
          MX->>Sender: Success!
      
    • כאשר אתה מתחבר לשרת ה-IMAP שלנו עם לקוח הדואר האלקטרוני שלך, הסיסמה שלך מוצפנת בזיכרון ומשמשת לקריאה ולכתיבה לתיבת הדואר שלך. ניתן לקרוא ולכתוב את תיבת הדואר שלך רק באמצעות סיסמה זו. זכור שמכיוון שאתה היחיד עם סיסמה זו, רק אתה יכול לקרוא ולכתוב לתיבת הדואר שלך כאשר אתה ניגש אליה. בפעם הבאה שלקוח הדואר שלך ינסה לבצע סקר לאימייל או לסנכרן, ההודעות החדשות שלך יועברו מתיבת הדואר הזמנית הזו ויאוחסנו בקובץ תיבת הדואר האמיתי שלך באמצעות הסיסמה שסיפקת. שים לב שתיבת הדואר הזמנית הזו נמחקת ונמחקת לאחר מכן, כך שרק תיבת הדואר המוגנת בסיסמה שלך מכילה את ההודעות.

    • אם אתה מחובר ל-IMAP (למשל באמצעות לקוח דוא"ל כגון Apple Mail או Thunderbird), אז איננו צריכים לכתוב לאחסון דיסק זמני. במקום זאת, סיסמת ה-IMAP המוצפנת בזיכרון שלך מאוחזרת ונעשה בה שימוש. בזמן אמת, כאשר הודעה מנסה להימסר אליך, אנו שולחים בקשת WebSocket לכל שרתי ה-IMAP ושואלים אותם אם יש להם הפעלה פעילה עבורך (זהו חלק האחזור), ולאחר מכן נעביר את זה סיסמה מוצפנת בזיכרון - כך שאיננו צריכים לכתוב לתיבת דואר זמנית, אנו יכולים לכתוב לתיבת הדואר המוצפנת בפועל שלך באמצעות הסיסמה המוצפנת שלך.

      sequenceDiagram
          autonumber
          actor You
          You->>IMAP: You connect to IMAP server using an email client.
          IMAP->>SQLite: Transfer message from temporary mailbox to your alias' mailbox.
          Note over IMAP,SQLite: Your alias' mailbox is only available in-memory using IMAP password.
          SQLite->>IMAP: Retrieves messages as requested by email client.
          IMAP->>You: Success!
      
  5. גיבויים של תיבות הדואר המוצפנות שלך נעשים מדי יום. אתה יכול גם לבקש גיבוי חדש בכל עת או להוריד את הגיבוי האחרון מ החשבון שלי דומיינים כינויים. אם תחליט לעבור לשירות דוא"ל אחר, תוכל להעביר בקלות, להוריד, לייצא ולנקות את תיבות הדואר והגיבויים שלך בכל עת.

טכנולוגיות

מאגרי מידע

בדקנו שכבות אחסון אפשריות אחרות של מסדי נתונים, אולם אף אחת לא סיפקה את הדרישות שלנו כמו SQLite:

מאגר מידעהצפנה במנוחהארגז חול תיבות דואררישיוןבשימוש בכל מקום
SQLite✅ כן עם SQLite3MultipleCiphers✅ תחום ציבורי
MongoDB"זמין ב-MongoDB Enterprise בלבד"❌ מסד נתונים יחסי❌ AGPL ו SSPL-1.0
rqliteרשת בלבד❌ מסד נתונים יחסיMIT
dqliteלא נבדק ועדיין לא נתמך?לא נבדק ועדיין לא נתמך?LGPL-3.0-only
PostgreSQLכן❌ מסד נתונים יחסיPostgreSQL (דומה ל BSD אוֹ MIT)
MariaDBעבור InnoDB בלבד❌ מסד נתונים יחסיGPLv2 ו BUSL-1.1
ג'וקDBתכונה ארגונית בלבד❌ מסד נתונים יחסיBUSL-1.1 ואחרים

הנה א פוסט בלוג המשווה מספר אפשרויות אחסון של מסדי נתונים של SQLite בטבלה למעלה.

בִּטָחוֹן

בכל עת אנו משתמשים הצפנה במנוחה (AES-256), הצפנה במעבר (TLS), DNS דרך HTTPS ("DoH") באמצעות 🍊 מַנדָרִינָה, ו sqleet (ChaCha20-Poly1305) הצפנה בתיבות דואר. בנוסף אנו משתמשים באימות דו-גורמי מבוסס אסימון (בניגוד ל-SMS שחשוד איש-באמצע-התקפות), מפתחות SSH מסובבים עם גישת שורש מושבתת, גישה בלעדית לשרתים דרך כתובות IP מוגבלות ועוד.

במקרה של א התקפת עוזרת רעה או עובד נוכל מספק צד שלישי, עדיין ניתן לפתוח את תיבת הדואר שלך רק עם הסיסמה שנוצרת. היה סמוך ובטוח, אנחנו לא מסתמכים על ספקי צד שלישי אחרים מלבד ספקי שרתי התלונות SOC Type 2 שלנו של Cloudflare, Digital Ocean ו-Vultr.

המטרה שלנו היא שיהיו כמה שפחות נקודת כשל אחת ככל האפשר.

תיבות דואר

tldr; שרתי ה-IMAP שלנו משתמשים במסדי נתונים מוצפנים של SQLite עבור כל אחת מתיבות הדואר שלך.

SQLite הוא פופולרי מאוד מסד נתונים משובץ - הוא פועל כעת בטלפון ובמחשב שלך - ומשמש כמעט את כל הטכנולוגיות העיקריות.

לדוגמה, בשרתים המוצפנים שלנו יש תיבת דואר של מסד נתונים של SQLite עבור linux@example.com, info@example.com, hello@example.com וכן הלאה – אחד לכל כא .sqlite קובץ מסד הנתונים. אנחנו גם לא קוראים לקבצי מסד הנתונים עם כתובת הדואר האלקטרוני - במקום זאת אנו משתמשים ב-BSON ObjectID וב-UUIDs ייחודיים שנוצרו שאינם חולקים למי שייכת תיבת הדואר או באיזו כתובת דוא"ל היא נמצאת (למשל. 353a03f21e534321f5d6e267.sqlite).

כל אחד מבסיסי הנתונים הללו מוצפן בעצמו באמצעות הסיסמה שלך (שרק לך יש). sqleet (ChaCha20-Poly1305). משמעות הדבר היא שתיבות הדואר שלך מוצפנות בנפרד, עצמאיות, ארגז חול, ונייד.

כוונון עדין של SQLite עם הדברים הבאים PRAGMA:

PRAGMAמַטָרָה
cipher=chacha20הצפנת מסד נתונים של ChaCha20-Poly1305 SQLite. התייחסות better-sqlite3-multiple-ciphers תַחַת פרויקטים לתובנה נוספת.
key="****************"זוהי הסיסמה המפוענחת בלבד בזיכרון המועברת דרך חיבור ה-IMAP של לקוח הדוא"ל שלך לשרת שלנו. מופעי מסד נתונים חדשים נוצרים ונסגרים עבור כל סשן קריאה וכתיבה (על מנת להבטיח ארגז חול ובידוד).
journal_model=WALWrite-ahead-log ("WAL") מה שמגביר את הביצועים ומאפשר גישה לקריאה במקביל.
busy_timeout=5000מונע שגיאות נעילת כתיבה בעוד כתיבה אחרת מתרחשת.
synchronous=NORMALמגביר את עמידות העסקאות ללא סיכון שחיתות נתונים.
foreign_keys=ONאוכפת שהפניות למפתח זר (למשל קשר מטבלה אחת לאחרת) נאכפות. כברירת מחדל זה לא מופעל ב-SQLite, אך לצורך אימות ושלמות הנתונים יש להפעיל אותו.
encoding='UTF-8'קידוד ברירת מחדל להשתמש כדי להבטיח שפיות מפתח.

כל ברירות המחדל האחרות הן מ-SQLite כפי שצוין מה- תיעוד רשמי של PRAGMA.

במקביל

tldr; אנו משתמשים rclone ו WebSocket לקריאה וכתיבה במקביל לתיבות הדואר המוצפנות של SQLite.

קורא

לקוח הדוא"ל שלך בטלפון שלך עשוי לפתור imap.forwardemail.net לאחת מכתובות ה-IP Digital Ocean שלנו - ולקוח שולחן העבודה שלך עשוי לפתור כתובת IP נפרדת משל אחרת ספק לְגַמרֵי.

לא משנה לאיזה שרת IMAP לקוח הדוא"ל שלך מתחבר, אנו רוצים שהחיבור יקרא ממסד הנתונים שלך בזמן אמת עם דיוק של 100%:

  • זה מושג על ידי שימוש rclone עם --vfs-cache-mode off (ברירת המחדל).

  • במקום להשתמש במטמון דיסק מקומי, המטמון נקרא ישירות מהרכיב המרוחק (בסיס הנתונים שלך) בזמן אמת.

  • במקרה שלא ניתן למצוא את הקובץ המקומי, זה מעיד על כך rclone נכשל בהרכבה או שיש לו בעיה. במקרה זה אנו משתמשים ב-a WebSocket חזרה לקריאה (שמפחיתה מעט את הביצועים, אך עדיין שומרת על שלמות השירות).

  • כל אחד מהשרתים שלנו מוגדר לעלות בעקביות ומתריע בזמן אמת על כל שגיאה.

כותב

הכתיבה למסד הנתונים שלך היא קצת שונה - מכיוון ש- SQLite הוא מסד נתונים משובץ ותיבת הדואר שלך חיה בקובץ בודד כברירת מחדל.

בדקנו אפשרויות כגון litestream, rqlite, ו dqlite להלן - אולם אף אחד מאלה לא עמד בדרישות שלנו.

כדי לבצע כתיבה עם רישום-לפני כן ("WAL") מופעל - עלינו לוודא שרק שרת אחד ("ראשי") אחראי לעשות זאת. WAL מאיץ בצורה דרסטית את המקבילות ומאפשר כותב אחד ומספר קוראים.

ה-Primary פועל על שרתי הנתונים עם אמצעי האחסון המורכבים המכילים את תיבות הדואר המוצפנות. מנקודת מבט של הפצה, אתה יכול לשקול את כל שרתי ה-IMAP הבודדים שמאחוריהם imap.forwardemail.net להיות שרתים משניים ("משניים").

אנו משיגים תקשורת דו כיוונית עם WebSockets:

  • שרתים ראשיים משתמשים במופע של wsשל WebSocketServer שרת.
  • שרתים משניים משתמשים במופע של wsשל WebSocket לקוח שעטוף בו websocket-כמו-מובטח ו reconnecting-websocket. שתי העטיפות הללו מבטיחות שה WebSocket מתחבר מחדש ויכול לשלוח ולקבל נתונים עבור כתיבת מסד נתונים ספציפיים.

גיבויים

tldr; גיבויים של תיבות הדואר המוצפנות שלך נעשים מדי יום. אתה יכול גם לבקש גיבוי חדש באופן מיידי או להוריד את הגיבוי האחרון בכל עת מ החשבון שלי דומיינים כינויים.

עבור גיבויים, אנו פשוט מפעילים את SQLite VACUUM INTO פקודה כל יום במהלך עיבוד פקודות IMAP, הממנף את הסיסמה המוצפנת שלך מחיבור IMAP בזיכרון. גיבויים מאוחסנים אם לא מזוהה גיבוי קיים או אם SHA-256 hash השתנה בקובץ בהשוואה לגיבוי האחרון.

שימו לב שאנו משתמשים ב- VACUUM INTO פקודה בניגוד למובנה backup פקודה כי אם דף שונה במהלך א backup פעולת הפקודה, אז היא צריכה להתחיל מחדש. ה VACUUM INTO הפקודה תצלם תמונת מצב. ראה הערות אלה על GitHub ו חדשות האקר לתובנה נוספת.

בנוסף אנו משתמשים VACUUM INTO בניגוד ל backup, בגלל ה backup הפקודה תשאיר את מסד הנתונים לא מוצפן למשך תקופה קצרה עד rekey מופעל (ראה GitHub זה תגובה לתובנה).

המשני ינחה את היסוד על WebSocket חיבור לביצוע הגיבוי - והראשי יקבל את הפקודה לעשות זאת ולאחר מכן:

  1. התחבר לתיבת הדואר המוצפנת שלך.
  2. רכשו מנעול כתיבה.
  3. הפעל מחסום WAL באמצעות wal_checkpoint(PASSIVE).
  4. הפעל את VACUUM INTO פקודת SQLite.
  5. ודא שניתן לפתוח את הקובץ המועתק באמצעות הסיסמה המוצפנת (הגנה/הגנת דמה).
  6. העלה אותו ל-Cloudflare R2 לאחסון (או לספק משלך אם צוין).
  7. דחוס את קובץ הגיבוי שהתקבל באמצעות gzip.
  8. העלה אותו ל-Cloudflare R2 לאחסון (או לספק משלך אם צוין).

זכור שתיבות הדואר שלך מוצפנות - ולמרות שיש לנו הגבלות IP ואמצעי אימות אחרים עבור תקשורת WebSocket - במקרה של שחקן גרוע, אתה יכול להיות סמוך ובטוח שאם לא למטען WebSocket יש את סיסמת ה-IMAP שלך, הוא לא יכול לפתוח את מסד הנתונים שלך .

רק גיבוי אחד מאוחסן לתיבת דואר בשלב זה, אך בעתיד אנו עשויים להציע שחזור נקודת זמן ("PITR").

שרתי ה-IMAP שלנו תומכים ב SEARCH פקודה עם שאילתות מורכבות, ביטויים רגולריים ועוד.

ביצועי חיפוש מהירים הם בזכות FTS5 ו sqlite-regex.

אנחנו מאחסנים Date ערכים בתיבות הדואר של SQLite as ISO 8601 מחרוזות דרך Date.prototype.toISOString (עם אזור זמן UTC להשוואות שוויון לתפקד כראוי).

מדדים מאוחסנים גם עבור כל הנכסים שנמצאים בשאילתות חיפוש.

פרויקטים

להלן טבלה המתארת פרויקטים שבהם אנו משתמשים בתהליך המקור ובתהליך הפיתוח שלנו (ממוינים בסדר אלפביתי):

פּרוֹיֶקטמַטָרָה
אנסיבלפלטפורמת אוטומציה DevOps לתחזוקה, קנה מידה וניהול של כל צי השרתים שלנו בקלות.
ברימתזמן עבודה עבור Node.js ו-JavaScript עם cron, תאריכים, ms, מאוחר יותר ותמיכה ידידותית לאדם.
תָאספריית רישום JavaScript ו-Node.js ידידותית למפתחים תוך מחשבה על אבטחה ופרטיות.
בָּחוּרמסגרת Node.js אשר מפעילה את כל הארכיטקטורה והתכנון ההנדסי שלנו עם MVC ועוד.
MongoDBפתרון מסד הנתונים של NoSQL שבו אנו משתמשים לאחסון כל שאר הנתונים מחוץ לתיבות הדואר (למשל החשבון שלך, הגדרות, דומיינים ותצורות כינוי).
נְמִיָהמודל מסמכי אובייקט MongoDB ("ODM") בו אנו משתמשים בכל הערימה שלנו. כתבנו עוזרים מיוחדים שמאפשרים לנו פשוט להמשיך להשתמש נמיה עם SQLite 🎉
Node.jsNode.js היא סביבת זמן ריצה של JavaScript חוצה פלטפורמות בקוד פתוח, המריץ את כל תהליכי השרת שלנו.
דואר הערותחבילת Node.js לשליחת מיילים, יצירת קשרים ועוד. אנחנו נותנים חסות רשמית לפרויקט הזה.
Redisמסד נתונים בזיכרון לאחסון במטמון, פרסום/הרשמה לערוצים ו-DNS על פני בקשות HTTPS.
SQLite3MultipleCiphersתוסף הצפנה עבור SQLite כדי לאפשר הצפנת קבצי מסד נתונים שלמים (כולל ה-write-ahead-log ("WAL"), יומן, חזרה לאחור, ...).
SQLiteStudioעורך SQLite חזותי (שאפשר גם להשתמש בו) כדי לבדוק, להוריד ולהציג תיבות דואר פיתוח.
SQLiteשכבת מסד נתונים משובצת לאחסון IMAP ניתן להרחבה, עצמאי, מהיר ועמיד.
סורק דואר זבלNode.js אנטי ספאם, סינון דואר אלקטרוני וכלי למניעת דיוג (החלופה שלנו ל מתנקש ספאם ו rspamd).
מַנדָרִינָהDNS על פני בקשות HTTPS עם Node.js ושמירת מטמון באמצעות Redis - מה שמבטיח עקביות גלובלית ועוד.
Thunderbirdצוות הפיתוח שלנו משתמש בזה (וממליץ גם על זה) בתור לקוח הדוא"ל המועדף לשימוש עם העבר דוא"ל.
UTMצוות הפיתוח שלנו משתמש במכונות וירטואליות ליצירת iOS ו-macOS כדי לבדוק לקוחות דוא"ל שונים (במקביל) עם שרתי ה-IMAP וה-SMTP שלנו.
אובונטומערכת הפעלה מודרנית מבוססת לינוקס מבוססת לינוקס המניעה את כל התשתית שלנו.
ברווז ברספריית שרת IMAP - ראה את ההערות שלה בנושא ביטול כפילות של קבצים מצורפים ו תמיכה בפרוטוקול IMAP.
better-sqlite3-מרובים-צפניםספריית API מהירה ופשוטה עבור Node.js לאינטראקציה עם SQLite3 באופן פרוגרמטי.
תבניות אימיילמסגרת דוא"ל ידידותית למפתחים ליצירה, תצוגה מקדימה ושליחת אימיילים מותאמים אישית (למשל התראות חשבון ועוד).
json-sqlבונה שאילתות SQL באמצעות תחביר בסגנון מונגו. זה חוסך זמן לצוות הפיתוח שלנו מכיוון שאנו יכולים להמשיך לכתוב בסגנון מונגו על פני כל הערימה בגישה אגנוסטית של מסד נתונים. זה גם עוזר להימנע מהתקפות הזרקת SQL על ידי שימוש בפרמטרים של שאילתה.
knex-schema-inspectorכלי SQL לחילוץ מידע על סכימת מסד נתונים קיימת. זה מאפשר לנו לאמת בקלות שכל המדדים, הטבלאות, העמודות, האילוצים ועוד תקפים והם 1:1 עם איך שהם צריכים להיות. אפילו כתבנו עוזרים אוטומטיים כדי להוסיף עמודות ואינדקסים חדשים אם נעשו שינויים בסכימות של מסד נתונים (גם עם התראת שגיאה מפורטת ביותר).
knexבונה שאילתות SQL שבו אנו משתמשים רק עבור העברות מסדי נתונים ואימות סכימה באמצעות knex-schema-inspector.
מַנדָרִיןאוֹטוֹמָטִי i18n תרגום ביטויים עם תמיכה בשימוש ב-Markdown Google Cloud Translation API.
mx-connectחבילת Node.js לפתרון ויצירת קשרים עם שרתי MX וטיפול בשגיאות.
אחר הצהריים 2מנהל תהליך הייצור של Node.js עם מאזן עומסים מובנה (מכוון עדין לביצועים).
שרת smtpספריית שרתי SMTP - אנו משתמשים בזה עבור חילופי הדואר שלנו ("MX") ושרתי SMTP יוצאים.
ImapTestכלי שימושי לבדיקת שרתי IMAP מול מדדים ותאימות פרוטוקול IMAP של מפרט RFC. פרויקט זה נוצר על ידי ה קו יונים צוות (שרת IMAP ו-POP3 פעיל בקוד פתוח מיולי 2002). בדקנו בהרחבה את שרת ה-IMAP שלנו עם הכלי הזה.

אתה יכול למצוא פרויקטים אחרים שבהם אנו משתמשים קוד המקור שלנו ב-GitHub.

ספקים

ספקמַטָרָה
Cloudflareספק DNS, בדיקות תקינות, מאזני עומסים ואחסון גיבוי באמצעות Cloudflare R2.
אוקיינוס דיגיטליאירוח שרתים ייעודי, אחסון חסימת SSD ומסדי נתונים מנוהלים.
Vultrאירוח שרת ייעודי ואחסון חסימת SSD.

מחשבות

עקרונות

העבר דוא"ל עוצב על פי העקרונות הבאים:

  1. היה תמיד ידידותי למפתחים, ממוקד אבטחה ופרטיות ושקוף.
  2. לדבוק MVC, יוניקס, KISS, DRY, YAGNI, 12 פקטור, סכין הגילוח של אוקאם, ו הפצה לפני הפצה
  3. כוון את השחורים, עם המגפיים, ו ראמן-רווחי מפתח

ניסויים

tldr; בסופו של דבר שימוש באחסון אובייקטים תואם S3 ו/או בטבלאות וירטואליות אינם אפשריים מבחינה טכנית מסיבות ביצועים ונוטים לשגיאות עקב מגבלות זיכרון.

עשינו כמה ניסויים שהובילו לפתרון SQLite הסופי שלנו כפי שנדון לעיל.

אחד מהם היה לנסות להשתמש rclone ו- SQLite יחד עם שכבת אחסון תואמת S3.

הניסוי הזה הוביל אותנו להבין ולגלות מקרי קצה סביב rclone, SQLite ו VFS נוֹהָג:

  • אם תפעיל --vfs-cache-mode writes דגל עם rclone, אז הקריאה תהיה בסדר, אולם הכתיבה תישמר במטמון.
    • אם יש לך שרתי IMAP מרובים המופצים ברחבי העולם, המטמון יהיה כבוי ביניהם אלא אם יש לך כותב יחיד ומאזינים מרובים (למשל גישת פאב/משנה).
    • זה מורכב להפליא והוספת כל מורכבות נוספת כזו תגרום ליותר נקודות כשל בודדות.
    • ספקי אחסון תואמי S3 אינם תומכים בשינויים חלקיים של קבצים - כלומר כל שינוי של .sqlite הקובץ יביא לשינוי מוחלט ולהעלאה מחדש של מסד הנתונים.
    • פתרונות אחרים כמו rsync קיימים, אבל הם לא מתמקדים ב-write-ahead-log ("WAL") תמיכה - אז בסופו של דבר בדקנו את Litestream. למרבה המזל, השימוש בהצפנה שלנו כבר מצפין את WAL קבצים עבורנו, אז אנחנו לא צריכים להסתמך על Litestream בשביל זה. עם זאת, עדיין לא היינו בטוחים ב-Litestream לשימוש בייצור ויש לנו כמה הערות בהמשך.
    • שימוש באפשרות זו של --vfs-cache-mode writesרק דרך להשתמש ב- SQLite over rclone לכתיבה) ינסה להעתיק את כל מסד הנתונים מאפס בזיכרון - טיפול בתיבת דואר אחת של 10 ג'יגה-בתים זה בסדר, אולם טיפול במספר תיבות דואר עם אחסון גבוה במיוחד יגרום לשרתי IMAP להיתקל במגבלות זיכרון. ENOMEM שגיאות, תקלות פילוח ושחיתות נתונים.
  • אם אתה מנסה להשתמש ב-SQLite טבלאות וירטואליות (למשל באמצעות s3db) כדי שהנתונים יהיו חיים בשכבת אחסון תואמת S3, תיתקלו בכמה בעיות נוספות:
    • הקריאה והכתיבה יהיו איטיים במיוחד מכיוון שנקודות קצה S3 API יצטרכו להיפגע עם HTTP GET, PUT, HEAD, ו POST שיטות.
    • מבחני פיתוח הראו שחרוג מ-500K-1M+ רשומות באינטרנט סיבים עדיין מוגבל על ידי תפוקת הכתיבה והקריאה לספקים תואמים S3. לדוגמה, המפתחים שלנו רצו for לולאות לעשות את שניהם SQL רציף INSERT הצהרות וכאלה שכתבו כמויות גדולות של נתונים. בשני המקרים הביצועים היו איטיים להפליא.
    • שולחנות וירטואליים לא יכול להיות אינדקסים, ALTER TABLE הצהרות, ו אַחֵר מגבלות - מה שמוביל לעיכובים של למעלה מ-1-2 דקות או יותר בהתאם לכמות הנתונים.
    • אובייקטים אוחסנו ללא מוצפן ואין תמיכה בהצפנה מקורית זמינה.
  • חקרנו גם שימוש sqlite-s3vfs שדומה מבחינה רעיונית וטכנית לנקודת התבליט הקודמת (ולכן יש לה את אותן בעיות). אפשרות תהיה להשתמש במנהג sqlite3 לבנות עטוף בהצפנה כגון wxSQLite3 (בה אנו משתמשים כעת בפתרון שלנו למעלה) דרך עריכת קובץ ההגדרות.
  • גישה פוטנציאלית נוספת הייתה להשתמש ב- הרחבה מרובהעם זאת, יש לכך מגבלה של 32 GB ויצריך כאבי ראש מורכבים של בנייה ופיתוח.
  • ALTER TABLE נדרשות הצהרות (אז זה שולל לחלוטין שימוש בטבלאות וירטואליות). אנחנו צריכים ALTER TABLE הצהרות על מנת להוק שלנו עם knex-schema-inspector לעבוד כראוי - מה שמבטיח שהנתונים לא פגומים ושורות שאוחזרו ניתנות להמרה למסמכים תקפים על פי שלנו mongoose הגדרות סכימה (הכוללת אילוץ, סוג משתנה ואימות נתונים שרירותי).
  • כמעט כל הפרויקטים התואמים ל-S3 הקשורים ל-SQLite בקהילת הקוד הפתוח נמצאים ב-Python (ולא ב-JavaScript שבו אנו משתמשים עבור 100% מהמחסנית שלנו).
  • ספריות דחיסה כגון sqlite-zstd (לִרְאוֹת הערות) נראה מבטיח, אבל ייתכן שעדיין לא מוכן לשימוש בייצור. במקום דחיסה בצד האפליקציה על סוגי נתונים כגון String, Object, Map, Array, Set, ו Buffer הולכת להיות גישה נקייה וקלה יותר (וגם קל יותר להגירה, מכיוון שנוכל לאחסן א Boolean דגל או עמודה - או אפילו להשתמש PRAGMA user_version=1 לדחיסה או user_version=0 ללא דחיסה כמטא נתונים של מסד נתונים).
    • למרבה המזל, כבר מיושם ביטול כפילויות של קבצים מצורפים באחסון שרת ה-IMAP שלנו - לכן כל הודעה עם אותו קובץ מצורף לא תשמור עותק של הקובץ המצורף - במקום זאת, קובץ מצורף אחד מאוחסן עבור מספר הודעות ושרשורים בתיבת דואר (וזר לאחר מכן נעשה שימוש בהפניה).
  • הפרויקט Litestream, שהוא פתרון שכפול וגיבוי של SQLite מבטיח מאוד וככל הנראה נשתמש בו בעתיד.
  • שחזור גיבוי צריך להיות חסר חיכוך וטריוויאלי. שימוש בפתרון כמו MongoDB עם mongodump ו mongoexport הוא לא רק מייגע, אלא זמן רב ובעל מורכבות תצורה.
    • מסדי נתונים של SQLite הופכים את זה לפשוט (זהו קובץ בודד).
    • רצינו לעצב פתרון שבו משתמשים יוכלו לקחת את תיבת הדואר שלהם ולעזוב בכל רגע.
      • פקודות Node.js פשוטות ל fs.unlink('mailbox.sqlite')) והוא נמחק לצמיתות מאחסון הדיסק.
      • אנו יכולים להשתמש באופן דומה ב-API תואם S3 עם HTTP DELETE כדי להסיר בקלות תמונות וגיבויים עבור משתמשים.
    • SQLite היה הפתרון הפשוט, המהיר והמשתלם ביותר.

חוסר אלטרנטיבות

למיטב ידיעתנו, אף שירותי דוא"ל אחרים לא מתוכננים כך וגם אינם בקוד פתוח.

אָנוּ חושב שאולי זה נובע לשירותי דואר אלקטרוני קיימים עם טכנולוגיה מדור קודם בייצור עם קוד ספגטי 🍝.

רוב אם לא כל ספקי שירותי הדוא"ל הקיימים הם בקוד סגור או מפרסמים כקוד פתוח, אבל במציאות רק הקצה הקדמי שלהם הוא קוד פתוח.

החלק הרגיש ביותר באימייל (אינטראקציית האחסון/IMAP/SMTP בפועל) הכל נעשה בקצה האחורי (שרת), ו לֹא בחזית (לקוח).

נסה את העבר אימייל

הירשם היום ב- https://forwardemail.net! 🚀