Kvanttiturvallinen sähköposti: Kuinka käytämme salattuja SQLite-postilaatikoita pitääksemme sähköpostisi turvassa

Kvanttiturvallinen salattu sähköpostipalvelun kuvaus

Esipuhe

Important

Sähköpostipalvelumme on 100 % avoimen lähdekoodin ja yksityisyyttä kunnioittava turvallisten ja salattujen SQLite-postilaatikoiden avulla.

Ennen kuin lanseerasimme IMAP-tuen, käytimme MongoDB:tä pysyvään tietovarastointiin.

Tämä teknologia on mahtava ja käytämme sitä edelleen – mutta MongoDB:n levossa olevan salauksen (encryption-at-rest) saamiseksi sinun täytyy käyttää palveluntarjoajaa, joka tarjoaa MongoDB Enterprisen, kuten Digital Ocean tai Mongo Atlas – tai maksaa yrityslisenssistä (ja sen jälkeen joutua odottamaan myyntitiimin vasteaikaa).

Tiimimme Forward Emaililla tarvitsi kehittäjäystävällisen, skaalautuvan, luotettavan ja salatun tallennusratkaisun IMAP-postilaatikoille. Avoimen lähdekoodin kehittäjinä teknologian käyttäminen, josta pitää maksaa lisenssimaksu saadakseen levossa olevan salauksen ominaisuuden, oli ristiriidassa periaatteidemme kanssa – joten kokeilimme, tutkimme ja kehitimme uuden ratkaisun alusta alkaen näiden tarpeiden täyttämiseksi.

Sen sijaan, että käyttäisimme jaettua tietokantaa postilaatikoidesi tallentamiseen, tallennamme ja salaamme postilaatikkosi yksilöllisesti salasanallasi (jonka vain sinä tiedät). Sähköpostipalvelumme on niin turvallinen, että jos unohdat salasanasi, menetät postilaatikkosi (ja sinun täytyy palauttaa se offline-varakopioiden avulla tai aloittaa alusta).

Jatka lukemista, kun sukellamme syvemmälle alla sähköpostipalveluntarjoajien vertailuun, palvelumme toimintaan, teknologiapinoomme ja muuhun.

Sähköpostipalveluntarjoajien vertailu

Olemme ainoa 100 % avoimen lähdekoodin ja yksityisyyttä kunnioittava sähköpostipalveluntarjoaja, joka tallentaa yksilöllisesti salatut SQLite-postilaatikot, tarjoaa rajattomasti domaineja, aliaksia ja käyttäjiä sekä tukee lähtevää SMTP:tä, IMAP:ia ja POP3:ta:

Toisin kuin muut sähköpostipalveluntarjoajat, sinun ei tarvitse maksaa tallennustilasta domain- tai aliaskohtaisesti Forward Emailin kanssa. Tallennustila on jaettu koko tilisi kesken – joten jos sinulla on useita omia domain-nimiä ja useita aliaksia kussakin, olemme täydellinen ratkaisu sinulle. Huomaa, että voit halutessasi asettaa tallennusrajoja domain- tai aliaskohtaisesti.

Lue sähköpostipalvelujen vertailu

