## Copyright (c) 2005-2021 Robert Ryszard Paciorek ## ## MIT License ## ## Permission is hereby granted, free of charge, to any person obtaining a copy ## of this software and associated documentation files (the "Software"), to deal ## in the Software without restriction, including without limitation the rights ## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ## copies of the Software, and to permit persons to whom the Software is ## furnished to do so, subject to the following conditions: ## ## The above copyright notice and this permission notice shall be included in all ## copies or substantial portions of the Software. ## ## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. # paczki dla serwera SMTP: exim4-daemon-heavy procmail spamassassin clamav-daemon greylistd mew-bin # exim -d+all -M 1JwyXH-0005nx-8z - przepuszczenie wskazanej wiadomości z kolejki w trybie debugowania (bez uwzględniania czasów ponawiania) # exim -bh host.OR.IP - testowanie reguł dla poczty z zadanego adresu # exim -brw adres - testowanie "rewrite" dla podanego adresu # exim -d+all -bt adres - testowanie ścieżki dostarczania dla podanego adresu ### ### KONFIGURACJA OGÓLNA ### exim_path = /usr/sbin/exim4 # logi - przez syslog i bezpośrednio do pliku log_file_path = syslog : /var/log/exim4/%s-%D.log # znacznik czasu dodawnay przez syslog syslog_timestamp = false # limit wielkości przesyłanego maila (gdy nie ustawiony to 50M) message_size_limit = 1500M daemon_smtp_ports = 25 : 465 keep_environment = # domeny dla których jesteśmy podstawowym MX # @[] odpowiada za przyjmowanie "literałów domenowych" na wszystkie nasze IP # kolejne nazwy domenowe w kolejnych liniach pliku, # warto podać także nazwę podstawowa bieżącego systemu (@ może nie najlepiej działać) # oraz nazwy skrucone hosta domainlist local_domains = @ : @[] : localhost : localhost.localdomain : /etc/mail/local_domains # domeny dla których jesteśmy zapasowym MX # będziemy próbować dostarczyć do serwera o najniższym MX # kolejne nazwy domenowe w kolejnych liniach pliku domainlist relay_to_domains = /etc/mail/relay_to_domains # adresy IP na których słucha serwer # local_interfaces = <; 127.0.0.1 ; 0.0.0.0 ; ::1 ; 2001:db8::1; [2001:db8::1]:8025 # podstawowa nazwa serwera pocztowego # gdyby wczytanie z innych źródeł dawało błędy ... #primary_hostname = "moja.domena" # instrukcje powyższą includujemy z innego pliku .include_if_exists /etc/mail/primary_hostname # hosty z których przyjmujemy pocztę hostlist relay_from_hosts = <; 127.0.0.1 ; ::1 ; /etc/mail/relay_from_hosts # pozwalamy na przyjmowanie "literałów domenowych" czyli np. postamaster@[127.0.0.1] allow_domain_literals # ponawianie wysyłania ignore_bounce_errors_after = 2d timeout_frozen_after = 7d # SSL # generacja kluczy: openssl req -new -x509 -days 365 -nodes -out server-fullchain.pem -newkey rsa:1024 -keyout server-privkey.pem tls_certificate = /etc/ssl/server-fullchain.pem tls_privatekey = /etc/ssl/server-privkey.pem tls_advertise_hosts = * tls_on_connect_ports = 465 # autoryzacja dostępna tylko po SSL auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}} # listy kontroli dostępu i filtrowania # osobna kontrola po adresach dla poczty do nas i poczty na zewnatrz acl_smtp_rcpt = ${if match_domain{$domain}{+local_domains} {acl_check_rcpt_in}{acl_check_rcpt_out}} # działa to na zasadzie ${if forany{$local_domains}{eqi{$item}{$domain}} ... acl_smtp_data = acl_check_data # daemon antywirusowy wykorzystywany przez malware ACL av_scanner = clamd:/var/run/clamav/clamd.ctl #av_scanner = clamd:192.168.1.1 7575 # daemon antyspamowy wykorzystywany przez spam ACL - zostawiamy ustawienia domyslne #spamd_address = localhost 783 ### ### SEKCJE ### ### listy kontroli dostępu, akceptacji i filtrowania begin acl # kontrola poczty wychodzacej na zewnatrz w oparciu o relay_from_hosts i autoryzacje acl_check_rcpt_out: # odrzucamy z niewlasiwymi znakami w adresie (kontrola poprawnosci adresu) deny message = Restricted characters in address local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ # wymagana weryfikacja adresu nadawcy require verify = sender # przyjmujemy gdy poczta nie donas i pochodzi od hosta z relay_from_hosts (w to tez sie wlicza host lokalny) accept hosts = +relay_from_hosts control = submission # przyjmujemy gdy poczta nie donas i pochodzi od zautoryzowanego użytkownika accept authenticated = * control = submission # kontrola przychodzącej do nas w oparciu o local_domains i greylisting # + ustawienie polityki filtrowania dela acl_data acl_check_rcpt_in: # wymagamy aby adresat był u nas # - inni adresaci są odrzucani (na tym etapie nie rozważamy już listów wysyłanych przez nasz serwer do innych # a tylko listy do nas (do obcych jeżeli uprawnione były już zaakceptowane wcześniej) # - działa po pojedynczych adresatach kopertowych require message = relay not permitted domains = +local_domains : +relay_to_domains # odrzucamy z niewłaściwymi znakami w adresie (kontrola poprawności adresu) deny message = Restricted characters in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/|] # podział na grupy adresów względem polityki filtrowania - ustawienia warn set acl_m_addr_mode = yes warn local_parts = postmaster : abuse : /etc/mail/users_no_filter set acl_m_addr_mode = no warn !condition = ${if def:acl_m_data_mode} set acl_m_data_mode = $acl_m_addr_mode # czasowe odrzucenie gdy adres w innej polityce niz obecna # dotyczy tylko drugich i kolejnych RCPT TO: oraz tylko adresow lokalnych defer message = Deferred - please try this recipient again later !condition = ${if eq{$received_protocol}{asmtp}} !condition = ${if eq{$acl_m_addr_mode}{$acl_m_data_mode}} # przyjmujemy na postmaster@_any_local_domain_ chyba ze w skutek poprzedniego RCPT TO zostało włączone filtrowanie accept local_parts = postmaster !condition = ${acl_m_data_mode} # wymagana weryfikacja adresu nadawcy require verify = sender # wymagana weryfikacja adresu odbiorcy require verify = recipient # weryfikacja SPF (niedostępna w standarowej paczce) #warn # spf = pass:fail:softfail:none:neutral:err_perm:err_temp # add_header = X-SPF: $spf_header_comment # czasowe odrzucanie w oparciu o greylist, patrz: http://projects.puremagic.com/greylisting/ (paczka Debiana: greylistd) defer message = $sender_host_address is not yet authorized to deliver \ mail from <$sender_address> to <$local_part@$domain>. \ Greylisting in action, please try later. log_message = greylisted. # !condition = ${if and{ { def:spf_result }{ eq{$spf_result}{pass} } } } !local_parts = ${if exists {/etc/mail/users_no_graylist}{/etc/mail/users_no_graylist}{}} !local_parts = postmaster !senders = : !hosts = : +relay_from_hosts : \ ${if exists {/etc/greylistd/whitelist-hosts}\ {/etc/greylistd/whitelist-hosts}{}} : \ ${if exists {/var/lib/greylistd/whitelist-hosts}\ {/var/lib/greylistd/whitelist-hosts}{}} !authenticated = * domains = +local_domains : +relay_to_domains verify = recipient/callout=20s,use_sender,defer_ok condition = ${readsocket{/var/run/greylistd/socket}\ {--grey $sender_host_address $sender_address $local_part@$domain}\ {5s}{}{false} } # akceptujemy całą resztę która dotarła do tego miejsca accept # weryfikacja treści - antyspamy i antywirusy ... acl_check_data: # akceptujemy gdy wszystkie adresy nie do nas accept !condition = ${if def:acl_m_data_mode} # akceptujemy gdy adresy z wylaczonym filtrowaniem accept !condition = $acl_m_data_mode # oznaczanie poczty wynikiem z SpamAssassin warn condition = ${if < {$message_size}{80K}} spam = nobody:true add_header = X-Spam-Score: $spam_score ($spam_bar) add_header = X-Spam-Report: $spam_report # odrzucamy poczte majaca powyzej 10 pkt w tescie antyspamowym deny message = This message was classified as SPAM condition = ${if >{$spam_score_int}{100}} # odrzucamy poczte z wirusami, patrz: http://www.exim.org/exim-html-4.67/doc/html/spec_html/ch41.html # aby to dzialalo clamav powinien nalezec do grupy Debian-exim (usermod -G Debian-exim clamav) deny message = This message contains malware ($malware_name) condition = ${if < {$message_size}{200K}} #demime = * malware = */defer_ok # akceptujemy całą resztę która dotarła do tego miejsca accept ### reguły kierowania do agentów dostarczania begin routers # kopie poczty wychodzącej w /home/mail/kopie outmail_backup_authenticated: driver = accept # ??? authenticated_id should be not tainted, but ... address_data = ${lookup{$authenticated_id}lsearch{/etc/mail/passwd.mail-users}{$value}} # tylko poczta wysyłana przez zautoryzowanych użytkowników condition = ${if !eq {$address_data} {}} # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN no_verify no_expn # przekazujemy kopię wiadomości (wiadomość będzie przetwarzana przez kolejne routery eximowe) unseen #set = r_backup_file = $authenticated_id #address_data = $authenticated_id user = $address_data transport = write_mail_backup #outmail_backup_others: # driver = accept # # # tylko poczta wysyłana z naszych domen lokalnych przez niezuatoryzowanych użytkowników # condition = ${if eq {$authenticated_id} {}} # condition = ${lookup {$sender_address_domain}lsearch{/etc/mail/local_domains} {yes}{no}} # # # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN # no_verify # no_expn # # # przekazujemy kopię wiadomości (wiadomość będzie przetwarzana przez kolejne routery eximowe) # unseen # # set = r_backup_file = $sender_address # transport = write_mail_backup # dostarczanie do innych hostów - po domenie dnslookup: driver = dnslookup check_srv = smtp domains = ! +local_domains ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1 transport = remote_smtp # dostarczanie do innych hostów - po ipliteral, gdy nie dało się po domenie domain_literal: driver = ipliteral domains = ! +local_domains ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1 transport = remote_smtp # prymitywny odpowiednik driver'a iplookup ... służy do sprawdzania /etc/hosts iplookup: driver = manualroute route_list = * $0 byname domains = ! +local_domains ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1 transport = remote_smtp no_more # dalej przechodzi tylko local_domains ... # obsługa /etc/mail/virtusertable # wbrew sugestii *_transport ... pozostały routing jest przetwarzany i obsługiwany (np. procmail) # format pliku # user@domena : user1, user2@domena1, user3@%2, %1@domena2, ... # w powyąszym przykładzie "%1@" zostanie zastąpione przez "user@" oraz "@%2" przez "@domena" # można podawać samo ^user@.* lub ^.*@domena (uwaga jest to wyrażenie regularne rozpoczynane od ^) # # możemy także korzystać z dyrektyw :include: :defer: :fail: np: # user@domena : :include:/etc/mail/lists/list1 # (dostarczenie do listy adresów wymienionej w pliku /etc/mail/lists/list1) # ^@domena.* : :fail: Unknow User # (w @domena nie ma więcej użytkowników (niż wymienieni wcześniej w pliku aliasów), # w szczególności nie ma użytkowników kont shelowych) # # zamiast forwardów możnaby próbować użyć "::fail: 551 User not local please try " # (czyli odrzuć z podaniem nowego adresu), ale większość serwerów nie spróbuje wykożystać tego adresu # warto zaznaczyc że jeżeli są one zaraz po kolumnie alisu to należy je odzielić dodatkowym : # (jak ma to miejsce w powyższym przykładzie) # # # możliwe jest także stosowanie dostarczania bezpośredniego (poprzedzenie nazwy \\) # (w zasadzie wydaje się że powinien starczać jeden \, ale praktyka pokazuje że trzeba dawać dwa ...) # oraz dostarczania do programów (|sciezka_lub_nazwa ) virtusertable_full_domain: driver = redirect allow_fail allow_defer data = ${expand:${sg\ {${sg\ {${lookup{$local_part@$domain}nwildlsearch{/etc/mail/virtusertable}}}\ {%1@}\ {$local_part@}\ }}\ {@%2}\ {@$domain}\ }} file_transport = address_file pipe_transport = address_pipe reply_transport = address_reply # obsługa plików /etc/mail/procmail_users/* # UWAGA 1: ze względu na tainted $local_part ruch powinien być kierowany do tych odbiorców przez wpisy w virtusertable # czyli `^abc@.* : abc_proc` w virtusertable i `abc_proc` w procmail_users a nie bezposrednio `abc` w procmail_users # UWAGA 2: nie można tu użyć $local_part_data bo będzie pusta jako że nie wymagamy lokalnego odbiorcy procmail_users: driver = accept # wymaga pliku /etc/mail/procmail_users/$local_part # jest sprawdzane w celu weryfikacji lokalnego odbiorcy domains = +local_domains require_files = /etc/mail/procmail_users/$local_part address_data = $local_part transport = procmail_pipe # kopie poczty w /home/mail/kopie mail_backup: driver = accept # wymaga lokalnego użytkownika domains = +local_domains check_local_user # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN no_verify no_expn # przekazujemy kopię wiadomości (wiadomość będzie przetwarzana przez kolejne routery eximowe) unseen user = $local_part_data #set = r_backup_file = $local_part address_data = $local_part_data transport = write_mail_backup # odpowiedzi automatyczne w oparciu o ~/exim_vacation.msg user_vacation: driver = accept # wymaga lokalnego użytkownika i pliku ~/exim_vacation.msg check_local_user require_files = $home/exim_vacation.msg # nie odpisujemy na błędy bądź listy dyskusyjne condition = "${if or {{match {$h_precedence:} {(?i)junk|bulk|list}} {eq {$sender_address} {}}} {no} {yes}}" senders = " ! ^.*-request@.*:\ ! ^.*@list*.*:\ ! ^owner-.*@.*:\ ! ^postmaster@.*:\ ! ^listmaster@.*:\ ! ^mailer-daemon@.*\ ! ^root@.*" # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN no_verify no_expn # przekazujemy kopię wiadomości unseen user = ${local_part_data} transport = vacation_reply # obsługa plików ~/.forward userforward: driver = redirect # wymaga lokalnego użytkownika i pliku $home/.forward # plik ten moze zawierac tradycyjne przekierowania, filtry sieve lub filtry exim # patrz: http://www.exim.org/exim-html-4.30/doc/html/filter_toc.html domains = +local_domains check_local_user require_files = $local_part_data:$home/.forward file = $home/.forward # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN no_verify no_expn check_ancestor allow_filter file_transport = address_file directory_transport = address_directory pipe_transport = address_pipe reply_transport = address_reply # obsługa dovecotowych plików sieve - ~/.dovecot.sieve # robimy to z użyciem dovecot'a ... # możliwa jest także obsługa sieve z użyciem avelsieve - patrz http://dfoerster.de/opensource/exim-sieve-howto.html dovecot_sieve: driver = accept # wymaga lokalnego użytkownika i pliku $home/.dovecot.sieve domains = +local_domains check_local_user require_files = $local_part_data:$home/.dovecot.sieve # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN no_verify no_expn transport = dovecot_pipe # obsługa plików ~/.procmailrc procmail: driver = accept # wymaga lokalnego użytkownika, obecnosci /usr/bin/procmail # i pliku $home/.procmailrc lub /etc/procmailrc domains = +local_domains check_local_user require_files = ${local_part_data}:\ ${if exists{/etc/procmailrc}\ {/etc/procmailrc}{${home}/.procmailrc}}:\ +/usr/bin/procmail # ignorowanie przy weryfikacji adresu oraz przy komendzie EXPN no_verify no_expn address_data = $local_part_data transport = procmail_pipe # dostarczanie lokalne do ~/mail/INBOX localuser: driver = accept # wymaga lokalnego użytkownika domains = +local_domains check_local_user transport = local_delivery cannot_route_message = Unknown user ### konfiguracja agentów dostarczania begin transports # przekazywanie do innych hostów w sieci remote_smtp: driver = smtp # dostarczanie lokalne do MAILDIR ~/MAIL/INBOX local_delivery: driver = appendfile maildir_format directory = $home/MAIL/INBOX create_directory directory_mode = 0700 delivery_date_add envelope_to_add return_path_add # znaczenie powyższych opcji zobacz w http://www.exim.org/exim-html-current/doc/html/spec_html/ch44.html # dostarczanie przez procmail procmail_pipe: driver = pipe path = "/bin:/usr/bin:/usr/local/bin" log_output = yes command = "/etc/exim4/procmail.sh /etc/mail/procmail_users/$address_data" #command = "procmail -t ORGMAIL=$home/MAIL/INBOX/ DEFAULT=$home/MAIL/INBOX/" return_path_add delivery_date_add envelope_to_add # dostarczanie przez dovecot dovecot_pipe: driver = pipe log_output = yes command = /usr/lib/dovecot/deliver message_prefix = message_suffix = return_path_add delivery_date_add envelope_to_add # auto-responder vacation_reply: driver = autoreply file = $home/exim_vacation.msg file_expand from = System Automatycznej Odpowiedzi <$original_local_part@$original_domain> log = $home/.exim_vacation.log once = $home/.exim_vacation.db once_repeat = 7d subject = ${if def:h_Subject: {Re: ${quote:${escape:${length_50:$h_Subject:}}} (autoreply)} {Informacja} } text = "!!! WIADOMOŚĆ WYGENEROWANA AUTOMATYCZNIE !!!\nPoniżej informacja od użytkownika <$original_local_part@$original_domain>\n\n" to = "$sender_address" # agenty techniczne (m.in. na potrzeby ~/.forward) address_reply: driver = autoreply address_pipe: driver = pipe return_output address_file: driver = appendfile delivery_date_add envelope_to_add return_path_add address_directory: driver = appendfile delivery_date_add envelope_to_add return_path_add check_string = "" escape_string = "" maildir_format # kopie zapasowe poczty write_mail_backup: driver = appendfile user = mail group = mail mode = 0660 mode_fail_narrower = false home_directory=/home/mail/kopie/ #file = /home/mail/kopie/$r_backup_file file = /home/mail/kopie/$address_data delivery_date_add envelope_to_add return_path_add ### ponawianie wysyłania begin retry * * F,6m,2m; F,15m,5m; F,2h,15m; G,16h,1h,1.5; F,4d,6h ### przetwarzanie nagłówków begin rewrite # zamiana adresu nadawcy wg danych z pliku /etc/mail/from-addresses-map o formacie: # stary@adres.pocztowy: nowy@adres.pocztowy *@* ${lookup{$1@$2}lsearch{/etc/mail/from-addresses-map}{$value}fail} frFs ### autoryzacja begin authenticators plain: driver = plaintext public_name = PLAIN server_prompts = : # hasła z: # - PAM #server_condition = "${if pam{$auth2:$auth3}{1}{0}}" # - osobnego pliku z hasłami tylko do poczty # (hasła można generować z uzyciem `mkpasswd --method=SHA-512 --stdin`) server_condition = ${lookup{$auth2}lsearch{/etc/mail/passwd.mail-users} {${if crypteq{$auth3}{${extract{1}{:}{$value}{$value}fail}}{true}{false} }}} server_set_id = $auth2 login: driver = plaintext public_name = LOGIN server_prompts = "Username:: : Password::" # hasła z: # - PAM #server_condition = "${if pam{$auth1:$auth2}{1}{0}}" # - osobnego pliku z hasłami tylko do poczty # (hasła można generować z uzyciem `mkpasswd --method=SHA-512 --stdin`) server_condition = ${lookup{$auth1}lsearch{/etc/mail/passwd.mail-users} {${if crypteq{$auth2}{${extract{1}{:}{$value}{$value}fail}}{true}{false} }}} server_set_id = $auth1 # UWAGA: autoryzacja przez PAM wymaga paczki exim4-daemon-heavy # oraz dodania użytkownika Debian-exim do grupy shadow # konfiguracja PAMu w /etc/pam.d/exim4 powinna być następująca: # #%PAM-1.0 # # @include common-auth # @include common-account # @include common-session