Knihovna Milter, sendmail a viry

Milan Keršláger

Největším problémem při použití jakéhokoliv nástroje pro kontrolu elektronické pošty byl vždy problém jednoduché integrace použitého nástroje do sendmailu. To platilo jak pro kontrolu příloh na počítačové viry, tak pro omezení nepříjemných spamů. Každý tvůrce takového programu musel tento problém nějakým způsobem vyřešit. Ne vždy byly všechny použité způsoby jednoduché a obvykle znamenaly poměrně razantní zásah do stávající konfigurace. Další problémy nastávaly obvykle se zvýšenou zátěží dotčeného počítače a s možnou koexistencí s dalšími lokálně použitými nástroji (spamové filtry apod.).

Proto bylo lidmi z vývojového týmu sendmailu vyvinuto rozhraní Milter, které poskytuje sofistikované API (Aplikační rozhraní) použitelné právě pro řešení tohoto problému. Soubor poskytovaných funkcí umožňuje s příchozími nebo i jen procházejícími maily provádět prakticky jakékoliv operace už na úrovni SMTP spojení. Elektronický dopis může být přijat, odmítnut, zničen i modifikován na základě rozhodnutí externího programu. Podrobnou dokumentaci najdete na adrese http://www.sendmail.com/partner/resources/development/milter_api/.

Další výhodou při použití tohoto API je možnost jednoduchého zřetězení libovolného počtu filtrů, které budete chtít použít. Vše je navrženo tak, aby byl co nejméně zatížen hostitelský systém a proto je komunikace mezi sendmailem a filtrem realizována přes unixový nebo TCP soket. Tím pádem není potřeba pro každý mail spouštět jeden nebo více speciálních procesů, které jsou posléze ukončeny.

Konfigurace sendmailu pro použití filtru je jednoduchá, protože je využíván makrojazyk M4. Knihovna existuje už delší dobu, takže není potřeba se obávat nestability řešení. Konfiguraci si ukážeme na jednoduchém příkladu a podrobnosti nechám na pozdější dobu, abyste se nevylekali :-)

Jako názorný příklad se pokusím použít jednoduchý nástroj, který přejmenovává nebezpečné názvy příloh v elektronické poště na neškodnou příponu .txt. Dosáhneme tak zadarmo poměrně silné "antivirové kontroly", aniž bychom museli investovat do (komerčního) antivirového programu.

Pro první ukázku schopností Milteru jsem si vybral program vbsfilter, který najdete na adrese http://aeschi.ch.eu.org/milter/. Je to krátký program napsaný v jazyce C (cca 400 řádků včetně komentářů). Kromě jednoduchosti si pohledem do jeho obsahu můžete udělat představu o tom, jak to celé funguje.

Abychom měli situaci ještě jednodušší, využijeme toho, že podpora knihovny Milter byla přidána již do sendmailu obsaženém v Red Hat Linuxu 7.2 (balíček sendmail-8.11.6-15). Naštěstí pro nás byly sendmaily ve starších verzích aktualizovány alespoň na verzi 8.11.6 (tj. jsou již s podporou knihovny Milter). Máte-li proto systém starší, než je 7.2, proveďte nejprve jeho aktualizaci. Balíček připravený pro verzi 7.3 by měl fungovat i v nižších verzích řady 7.x. Pro verzi 6.x si budete muset program sami přeložit ze SRC balíčku.

Balíček s programem vbsfilter najdete na adresách:

Pro instalaci, spuštění a nastavení automatického startu programu použijte příkazy:

rpm -Uvh vbsfilter-1.11-0.i386.rpm
/etc/init.d/vbsfilter start
chkconfig vbsfilter on

Program si po startu vytvoří unixový soket /var/run/vbsfilter.sock, který bude sloužit pro komunikaci se sendmailem.

Nyní přichází na řadu samotný sendmail. Nejprve se ujistěte, že máte v systému nainstalován balíček sendmail-cf a m4 (jsou součástí distribuce). Dále je potřeba upravit M4 soubor, ze kterého se generuje vlastní konfigurační soubor sendmailu (v RH 7.x je to /etc/sendmail.cf, ve verzi 8.0 pak /etc/mail/sendmail.cf). Do souboru /etc/mail/sendmail.mc přidejte následující řádky:

define(`_FFR_MILTER', `1')dnl
INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/vbsfilter.sock, F=T')

Výše uvedené volby zapínají podporu API Milter a definují soket, na kterém bude sendmail očekávat spolupracující aplikaci (tj. vbsfilter). Volba F=T říká, že v případě nepřítomnosti spolupracující aplikace má sendmail hlásit dočasné selhání SMTP služby. Pokud by F nebylo definováno, sendmail by v případě nedostupnosti spolupracující aplikace pokračoval jako kdyby žádný filtr nebyl definován.

Na závěr musíme ještě vytvořit konfigurační soubor sendmail.cf (cestu zadejte podle jeho umístění ve vaší distribuci). Po přepsání původního konfiguračního souboru naší novou verzí restartujte sendmail.

cd /etc/mail
m4 sendmail.mc > sendmail.mc
/etc/init.d/sendmail restart

Teď už nastává čas pro kontrolu funkce filtru. Zkontrolujte, zda se v hlavičkách procházejících mailů objevuje text X-Filter-Version: 1.11. V případě, že filtr přejmenuje název souboru s koncovkou .EXE v příloze, najdete v hlavičce poznámku X-Filter: 1 attachment changed to TXT. Pokud je vše v pořádku, můžete si pogratulovat!

Podrobnější informace

Ne všichni budete mít možnost nebo budete chtít využít předem hotových polotovarů, takže se pokusím sdělit podrobnější informace.

Sendmail

Pokud budete sami překládat sendmail, měli byste použít aktuální verzi z http://sendmail.org nebo alespoň verzi 8.11, protože verze 8.10 obsahovala nekompatibilní verzi Milter API. Dále je potřeba překládat na systému s alespoň Glibc verze 2. Libc5 nestačí, protože ještě neobsahovala podporu threadů.

Při překladu sendmailu přidejte do souboru .../sendmail-8.10.*/devtools/Site/site.config.m4 následující řádky:

APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER=1')
APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER=1')

Pak spusťte make v adresáři .../sendmail-8.*/libmilter a znovu sestavte sendmail (podle návodu v souboru INSTALL, který je v tarballu sendmailu obsažen).

Při úpravě M4 souboru pro generování konfiguračního souboru sendmailu můžete použít několik doplňujících možností, které krátce představím. Nejprve pár příkladů pro definici filtru:

INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/vbsfilter.sock, F=R')
INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m')
INPUT_MAIL_FILTER(`filter3', `S=inet:3333@10.0.0.123')

V příkladu jsou nadefinovány 3 různé filtry, které se budou na zpracování pošty podílet. Použitý soket je nejprve unixový, druhý řádek obsahuje odkaz na filtr komunikující přes TCP IPv6 soket a třetí řádek umožňuje spojení s filtrem běžícím na počítači s IP adresou 10.0.0.123 na portu 3333. V příkladech jsou také změněny některé parametry komunikace sendmailu s filtrem. Parametr F může nabývat dvou hodnot:

K dispozici je ještě příznak T, kterým můžeme podrobněji definovat timeouty při spojení s filtrem. Měnit můžete tyto parametry:

Vbsfilter

Pro překlad programu vbsfilter budete potřebovat následující soubory:

Umístěte je do nějakého vhodného adresáře a zkontrolujte, zda máte v systému soubor /usr/include/libmilter/mfapi.h. Pokud ne, vyzvedněte jej ze zdrojových kódů sendmailu, případně nainstalujte balíček sendmail-devel (Red Hat 7.3 a 8.0). Pak stačí jen napsat make a umístit výsledný binární soubor do vhodného adresáře.

Program vbsfilter spouštíme s parametrem -p, který určuje umístění soketu filtru. Umístění musí souhlasit s definicí v použitém M4 souboru pro sendmail (resp. s definicí v souboru sendmail.cf). Program může odmítnout spuštění v případě, že soket již existuje nebo že má nedostatečná práva pro jeho vytvoření. Příklad spuštění:

vbsfilter -p unix:/var/run/vbsfilter.sock

Využití knihovny Milter pro RAV antivirus

Antivirový program RAV je distribuován i ve verzi využívající API Milter. Pokud ho chcete využít, postupujte následujícím způsobem (předpokládám, že používáte distribuci s RPM balíčky):

Stáhněte si volně dostupnou verzi RAV antiviru z http://www.ravantivirus.com. Nejsnadněji ji naleznete tak, že v políčku vyhledávání napíšete "milter" a vyberete verzi pro Linuxový desktop s podporou knihovny Milter. Stažený soubor je tar.gz, který obsahuje kromě návodu k instalaci 3 RPM balíčky. Po jejich nainstalování jsem musel nastavit správného vlastníka adresáře pro vytvoření soketu:

chown ravms /usr/local/rav8/private

Dále jsem snížil četnost spouštění automatické aktualizace na 1x denně přesunutím symbolické linky /etc/cron.hourly/ravmdupdate.sh do adresáře /etc/cron.daily a cestu /opt/rav/bin jsem přidal do PATH (abych mohl RAV antivirus spouštět i z příkazové řádky). Název místní domény a plné jméno počítače je umístěno v souboru /etc/opt/rav/domains. RAV antivirus totiž maily směřující do jiných domén ignoruje. Pak už stačilo jen podle návodu modifikovat M4 soubor pro sendmail (tj. přidat položku pro komunikaci s filtrem), vygenerovat nový sendmail.cf, a pomocí skriptů /etc/init.d/ravmail a /etc/init.d/ravmilter spustit filtr a scanner. Po restartu sendmailu už stačilo jen vymyslet, jak šéfovi vysvětlit, že by měl do 30 dnů zaplatit roční licenci (než vyprší povolená zkušební doba). :-)

Další využití knihovny Milter

Filtry lze psát kromě jazyka C také v Pythonu nebo v Perlu. Rozšíření pro jazyk Python najdete na adrese http://www.bmsi.com/python/milter.html, rozšíření pro Perl najdete na adrese http://sourceforge.net/projects/sendmail-milter/. Nakonec zkusím uvést pár odkazů na další zajímavé projekty:

Další odkazy jistě naleznete sami :-)