baseciq.org

Konfiguracja Exima

Sierpień 2003 to chyba szczytowy moment rozkwitu naszej sieci osiedlowej. A także prób w odejściu od sendmaila. Sporo rzeczy będzie nieaktualne, ale być może pomoże komuś zrozumieć config Exima. No chyba że się używa debiana.

Domeny lokalne

Domeny lokalne, to takie które Exim ma traktować jako ‘swoje’ domeny. Mail zadresowany @jakas.domena.lokalna który dotrze do Exim’a zostanie dostarczony lokalnie. Domeny takie definuje w dyrektywie ‘domainlist local_domains’. Standardowo, przyjmowana jest poczta wysyłana do domeny identycznej jak hostname serwera:

domainlist local_domains = @

Znak ‘@’ oznacza właśnie ‘moja nazwa’. Aby dopisać kolejne domeny wystarczy dodać je do tej listy rodzielając je dwukropkami:

domainlist local_domains = @ : domena.pl : baseciq.org

Oczywiście cały czas mówię o zmianach w pliku konfiguracyjnym Exim’a (czyli jeżeli kompilowaliście go wg. mojego opisu albo macie Exim4 z PLD – /etc/mail/exim.conf). Oczywiście nie muszę mówić, iż każda zmiana w pliku konfiguracyjnym wymaga restartu Exim’a. Można także to zrobić w inny sposób:

domainlist local_domains = @ : domena.pl : baseciq.org : /etc/mail/local_domains

Poza domena.pl, baseciq.org, Exim będzie teraz także akceptował domeny wypisane w pliku /etc/mail/local_domains. Domeny tam należy wpisywać w oddzielnych linijkach. Exim o tyle fajnie działa, że po dopisaniu ścieżki do pliku, wystarczy go raz zrestartować. Jakiekolwiek kombinacje w /etc/mail/local_domains nie będą wymagały restartu. Tak więc najwygodniej będzie dopisać do pliku konfiguracyjnego:

domainlist local_domains = @ : /etc/mail/local_domains

Domeny dla których mamy być zapasowym MX’em

Jest to wbrew pozorm łatwe. Linijkę pod ‘domainlist local_domains’ jest ‘domainlist relay_to_domains’. Działa to w taki sam sposób jak konfiguracja domen lokalnych, czyli, piszemy:

domainlist relay_to_domains = /etc/mail/relay_to_domains

Od teraz, Exim będzie akceptował każdą pocztę zaadresowaną do domen zawartych w pliku ‘/etc/mail/relay_to_domains’. A co z nią zrobi? Jak wiadomo, jeżeli domena ma kilka MX’ów, to Exim będzie starał się ją dostarczyć do serwera o najniższym priorytecie MX. Chyba że on ma najniższy, to wygeneruje błąd.

Relaying

Czyli określenie kto może przez nasz serwer wysyłać pocztę. I tutaj, listę adresów i hostów buduje się w podobny sposób do local_domains i relay_to_domains. Wystarczy stworzyć listę o nazwie ‘relay_from_hosts’:

hostlist   relay_from_hosts = 127.0.0.1 : 192.168.0.0/16

Budowa pliku konfiguracyjnego

Na chwilę przystopujmy. Plik konfiguracyjny Exim’a wygląda mniej więcej tak:

# głowna sekcja ...

opcje i dyrektywy sekcji głównej

begin sekcja1

opcje i dyrketywy sekcji1

begin sekcja3

...

Tak więc plik ten jest zbudowany z sekcji które rozpoczyna się słowem ‘begin nazwa’, z wyjątkiem sekcji głównej, która jest na samym początku pliku i nie posiada swojego begina. Sekcje również nie mają żadnych słów kluczowych któe by je zamykały – poprostu początek (begin) nowej sekcji oznacza zakończenie poprzedniej. I tak, standardowo mamy następujące sekcje:

Co to są te całe ‘transportery’ i ‘routery’? Właściwie to serce Exima. Jeżeli Exim dostaje jakiegoś maila to najpierw puszcza go przez routery, które można porównać do reguł ipchains/iptables – jeżeli mail załapie się na jakąś regułę (router) to jest przekazywany do transportu określonego przez ten router. Inaczej mówiąc router w Eximie kieruje maila do odpowiedniego transportera. Transporter natomiast robi już z mailem co należy – doręcza go lokalnie, albo przekierowywuje gdzieś indziej albo odsyła do innego serwera. Wiem że w tym momencie może wydawać się to skomplikowane, ale nie przejmujcie się, to tylko wiedza teoretyczna która na początku nie będzie wam potrzebna. Musiałem natomiast wam wytłumaczyć że są sekcje i że musicie nauczyć się tego że jak napiszę ‘dopisać w sekcji głównej’ to należy coś dopisać na początku pliku ;-)