Miten se toimii

  1. Käyttämällä sähköpostiasiakastasi, kuten Apple Mailia, Thunderbirdiä, Gmailia tai Outlookia – yhdistät turvallisiin IMAP -palvelimiimme käyttäjätunnuksellasi ja salasanallasi:

    • Käyttäjätunnuksesi on koko alias sähköpostiosoitteellasi, esimerkiksi hello@example.com.
    • Salasanasi on satunnaisesti luotu ja näytetään sinulle vain 30 sekunnin ajan, kun napsautat Luo salasana kohdasta Oma tili Domainit Aliakset.
  2. Kun yhteys on muodostettu, sähköpostiohjelmasi lähettää IMAP-protokollan komentoja IMAP-palvelimellemme pitääkseen postilaatikkosi synkronoituna. Tämä sisältää luonnosten kirjoittamisen ja tallentamisen sekä muut toimet, joita saatat tehdä (esim. merkitä sähköpostin Tärkeäksi tai liputtaa sähköpostin Roskapostiksi/Junk Mailiksi).

  3. Sähköpostinvaihtopalvelimet (yleisesti tunnettuina "MX"-palvelimina) vastaanottavat uudet saapuvat sähköpostit ja tallentavat ne postilaatikkoosi. Kun tämä tapahtuu, sähköpostiohjelmasi saa ilmoituksen ja synkronoi postilaatikkosi. Sähköpostinvaihtopalvelimemme voivat edelleenlähettää sähköpostisi yhdelle tai useammalle vastaanottajalle (mukaan lukien webhookit), tallentaa sähköpostisi salattuun IMAP-tallennustilaamme, tai molempia!

  4. Taustalla turvallinen sähköpostin tallennusratkaisumme toimii kahdella tavalla pitääkseen postilaatikkosi salattuina ja vain sinun käytettävissäsi:

    • Kun sinulle saapuu uutta sähköpostia lähettäjältä, sähköpostinvaihtopalvelimemme kirjoittavat yksilölliseen, väliaikaiseen ja salattuun postilaatikkoon sinulle.

    • Kun yhdistät sähköpostiohjelmallasi IMAP-palvelimeemme, salasanasi salataan muistin sisällä ja sitä käytetään postilaatikkosi lukemiseen ja kirjoittamiseen. Postilaatikkoasi voi lukea ja siihen voi kirjoittaa vain tällä salasanalla. Muista, että koska olet ainoa, jolla on tämä salasana, vain sinä voit lukea ja kirjoittaa postilaatikkoosi, kun käytät sitä. Seuraavalla kerralla, kun sähköpostiohjelmasi yrittää hakea postia tai synkronoida, uudet viestisi siirretään tästä väliaikaisesta postilaatikosta ja tallennetaan varsinaiseen postilaatikkotiedostoosi käyttämällä antamaasi salasanaa. Huomaa, että tämä väliaikainen postilaatikko tyhjennetään ja poistetaan sen jälkeen, jotta vain salasanalla suojattu postilaatikkosi sisältää viestit.

    • Jos olet yhteydessä IMAPiin (esim. käyttäen sähköpostiohjelmaa kuten Apple Mail tai Thunderbird), meidän ei tarvitse kirjoittaa väliaikaiseen levytilaan. Sen sijaan haetaan ja käytetään muistin sisällä salattua IMAP-salasanaasi. Reaaliajassa, kun viesti yritetään toimittaa sinulle, lähetämme WebSocket-pyynnön kaikille IMAP-palvelimille kysyen, onko heillä aktiivista istuntoa sinulle (tämä on hakuvaihe), ja sen jälkeen välitämme tämän salatun muistin sisällä olevan salasanan – joten meidän ei tarvitse kirjoittaa väliaikaiseen postilaatikkoon, voimme kirjoittaa varsinaiseen salattuun postilaatikkoosi käyttäen salattua salasanaasi.

  5. Salattujen postilaatikoidesi varmuuskopiot tehdään päivittäin. Voit myös pyytää uutta varmuuskopiota milloin tahansa tai ladata uusimman varmuuskopion osoitteesta Oma tili Domainit Aliakset. Jos päätät vaihtaa toiseen sähköpostipalveluun, voit helposti siirtää, ladata, viedä ja poistaa postilaatikkosi ja varmuuskopiosi milloin tahansa.

Teknologiat

Tietokannat

Tutkimme muita mahdollisia tietokantakerroksia, mutta mikään ei täyttänyt vaatimuksiamme yhtä hyvin kuin SQLite:

Tietokanta Salaus levossa Säilötty Postilaatikot Lisenssi Käytössä kaikkialla
SQLite ✅ Kyllä SQLite3MultipleCiphers avulla ✅ Public Domain
MongoDB "Saatavilla vain MongoDB Enterprisessa" ❌ Relaatiotietokanta ❌ AGPL ja SSPL-1.0
rqlite Vain verkossa ❌ Relaatiotietokanta MIT
dqlite Testaamaton eikä vielä tuettu? Testaamaton eikä vielä tuettu? LGPL-3.0-only
PostgreSQL Kyllä ❌ Relaatiotietokanta PostgreSQL (samankaltainen kuin BSD tai MIT)
MariaDB Vain InnoDB:lle ❌ Relaatiotietokanta GPLv2 ja BUSL-1.1
CockroachDB Vain Enterprise-ominaisuus ❌ Relaatiotietokanta BUSL-1.1 ja muut

