Tartalmi kivonat
Webes felületen hozzáférhető felhasználói e-mail napló szolgáltatás Skopkó Tamás Debreceni Egyetem Informatikai Szolgáltató Központ skopkot@unideb.hu Tartalomjegyzék 1. Absztrakt 3 2. A környezet 4 3. A rendszer ismertetése 4 3.1 A mailgw rész 5 3.11 Postfix queue kezelés5 3.12 Az after-queue filter 6 3.13 A logfilter 7 3.2 A mailsrv rész 7 3.3 A webapp rész 8 3.4 A backend rész 10 3.41 Az adatbázis szerkezete 10 3.42 Hozzáférésszabályozás 11 4. Konklúzió 12 5. Bibliográfia 13 1 . Absztrakt A mai napig az egyik legnépszerűbb internetes szolgáltatás az SMTP alapú elektronikus levelezés. A megoldás gyökerei az internet gyermekkorába nyúlnak vissza, ma már azonban számos kihívással küszködik. Részben ezen hiányosságok miatt az utóbbi 10 évben dinamikusan növekvő kéretlen levélforgalom kering az interneten, amely egyre inkább megnehezíti az elektronikus levelezési szolgáltatás színvonalának biztosítását. Ezért egy
korszerű levelezőrendszer első védelmi vonalát képező vírus- és spamszűrő alkalmazást folyamatosan hangolni kell. A hatásfok növelésének a hangolhatóság mellett a különböző szűrési technológiák kombinációjának alkalmazása (RBL, szürkelistázás, stb) is eszköze. A felhasználók ugyanakkor joggal várják el, hogy postafiókjukat ne árassza el levélszemét, viszont legitim levelezésük se vesszen el. Emellett a hozzáférés történjék valamilyen felhasználóbarát felületen. Ezen elvárásoknak megfelelően egy olyan rendszert építettünk ki, amely egy saját fejlesztésű postfix after-queue filter és egy logfilter segítségével minden postafiókhoz köthető, áthaladó e-mailt egy nagy tárolókapacitású külső szerveren tárol le és a levelekhez kapcsolódó metaadatokat egy relációs adatbázisban helyezi el. A hozzáférést a felhasználók számára egy kényelmes, szintén saját fejlesztésű Drupal-modulon alapú webes
felülettel valósítottuk meg. Az így összeállított rendszer – tárolókapacitástól függően – akár hetekre visszamenőleg is tárolni tudja a levélforgalmat, onnan a felhasználók megtekinthetik, lementhetik leveleiket. Hozzáadott szolgáltatásként a napi levélforgalmat összegző kivonat (digest) is kipostázható az azt igénylő felhasználók számára. A rendszer további jellemzője, hogy bizonyos keretek közt skálázható, valamint egy XMLRPC API-n keresztül lehetőséget biztosít további szervezeti egységek rendszerüzemeltetőinek, hogy felhasználóik számára is elérhetővé tegyék ezt a szolgáltatást. Előadásomban ezen rendszer koncepcióját szeretném ismertetni. 2 . A környezet A Debreceni Egyetem Orvos- és Egészségtudományi Centrumán számos maildomaint kell menedzselnünk, amelyhez több, az azokat kiszolgáló SMTP szerver is tartozik, ezek tárolják a postafiókokat[1]. Mivel többezres postafiókszámról van szó, a
hozzájuk kötődő szűrőteljesítmény igény meglehetősen magas, ezért külön szűrőszervereket állítottunk fel, amelyek kizárólag a különböző maildomainek irányába haladó, ill. az intézményből kifele irányuló levelek szűrésével foglalkoznak. FreeBSD 7x alapú szervereink közt DNS-alapú teljesítményelosztást alkalmazunk, mivel azonos teljesítményű fizikai gépekről van szó. Erre a rendszerre építettük fel e-mail naplózó szolgáltatásunkat, amelyre időnként “mailstat” néven fogok hivatkozni. Az alapját az az ötlet képezi, ha a szűrőn beérkező levél feladójának vagy címzettjének postafiókja beazonosítható (nálunk létezik), akkor az útját nyomon követhetjük a célt képező SMTP szerverig. Mivel könnyűsúlyú és széles körben konfigurálható, a Postfix SMTP szervert (2.4+) preferáljuk mind SMTP szervereinken, mind a szűrőszervereken[2]. 3 . A rendszer ismertetése A naplózó rendszert alkotó komponensek
saját fejlesztésű Perl és PHP szkriptek, amelyek a következők: • • • • mailgw modul: a szűrőszervereken fut mailsrv modul: a cél SMTP szervereken fut backend: ahol az információ tárolódik webapp modul: a felhasználói napló webalkalmazás 1. ábra: a rendszer felépítése Miért van ennyi részre bontva? Egyfelől lehetőséget ad, hogy egyes funkciók külön szerverekre kerülhessenek. A skálázódást is segíthetjük vele. Másfelől segítségével bizonyos fokú hozzáférésszabályozást vihetünk a rendszer elemei közé. 3.1 A mailgw modul Két fő rész alkotja: egy Postfix after-queue filter és egy logfilter[3]. A feladat: a beérkező levelek azonosítása, szükség esetén eltárolása. A későbbiekben a rá vonatkozó státuszinformációk frissítése. 3.11 Postfix queue kezelés A Postfixnek négy különböző queue-ja van: maildrop, beérkező, aktív és halasztott. A lokális céllal rendelkezők a maildropba kerülnek, és a
beérkezőbe másolódnak át némi megtisztítás után. A beérkező queue szolgál az épp beérkező vagy azon levelek számára, amelyekkel a queue menedzser még nem foglalkozott. Az aktív egy korlátozott méretű sor azon levelek számára, amelyek kézbesítésével épp foglalkozik a Postfix. A nem kézbesíthető levelek a halasztott sorba kerülnek, így nem akadályozzák az egyéb kézbesítést. A rendszer az aktív sorral kapcsolatos információkat a memóriában tárolja. A sor mérete (qmgr message active limit beállítás) a szimultán kézbesítő processzek egész számú többszöröse. Ezt igény szerint választhatjuk meg A sorkezelő elől nem szabad elfogyjon a memória egy véletlenül bekövetkező levélforgalmi csúcs miatt[4]. Másik memóriatakarékossági trükk, hogy teljes fájlok memóriába olvasása helyett fix méretű buffereket használunk, amelyek egyfajta ablakként funkcionálnak ezen fájlokra. Így a fájl méretének nincs hatása
a memóriafelhasználásra. A postfix aktív sora is csak egy ablak egy nagyobb méretű sorra. 3.12 Az after-queue filter Feladata a Postfix által sorbaállított levelek feladójának és címzettjének beazonosítása. Amennyiben találtunk hozzá létező postafiókot, regisztrálja azt a backend szerveren (eltárolja a levéltörzset, és számos metaadatot a levélre vonatkozóan). Miért nem before-queue filter? Bármi probléma lép fel a szkriptben, a Postfix teljesítményére drasztikus hatással lehet. Emellett még queue id sincs, ez viszont fontos a számunkra további nyomonkövethetőséghez. A queue-ba kerülés előtt általában azon levelek pattannak le, amelyek pl. hibás formázásúak, vagy feketelistás címekről (RBL) érkeznek. Ezekhez amúgyis csak ritkán találnánk hozzárendelhető postafiókot a fals címzés miatt. Működés A szkript SMTP proxy-ként üzemel, vagyis egyik irányban SMTP szerverként, másikban SMTP kliensként kommunikál (az
MSDW::SMTP::* Perl modulokra alapozva)[5]. Minden beérkező üzenet esetében az alábbi parancsokat és mezőket feldolgozza: MAIL FROM, RCPT TO(k), Message-ID, Subject, Received-from (amelyben szerepel a levélszűrő szerver neve). Az adatok birtokában aztán a backendhez fordul ellenőrizni, van-e érintett mailbox akár feladó akár címzett tekintetében. Amennyiben nincs, figyelmen kívül hagyja Amennyiben van, regisztrálja az aktuális levelet, vagyis a metaadatok és a levélforrás a backendre kerülnek. Kapcsolódás a Postfixhez A szűrőt ún. szendvics szerkezetben kapcsoljuk a postfixhez: 2 . ábra: az after-queue filter elhelyezése ahol: • m addr / m port: mailstat listen addr / port • f1 addr / f1 port : 1. szűrő addr / port • pb addr / pb port : a postfix ezen a címen / porton veszi vissza a megszűrt leveket master.cf smtp inet n n -o content filter=smtp:[m addr]:m port -o disable mime output conversion=yes - smtpd Az alábbi csak akkor kell,
ha még nem állítottunk be szűrőt ilyen felállásban: pb addr:pb port inet n -o content filter= -o local recipient maps= -o myhostname=VBMS.dummy -o mynetworks=127.000/8 -o strict rfc821 envelopes=yes n - 64 smtpd A szkript démon módban fut, indításkor kötelezően megadandó a listen és talk to cím és port. Tipikusan: • listen address:port : m addr:m port • talk to address:port : f1 addr:f1 port (tovább szűrő esetén), vagy pb addr:pb port 3.13 A logfilter Figyeli és feldolgozza a Postfix syslog üzeneteit (mail log facility). A levelekre vonatkozó státuszinformációkat frissíti a backenden, amennyiben queue id változás történik, vagy egy lépés a továbbításban (legyen az akár sikeres, akár sikertelen). Az egyes levelek aktuális queue id-ja számon van tartva, így a levelek nyomonkövetése megoldott. A sikertelen továbbítást nem minden esetben tudjuk megállapítani, mert amennyiben a tartalomszűrő blokkolja a levelet (spam), az nem jut
vissza a Postfixhez, így logbejegyzésünk sem lesz róla. Oly módon következtethetünk egy üzenet blokkoltságára, hogy az utolsó relay szerver maga a mailgw marad. Ez kétségkívül nem szép megoldás Az alkalmazott tartalomszűrőhöz készített logfilterrel ezt a hiányosságot is pótolni lehetne.) Kapcsolódás a syslog-ng-hez syslog-ng.conf destination mailstat { program("/path/to/mailstat/logfilter.pl"); }; log { source(src); filter(f mail); filter(f info); destination(mailstat); }; 3.2 A mailsrv modul A levelezőszerver ismeri a saját maildomainjein létező postafiókok, aliasok listáját. Emiatt az alábbi szkriptek segítéségével ő tudja frissíteni ezen információkat a backenden. A sync-users script egy bizonyos maildomainhez tartozó mailboxok és aliasok listájának szinkronizálását végzi a backendhez. A legutóbbi futás óta létrejötteket a backenden is létrehozza, a megszűnteket onnan is eltávolítja. Cron job-ként
futtatható A postafióklista kinyerésének módja az adott SMTP szerver konfigurációjától függ. Mi virtuális postafiókokkal konfigurált Postfixet használunk, ahol a postafiók adatokat MySQL adatbázis tárolja. A szkript ennek megfelelően ezen adatbázisból dolgozik Az update-quota opcionális szkript, a postafiókok aktuális helyfoglalását frissíti, ez jellemzően a POP3-at használó postafióktulajdonosok számára érdekes információ. (Ugyanis a Postfix megfelelő beállítása esetén a lemezterület felhasználtság IMAP protokollon keresztül lekérdezhető.) Szintén cron job-ként futtatható A lastlogin-filter szintén opcionális, az utolsó bejelentkezéssel kapcsolatos információkat frissíti. Syslog filterként használható 3.3 A webapp modul A felhasználó számára látható és igénybevehető részt Drupal modulként implementáltam[6]. Ez egy webes alkalmazás (webapp), amelyet egy maildomainnel kell összerendelnünk. A felhasználói
autentikációt explicit meg kell valósítani: az accountokat szinkronizálni a levelezőszerverrel és a jelszavakat pl. IMAP-en keresztül ellenőrizni, de a konkrét megvalósítás fantázia és az adott környezet függvénye. A webes felületen a felhasználó bejelentkezés után megtekinteti aznapi levélforgalmát. Az időintervallum természetesen módosítható. A kiválasztott levél tartalma a részletek gombra klikkelve tekinthető meg. Ekkor lehetőség nyílik a teljes levélforrás vagy csak bizonyos részek, csatolmányok lementésére. Lehetőség van feladó vagy címzett, ill. tárgy szerinti keresésre is Amennyiben egy felhasználó igényt tart rá, az elmúlt napi forgalmáról összesítőt (digest) is kiküld a rendszer. 1. kép : Eg y fel has zná ló azn api lev ele zés éne k list ája 2. kép : Sta tisz tika i és egy éb info rmá ciók a lap aljá n 3. kép: Konkrét levél tartalmának megtekintése 3.4 A modul backend A háttérrendszer
(backend) tulajdonképpen egy PHP webes alkalmazás (middleware), amely az adatkommunikációt valósítja meg az adatbázis és a további modulok (mailgw, mailsrv, webapp) között. Az alkalmazást Apache (22+) webszerver szolgálja ki Működés: A modulok kliensként mind ide fordulnak a kívánt műveletekkel, egymással nem is kommunikálnak. A kommunikáció XML-RPC felületen zajlik[7] A paraméterek ellenőrzése után a backend végrehajtja a műveletet és visszaadja a művelet eredményét. A metaadatok tárolására és visszakeresésére a MySQL (5.0+) adatbázis szolgál A levelek forrását fájlrendszerben tárolja. Minden nap számára külön alkönyvtárat hoz létre, a fájlnév a legelső queue id lesz. A túl régi adatok törléséről cron szkript gondoskodik 3.41 Az adatbázis szerkezete Az Aliases tábla tárolja a postafiókokhoz tartozó aliasokat, amelyeket az alias stringhez rendelt maildomain id és mailbox id ír le. A Clients tábla a
hozzáférésszabályozás eszköze. Minden sora egy hostot (valamint annak kulcsát) rendel össze egy modultípussal. A Mailboxes tábla tárolja az összes maildomain összes postafiókjának adatait. A legfontosabb információk (id, username, maildomain id) mellett járulékos információkat is gyűjthetünk bele (kvóta kihasználtság, utolsó bejelentkezés). A Maildomains tábla az egyes maildomaineket tartalmazza, mindegyikhez megjelölve a mailsrv host azonosítóját és az SMTP szerver nevét. Ez utóbbi a levél célbaérkeztének megállapítását segítő információ is egyben. A Maildomain aliases tábla a meglevő maildomainek mellé alternatív maildomainek hozzárendelését teszi lehetővé. (Használata nem kötelező) A Mails magukat a leveleket leíró metaadatok leírását tartalmazó tábla. A mezők: id (a levél azonosítószáma), mailgw id (melyik mailgw fogadta), message id, queue id (aktuális queue id), timestamp (a feldolgozás időpontjának
időbélyege), sender mailbox id, recipient mailbox id (a feladó és küldő mailboxának azonosítója), mail from (a MAIL FROM: parancs mögötti szöveg), rcp to (az RCPT TO: parancs mögötti szöveg), subject (a levél tárgya), mail file name (a levél forrásszövege ebben a fájlban került elhelyezésre), relay (a legutolsó relay információ), status, status code, status message, size (a levél mérete bájtban). A szöveges mezőket UTF8 kódolással tárolja Természetesen a Mails tábla sorainak száma lesz a legmagasabb. Tapasztalataim szerint néhányszázezres sorszámig nem probléma a MyISAM tárolómotor használata (az indexek elég gyors keresést tesznek lehetővé), de milliós nagyságrendnél érdemes lehet az InnoDB tárolómotor megfontolása. 3.42 Hozzáférésszabályozás Mivel minden kommunikáció a backend és valamely egyéb rész között zajlik, ezért a hozzáférésszabályozást is ezen ponton valósítjuk meg. Nincsenek felhasználók,
csak szerverek, maildomainek és azokhoz kapcsolódó postafiókok, aliasok, ezért a szabályozást minden modul egyedi kulccsal való összerendelésével oldottam meg. A művelet végrehajtása legelején ezt a kulcsot ellenőrzi a backend. Egy mailgw jogosult az összes maildomain lista lekérésére. Minden maildomainhez megkérdezheti egy adott postafiók létezését (lookup). Regisztrálhat levelet és frissítheti a rá vonatkozó státuszinformációkat. A mailsrv saját maildomainjeinek postafiók és alias listájának karbantartására jogosult. A webapp saját maildomainjének postafiókjai közti keresésre (lookup), egy adott felhasználó levelei közti keresére és a levél tartalmának, valamint a hozzá kapcsolódó metaadatok lekérésére jogosult. A hozzáférésszabályozás egy másik pontja a webapp, amely a hozzárendelt maildomain postafiókjaihoz való hozzáférését hivatott kontrollálni. 4 . Konklúzió A tárgyalt rendszer nagy előnye, hogy nyílt
forrású, ingyenes szoftverelemekből épíkezik. Megfelelő feltétleknek eleget tevő környezetben nem kívánja a levelezőrendszer drasztikus átalakítását, lazán kapcsolódik hozzá, nem szól bele működésébe. A felhasználók számára pedig jelentős hozzáadott értékkel bír. Az alkalmazást továbbfejlesztés szempontjából az alábbi pontokon érdemes körbejárni: A webes felület további kényelmi funkciókkal bővíthető, pl. levelek újraküldése a felhasználó inboxába, kijelölt levelek letöltése egy ZIP fájlban. A backend esetében hasznos lenne több szerver párhuzamos alkalmazása egyszerre, teljesítményelosztás, skálázhatóság és hibatűrés szempontjából. A tartalomszűrőhöz célszerű dedikált logfilter megírása, így elkerülhető a blokkolt üzenetek “beragadtként” való megjelenése. A szkriptek optimalizációja folytán csökkenteni az RPC-hívások számát, ill. batchelése, ezáltal csökkentve a backend
terhelését. 5. Referenciák (1) (2) (3) (4) (5) (6) (7) RFC 2821: SMTP, http://www.ietforg/rfc/rfc2821txt Postfix Documentation, http://www.postfixorg/documentationhtml Postfix After-queue filter, http://www.postfixorg/FILTER READMEhtml Postfix Queue Management, http://www.porcupineorg/postfix/queueinghtml DomainKeys filter for Postfix, http://jason.longname/dkfilter/ Drupal API reference, http://api.drupalorg/ XML-RPC homepage, http://www.xmlrpccom/