Úvod do elektronické pošty a program sendmail

Helena Vildová, xvildova@fi.muni.cz


Obsah


1. Elektronická pošta

1.1. Něco málo historie

Původně šlo o jednoduchou službu, která pouze kopírovala zprávu z jednoho počítače na druhý, kde ji připojila k souboru poštovní schránky příjemce. Toto v principu platí dodnes, i když bylo nezbytné více propracovat doručovací mechanismus.

V síti internet se elektronická pošta řídí standartem RFC 822 (doplněným o další RFC standarty, např. MIME). Pomocí tohoto standartu je možné přenášet prakticky cokoliv, obraz, zvuk i jiné "problematické" části zpráv. Dalším existujícím standartem je X.400 od společnosti CCITT, ten se však již vytrácí.

Způsob zápisu a interpretace poštovní adresy se liší podle používaného typu sítě. Jde ale čím dál více o historické záležitosti. Na sítích TCP/IP jsou adresy ve formátu RFC 822, tzn. user@host.domain. Např. na UUCP sítích bývaly adresy tvaru path!host!user, kde path popisovala konkrétní řadu hostitelů, kterými zpráva musela na cestě projít. Dnes už většina UUCP sítí převzala také doménový zápis adresy ze standartu RFC 822.

1.2. Jak to chodí

(Pro TCP/IP sítě.)
Mail napíšeme v poštovním klientovi, programu, spadajícím mezi tzv. MUA (Mail User Agent) - příkladem jsou programy jako pine, mutt, MS Outlook. Pisatel jen zadá adresáta a text mailu, na MUA je, aby přidal nezbytnou hlavičku a předal poštu dál. Dalším na řadě je MTA (Mail Transfer Agent), jeho častým představitelem je program sendmail (bude podrobněji zmíněn později) nebo v poslední době stále častěji např. qmail, Postfix či Exim. MTA doplní hlavičku mailu o další informace a podle doménové části adresy příjemce zjistí, kam mail poslat. Následuje spojení se strojem odpovědným za příjem pošty pro doménu adresáta a komunikace v SMTP protokolu, při které dojde k přenosu zpávy. Spojení nemusí být nutně přímé, náš mail může na cestě k cíli projít pod rukama více MTA, které si ho pomocí SMTP předávají (po cestě dochází k tzv. směrování pošty, při němž se MTA, který momentálně drží mail, dotazuje DNS serveru na MX záznamy a podle jejich priority se snaží najít jiný MTA co nejblíže adresátovi - snaží se směrovat mail na nejpreferovanější počítač podle váhy MX záznamů. Při výpadku nejpreferovanějšího stroje lze použít záložní příjemce pošty podle MX záznamů, jsou-li uvedeny. Je dodržováno hierarchické předávání pošty, aby nevznikl nekonečný cyklus. Pokud MX záznamy chybí, MTA kontaktuje přímo IP cílového stroje.). MTA na cílovém stroji zprávu předá programu MDA (Mail Delivery Agent), mezi typické představitele patří program Procmail. MDA poštu roztřídí a podle uživatelem určených pravidel s ní naloží - nejčastěji ji doručí do poštovní schránky příjemce, níž ji pro uživatele vyzvedne zase MUA nebo je distribuována na lokální počítače uživatelů pomocí protokolů jako POP3 nebo IMAP.

                   +-----------+          +--------+
+-------+  napise  |odesilajici|  vola    |zdrojovy|
| Alice |--------->|   MUA     |--------->|  MTA   |::::>::::
+-------+          |           |          |        |       ::   na odesilajicim
                   +-----------+          +--------+       ::   pocitaci
                                                           ::
.......................................................................
                             SMTP                          ::
 ::::::::::::::::::::::::::::<:::::::::::::::::::::::::::::::
 ::
 ::   +---------+          +-----+                +-------+
 ::   | cilovy  |  vola    |     |  doruci do     |Bobova |
 ::::>|   MTA   |--------->| MDA |===============>|chranka|  na prijimajicim
      |         |          |     |                |       |  pocitaci
      +---------+          +-----+                +-------+

Ukázka komunikace v SMTP protokolu:

Definováno v RFC 821 - Simple Mail Transfer Protocol (SMTP). Chcete-li si vyzkoušet SMTP protokol sami, můžete použít třeba z aisy $ telnet aisa 25 :-).

      (S = Send, R = Reply)

      S: MAIL FROM:
      R: 250 OK
      S: RCPT TO:
      R: 250 OK
      S: DATA
      R: 354 Start mail input; end with .
      S: From: "Alice" 
      S: Message-Id: <199711131704.MAA18447@zrcadlo.cz>
      S: Subject: Nevidel jsi meho velkeho bileho kralika?
      S: To: bob@zemedivu.cz (Bob)
      S: Date: Wed, 16 Oct 2002 12:04:05 -0500 (CET)
      S: Content-Type: text
      S:
      S: Mozna spadnul do diry :-(.
      S: --
      S:                                                 >>alice>>
      S: .
      R: 250 OK


2. Program sendmail

2.1. Co je to sendmail?

sendmail je typickým představitelem MTA, tzn. programu pro předávání pošty. Je to program s dlouhou historií (proto ovládá i mnoho věcí dnes už téměř nepotřebných, např. doručování faxem), složitý na konfiguraci, ale velmi výkonný. Během svého života prošel obdobími mnoha bezpečnostních nedostatků, v dnešní době se názory na jeho bezpečnost různí :-).

2.2. Instalace a konfigurace

2.2.1. Instalace

sendmail je obvyklou součástí většiny Linuxových distribucí, přesto je doporučováno instalovat ho přímo ze zdrojových textů, zejména, jde-li nám o bezpečnost. Zdrojové texty jsou k nalezení na http://www.sendmail.org/ nebo na ftp.sendmail.org.

Příklad instalace:
$ cd /usr/local/src
$ tar xvfz sendmail.8.9.3.tar.gz
$ cd src
$ ./Build
a nainstalování binárek provedeme jako root
$ cd obj.Linux.2.0.36.i586
$ make install
Program sendmail bude nainstalován v /usr/sbin.

2.2.2. Konfigurace

"Říká se, že skutečným správcem Unixu nebudete, dokud ručně neupravíte soubor sendmail.cf. Také se říká, že musíte být blázen, když to chcete zkoušet i podruhé."

Tak zle naštěstí s novějšími verzemi sendmailu není. Už není nutno upravovat přímo soubor sendmail.cf (k nalezení nejčastěji v /etc/mail/sendmail.cf, u některých distribucí v /etc/sendmail.cf) - ten lze automaticky vygenerovat z poměrně jednoduchých makrosouborů tzv. m4 maker, které pak unixovým nástrojem m4 přetvoříme v očekávaný sendmail.cf. Proto se budeme dále zabývat pouze tvorbou těchto maker a ne editací vlastního sendmail.cf. Samozřejmě ve velmi speciálních a složitých případech se může stát, že ani makra nepokryjí naše potřeby, pak nezbývá než vygenerovaný sendmail.cf ručně doeditovat. Syntaxe souboru sendmail.cf je velmi komplikovaná a většina rozumných lidí se jeho přímé editaci vyhýbá.

příklad syntaxe:

R$* :: $* <@>           $: $1 :: $2                     unmark node::addr
R:include: $* <@>       $: :include: $1                 unmark :include:...
R$* [ IPv6 $- ] <@>     $: $1 [ IPv6 $2 ]               unmark IPv6 addr
R$* : $* [ $* ]         $: $1 : $2 [ $3 ] <@>           remark if leading colon

Program sendmail má obrovské množství voleb a nastavení a to i pokud použijeme konfiguraci pomocí maker. Proto zde nastíním pouze příklad možného postupu s vysvětlením.

Soubor s m4 makry nazýváme sendmail.mc (není to však nutné, pokud spravujeme více poštovních systémů, můžeme makrosoubory klidně ukládat např. pod názvy hostitelů) a pro přehlednost je užitečné ho uchovávat vždy s odpovídajícím sendmail.cf. Makro se skládá z názvu makra (velkými písmeny na začátku řádku) a z jeho parametrů (text v závorkách za makrem). Komentáře v makrosouboru píšeme dvojím způsobem - pokud chceme, aby se komentář přepsal do výsledného sendmail.cf, zapíšeme ho standartně za znak #. Pokud chceme komentář pouze v makrosouboru, vložíme ho buď mezi tokeny divetr(-1) a divert(0) ("závorkuje" komentář), nebo za token dnl (komentář do konce řádku + odřádkování).

Příklad makrosouboru sendmail.mc (komentář vždy předchází použití makra):
divert(-1)
#
# Příklad konfigurace sendmail.mc
# 
divert(0)

