Почтовый сервер с хранением данных в PostgreSQL (продолжение)

В этом посте будут рассмотрены дальнейшие приключения по настройке почтового сервера. А именно настройка МТА Exim и его связка с MDA DBmail.Исходя из комментариев к предыдущей статье, постараюсь изложение сделать более подробным.В комментариях к прошлой статье многие задавали вопрос почему выбран именно такой вариант хранения сообщений, а именно в базе данных. Ведь есть уже проверенный временем способ хранения в файловой системе. Тем более что сама СУБД работает поверх файловой системы и зависит от неё. Касаемо хранения почты есть замечательный формат хранения почты Maildir, который прекрасно стыкуется с распространёнными opensource SMTP-серверами Exim и Postfix.Давайте вкратце для сравнения посмотрим как обычно обстоит дело с хранением почтовых соообщений в формате Maildir: пришедшие письма складируются в соответствующие директории на почтовом сервере, где ждут своей участи — быть удалёнными после того как их заберёт почтовый клиент, либо остаться (зависит от настроек и задумок). Находясь на сохранение почтовые сообщения представляют собой обыкновенные файлы, доступ к которым ограничен лишь настройками, определяемыми правами доступа на уровне файловой системы. Помимо этого как и все данные, которые не обрабатываются, а хранятся, любят резервное копирование и прочёсывание на предмет анализа. Ну и разбухать со временем имеют тягу. Вроде бы ничего сложного и особых проблем тоже нет.Чем же тогда привлекательно хранение в базе данных? Как выше было замечено СУБД работает поверх файловой системы, только при этом имеет столько нюансов и особенностей, настроив которые, можно добиться большей скорости обращения к объектам базы данных нежели к индивидуальным файлам. Реляционные СУБД лучше приспособлены к обработке больших объемов структурированных данных. По гибкости и своим возможностям SQL-запросы несоизмеримы с тем, что можно сделать, обрабатывая Maildir различными самописными скриптами на Perl или Python. Также можно задейстовать различные механизмы предоставляемые СУБД: репликация, фрагментирование, балансировка нагрузки, резервное копирование. Помимо этого такой подход позволяет довольно легко разнести хранилище почтовых сообщений и сервисы приёма и отправки сообщений, что удобно при распихивании по контейнерам и виртуальным машинам.4 Установка и настройка МТА Exim4.1 Установка МТА Exim Поскольку почтовый сервер postfix, идущий по умолчанию не нужен, поэтому он остановлен и выключен из автозапуска: /etc/init.d/postfix stop chkconfig postfix off Будут установлены два основных пакета — сам МТА exim и пакет для работы с СУБД Postgresql — exim-pgsq. Если душа или производственная необходимость требуют обработчика серых списков (exim-greylist) или монитора exim (exim-mon), то доустановить их можно по собственному усмотрению. yum install exim exim-pgsql Для корректной работы с TLS сертификатами, системный пользователь exim добавлен в группу mail: usermod -a -G mail exim Postfix уже не нужен, поэтому удаляется. После его деинсталяции, символические автоматически будут переправлены на exim: yum erase postfix Затем добавить в автозапуск exim и сделать сервером почты по умолчанию: chkconfig --level 35 exim on alternatives --config mta Имеется 1 программа, которая предоставляет 'mta'.

Выбор Команда ----------------------------------------------- *+ 1 /usr/sbin/sendmail.exim

Enter — сохранить текущий выбор[+], или укажите номер: 1 4.2 Настройка МТА Exim Конфигурационный файл exim.conf приводится к такому виду: Осторожно! Много букв. Содержимое файла /etc/exim/exim.conf # Имя хоста. Используется в EHLO. primary_hostname = wow.test.com

# Доменная зона, куда будут приходить письма domainlist local_domains = test.com: localhost

# Список хостов с которых разрешён неавторизованый релей. hostlist relay_from_hosts = 127.0.0.1: localhost

# Список локальных подсетей. hostlist local_area = 192.168.0.0/24: 192.168.17.0/24

# Эта опция задаёт хосты для которых резервируются SMTP-соединения. # Имеет смысл включать при большой нагрузке на сервер. ##smtp_reserve_hosts = local_area

# ACL acl_smtp_auth = acl_check_auth acl_smtp_helo = acl_check_helo acl_smtp_connect = acl_check_connect acl_smtp_rcpt = acl_check_rcpt acl_smtp_data = acl_check_data acl_smtp_mime = acl_check_mime