Tässä on blogikirjoitus, joka vertaa useita SQLite-tietokannan tallennusvaihtoehtoja yllä olevassa taulukossa.

Turvallisuus

Käytämme aina salausta levossa (AES-256), salausta siirrossa (TLS), DNS over HTTPS ("DoH") käyttäen 🍊 Tangerine -palvelua, sekä sqleet (ChaCha20-Poly1305) salausta postilaatikoissa. Lisäksi käytämme token-pohjaista kaksivaiheista tunnistautumista (toisin kuin tekstiviestipohjaista, joka on altis man-in-the-middle-hyökkäyksille), kierrätettyjä SSH-avaimia, joiden root-käyttö on estetty, yksinoikeudella rajoitettuihin IP-osoitteisiin perustuvaa palvelimien käyttöä ja muuta. Jos tapahtuu evil maid -hyökkäys tai kolmannen osapuolen toimittajan epäluotettava työntekijä, postilaatikkosi voidaan silti avata vain luomallasi salasanalla. Voit olla varma, että emme luota mihinkään kolmannen osapuolen toimittajiin lukuun ottamatta SOC Type 2 -vaatimustenmukaisia palveluntarjoajiamme Cloudflare, DataPacket, Digital Ocean, GitHub ja Vultr.

Tavoitteenamme on, että yksittäisiä vikatilanteita olisi mahdollisimman vähän.

Postilaatikot

tldr; IMAP-palvelimemme käyttävät erikseen salattuja SQLite-tietokantoja jokaiselle postilaatikollesi.

SQLite on erittäin suosittu upotettu tietokanta – se toimii tällä hetkellä puhelimessasi ja tietokoneessasi – ja lähes kaikkien suurten teknologioiden käytössä.

Esimerkiksi salatuilla palvelimillamme on SQLite-tietokantapostilaatikko linux@example.com, info@example.com, hello@example.com ja niin edelleen – yksi jokaiselle .sqlite-tietokantatiedostona. Emme myöskään nimeä tietokantatiedostoja sähköpostiosoitteen mukaan – sen sijaan käytämme BSON ObjectID:tä ja uniikkeja UUID:ita, jotka eivät paljasta, kenelle postilaatikko kuuluu tai minkä sähköpostiosoitteen alla se on (esim. 353a03f21e534321f5d6e267.sqlite).

Jokainen näistä tietokannoista on salattu itse käyttäen salasanaasi (joka on vain sinulla) sqleetin avulla (ChaCha20-Poly1305). Tämä tarkoittaa, että postilaatikkosi ovat erikseen salattuja, itsenäisiä, sandboxattuja ja siirrettäviä.

Olemme hienosäätäneet SQLitea seuraavilla PRAGMA -asetuksilla:

PRAGMA Tarkoitus
cipher=chacha20 ChaCha20-Poly1305 SQLite -tietokannan salaus. Katso better-sqlite3-multiple-ciphers kohdasta Projects saadaksesi lisätietoja.
key="****************" Tämä on purettu muistissa oleva salasana, joka välitetään sähköpostiohjelmasi IMAP-yhteyden kautta palvelimellemme. Uudet tietokanta-instanssit luodaan ja suljetaan jokaiselle luku- ja kirjoitussessiolle (sandboxauksen ja eristyksen varmistamiseksi).
journal_model=WAL Write-ahead-log ("WAL") joka parantaa suorituskykyä ja sallii samanaikaisen lukuoikeuden.
busy_timeout=5000 Estää kirjoituslukitusvirheitä kun muita kirjoituksia tapahtuu.
synchronous=NORMAL Lisää transaktioiden kestävyyttä ilman tietojen korruptioriskiä.
foreign_keys=ON Pakottaa viittaukset vieraisiin avaimiin (esim. suhde taulusta toiseen) noudatettavaksi. SQLite ei oletuksena käytä tätä, mutta validoinnin ja tietojen eheyden vuoksi se tulisi ottaa käyttöön.
encoding='UTF-8' Oletuskoodaus kehittäjän mielenrauhan varmistamiseksi.

