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, 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
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.
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
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 ;-)
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 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
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 ;)
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 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! :)
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"
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%
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’.
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.