Spam elleni védekezés Postfix-el
 
Kadlecsik József
kadlec@sunserv.kfki.hu
KFKI RMKI SZHK

Networkshop'2000 konferenciaelőadás, 2000. április 18-20., Gödöllő
 
 
A spam (kéretlen elektronikus levél) elleni védekezés az elmúlt évek során igen fontossá vált. A legfiatalabb mail kezelő szoftver, a Postfix spam ellen való védekezési lehetőségeit tárgyaljuk meg az általunk készített Postfix-bővítésekkel együtt. A KFKI telephely levélforgalmának kezelése során nyert gyakorlati tapasztalatainkat közreadjuk.
 
 
Bevezetés
 
Postfix a legfiatalabb E-mail kezelő rendszer (MTA), amelyet Wietse Venema írt az IBM szponzorálásával.
 
A szerző legfontosabb céljai a szoftver megírása során a következők voltak:
 
ˇSzabad terjeszthetőség, hogy a szoftver széles körben elfogadottá váljon.
ˇTeljesítmény. Egy Postfix-et futtató PC képes naponta egymilliónyi különböző üzenet kézbesítésére.
ˇKompatibilitás. A Postfix sendmail-kompatibilis az áttérés megkönnyítése végett. Támogatja a /var/spool/mail, /etc/aliases, NIS és ~/.forward fájlokat. Azonban a könnyű adminisztrálhatóság végett nem használ sendmail.cf fájlt.
ˇRobusztus működés. A Postfix szélsőséges körülmények között is (a lokális gépnek kevés a memóriája, elfogy a rendelkezésre álló diszkterület, stb.) racionálisan viselkedik, nem téve még rosszabbá a helyzetet. A Postfix nem nő határtalanul, ahogy nő a kézbesítendő üzenetek száma.
ˇRugalmasság. A Postfix egy tucatnyi kicsi programból áll, amelyek mind egyetlen feladatért felelősek: üzenet fogadása az SMTP porton, lokális üzenet-kézbesítés, cím-átírás, stb. A helyi igényektől függően részel más alternatív programokkal helyettesíthetők, vagy elhagyhatók (pl. tűzfalon nincs szükség lokális üzenet-kézbesítésre).
ˇBiztonság. A Postfix többszintű védekezést használ. Majdnem az összes Postfix daemon futtatható ún. chroot jail-ben. Nincs közvetlen kapcsolat az SMTP daemon és a lokális üzenet-kézbesítő program között: egy betörőnek több program védelmén kell keresztüljutni ahhoz, hogy elérje azt. A Postfix még a saját queue fáljának a tartalmában vagy a belső IPC üzeneteinek sem "hisz". A Postfix nem igényel egyetlen setuid-os programot sem.
 
A komponensek és tulajdonságok közül egyedül az SMTP daemon beépített spam elleni védekezési módokkal foglalkozunk.
 
1. Standard spam elleni védelem
 
Postfix esetén az SMTP kommunikáció során nyert adatok alapján több módon léptethetünk életbe szűrőfeltételeket:
 
ˇ csak a kliens neve vagy címe alapján (smtpd_client_restrictions)
ˇa kliens neve, címe valamint az SMTP HELO/EHLO parancsok által átadott azonosító alapján (smtpd_helo_restrictions)
ˇa kliens neve, címe, az SMTP HELO/EHLO parancsok által átadott azonosító valamint a MAIL FROM paranccsal átadott feladói cím szerint (smtpd_sender_restrictions)
ˇa kliens neve, címe, az SMTP HELO/EHLO parancsok által átadott azonosító, a MAIL FROM parancs szerintit feladói cím valamint a RCPT TO paranccsal átadott címzett alapján (smtpd_recipient_restrictions)
 
A szűrési feltételek (több mint 20!) néhány kategóriába sorolhatók:
 
ˇszintaktikai ellenőrzések
ˇDNS regisztrációs ellenőrzések, RBL típusú ellenőrzések
ˇmás Postfix paraméterekkel való összevetés alapján való szűrés (mydestination, virtual_maps, relay_domains, stb.)
ˇa paraméter (vagy részeinek) táblázatokban való jelenléte alapján
 
A táblázatok használata az egyik erőssége a Postfix-nek - és annak következménye, hogy nincs olyan makró nyelve, mint például a sendmail-nek. Amit a sendmail a szabályokkal valósít meg, azt Posfix-ben táblázatokkal oldjuk meg.
 
A Postfix által támogatott táblázatok:
 
ˇkörnyezeti változók
ˇpassword fájl
ˇDBM adatbázis
ˇBerkeley DB hash és btree formátumban egyaránt
ˇNIS/NIS+, NetInfo
ˇLDAP
ˇmySQL
ˇPerl-kompatibilis reguláris kifejezések
ˇPOSIX-kompatibilis reguláris kifejezések.
 