Kaikki muut oletusarvot ovat SQLitesta, kuten on määritelty virallisessa PRAGMA-dokumentaatiossa.

Samanaikaisuus

yhteenveto; Käytämme WebSocket-yhteyttä samanaikaisiin lukuihin ja kirjoituksiin salatuissa SQLite-sähköpostilaatikoissasi.

Luvut

Sähköpostiohjelmasi puhelimessa saattaa ratkaista imap.forwardemail.net osoittamaan johonkin Digital Oceanin IP-osoitteista – ja työpöytäasiakas saattaa ratkaista eri IP-osoitteen toiselta palveluntarjoajalta.

Riippumatta siitä, mihin IMAP-palvelimeen sähköpostiohjelmasi yhdistää, haluamme yhteyden lukevan tietokannastasi reaaliajassa 100 % tarkkuudella. Tämä toteutetaan WebSocketien avulla.

Kirjoitukset

Tietokantaan kirjoittaminen on hieman erilaista – koska SQLite on upotettu tietokanta ja sähköpostilaatikkosi sijaitsee oletuksena yhdessä tiedostossa.

Olimme tutkineet vaihtoehtoja kuten litestream, rqlite ja dqlite alla – mutta mikään näistä ei täyttänyt vaatimuksiamme.

Kirjoitusten toteuttamiseksi kirjoitusennakoinnin ("WAL") ollessa käytössä – meidän täytyy varmistaa, että vain yksi palvelin ("Primary") on vastuussa tästä. WAL nopeuttaa merkittävästi samanaikaisuutta ja sallii yhden kirjoittajan ja useita lukijoita.

Primary-palvelin toimii datapalvelimilla, joissa on liitetyt volumet, jotka sisältävät salatut sähköpostilaatikot. Jakelun näkökulmasta voit pitää kaikkia yksittäisiä IMAP-palvelimia imap.forwardemail.net takana toissijaisina palvelimina ("Secondary").

Saavutamme kaksisuuntaisen viestinnän WebSocketien avulla:

  • Primary-palvelimet käyttävät ws -kirjaston WebSocketServer-instanssia.
  • Secondary-palvelimet käyttävät ws -kirjaston WebSocket-asiakasinstanssia, joka on kääritty websocket-as-promised ja reconnecting-websocket -kirjastoilla. Nämä kaksi käärettä varmistavat, että WebSocket yhdistää uudelleen ja voi lähettää sekä vastaanottaa dataa tiettyjä tietokantakirjoituksia varten.

Varotoimet

yhteenveto; Salattujen sähköpostilaatikoidesi varmuuskopiot tehdään päivittäin. Voit myös välittömästi pyytää uutta varmuuskopiota tai ladata viimeisimmän varmuuskopion milloin tahansa osoitteesta Oma tili Verkkotunnukset Alias-nimet.

Varmuuskopioita varten suoritetaan yksinkertaisesti SQLite-komento VACUUM INTO joka päivä IMAP-komentojen käsittelyn aikana, joka hyödyntää salaustasi muistissa olevasta IMAP-yhteydestä. Varmuuskopiot tallennetaan, jos olemassa olevaa varmuuskopiota ei havaita tai jos tiedoston SHA-256 -tiiviste on muuttunut verrattuna viimeisimpään varmuuskopioon.

Huomaa, että käytämme VACUUM INTO -komentoa sisäänrakennetun backup-komennon sijaan, koska jos sivua muokataan backup-komennon aikana, komennon täytyy aloittaa alusta. VACUUM INTO ottaa tilannevedoksen. Katso näitä kommentteja GitHubissa ja Hacker Newsissa lisätietoja varten.

Lisäksi käytämme VACUUM INTO-komentoa backup-komennon sijaan, koska backup-komento jättäisi tietokannan hetkeksi salaamattomaksi, kunnes rekey suoritetaan (katso tämä GitHub-kommentti tästä lisätietoja varten).

Secondary ohjaa Primarya WebSocket-yhteyden kautta suorittamaan varmuuskopion – ja Primary vastaanottaa komennon ja suorittaa sen jälkeen:

  1. Yhdistää salattuun sähköpostilaatikkoosi.
  2. Hankkii kirjoituslukon.
  3. Suorittaa WAL-tarkistuspisteen komennolla wal_checkpoint(PASSIVE).
  4. Suorittaa SQLite-komennon VACUUM INTO.
  5. Varmistaa, että kopioitu tiedosto voidaan avata salasanalla (turvatoimi).
  6. Lataa sen Cloudflare R2 -palveluun tallennusta varten (tai omaan palveluntarjoajaasi, jos määritelty).