# Подключение к spamassasin ##spamd_address = 127.0.0.1 783

# Чтобы быстрее работало подключаемся через сокет: spamd_address = /var/run/spamassassin/spamd.sock

# TLS tls_advertise_hosts = +local_area tls_certificate = /etc/pki/tls/certs/wow.test.com.pem tls_privatekey = /etc/pki/tls/private/wow.test.com.pem tls_on_connect_ports = 465 tls_require_ciphers = AES: MD5 gnutls_require_mac = SHA_512 tls_verify_certificates = *

# Server # Дефолтовые порты daemon_smtp_ports = 25: 465

# Число повторов при неудачном запуске daemon_startup_retries = 5

# Время ожидания между повторными запускам daemon_startup_sleep = 30s

# Cписок ip адресов и портов через двоеточие, откуда exim будет принимать # почту. Только эти адреса считаются локальными при маршрутизации и # проверке зацикливания почты local_interfaces = 127.0.0.1: 192.168.0.2

# Имя домена добавляемое для локальных отправителей (реальных юзеров системы) т.е. Почта # отправляемая от root, будет от root@домен_указанный_здесь. qualify_domain = test.com

# Имя хоста для ситуации, обратной предыдущей, — это имя домена добавляемое # к почте для системных юзеров, ну и вообще для почты пришедшей на адрес # типа root. qualify_recipient = test.com

# Не принимать почту, когда вместо доменного адреса указывается адрес IP allow_domain_literals = false

# Exim отказывается от root привилегий при запуске процесса доставки, # и повсюду работает как пользователь exim. Это строго ограничивает # возможные виды локальной доставки, но жизнеспособно лишь в # определённых типах конфигурации, например при даставке по протоколу lmtp # через сетевую подсистему (см. transport_dbmail). # Имеет смысл включать при доставке по tcp/ip. ###deliver_drop_privilege = true

# Указываю пользователя и группу от которых будет работать exim exim_user = exim exim_group = exim

# Запрет работы доставки под пользователями root, daemon, bin, sync, adm # в целях безопасности never_users = root: daemon: bin: sync: adm

# Проверка соответствие прямой и обратной зон для всех хостов. host_lookup = *

# Требовать авторизацию через безопасное SSL соединение auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}}

# Если эта опция установленна, обработка очереди останавливается, # когда средняя загрузка системы больше значения этой опции. # Т. е. при превышении указанного значения load avarege, останавливается # обработка почтовых сообщений в очереди deliver_queue_load_max = 10

# LOGING log_selector = \ +all_parents \ +connection_reject \ +lost_incoming_connection \ +received_sender \ +received_recipients \ +smtp_confirmation \ +smtp_syntax_error \ +smtp_protocol_error \ -queue_run

# Убираю проверку identd на клиентской стороне. rfc1413_query_timeout = 0s

# Если сообщение не было доставлено, то создаётся сообщение об ошибке. # Если сообщение об ошибке не удалось доставить то оно замораживается # на указанный в этом пункте срок, после чего снова осуществляется попытка доставить его. ignore_bounce_errors_after = 2d

# Замороженные сообщения, находящиеся в очереди, дольше указанного # времени удаляются и создаётся сообщение об ошибке (при условии, # что это не было недоставленное сообщение об ошибке) timeout_frozen_after = 7d

# Список адресов, разделённых через запятой, на которые засылаются письма # о замороженных сообщениях freeze_tell = support@test.com

# Через какое время повторять попытку доставки замороженного сообщения auto_thaw = 4h

# Ограничение размера сообщения message_size_limit = 12M

# Если число получателей (RCPT) превышает это число, то на все # последующие команды RCPT возвращается код возврата 452, #, но все ранние получатели обрабатываются нормально recipients_max = 24

# Полностью отвергать SMTP соединение со слишком большим числом # получателей — коды 552, 554 recipients_max_reject = true

# Максимальное число одновременных подключений по SMTP. smtp_accept_max = 24

# Максимальное число сообщений принимаемое за одно соединение # от удалённого сервера (или пользователя) smtp_accept_max_per_connection = 96

# Максимальное число подключений с одного хоста smtp_accept_max_per_host = 8

