Kvanttiturvallinen sähköposti: Kuinka käytämme salattuja SQLite-postilaatikoita pitääksemme sähköpostisi turvassa
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
-
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.
- Käyttäjätunnuksesi on koko alias sähköpostiosoitteellasi, esimerkiksi
-
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).
-
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!
Tip
Haluatko oppia lisää? Lue kuinka sähköpostin edelleenlähetys asetetaan, kuinka sähköpostinvaihtopalvelumme toimii tai katso oppaamme.
-
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.
-
-
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äWebSocketyhdistää 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:
- Yhdistää salattuun sähköpostilaatikkoosi.
- Hankkii kirjoituslukon.
- Suorittaa WAL-tarkistuspisteen komennolla
wal_checkpoint(PASSIVE). - Suorittaa SQLite-komennon
VACUUM INTO. - Varmistaa, että kopioitu tiedosto voidaan avata salasanalla (turvatoimi).
- 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").
Haku
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:
- Ole aina kehittäjäystävällinen, turvallisuus- ja yksityisyyskeskeinen sekä läpinäkyvä.
- Noudata MVC, Unix, KISS, DRY, YAGNI, Twelve Factor, Occamin partaveitsiä ja dogfoodingia.
- 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
rsyncon 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,HEADjaPOST-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 SQLINSERT-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.
- Lukeminen ja kirjoittaminen on erittäin hidasta, koska S3-API-päätepisteisiin täytyy tehdä HTTP
- 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). TarvitsemmeALTER TABLE-lauseita, jottaknex-schema-inspector-hookimme toimii oikein – tämä varmistaa, ettei data vahingoitu ja haetut rivit voidaan muuntaa kelvollisiksi dokumenteiksimongoose-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,SetjaBufferon siistimpi ja helpompi lähestymistapa (ja helpompi myös migroida, koska voisimme tallentaaBoolean-lipun tai sarakkeen – tai käyttääPRAGMAuser_version=1pakkausta varten taiuser_version=0ilman 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- jamongoexport-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ä.
- Yksinkertaiset Node.js-komennot kuten
- 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! 🚀