dnl - Makro VERSIONID je nepovinné, používá se k zapsání užitečného komentáře do sendmail.cf, např. verze konfigurace
VERSIONID(`@(#)sendmail.mc 8.9 (Linux) 16-10-2002')

dnl - Typ operačního systému. Důležité! Přidá standartní konfigurační nastavení se správnými hodnotami pro uvedený systém.
dnl - Toto makro se uvádí na začátku sendmail.mc, protože na něm závisí mnoho dalších voleb.
OSTYPE(`linux')

divert(-1)
# Typ domény. Nastavení je určeno pro správce velkých systémů, slouží k nakonfigurování více počítačů
# stejným způsobem. Pro použití tohoto makra je nutné vytvořit si vlastní makrosoubor se standartním nastavením
# pro všechny naše systémy (např. definice předávacího hostitele nebo poštovního uzlu) a ten uložit
# do adresáře /usr/share/sendmail.cf/domain nebo jeho obdoby (konkrétně na RH Linuxu je to /usr/share/sendmail-cf/domain)
# jako soubor typ-domény.m4. Soubor generic.m4 už bývá standartně v tomto adresáři obsažen. Pokud konfigurujeme
# jen několik počítačů, použití DOMAIN nestojí za to.
divert(0)
DOMAIN(`generic')

divert(-1)
# V CF souboru dodávaném s programem sendmail lze najít popis předdefinovaných funkcí, které lze pomocí FEATURE
# jednoduše zahrnout do konfigurace.
# U některých funkcí lze uvádět nepovinné parametry (zde konkrétně použitá funkce local_procmail určuje, který program se
# má použít na zpracování příchozí pošty, tzn. každý uživatel si může udělat svoje nastavení, jak poštu zpracovat. Z názvu
# by se mohlo zdát, že je tímto vždy nastaven program Procmail, ale není to tak, local_procmail je funkce, která může mít
# parametr, kterým program určíme; v případě neudání parametru je implicitní hodnotou Procmail.).
# V souboru CF je také popis všech předdefinovaných maker sendmailu, označovaných jako "lokální makra". Ta se používají
# uvedením jména makra a hodnot případných proměnných makra.
divert(0)
FEATURE(`local_procmail')

divert(-1)
# Makro MAILER říká, jaké způsoby doručování pošty jsou povoleny.
# Transportní protokol "local" je zapnut implicitně, lze ho však pro přehlednost uvést.
# Je dobré vědět, že pokud chceme zohlednit i protokol UUCP, je nutné nejdřív zapsat MAILER(`smtp') 
# a až pak MAILER(`uucp').
# MAILER(`procmail') umožňuje používat Procmail pro forwardování pošty na úrovni sendmailu (např. přesměrovat všechnu
# poštu, která přišla do nějaké domény na jednoho konkrétního uživatle).
divert(0)
MAILER(`local')
MAILER(`smtp')
dnl - zde bychom mohli uvést MAILER(`uucp')
MAILER(`procmail')

Úplný popis dalších maker a možností nastavení v souboru sendmail.mc a sendmail.cf lze najít např. v literatuře odkazované na http://www.sendmail.org/books.html, nebo dosti podrobně také v knize Linux - dokumentační projekt, též volně dostupné v PDF formátu na http://www.cpress.cz/knihy/ldp2/.

Přepisovací pravidla:

Za zmínku stojí určitě ještě velmi mocná funkce sendmailu - přepisovací pravidla. Pomocí nich sendmail zjišťuje, jak naložit s příchozími zprávami (zde je např. možnost antispamové ochrany pomocí tzv. blacklistu, seznamu "podezřelých" doménových jmen). Pomocí nich se také může chovat jinak k lokální poště a k poště směrované ven z lokální sítě (např. lokální poštu doručovat pomocí SMTP a venkovní přes určený stroj pomocí UUCP). Také lze vyměňovat jména lokálních strojů v adresách za jednotné doménové jméno apod.

Pravidla mají levou a pravou stranu oddělenou nejméně jedním tabulátorem, levá strana definuje vzor, kterému má adresa v hlavičce pošty vyhovovat; pokud vyhovuje, je nahrazena pravou stranou a znovu zpracována. Pravidla jsou v číslovaných sadách, které se definují přímo v souboru sendmail.cf, lze je ovšem měnit i pomocí maker v makrosouboru sendmail.mc. Sady pravidel jsou celkem čtyři, přičemž adresa je nejprve zpracována sadou 3 a naposled sadou 0. Sady 2 a 1 bývají typicky prázdné. Tvorba pravidel není záležitost triviální a podrobný popis jak je tvořit by byl nad rámec tohoto referátu. Pro vysvětlení jaká makra použít a jak doporučuji opět knihu Linux - dokumentační projekt z roku 2001, str. 552, Interpretace a vytváření přepisovacích pravidel.

Jako příklad uvedu konkrétní zápis jednoho pravidla, jak jej lze zapsat do souboru sendmail.mc. Příklad předpokládá zadefinovaného předávacího hostitele. Např. pokud bychom používali odesílání do venkovní sítě přes UUCP, připsali bychom do sendmail.mc z příkladu výše toto (hned pod makro OSTYPE):

define('SMART_HOST', 'uucp-new:moria')
což určuje stroj moria za předávacího hostitele a za používaný přenos UUCP-NEW
a rovněž bychom museli použít
MAILER(`uucp')
v místě, kde jsme definovali protokoly používané pro přenos pošty.
Následovala by definice pravidla:
LOCAL_NET_CONFIG
R$* < @ $* .$m. > $*			$#smtp $@ $2.$m. $: $1 < @ $2.$m. > $3
Toto pravidlo zajišťuje, že všechna lokální pošta se posílá přes smtp, ostatní pošta jde přes předávacího hostitele. Kdo má zájem vědět přesné významy interních maker sendmailu (např. $* a $m), dozví se víc např. ve výše zmiňované kapitole z LDP.

Generování souboru sendmail.cf:

Náš vytvořený makrosoubor převedeme na soubor sendmail.cf třeba takto (pozor na přesné cesty, takto je to v RH Linuxu 7.3):

$ cd /etc
$ m4 /usr/share/sendmail-cf/m4/cf.m4 sendmail.mc > sendmail.cf

Spouštění a běh programu sendmail:

sendmail typicky běží jako dva démony (v minulosti býval jeden démon a všechny jeho instance se spouštěly jako suid s právy roota, od toho bylo z pochopitelných důvodů upuštěno) - jeden je privilegovaný a běží jako SMTP server (čeká na spojení na TCP portu 25 a stará se o odeslání čekající pošty z fronty v /var/spool/mqueue), tento démon používá již zmíněný konfigurační soubor sendmail.cf. Druhý démon je neprivilegovaný, občas nahlédne do neprivilegované fronty /var/spool/clientmqueue s poštou nepřijatou k odeslání (většinou proto, že se nepodařilo kontaktovat cílový server) a pokusí se o její opětovné odeslání (tento démon někdy používá jiný konfigurační soubor s názvem submit.cf). Tento mechanismus je zaveden z důvodu bezpečnosti, aby uživatelské MUA nespouštěly pro odeslání mailů privilegovanou instanci sendmailu.

Při odesílání pošty spustí uživatelský poštovní program neprivilegovanou instanci programu sendmail (program je sgid a běží pod skupinou smmsp) a předá mu data zprávy. sendmail zkusí kontaktovat SMTP server a předat mu poštu k vyřízení. Je-li vše v pořádku, SMTP server data převezme a postará se o další postup. Pokud SMTP server nemohl být kontaktován, sendmail uloží poštu k pozdějšímu doručení do neprivilegované fronty /var/spool/clientmqueue a dál se o její osud nestará.

Chování sendmailu jako SMTP serveru: když dojde požadavek na port 25, sendmail si ověří oprávnění (většinou bývá povoleno uživatelům z místní sítě odeslat poštu kamkoliv a uživatelům zvenku doručit poštu místním uživatelům). Provede další testy, a pokud je vše v pořádku, poštu převezme a pokouší se ji doručit. Přitom používá frontu /var/spool/mqueue, kam si odkládá procházející poštu a poštu, kterou se zatím nepodařilo odeslat. Pokud se odeslání podaří, smaže ji z fronty a jeho úkol je splněn. Pokud ne, periodicky se pokouší odeslat ji znovu. Pokud se to nepovede ve stanoveném čase, pošle nejdříve odesílateli varování, po delší době pak chybové hlášení a poštu z fronty vyřadí.

Druhá, neprivilegovaná instance démonu sendmail běží pod skupinou smmsp a uživatelem smmsp a hlídá, zda do neprivilegované fronty /var/spool/clientmqueue nepřibyla nějaká neodeslaná pošta. Tu se pak periodicky pokouší odeslat místnímu SMTP serveru. V ostatních ohledech se chová podobně jako první instance (ale nehlídá port 25).

Odkazy

http://www.sendmail.org/
http://www.sendmail.org/books - informace o literatuře k sendmailu.
http://www.cpress.cz/knihy/ldp2/ - Linux - dokumentační projekt (PDF verze)