# Если у сообщения много адресатов на удалённых хостах, то запускается # до указанного числа максимально число параллельных процессов доставки remote_max_parallel = 12

# Если средняя загрузка системы становиться выше чем тут указано, входящие # SMTP-соединения принимаются только от тех хостов, которые совпадают с # указанным в «smtp_reserve_hosts» ##smtp_load_reserve = 8

# Приветствие smtp_banner = «Post Server»

accept_8bitmime = true

# Подключение к базе данных # [hide mysql_servers = имя-сервера/имя-БД/имя пользователя/пароль], # (PgSQL для получения данных маршрутизации) Или чтобы работать через # сокет: hide pgsql_servers = (/var/run/postgresql/.s.PGSQL.5432)/dovecot/pig/wes ##hide pgsql_servers = localhost/dovecot/pig/wes

# Отключение поддержки IPv6 disable_ipv6 = true

# Принудительная синхронизация. Если отправитель торопится подавать # команды, не дождавшись ответа, то он посылается далеко и надолго smtp_enforce_sync = false

# Убрать собственную временную метку exim`a из логов, её ставит # сам syslogd syslog_timestamp = no

###################################################################### # ACL CONFIGURATION # # Specifies access control lists for incoming SMTP mail # ###################################################################### begin acl

# В acl_check_auth проверяется тип аутентификации. Разрешаю все типы # аутентификации при использовании TLS и только CRAM аутентификации # без TLS. acl_check_auth:

accept encrypted = +local_domains accept condition = ${if eq{${uc:$smtp_command_argument}}{CRAM-MD5}}

deny

# Проверка правильности поля HELO acl_check_helo:

# Белый список для кривоватых отправителей до нас: accept hosts = wildlsearch;/etc/exim/custom/white_list

# Спам лист для отъявленных: deny condition = ${lookup {$sender_helo_name}wildlsearch{/etc/exim/custom/block_list}{yes}{no}} delay = 30s log_message = REJECT: a block list pessenger

# Запрет тех, кто не обменивается приветственными сообщениями (HELO/EHLO) deny condition = ${if eq{$sender_helo_name}{}{yes}{no}} hosts = * message = Nice boys say HELO first log_message = REJECT: HELO/EHLO require by SMTP RFC # Запрет тех, кто подставляет свой IP в HELO deny condition = ${if eq{$sender_helo_name}{$sender_host_address}{yes}{no}} hosts = * delay = 30s log_message = REJECT: HELO/EHLO require by SMTP RFC

deny condition = ${if eq{$sender_helo_name}{$interface_address}{yes}{no}} hosts = !127.0.0.1: ! localhost: !192.168.0.2: * delay = 30s log_message = REJECT: HELO/EHLO require by SMTP RFC

deny condition = ${if match{$sender_helo_name}{^[0–9]\.[0–9]\.[0–9]\.[0–9]}{yes}{no}} delay = 30s log_message = REJECT: HELO/EHLO require by SMTP RFC

# Запрет HELO с нашим именем deny condition = ${if match_domain{$sender_helo_name} \ {$primary_hostname: +local_domains }{true}{false}} delay = 30s log_message = REJECT: HELO с нашим именем

accept

# Проверка для начала SMTP соединения acl_check_connect:

# Белый список для кривоватых отправителей до нас: accept hosts = wildlsearch;/etc/exim/custom/white_list

# Спам лист для отъявленных: drop hosts = wildlsearch;/etc/exim/custom/block_list message = Sram blocking! log_message = REJECT: Host in Black list

# Запрет пользователей с хостами, подпадающими # под список ip-адресов /etc/exim/custom/net_block drop hosts = net-iplsearch;/etc/exim/custom/net_block message = This ip-address in our blacklist log_message = REJECT: Net in black list

accept

# Этот список доступа описывает проверки, осуществляемые при вызове любой RCPT команды acl_check_rcpt:

# Принимать сообщения которые пришли с локалхоста, не по TCP/IP accept hosts = : control = dkim_disable_verify

# Проверка на недопустимые символы для локальных получателей: deny message = Restricted characters in address domains = +local_domains local_parts = ^[.] : ^.*[@%!/\]

# Проверка на недопустимые символы для нелокальных получателей deny message = Restricted characters in address domains = ! +local_domains local_parts = ^[./\] : ^.*[@%!] : ^.*/\\.\\./