Hostname, banner i inne bajery

Czasami (czytaj: gdy mamy sieczkę w /etc/hosts) Exim zgłasza się nie jako serwer.domena.pl a jako sam ‘serwer’. Jeżeli zmiana wpisów w /etc/hosts nie pomaga, albo gdy chcemy aby nasze MTA przedstawiało się inaczej niż hostname maszyny na którym stoii wystarczy ustawić (bądź dodać gdy jej nie ma) opcję ‘primary_hostname’ w głównej sekcji (nie wiesz gdzie to? jazda czytać ‘Budowa pliku konfiguracyjnego’ powyżej):

primary_hostname = serwer.domena.pl

W czasach zabawy z sendmailem podawałem także sposób na ograniczenie bannera który się pojawiał po telnecie na port 25. W Eximie nie jest to skomplikowane i służy do tego opcja ‘smtp_banner’ w sekcji głównej:

smtp_banner = $primary_hostname ESMTP $tod_full

Spowoduje to wyświetlanie następującego tekstu jako bannera:

220 serwer.domena.pl ESMTP Wed, 23 Jul 2003 15:18:04 +0200

Chyba nie muszę tłumaczyć że aby usunąć datę, należy wywalić ‘$tod_full’.

Aliasy

Aliasy powinny być w /etc/mail/aliases. Jest to czysty plik tekstowy, tak więc zmiany w nim wprowadzone nie wymagają żadnego ‘newaliases’ czy restartu demona. Jeżeli jednak nie macie pewności czy tam powinien być plik z aliasami, w sekcji routers odszukajcie ciągu ‘system_aliases:’ – jest definicja routera odpowiedzialnego za rozwiązywanie aliasów. Tam też, w linijce data widać ścieżkę do pliku z aliasami:

system_aliases:
   driver = redirect
   allow_fail
   allow_defer
   data = ${lookup{$local_part}lsearch{/etc/mail/aliases}}
   file_transport = address_file
   pipe_transport = address_pipe

Autoryzacja

Jeżeli z naszego SMTP korzystają użytkownicy mobilni (dial-up’y) przyda nam się autoryzacja. O samej autoryzacji, oraz o tym jak ją sprawdzać pisałem już przy okazji autoryzacji w sendmailu. W tym wypadku, sprawa w Eximie jest dosyć zawiła. Otóż Exim zbyt wcześnie zrzuca uprawnienia root’a, tak że opisywany na wielu stronach opis zrobienia autoryzacji via PAM najczęściej nie działa. Z pomocą przyjdzie nam pakiet cyrus-sasl, a dokładniej pwcheck daemon (w PLD cyrus-sasl-saslauthd, a w przypadku źródeł należy dodać do ./configure parametr –with-pwcheck). Jeżeli posiadamy cyrusa w wersji 1.5.x, w sekcji ‘AUTHENTICATORS’ wpisujemy następujące linijki:

plain:
  driver = plaintext
  public_name = PLAIN
  server_prompts = :
  server_condition = ${if pwcheck{$2:$3}{1}{0}}
  server_set_id = $2

login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_condition = ${if pwcheck{$1:$2}{1}{0}}
  server_set_id = $1

Po restarcie serwera autoryzacja powinna chodzić. Sprawdzamy ją w stary, dobry, sprawdzony sposób:

[baseciq@viper baseciq]$ printf 'login\0login\0haslo'|mimencode
bG9naW4AbG9naW4AaGFzbG8=
[baseciq@viper baseciq]$ telnet localhost 25
Trying localhost.25...
Connected to localhost
Escape character is '^]'.
220 viper.rulez.pl ESMTP Exim 4.20 Sun, 10 Aug 2003 03:49:55 +0200
EHLO localhost
250-viper.rulez.pl Hello baseciq at localhost [127.0.0.1]
250-SIZE 52428800
250-PIPELINING
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
AUTH PLAIN bG9naW4AbG9naW4AaGFzbG8=
235 Authentication succeeded