Muista, että postilaatikkosi ovat salattuja – ja vaikka meillä on IP-rajoituksia ja muita todennustoimia WebSocket-yhteyksille – pahantekijän tapauksessa voit olla varma, että ellei WebSocketin sisältö sisällä IMAP-salasanaasi, se ei voi avata tietokantaasi.

Tällä hetkellä tallennetaan vain yksi varmuuskopio per postilaatikko, mutta tulevaisuudessa saatamme tarjota pisteaikapalautuksen ("PITR").

IMAP-palvelimemme tukevat SEARCH-komentoa monimutkaisilla hauilla, säännöllisillä lausekkeilla ja muulla.

Nopea hakutoiminto on mahdollista FTS5 ja sqlite-regex ansiosta.

Tallennamme Date-arvot SQLite-postilaatikoihin ISO 8601 -merkkijonoina käyttäen Date.prototype.toISOString -metodia (UTC-aikavyöhykkeellä, jotta yhtäsuuruusvertailut toimivat oikein).

Indeksit tallennetaan myös kaikille ominaisuuksille, joita haussa käytetään.

Projektit

Tässä on taulukko, joka kuvaa lähdekoodissamme ja kehitysprosessissamme käyttämiämme projekteja (aakkosjärjestyksessä):

Projekti Tarkoitus
Ansible DevOps-automaatioalusta, jolla ylläpidämme, skaalaamme ja hallinnoimme koko palvelinlaivastoamme helposti.
Bree Työaikatauluttaja Node.js:lle ja JavaScriptille, tukee cronia, päivämääriä, ms, later-kirjastoa ja ihmisläheistä käyttöä.
Cabin Kehittäjäystävällinen JavaScript- ja Node.js-lokin kirjastona, jossa huomioidaan turvallisuus ja yksityisyys.
Lad Node.js-kehys, joka pyörittää koko arkkitehtuurimme ja suunnittelumme MVC:llä ja muulla.
MongoDB NoSQL-tietokantaratkaisu, jota käytämme kaiken muun datan tallentamiseen postilaatikoiden ulkopuolella (esim. tilisi, asetukset, domainit ja alias-määritykset).
Mongoose MongoDB:n objektidokumenttimallinnus ("ODM"), jota käytämme koko pinossamme. Kirjoitimme erityisiä apuvälineitä, jotka mahdollistavat Mongoose:n käytön SQLite:n kanssa 🎉
Node.js Node.js on avoimen lähdekoodin, monialustainen JavaScript-ajoympäristö, joka pyörittää kaikkia palvelinprosessejamme.
Nodemailer Node.js-paketti sähköpostien lähettämiseen, yhteyksien luomiseen ja muuhun. Olemme tämän projektin virallinen sponsori.
Redis Muistipohjainen tietokanta välimuistille, julkaisutilaus-kanaville ja DNS over HTTPS -pyynnöille.
SQLite3MultipleCiphers Salauslaajennus SQLite:lle, joka mahdollistaa koko tietokantatiedostojen salaamisen (mukaan lukien write-ahead-log ("WAL"), journal, rollback, …).
SQLiteStudio Visuaalinen SQLite-editori (jota voit myös käyttää) kehityspostilaatikoiden testaamiseen, lataamiseen ja tarkasteluun.
SQLite Upotettu tietokantakerros skaalautuvaan, itsenäiseen, nopeaan ja vikasietoiseen IMAP-tallennukseen.
Spam Scanner Node.js:n roskapostinestotyökalu, sähköpostisuodatus ja kalastelunestotoiminto (vaihtoehtomme Spam Assassinille ja rspamdille).
Tangerine DNS over HTTPS -pyynnöt Node.js:llä ja välimuisti Redisillä – joka takaa globaalin yhdenmukaisuuden ja paljon muuta.
Thunderbird Kehitystiimimme käyttää tätä (ja suosittelee myös) ensisijaisena sähköpostiohjelmana Forward Emailin kanssa.
UTM Kehitystiimimme käyttää tätä luodakseen virtuaalikoneita iOS:lle ja macOS:lle testatakseen eri sähköpostiohjelmia (samanaikaisesti) IMAP- ja SMTP-palvelimillamme.
Ubuntu Moderni avoimen lähdekoodin Linux-pohjainen palvelinkäyttöjärjestelmä, joka pyörittää koko infrastruktuuriamme.
WildDuck IMAP-palvelinkirjasto – katso sen muistiinpanot liitetiedostojen duplikaattien poisto ja IMAP-protokollan tuki.
better-sqlite3-multiple-ciphers Nopea ja yksinkertainen API-kirjasto Node.js:lle SQLite3:n ohjelmalliseen käyttöön.
email-templates Kehittäjäystävällinen sähköpostikehys mukautettujen sähköpostien luomiseen, esikatseluun ja lähettämiseen (esim. tilitiedotteet ja muuta).
json-sql-enhanced SQL-kyselyrakentaja, joka käyttää Mongo-tyylistä syntaksia. Tämä säästää kehitystiimimme aikaa, koska voimme jatkaa Mongo-tyylin kirjoittamista koko pinossa tietokantariippumattomalla lähestymistavalla. Se auttaa myös välttämään SQL-injektiohyökkäyksiä käyttämällä kyselyparametreja.
knex-schema-inspector SQL-työkalu olemassa olevan tietokantarakenteen tietojen poimimiseen. Tämä mahdollistaa meille helpon validoinnin, että kaikki indeksit, taulut, sarakkeet, rajoitteet ja muut ovat oikeita ja 1:1 sellaisia kuin niiden pitää olla. Kirjoitimme jopa automatisoituja apuvälineitä uusien sarakkeiden ja indeksien lisäämiseen, jos tietokantarakenteisiin tehdään muutoksia (erittäin yksityiskohtaisella virheilmoituksella).
knex SQL-kyselyrakentaja, jota käytämme vain tietokantamigraatioihin ja skeeman validointiin knex-schema-inspector-työkalun kautta.
mandarin Automaattinen i18n -lausekekäännös, joka tukee Markdownia käyttäen Google Cloud Translation API:a.
mx-connect Node.js-paketti MX-palvelimien ratkaisemiseen ja yhteyksien muodostamiseen sekä virheiden käsittelyyn.
pm2 Node.js:n tuotantoprosessien hallintaohjelma sisäänrakennetulla kuormantasaimella (hienosäädetty suorituskyvyn parantamiseksi).
smtp-server SMTP-palvelinkirjasto – käytämme tätä postinvaihto- ("MX") ja lähtevien SMTP-palvelimien toteutukseen.
ImapTest Kätevä työkalu IMAP-palvelimien testaamiseen vertailuarvoja ja RFC-spesifikaation IMAP-protokollan yhteensopivuutta vastaan. Tämä projekti on luotu Dovecot -tiimin toimesta (aktiivinen avoimen lähdekoodin IMAP- ja POP3-palvelin vuodesta 2002). Testasimme IMAP-palvelintamme laajasti tällä työkalulla.