# Не принимать почту для постмастеров deny local_parts = postmaster

# Проверка отправителя (присутствует ли в списке пользователей локального домена) require verify = sender require message = Sender did not verify

# Проверка аутентификации accept authenticated = * control = submission control = dkim_disable_verify

# Проверка наличия получателя в локальных доменах accept domains= +local_domains require verify = recipient message = Recipient did not verify

# Запрет хостов типа *adsl*; *dialup*; *pool*;… Ведь нормальные люди с таких не пишут. deny condition = ${if match{$sender_host_name}{adsl|dsl|dialup|pool|peer|dhcp} {yes}{no}} message = Your host is not pleasant to Chuck Norris log_message = REJECT: Bad type host

# Задержка. Это такой метод борьбы со спамом, основанный на принципе его # рассылки. Считается, на этом задерживается почти весь спам. warn # Ставим дефолтовую задержку в 20 секунд set acl_m0 = 20s

# Ставим задержку в 0 секунд своим хостам и дружественным сетям hosts = local_area set acl_m0 = 0s

warn condition = ${if and {{! match{$sender_host_name} \ {\N.+.outblaze.com$\N}} \ {eq{$acl_c0}{outblaze_helo}}}{yes}{no}} set acl_m0 = 99s

warn condition = ${if and {{! match{$sender_host_name} \ {\N.+.outblaze.com$\N}} \ {eq{$acl_c2}{outblaze_domain}}}{yes}{no}} set acl_m0 = 99s

# Пропускаем остальное accept

# Проверка тела письма acl_check_data:

# Защита от спама с помощью SpamAssassin. # Bypass SpamAssassin checks if the message is too large (100 кБ). accept condition = ${if >={$message_size}{100000} {1}} add_header = X-Spam-Note: SpamAssassin run bypassed due to message size

# Run SpamAssassin, but allow for it to fail or time out. Add a warning message # and accept the mail if that happens. Add an X-Spam-Flag: header if the SA # score exceeds the SA system threshold. warn spam = nobody/defer_ok add_header = X-Spam-Flag: YES

accept condition = ${if! def: spam_score_int {1}} add_header = X-Spam-Note: SpamAssassin invocation failed

# Unconditionally add score and report headers warn add_header = X-Spam-Score: $spam_score ($spam_bar)\n\ X-Spam-Report: $spam_report

# And reject if the SpamAssassin score is greater than ten deny condition = ${if >{$spam_score_int}{120} {1}} message = Your message scored $spam_score SpamAssassin point. \n\ Report follows: $spam_report

# Проверка содержимого писем. deny condition = ${if >{$demime_errorlevel}{2}{1}{0}} message = This message contains a MIME error ($demime_reason) log_message = REJECT: Error in MIME demime = *

deny message = Possible Microsoft attack ($found_extension) log_message = REJECT: Bad attachment demime = mad: maf: mag: mam: maq: mar: mas: mat: mav: maw \ : xnk: wsc: wsf: wsh: vbs: vbe: sct: scf: ins: hta: cnf: chm \ : reg: js: com: cmd: scr: vbs: bat: lnk: pif: dll: cpl

deny condition = ${if >{$body_zerocount}{0}{1}{0}} log_message = REJECT: NUL characters! message = This message contains NUL characters

deny message = Incorrect headers syntax log_message = REJECT: Incorrect header syntax ! verify = header_syntax

# Пропускаем остальное accept

acl_check_mime:

# Декодирование mime сообщений. Полезно для дальнейшей проверки # на вирусы warn decode = default

# Можно очень быстро отсеять сообщения, просто запретив некоторые # mime вложения, чаще всего содержащие вирусы, хотя, конечно, это не панацея. # Поэтому следует на своё одуманное усмотрение. deny message = Blacklisted file extension detected condition = ${if match {${lc:$mime_filename}}{\N (\.acm|\.ax|\.bin|\.bpl|\.cat \n\ |\.chm|\.com|\.cpl|\.dat|\.drv|\.hlp|\.ini|\.msc|\.nls \n\ |\.ocx|\.olb|\.pif|\.rom|\.scr|\.src|\.sys|\.tlb|\.vbs|\.vxd \n\ |\.exe|\.bat|\.cmd|\.msi|\.asf \n\ $\N}{1}{0}}

# Это китайского спама поубавит. deny message = Sorry, noone speaks chinese here condition = ${if eq{$mime_charset}{gb2312}{1}{0}}