Sprawa się nieco komplikuje w przypadku cyrus-sasl 2.x, gdzie demon autoryzacji działa trochę inaczej. W tym wypadku Exim (4.20 i starszy potrzebuje łatki do obsługi saslauthd dostępnej pod tym adresem (kopia tutaj). Uwaga! Exim od wersji 4.21 nie potrzebuje już tej łaty i wspiera saslauthd w sposób opisany niżej! Po nałożeniu tej łaty, ustawieniu CYRUS_SASLAUTHD_SOCKET w Makefile i przebudowaniu Exima możemy dopisać do sekcji ‘authenticators’ następujący wpis:

plain:
  driver = plaintext
  public_name = PLAIN
  server_prompts = :

  server_condition = ${if saslauthd{$2:$3:smtp}{1}{0}}
  server_set_id = $2

login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"
  server_condition = ${if saslauthd{$1:$2:smtp}{1}{0}}
  server_set_id = $1

A dla Exim-4.22 (i nowszych oczywiście) ten wpis wygląda tak:

plain:
  driver = plaintext
  public_name = PLAIN
  server_condition = ${if saslauthd{{$2}{$3}}{1}{0}}
  server_prompts = :
  # powyższy wpis zadziała przy saslauthd -a shadow, jeżeli
  # uruchomicie saslauthd -a pam (np. PLD) wpiszcie wtedy:
  # server_condition = ${if saslauthd{{$2}{$3}{smtp}}{1}{0}}
  server_set_id = $2

login:
  driver = plaintext
  public_name = LOGIN
  server_prompts = "Username:: : Password::"

  server_condition = ${if saslauthd{{$1}{$2}}{1}{0}}
  # powyższy wpis zadziała przy saslauthd -a shadow, jeżeli
  # uruchomicie saslauthd -a pam (np. PLD) wpiszcie wtedy:
  # server_condition = ${if saslauthd{{$1}{$2}{smtp}}{1}{0}}
 server_set_id = $1

Ostnią rzeczą przy saslauthd (odpalonym z -a pam) jaką trzeba stworzyć to plik /etc/pam.d/smtp:

#%PAM-1.0
#
# example PAM file for saslauthd - place it as /etc/pam.d/service
# (e.g. /etc/pam.d/smtp if you want to use saslauthd for SMTP AUTH)
#
auth	required	/lib/security/pam_listfile.so item=user sense=deny file=/etc/security/blacklist onerr=succeed
auth	required	/lib/security/pam_unix.so
auth	required	/lib/security/pam_tally.so file=/var/log/faillog onerr=succeed no_magic_root
auth	required	/lib/security/pam_nologin.so
account	required	/lib/security/pam_tally.so deny=0 file=/var/log/faillog onerr=succeed no_magic_root
account	required	/lib/security/pam_unix.so session	required	/lib/security/pam_unix.so

Pozostaje mi tylko wam przypomnieć, że przed sprawdzaniem autoryzacji należy także odpalić pwcheck/saslauthd ;)

Autoryzacja tylko poprzez SSL

martii <martii@obgyn.edu.pl> podesłał mi info jak ograniczyć autoryzację by była dostępna tylko dla klientów którzy uruchomili SSL. Wystarczy w sekcji głównej dopisać:

auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}}

Podobną rzecz da się również zrobić w tpop3d.

Exim i SSL

Exim sobie bardzo dobrze radzi sobie z połączeniami szyfrowanymi przy użyciu protokołu SSL (wspiera metodę STARTTLS). O ile został skompilowany z odpowiednimi bilbiotekami, wystarczy wygenerować odpowiednie certyfikaty:

[baseciq@viper baseciq]$ openssl genrsa -out /etc/mail/exim.key 1024
Generating RSA private key, 1024 bit long modulus
.......++++++
..............................++++++
e is 65537 (0x10001)
[baseciq@viper baseciq]$ openssl req -new -x509 -days 365 -key /etc/mail/exim.key -out /etc/mail/exim.crt
Using configuration from /var/lib/openssl/openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:PL
State or Province Name (full name) [Some-State]:Mazowsze
Locality Name (eg, city) []:Warsaw
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Baseciq Ltd.
Organizational Unit Name (eg, section) []:Baseciq's Mail Server
Common Name (eg, YOUR name) []:viper.baseciq.org
Email Address []:baseciq@baseciq.org

Oczywiście na pytania odpowiadajcie podając swoje dane… Po takim zabiegu do sekcji głównej Exim’a dopiszcie:

tls_certificate = /etc/mail/exim.crt
tls_privatekey = /etc/mail/exim.key
tls_advertise_hosts = *

Po tym zabiegu i restarcie Exim powinien bez problemu komunikować się po SSL, co zresztą widać w logach:

2003-09-07 01:48:36 19vmnC-0006EG-27 <= bensonzow@beer.com H=plug.atn.pl [217.8.186.28] U=exim P=esmtp X=TLSv1:DES-CBC3-SHA:168 S=2909 id=ebb601c374e2$80dace00$cab00a12@fv

Warto by było, żeby także pop3d obsługiwał SSL’a natywnie ssl’a (bez jakichś stunneli i innych wynalazków). Ja osobiście polecam opisany w tekście Exim i MySQL demonik tpop3d, którego konfiguracja jest bardzo prosta. Wystarczy że standardowe ‘listen-address’ na takie:

listen-address: 0.0.0.0;tls=stls,/etc/mail/exim.crt,/etc/mail/exim.key \
                0.0.0.0;tls=immediate,/etc/mail/exim.crt,/etc/mail/exim.key

Jeżeli chcecie wymusić korzystanie z SSL to pewnie was zainteresuje informacja że dopisanie tej linijki:

apop-only: yes

Spowoduje to, że w trybie bez TLS wymagana jest autoryzacja APOP inaczej nie odbierzemy maili. Natomiast przy połączeniu kodowanym ta reguła przestaje obowiązywać. I można po udanym STARTLS można autoryzować się plainem. Od teraz tpop3d na porcie 110 będzie obsługiwał SSL po wykonaniu komendy ‘STLS’ (np. TheBat potrafi tak zacząć sesję SSL) a na porcie 995 będzie odrazu używał SSL’a (TheBat, Outlook Express). Za pomoc w tpop3d+ssl chciałbym w tym miejscu podziękować Arkadiuszowi Miśkiewiczowi ;-) Dzięki Arek! :)

Exim i SSL na porcie 465

W nowszych wersjach Exim’a (dokładnie nie pamiętam w których, ale napewno 4.5x i 4.6x) należy poza operacjami podanymi powyżej dodać następujące wpisy w sekcji głównej pliku konfiguracyjnego:

daemon_smtp_ports = 25 : 465
tls_on_connect_ports = 465

Pierwsza opcja powoduje że poza portem 25 Exim zacznie nasłuchiwać także na 465, natomiast druga instruuje go żeby port 465 był od razu wykorzystywany jako port z szyfrowaniem połączenia. Natomiast w starszych wersjach Exim’a można to jedynie osiągnąć przy użyciu inetd (normalny Exim jako daemon, Exim po SSLu z inetd). Oto przykładowe konfiguracje dla poszczególnych inetd:

rlinetd:

service "exim-ssl" {
	protocol	tcp;
	port		"465";
	user		"root";
	tcpd		{ exit; }
	exec		"/usr/bin/exim -bs -tls-on-connect";
}

xinetd:

service exim-ssl
{
	socket_type= stream
	protocol	= tcp
	port		= 465
	user		= root
	server		= /usr/bin/exim
	server_args	= -bs -tls-on-connect
	wait		= no
}

inetd: (sprawdzone przez kflis’a – dzięki!)

465	stream	tcp	nowait	root	/usr/sbin/tcpd	/usr/bin/exim -bs -tls-on-connect

rc-inetd (PLD): (należy utworzyć plik /etc/sysconfig/rc-inetd/smtps i wstawić tam to co poniżej)

SERVICE_NAME=smtps
SOCK_TYPE=stream
PROTOCOL=tcp
PORT=465
FLAGS=nowait
USER=root
SERVER=tcpd
DAEMON=/usr/bin/exim
DAEMONARGS="-bs -tls-on-connect"

Quota i okolice

Generalnie nie ma sensu męczyć kernela i filesystemu żeby pilnował quoty na pocztę. Szczególnie gdy MTA samo sobie może z tym poradzić. Służy do tego parametr ‘quota’ w konfiguracji transportów (hint: poczytaj wyżej co to są transportery, routery itp.). I tak, w najprostszy sposób można lokalną quotę per user ustawić w konfiguracji transportu ‘local_delivery’ (odpowiedzialnego za lokalne dostarczanie poczty):

local_delivery:
	driver = appendfile
	file = /var/mail/$local_part
	delivery_date_add
	envelope_to_add
	return_path_add
	# A tutaj dodajemy quotę w wysokości 20MB:
	quota = 20M

Proste, prawda? Tak naprawdę ma to zastosowanie w systemach poczty wirtualnej gdzie możemy w bazie danych przechowywać quotę użytkownika i można skonstruować zapytanie SQL do odpytania ile miejsca ma dany użytkownik. Ale jeżeli nie możecie sobie poradzić z quotą systemową, możecie zamiast ‘quota = 20M’ dopisać coś takiego:

quota = ${lookup{$local_part}lsearch{/etc/mail/quota.conf}{$value}{0M}}

Od tego momentu w pliku /etc/mail/quota.conf możesz trzymać wielkości skrzynek dla poszczególnych użytkowników. Jeżeli ktoś nie zostanie tam wymieniony, to nie będzie miał żadnych limitów na swoją skrzynkę pocztową. Plik taki powinien wyglądać mniej-więcej tak:

lukasz:	100M
kflis:	5M
ania:	20M

I tak oto ja mam 100mb na pocztę, kubuś tylko 5, a siostra 20 MB ;) Podobnym paramterem każdego transportera jest ‘message_size_limit’. Wystarczy wpisać:

message_size_limit = 10M

Oczywiście jak na Exim’a przystało, od quoty jest więcej bajerków. Chyba najbardziej pożądanym ‘gwizdkiem’ będzie opcja ‘quota_warn_message’. Jest to nic innego jak mail ostrzegający usera o tym że skrzynka jest zapchana po same brzegi. Zanim jednak polecisz to wdrażać, zainteresuj się jak to działa. Otóż po dostarczeniu każdego maila Exim będzie sprawdzał czy został przekroczony konkretny próg (podany w megabajtach, lub w procentowo). Jeżeli tak, wygeneruje on odpowiednią wiadomość. I tak, dodajemy do molestowanego przez nas ‘local_delivery’ następujące opcje:

quota_warn_message = "\
Content-Type: text/plain; charset=ISO-8859-2\n\
To: $local_part@$domain\n\
Reply-to: Administratorzy sieci <admins@twojadomena.pl>\n\
\n\
*** Ta wiadomo¶æ zosta³a wygenerowana automatycznie ***\n\
\n\
Uprzejmie informujemy, iż Twoja skrzynka pocztowa została zapełniona w 90%\n\
swojej pojemności. W momencie zapełnienia jej w 100% nie będą dostarczane\n\
do Ciebie nowe wiadomości. Opróżnij swoją skrzynkę pocztową ze starych\n\
wiadomości.\n"
quota_warn_threshold = 90%

Manualroute czyli przekazywanie poczty do konkretnego MX’a

Exim jak pisałem sam stara się znaleźć adres MX’a do którego ma przekazywać pocztę. Jednak czasami musimy przekazywać tą pocztę do konkretnego hosta, niekoniecznie wpisanego jako MX w DNS’ach. W takim wypadku, w sekcji ‘ROUTERS’ przed ‘dnslookup’ dopisujemy:

manual_route:
	transport = remote_smtp
	driver = manualroute
	domains = ! +local_domains : +relay_to_domains
	route_data = ${lookup{$domain} lsearch{/etc/mail/manual_routes}}

Po tym zabiegu, jeżeli dopiszemy pocztę do relay_to_domains możemy w pliku /etc/mail/manual_routes wpisać gdzie poczta z danej domeny ma być przekazywana, np:

baseciq.org:	mx2.baseciq.org

W powyższym przykładzie poczta dla ‘baseciq.org’ będzie przekazywana do ‘mx2.baseciq.org’.

Określanie dozwolonych nadawców dla pojedyńczego adres e-mail.

Typowo – zrobiliśmy aliasa prowadzącego do 50 osób, np. ‘wszyscy@domena.pl’. Jak łatwo zgadnąć, każdy może na ten adres wysłać, po pewnym czasie adres taki znajduje się już na listach spamerskich i jesteśmy załatwieni. Najlepiej, zrobić filtr osób które mogą na ten adres wysyłać. Tak więc, odszukujemy ‘acl_check_rcpt’ w pliku konfiguracyjnym i piszemy:

deny	message         = Nie jestes uprawniony aby wysylac poczte na ten adres
	condition       = ${if exists{/etc/mail/senderslists/${local_part}@${domain}}{1}{0}}
	senders         = ! /etc/mail/senderslists/${local_part}@${domain}

Teraz, w pliku /etc/mail/senderslists/wszyscy@domena.pl dopisujemy po jednym w każdej linijce adresy e-mail które mają prawo wysyłać maile do wszyscy@domena.pl. Oczywiście, w ten sposób nie chronimy tylko aliasów, a cały ruch na naszym serwerze. Dla przykładu – można w ten sposób chronić adresy nie znajdujące się na naszym serwerze, ale także te znajdujące się na innych serwerach, oczywiście ochrona ta będzie działać tylko na osoby przesyłające przez nasz serwer.