Löydät muita käyttämiämme projekteja lähdekoodistamme GitHubissa.

Tarjoajat

Tarjoaja Tarkoitus
Cloudflare DNS-tarjoaja, terveystarkastukset, kuormantasaimet ja varastointivaraukset käyttäen Cloudflare R2.
GitHub Lähdekoodin isännöinti, CI/CD ja projektinhallinta.
Digital Ocean Omistettu palvelin ja hallinnoidut tietokannat.
Vultr Omistettu palvelin.
DataPacket Omistettu palvelin.

Ajatuksia

Periaatteet

Forward Email on suunniteltu näiden periaatteiden mukaisesti:

  1. Ole aina kehittäjäystävällinen, turvallisuus- ja yksityisyyskeskeinen sekä läpinäkyvä.
  2. Noudata MVC, Unix, KISS, DRY, YAGNI, Twelve Factor, Occamin partaveitsiä ja dogfoodingia.
  3. Kohdista pieneen, itse rahoitettuun ja ramen-voittoiseen kehittäjään.

Kokeilut

tldr; Lopulta S3-yhteensopivan objektivaraston ja/tai virtuaalitaulujen käyttäminen ei ole teknisesti toteuttamiskelpoinen suorituskykyrajoitusten vuoksi ja on altis virheille muistirajoitusten takia.