# Пропускаем остальное accept

###################################################################### # ROUTERS CONFIGURATION # # Specifies how addresses are handled # ###################################################################### begin routers

# Роутер, осуществляющий поиск по MX-записям в DNS — поиск маршрута к хосту в DNS. Не проверяются локальные домены, 0.0.0.0 и 127.0.0.0/8 # За коментарием ### вариант транспорта при доставке через tcp/ip. # В данном случае рассматривается доставка через lmtp-socket.

dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0: 127.0.0.0/8 no_more

# Всё что осталось — это локальные адресаты.

# Доставка почты в dbmail dbmail_user: driver = accept condition = ${lookup pgsql{SELECT alias_idnr FROM \ dbmail_aliases WHERE \ alias='${quote_pgsql:$local_part@$domain}' OR \ alias='${quote_pgsql:@$domain}'}{yes}{no}} ##'#transport = transport_dbmail transport = local_lmtp cannot_route_message = Unknown user

###################################################################### # TRANSPORTS CONFIGURATION # ###################################################################### begin transports

# Доставка на удалённые хосты — по SMTP

remote_smtp: driver = smtp

### Закоментирован вариант удалённой доставки по lmtp через tcp/ip ###transport_dbmail: ### driver = smtp ### protocol = lmtp ### hosts = 127.0.0.1 ### allow_localhost ### return_path_add

# Локальная доставка через сокет lmtp, ну чтоб быстрее local_lmtp: driver = lmtp socket = /var/run/dbmail/lmtpd.sock batch_max = 8 user = exim

###################################################################### # RETRY CONFIGURATION # ###################################################################### # Повторы недоставленных писем. begin retry

# Domain Error Retries * * F,2h,20m; G,16h,1h,1.5; F,4d,6h

##################################################################### # REWRITE CONFIGURATION # ###################################################################### # Преобразование адресов. begin rewrite

#################################################################### # AUTHENTICATION CONFIGURATION # ###################################################################### # Секция авторизации при отправке писем. begin authenticators

# Так авторизуется TheBat! client_auth: driver = cram_md5 public_name = CRAM-MD5 server_secret = ${lookup pgsql{SELECT passwd FROM dbmail_users \ WHERE userid = '${quote_pgsql:$1}'}{$value}fail} server_set_id = $1 server_advertise_condition = ${if eq{$tls_cipher}{}{no}{yes}}

# Аутентификация по PLAN PLAIN: driver = plaintext server_set_id = $auth2 server_prompts = : server_condition = ${lookup pgsql{SELECT user_idnr FROM dbmail_users \ WHERE userid = '${quote_pgsql:$2}' \ AND passwd = '${quote_pgsql:$3}'}{1}fail} server_advertise_condition = ${if eq{$tls_cipher}{}{no}{yes}}

# Аутентификация через LOGIN LOGIN: driver = plaintext server_set_id = $auth1 server_prompts = <| Username: | Password: server_condition = ${lookup pgsql{SELECT user_idnr FROM dbmail_users \ WHERE userid = '${quote_pgsql:$1}' \ AND passwd = '${quote_pgsql:$2}'}{1}fail} server_advertise_condition = ${if eq{$tls_cipher}{}{no}{yes}}

###################################################################### # CONFIGURATION FOR local_scan () # ###################################################################### # begin local_scan # End of Exim configuration file

# End of Exim configuration file Создание дополнительных файлов с белыми и чёрными списками, описанных ранее в конфигурационном файле Exim: mkdir /etc/exim/custom/ touch /etc/exim/custom/white_list /etc/exim/custom/block_list /etc/exim/custom/net_block chcon -R -u system_u /etc/exim/custom/* restorecon -R -v /etc/exim/custom/* Примерное содержимое файла /etc/exim/custom/white_list: *.rmc.tog.me 2-smtp.mecrury.ru Примерное содержимое файла /etc/exim/custom/block_list: *.virtual.com.ar *.doory.net *.uwpronto.ca *.ventil.pl *.ntdalin.net *subscribe.ru *ucoz.net Примерное содержимое файла /etc/exim/custom/net_block: 221.128.0.0/16 221.129.0.0/16 Огромная благодарность Лиссяре за перевод документации по Exim и статьи по настройке.