A spam védelem esetén a rendszer megkeresi az adott táblázatban a kérdéses paramétert (kliens IP címe, neve, HELO hosztnév, feladó vagy címzett címe) vagy annak egy részét (domain, usernév az E-mail címből) majd visszaadja a hozzá tartozó értéket. Ha az REJECT vagy "[45]xx szöveg", akkor a táblázatban való keresés végeredménye az üzenet visszautasítása, egyébként folytatódik tovább a megszorítások kiértékelése.
 
Ez még mindíg nem adna elég rugalmasságot, mivel nincs lehetőség ÉS feltételek megadására (pl.kliens gépe xxx domain-ben van ÉS a címzett xy@valahol, akkor REJECT/ACCEPT).
 
Az ÉS feltételek kialakításához az smtpd_restriction_classes paramétert ad segítséget. Vele definiálhatjuk azokat a feltételeket, amelyeket majd a táblázatok kiértékelése során azok "jobb oldalán" használhatunk. Egy-egy ilyen feltétel ezek után újabb kiértékelésen esik át, így valósítva meg a feltétel-kombinációt. Példa: @xyz.domain-ből csak a @zzz.mydomain címeknek engedünk levelet küldeni
 
smtpd_restriction_classes = class_xyz_domain
class_xyz_domain = check_recipient_access hash:/etc/postfix/may_send, reject
smtpd_sender_restrictions = hash:/etc/postfix/check_sender
 
Ekkor a két file tartalma a következő:
 
/etc/postfix/check_sender:
 
xyz.domain       class_xyz_domain
 
/etc/postfix/may_send:
 
zzz.mydomain       OK
 
2. Kiterjeztett spam elleni védelem
 
Noha az eddigieg alapján a Postfix spam elleni védelme kellően rugalmasnak tűnik, azért van néhány probléma:
 
ˇRBL típusú ellenőrzéseket csak a maps_rbl_domains változóban felsorolt összes domain-ben lehet végrehajtani
ˇA beépített ellenőrzések hibaüzeneteit csak a forrásba való belejavítással lehet átírni
ˇCsak igen nehézkesen valósítható meg, hogy felhasználók adott szűrési feltételek közül tetszőlegesen válogathassanak.
 
Mindezek miatt a KFKI RMKI Számítógép Hálózati Központban kiterjesztettük a Postfix spam védelmét néhány új tulajdonsággal.
 
2.1 Feltételes makró-kiértékelés
 
A Posfix konfigurációs fáljban a paraméterek értékeire a $parameter szintaxissal lehet hivatkozni. Létezik feltételes kiértékelés is ${parameter?szoveg} és ${parameter:szoveg} formában, ahol a kiértékelés végeredménye a szöveg, ha a paraméter definiálva van (első eset), vagy ha nincs (második eset.)
 
A ${parameter?szoveg1:szoveg2} makró kiértékelés nem létezett. Ezt implementáltuk egy kis szintaktikai változtatással:
 
Eredeti makró-kiértékelések
Új makró-kiértékelések
${name?text}
${name?text}
 
${name?text1:text2}
${name:text}
${name!text}
 
${name!text1:text2}
 
2.2 Új makrók
 
A spam szűréseknél alkalmazott táblázatbeli keresések visszaadhatnak szöveges hibaüzenetet
 
[45]xx a kívánt hibaüzenet
 
formában, amelyben makrókra is lehet hivatkozni. Ezért néhány új makrót vezettünk be:
 
$client_name
a kliens hosztneve (vagy unknown)
$client_address
a kliens IP címe
$client
$client_name [$client_address]
$helo
HELO/EHLO-val átadott név
$sender
a feladó E-mail címe
$recipient
a címzett E-mail címe
$rbl_txt
a kliensre vonatkozó DNS-beli TXT érték az aktuális RBL domain-ben (lásd 2.4)
2.3 Tetszőleges hibaüzenetek
 
restrictions néven egy új táblázatot vezettünk be, amelyben a kulcs bármely szűrőfeltétel lehet (beleértve az smtpd_restriction_classes által definiált szűrő osztályokatt) kivéve a check_*_restrictions map:mapname típusúakat, míg az érték lehet REJECT, DUNNO, OK, "45[xx] szöveg" vagy szűrő osztály.
 
Egy ilyen táblázat kiértékelése a következő algoritmus szerint történik:
 
1Kiértékelődik az első kulcs
2Ha az értéke OK, akkor a táblázatkiértékelés eredménye OK
3Ha az értéke REJECT (vagy azzal ekvivalens), akkor kiértékeljük a kulcshoz tartozó értéket és az lesz a végeredmény
4Ha a táblázat végére értünk, akkor a visszatérési érték DUNNO
5Előrelépünk a következő kulcsra és visszatérünk 1-hez
 