Olemme tehneet muutamia kokeiluja, jotka johtivat yllä käsiteltyyn lopulliseen SQLite-ratkaisuun.

Yksi näistä oli yrittää käyttää rclonea ja SQLitea yhdessä S3-yhteensopivan tallennuskerroksen kanssa.

Tämä kokeilu auttoi meitä ymmärtämään ja löytämään reunatapauksia liittyen rcloneen, SQLiteen ja VFS -käyttöön:

  • Jos otat käyttöön --vfs-cache-mode writes -lipun rclonessa, lukeminen toimii hyvin, mutta kirjoitukset välimuistitetaan.
    • Jos sinulla on useita maailmanlaajuisesti hajautettuja IMAP-palvelimia, välimuisti ei synkronoidu niiden välillä, ellei sinulla ole yhtä kirjoittajaa ja useita kuuntelijoita (esim. pub/sub-malli).
    • Tämä on uskomattoman monimutkaista, ja lisämonimutkaisuus johtaa useampiin yksittäisiin vikapisteisiin.
    • S3-yhteensopivat tallennuspalvelut eivät tue osittaisia tiedostomuutoksia – mikä tarkoittaa, että .sqlite-tiedoston jokainen muutos johtaa koko tietokannan uudelleenlähetykseen.
    • Muita ratkaisuja kuten rsync on olemassa, mutta ne eivät tue kirjoituslokia ("WAL") – joten päädyimme tarkastelemaan Litestreamiä. Onneksi salauksemme salaa jo WAL -tiedostot, joten emme tarvitse Litestreamiä siihen. Emme kuitenkaan olleet vielä varmoja Litestreamin tuotantokäytöstä ja alla on muutama huomio siitä.
    • Tämän --vfs-cache-mode writes -vaihtoehdon (ainoa tapa käyttää SQLitea kirjoituksiin rclonen yli) käyttäminen yrittää kopioida koko tietokannan alusta alkaen muistiin – yhden 10 GB postilaatikon käsittely on ok, mutta useiden erittäin suurten postilaatikoiden käsittely johtaa IMAP-palvelimien muistirajoituksiin, ENOMEM-virheisiin, segmentointivirheisiin ja tietojen vioittumiseen.
  • Jos yrität käyttää SQLite Virtuaalitauluja (esim. s3db) saadaksesi datan elämään S3-yhteensopivalla tallennuskerroksella, kohtaat useita muita ongelmia:
    • Lukeminen ja kirjoittaminen on erittäin hidasta, koska S3-API-päätepisteisiin täytyy tehdä HTTP GET, PUT, HEAD ja POST -kutsuja.
    • Kehitystesteissä yli 500K-1M+ tietueen käsittely kuitu-internet-yhteydellä rajoittui edelleen S3-yhteensopivien tarjoajien kirjoitus- ja lukunopeuteen. Esimerkiksi kehittäjämme suorittivat for-silmukoita sekä peräkkäisille SQL INSERT -lauseille että suurten tietomäärien massakirjoituksille. Molemmissa tapauksissa suorituskyky oli hämmästyttävän hidas.
    • Virtuaalitauluilla ei voi olla indeksejä, ALTER TABLE -lauseita eikä muita rajoituksia – mikä johtaa jopa 1-2 minuutin tai pidempiin viiveisiin datan määrästä riippuen.
    • Objektit tallennettiin salaamattomina eikä natiivisti saatavilla ole salaustukea.
  • Tutkimme myös sqlite-s3vfs -projektia, joka on konseptuaalisesti ja teknisesti samanlainen kuin edellinen kohta (siis samat ongelmat). Mahdollisuus olisi käyttää räätälöityä sqlite3-käännöstä, joka on kääritty salauksella kuten wxSQLite3 (jota käytämme ratkaisussamme yllä) muokkaamalla asetustiedostoa.
  • Toinen mahdollinen lähestymistapa oli käyttää multiplex-laajennusta, mutta siinä on 32 GB:n rajoitus ja se vaatisi monimutkaista rakentamista ja kehitystyötä.
  • ALTER TABLE -lauseita tarvitaan (joten virtuaalitaulut ovat täysin poissuljettu vaihtoehto). Tarvitsemme ALTER TABLE -lauseita, jotta knex-schema-inspector -hookimme toimii oikein – tämä varmistaa, ettei data vahingoitu ja haetut rivit voidaan muuntaa kelvollisiksi dokumenteiksi mongoose-skeemojen mukaan (mukaan lukien rajoitteet, muuttujatyypit ja mielivaltaiset datan validoinnit).
  • Lähes kaikki S3-yhteensopivat SQLite-projektit avoimen lähdekoodin yhteisössä ovat Pythonilla (eivät JavaScriptillä, jota käytämme koko pinossamme).
  • Pakkauskirjastot kuten sqlite-zstd (katso kommentit) vaikuttavat lupaavilta, mutta eivät ehkä ole vielä valmiita tuotantokäyttöön. Sen sijaan sovelluspuolen pakkaus datatyypeille kuten String, Object, Map, Array, Set ja Buffer on siistimpi ja helpompi lähestymistapa (ja helpompi myös migroida, koska voisimme tallentaa Boolean-lipun tai sarakkeen – tai käyttää PRAGMA user_version=1 pakkausta varten tai user_version=0 ilman pakkausta tietokannan metatietona).
    • Onneksi meillä on jo liitetiedostojen duplikaattien poisto toteutettuna IMAP-palvelimen tallennuksessa – näin jokainen viesti, jossa on sama liite, ei säilytä kopiota liitteestä – vaan yksi liite tallennetaan useille viesteille ja ketjuille postilaatikossa (ja vierasviite käytetään sen jälkeen).
  • Litestream-projekti, joka on SQLite:n replikaatio- ja varmuuskopiointiratkaisu, on erittäin lupaava ja todennäköisesti käytämme sitä tulevaisuudessa.
    • Emme halua vähätellä tekijöitä – koska rakastamme heidän työtään ja panostuksiaan avoimeen lähdekoodiin yli vuosikymmenen ajan – mutta käytännön kokemusten perusteella näyttää siltä, että ongelmia ja mahdollisia tietojen menetyksiä voi esiintyä.
  • Varmuuskopioiden palautuksen tulee olla kitkatonta ja yksinkertaista. Ratkaisut kuten MongoDB mongodump- ja mongoexport-työkaluilla ovat paitsi työläitä, myös aikaa vieviä ja konfigurointinsa puolesta monimutkaisia.
    • SQLite-tietokannat tekevät siitä helppoa (se on yksi tiedosto).
    • Halusimme suunnitella ratkaisun, jossa käyttäjät voivat ottaa postilaatikkonsa ja poistua milloin tahansa.
      • Yksinkertaiset Node.js-komennot kuten fs.unlink('mailbox.sqlite') poistaa tiedoston pysyvästi levyltä.
      • Vastaavasti voimme käyttää S3-yhteensopivaa APIa HTTP DELETE -kutsulla helposti poistaaksemme snapshotit ja varmuuskopiot käyttäjiltä.
    • SQLite oli yksinkertaisin, nopein ja kustannustehokkain ratkaisu.

Vaihtoehtojen puute

Tietojemme mukaan mikään muu sähköpostipalvelu ei ole suunniteltu tällä tavalla eikä ole avoimen lähdekoodin.

Uskomme tämän johtuvan siitä, että olemassa olevilla sähköpostipalveluilla on tuotannossa vanhentunutta teknologiaa, jossa on spagettikoodia 🍝.

Useimmat, elleivät kaikki, nykyiset sähköpostipalveluntarjoajat ovat joko suljetun lähdekoodin tai mainostavat olevansa avoimen lähdekoodin, mutta todellisuudessa vain niiden käyttöliittymä on avoimen lähdekoodin.

Sähköpostin herkin osa (varsinainen tallennus/IMAP/SMTP-vuorovaikutus) toteutetaan kokonaan taustapalvelimella (serverillä), eikä asiakaspuolella (clientissä).

Kokeile Forward Emailia

Rekisteröidy tänään osoitteessa https://forwardemail.net! 🚀