4.3 Настройки SELinux для Exim По идее модуль политики для Exim должен быть установлен: semodule -lv |grep exim exim 1.4.2 Если его по какой-то причине нет, то в каталоге /usr/share/selinux/targeted лежит много разных интересных политик. Здесь имеется политика SELinux для exim. Её можно взять для своих нужд: bunzip2 -d exim.pp.bz2 semodule -i exim.pp Разрешить подключаться exim-у к БД: setsebool -P exim_can_connect_db on Поскольку пользовательские данные будут храниться в БД, следовательно права на управление непривилегированными файлами пользователей не требуются, поэтому переключатели exim_manage_user_files и exim_read_user_files остаются в состояние по умолчанию.Здесь приведены настройки политики TE для SELinux, выловленных силами утилиты audit2allow (grep exim /var/log/audit/audit.log | audit2allow), созерцанием вывода netstat -anZ и многочисленными опытами: Содержимое файла post.te: module post 1.0;

require {

type sysfs_t; type exim_t; type spamd_t; type initrc_t; type var_run_t; type spamd_var_run_t; class file { open read }; class dir search; class sock_file { read write }; class unix_stream_socket connectto;

}

#============= exim_t ============== allow exim_t sysfs_t: dir search; allow exim_t sysfs_t: file { open read };

allow exim_t spamd_var_run_t: dir search; allow exim_t spamd_var_run_t: sock_file write; allow exim_t spamd_t: sock_file { read write };

allow exim_t var_run_t: sock_file write;

allow exim_t initrc_t: dir search; allow exim_t initrc_t: sock_file { read write }; allow exim_t initrc_t: unix_stream_socket connectto; Лирическое отступление. Прошу обратить внимание и действовать только исходя из своих сил и возможностей. В данной политике есть довольно слабое место — exim подключается к сокет-файлу, который работает в домене initrc_t. Причиной тому что агент доставки сообщений конечным пользователям DBmail работает в этом домене. Перерыл интернеты, так и не нашёл политики для этого приложения, а написать грамотную и безопасную политику, каюсь, пока не по зубам. Если есть сомнения по поводу безопасности, то лучше плюнуть на эти сокеты и работать через tcp/ip.Компилирование и загрузка модуля политики SELinux: checkmodule -M -m -o post.mod post.te && semodule_package -o post.pp -m post.mod semodule -i post.рр 5 Проверка работоспособности связки Dbmail+Exim+PostgreSQL У DBmail есть хорошая возможность, он позволяет хранить в базе данных пароли сразу в зашифрованном виде (enryption_type=md5). Для этого в параметрах команды управления пользователями необходимо указать -p md5-hash: dbmail-users -a user@test.com -p md5-hash -w shmser -s user@test.com Adding INBOX for new user… ok. [user@test.com] Done user@test.com: x:4:0:0.00:0.00: user@test.com В базу пароль будет записан в виде:$1$SKWJC5xL$PVynlB6pq3VflNi9IL7ow.Более подробно о управлении пользователями dbmail здесь, тут и тама.Теперь очередь проверить конфигурационный файл exim на наличие ошибок: exim -bV Если ошибок не найдено, можно запустить exim в режиме отладки: exim -bd -d+all& Если и здесь ошибок нет, то уже можно проверить распознавание локальной почты: exim -bt user@test.com

user@test.com router = dbmail_user, transport = lmtp_delivery Если ошибок нет, проверим распознавание почты на внешние адреса: exim -bt support@microsoft.com

router = dnslookup, transport = remote_smtp host microsoft-com.mail.protection.outlook.com [207.46.163.138] MX=10 host microsoft-com.mail.protection.outlook.com [207.46.163.215] MX=10 host microsoft-com.mail.protection.outlook.com [207.46.163.247] MX=10 В случае положительного исхода, можно пробовать отправлять самые настоящие тестовые письма локальному пользователю и себе любимому на внешний ящик: exim -v user@test.com From: user@test.com To: user@test.com Subject: Splin

Check the microphone ^D На всякий случай Шпаргалки по полезным командам exim 1, 2, 3.В следующей (заключительной) статье собираюсь дорассмотреть окончательно настройку почтового сервера. Туда войдут описание настройки Spamassassin, подсистемы аудита и журналирования системных событий Auditd, а так же программы защиты системы от попыток вторжения Fail2ban.

© Habrahabr.ru