Példa egy beépített Postfix szűrőfeltétel hibaüzenetének az átírására:
 
/etc/postfix/main.cf:
 
smtpd_recipient_restrictions = restrictions:/etc/postfix/unknown_client
 
/etc/postfix/unknown_client:
 
reject_unknown_client 450 Cannot find your hostname [$client_address]. Ask your
system manager to fix your domain name registration.
 
2.4 Egyéni RBL ellenőrzések
 
Az egyéni RBL szűrések lehetővé tételéhez rbl néven egy új táblázatot vezettünk be, ahol a kulcs egy domain név, az érték pedig REJECT, DUNNO, OK, "45[xx] szöveg" vagy szűrő osztály lehet.
 
A kiértékelése a következő módon történik: ha a kliens IP címe benne van az első kulcs által megadott RBL domain-ben, akkor az ahhoz tartozó érték kiértékelése lesz a végeredmény; egyébként a következő kulccsal próbálkozunk. Példa rbl táblázatra és $rbl_txt makróra:
 
/etc/postfix/main.cf:
 
smtpd_recipient_restrictions = rbl:/etc/postfix/rbl_domain
 
/etc/postfix/rbl_domain:
 
relays.orbs.org 554 Services unavailable, [$client_address] blocked
using relays.orbs.org.
${rbl_txt?$rbl_txt:See http://www.orbs.org/ for details.}
Az rbl táblázat során nem történik automatikus DNS TXT lekérdezés a kliens IP címére az adott domain-ben - az csak az rbl_txt makró kiértékelése során történik meg.
 
2.5 A szűrő osztályok perfixes jelölése
 
Az általunk bevezetett prefixes jelölés lehetővé teszi a több szűrő osztályra való egyszerű hivatkozást. Ennek akkor van jelentősége, ha a felhasználók számára lehetővé szeretnénk tenni az egyéni szűrési feltételek beállíthatóságát és sok szűrőfeltétel közötti választást akarunk biztosítani. Ekkor két új paraméter segítségével kapcsolhatjuk be a prefixes jelölést:
 
smtpd_restriction_class_prefix
a prefix, amellyel az osztályokra hivatkozunk
smtpd_restriction_class_delimiter
az elválasztójel a prefix nálküli osztályazonosítók között
 
Ha mindkét paraméter definiált, akkor egy prefixes jelölésű osztályt az smtpd_restriction_class_prefix fog azonosítani. Annak kiértékelése a következő lépésekben történik:
 
1Leszakítjuk a prefixet
2Szétválasztjuk az osztály azonosítókat az smtpd_restriction_class_delimiter szerint
3Az eredményül kapott stringeken a következő ciklust hajtjuk végre:
1. Visszatesszük a prefixet
2. Kiértékelkjük az osztályt
3. Ha az értéke DUNNO, folytatjuk a ciklust a következő stringgel, egyébként pedig megállunk
 
Következzék egy leegyszerűsített részlet a KFKI egyik mail gateway gépén lévő Postfix konfigurációból:
 
/etc/postfix/main.cf:
 
# The definition of the "atomic" restriction classes
smtpd_restriction_classes =
class_ip,
class_sender,
class_dns,
class_kfki,
class_cern,
class_rbl,
class_dul,
class_orbs,
class_rss,
class_accept
 
smtpd_restriction_class_prefix = class_
smtpd_restriction_class_delimiter = _
 
class_ip = check_client_access hash:/etc/postfix/ip_address
# ...
class_rss = rbl:/etc/postfix/rbl_domain_rss
# We have per site default restriction, so we need class_accept as well.
class_accept = permit
 
smtpd_recipient_restrictions =
reject_non_fqdn_sender,
reject_non_fqdn_recipient,
permit_mynetworks,
reject_unauth_destination,
check_recipient_access hash:/etc/postfix/recipients,
class_ip_sender_dns_kfki_cern_rbl_dul_orbs_rss
 
/etc/postfix/recipients:
 
abuse@kfki.hu class_accept
foo@kfki.hu class_ip_sender_kfki_rbl_accept
bar@kfki.hu class_ip_sender_dns_kfki_cern_rbl_dul_accept
 
Összegezés
 
Postfix rendszerek kezelik a KFKI telephely teljes levélforgalmát. A Postfix-ben rendelkezésre álló és az általunk kifejlesztett kiterjesztések segítségével egy igen finomhangolható, kényelmes, felhasználói igények szerint konfigurálható spam szűrést vezethettünk be. Ez a rendszer 1999 októbere óta működik
 
URL-ek
 
http://www.postfix.org/
http://www.kfki.hu/~kadlec/sw/postfix_patch.html