-
-
Save msamoylov/31d42388cd3b7f058e22 to your computer and use it in GitHub Desktop.
Exim4 conf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
###################################################################### | |
# Runtime configuration file for Exim # | |
###################################################################### | |
# Здесь мы определяем макросы, описывающие различные пути | |
local_interfaces = <; ::0 ; 0.0.0.0 | |
CONFIG_PREFIX=/etc/exim4 | |
warn_message_file = CONFIG_PREFIX/messages/warn_message_file | |
bounce_message_file = CONFIG_PREFIX/messages/bounce_message_file | |
DKIM_DOMAIN = domain.ru | |
DKIM_FILE = /etc/exim4/dkim/domain.ru.pem | |
DKIM_PRIVATE_KEY = ${if exists{DKIM_FILE}{DKIM_FILE}{0}} | |
# Здесь мы указываем, где находить наш postgresql сервер, соединение | |
# осуществляется через локальный сокет, команда hide помогает спрятать эту | |
# настройку при вызове exim -bP, когда exim выводит | |
# все конфигурационные опции в | |
# стандартный вывод. Учтите, | |
# что сам /usr/local/etc/exim/configure должен иметь владельца root:wheel и | |
# иметь права доступа 0600, что отличается от того, что принято по умолчанию | |
# (0644) | |
#hide pgsql_servers = host/database/db_user/password | |
hide pgsql_servers = localhost/exim/exim/exim | |
# Тут мы описываем списки доменов | |
# Local_domains включает домены, считающиеся локальными, то есть те домены, для | |
# которых exim делает локальную доставку, для остальных доменов почта | |
# доставляется по MX записям в DNS. | |
domainlist local_domains =${lookup pgsql{SELECT domain FROM local_domain}} | |
# Список хостов, почту на которые мы явно отвергаем | |
hostlist host_reject = ${lookup pgsql{SELECT domain FROM hostreject}} | |
#Список доменов куда разрешен прием | |
domainlist relay_to_domains = ${lookup pgsql{SELECT hosts FROM relaytohosts}} | |
# Список адресов, с которых разрешена передача почты во внешний мир | |
#hostlist relay_from_hosts =${lookup pgsql{SELECT hosts FROM relayfromhosts}} | |
hostlist relay_from_hosts = localhost:127.0.0.0/8:192.168.0.0/16 | |
# Проверка получателя | |
acl_smtp_rcpt = acl_check_rcpt | |
# Проверка mime содержимого | |
acl_smtp_mime = acl_check_mime | |
# Проверка на спам и вирусы | |
acl_smtp_data = acl_check_data | |
# Здесь мы описываем наш антивирус | |
av_scanner = clamd:127.0.0.1 3310 | |
# И spamassasin | |
spamd_address = 127.0.0.1 783 | |
# Настройки пользователя и группы по умолчанию | |
exim_user = Debian-exim | |
exim_group = mail | |
# Никогда не осуществляем доставку под рутом - root должен быть алиасом на | |
# другого локального пользователя. Кстати, это _обязательное_ условие, заданное | |
# еще на этапе компиляции | |
never_users = root | |
# Настройки директории для очереди | |
spool_directory = /var/spool/exim | |
# Разделяем spool_directory на несколько более маленьких - аналог хеш таблицы, | |
# ускоряет обработку spool'а | |
split_spool_directory | |
# Пытаемся сделать соответствие прямой и обратной зоны dns для каждого хоста. | |
# Несколько затратно, но весьма полезно | |
# прописываем локалку чтобы не получать сообщения об идентификации локалки | |
host_lookup = !192.168.0.0/16 : * | |
# Убираем проверку identd на клиентской стороне. Из-за неправильно настроенных | |
# firewall'ов это часто вызывает длительные тайм-ауты, кроме того, этот сервис | |
# поднят не у многих | |
rfc1413_query_timeout = 0s | |
# Указываем кое-какие лимиты (их назначение ясно из названия) | |
smtp_accept_max = 50 | |
smtp_connect_backlog = 40 | |
smtp_accept_max_per_host = 10 | |
smtp_accept_queue = 22 | |
smtp_accept_queue_per_connection = 10 | |
recipients_max = 16 | |
recipients_max_reject = true | |
message_size_limit = 20M | |
accept_8bitmime | |
# Игнорируем сообщения, которые приходят нам же, | |
# давность которых более 12-ти часов | |
ignore_bounce_errors_after = 12h | |
# Удаляем замороженные сообщения, давность которых больше 1 дней. | |
timeout_frozen_after = 1d | |
# Настройки TLS | |
#tls_certificate = CONFIG_PREFIX/certs/mailed.crt | |
#tls_privatekey = CONFIG_PREFIX/certs/mailed.key | |
#tls_advertise_hosts = * | |
#tls_verify_certificates = * | |
# Следующая опция закомментирована, но весьма полезна, | |
# позволяя авторизироваться | |
# только через безопасный ssl канал | |
#auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}} | |
###################################################################### | |
# ACL CONFIGURATION # | |
# Specifies access control lists for incoming SMTP mail # | |
###################################################################### | |
begin acl | |
# Этот список доступа описывает проверки, осуществляемые при вызове любой RCPT | |
# команды | |
acl_check_rcpt: | |
# принимать сообщения которые пришли с локалхоста, | |
# не по TCP/IP | |
accept hosts = : | |
# разрешаем почту от корпоративных сетей | |
accept hosts = 127.0.0.1 : 192.168.0.0/16 | |
# проверка на backresolv | |
# deny message = "No backresolv for your IP!" | |
# !senders = : | |
# condition = ${if eq{$sender_host_name}{}{yes}{no}} | |
# Запрещаем письма содержащие в локальной части | |
# символы @; %; !; /; |. Учтите, если у вас было | |
# `percent_hack_domains` то % надо убрать. | |
# Проверяются локальные домены | |
deny message = "Forbidden characters in the recepient name" | |
domains = +local_domains | |
local_parts = ^[.] : ^.*[@%!/|] | |
# Проверяем недопустимые символы для | |
# нелокальных получателей: | |
deny message = "Forbidden characters in the recepient name" | |
domains = !+local_domains | |
local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ | |
# Принимаем почту для постмастеров локальных доменов без | |
# проверки отправителя (я закомментировал, т.к. это - | |
# основной источник спама с мой ящик). | |
# accept local_parts = postmaster | |
# domains = +local_domains | |
# Запрещщаем, если невозможно проверить отправителя | |
# (отсутствует в списке локальных пользователей) | |
# У себя я это закоментил, по причине, что некоторые | |
# железяки (принтеры, & etc) и программы (Касперский, DrWEB) | |
# умеют слать почту, в случае проблем но не умеют ставить | |
# нужного отправителя. Такие письма эта проверка не пускает. | |
# require verify = sender | |
# Запрещщаем тех, кто не обменивается приветственными | |
# сообщениями (HELO/EHLO) | |
deny message = "HELO/EHLO should be configured" | |
condition = ${if eq{$sender_helo_name}{}{yes}{no}} | |
# Принимаем сообщения от тех, кто аутентифицировался: | |
# Вообще, большинство конфигов в рунете - это один и тот же | |
# конфиг написанный Ginger, в котором этот пункт расположен | |
# внизу. Но при таком расположении рубятся клиенты с adsl, | |
# ppp, и прочие зарезанные на последующих проверках. Но это | |
# жа неправильно! Этом мои пользователи из дома! Потому | |
# я это правило расположил до проверок. | |
accept authenticated = * | |
# Рубаем нах, тех, кто подставляет свой IP в HELO | |
deny message = "Your IP address should not be presented as HELO!" | |
hosts = *:!+relay_from_hosts | |
condition = ${if eq{$sender_helo_name}\ | |
{$sender_host_address}{true}{false}} | |
# Рубаем тех, кто в HELO пихает мой IP | |
deny condition = ${if eq{$sender_helo_name}\ | |
{$interface_address}{yes}{no}} | |
hosts = !127.0.0.1 : !localhost : * | |
message = "Don't try to cheat me with my own address" | |
# Рубаем тех, кто в HELO пихает только цифры | |
# (не бывает хостов ТОЛЬКО из цифр) | |
deny condition = ${if match{$sender_helo_name}\ | |
{\N^\d+$\N}{yes}{no}} | |
hosts = !127.0.0.1:!localhost:* | |
message = "HELO can't contain numbers only!" | |
# Рубаем хосты типа *adsl*; *dialup*; *pool*;.... | |
# Нормальные люди с таких не пишут. Если будут | |
# проблемы - уберёте проблемный пункт (у меня клиенты | |
# имеют запись типа asdl-1233.zone.su - я ADSL убрал...) | |
# deny message = "I don't like your hostname..." | |
# condition = ${if match{$sender_host_name} \ | |
# {adsl|dialup|pool|peer|dhcp} \ | |
# {yes}{no}} | |
# Рубаем тех, кто в блэк-листах. Серваки перебираются | |
# сверху вниз, если не хост не найден на первом, то | |
# запрашивается второй, и т.д. Если не найден ни в одном | |
# из списка - то почта пропускается. | |
deny message = "host in blacklist- $dnslist_domain \n $dnslist_text" | |
dnslists = opm.blitzed.org : \ | |
proxies.blackholes.easynet.nl : \ | |
cbl.abuseat.org : \ | |
bl.spamcop.net : \ | |
bl.csma.biz : \ | |
dynablock.njabl.org : | |
# dnslists = : | |
# Задержка. (это такой метод борьбы со спамом, | |
# основанный на принципе его рассылки) На этом рубается | |
# почти весь спам. Единственно - метод неприменим на | |
# реально загруженных MTA - т.к. в результате ему | |
# приходится держать много открытых соединений. | |
# но на офисе в сотню-две человек - шикарный метод. | |
# | |
# более сложный вариант, смотрите в статье по exim и | |
# курьер имап. Т.к. там метод боле умный (просто правил | |
# больше :), то можно и на более загруженные сервера ставить) | |
warn | |
# ставим дефолтовую задержку в 20 секунд | |
set acl_m0 = 10s | |
warn | |
# ставим задержку в 0 секунд своим хостам и | |
# дружественным сетям (соседняя контора :)) | |
hosts = +relay_from_hosts | |
set acl_m0 = 0s | |
# Проверка получателя в локальных доменах. | |
# Если не проходит, то проверяется следующий ACL, | |
# и если непрошёл и там - deny | |
accept domains = +local_domains | |
endpass | |
message = "We don't have this address here" | |
verify = recipient | |
# Проверяем получателя в релейных доменах | |
# Опять-таки если не проходит -> следующий ACL, | |
# и если непрошёл и там - deny | |
accept domains = +relay_to_domains | |
endpass | |
message = "I don't route this address..." | |
verify = recipient | |
# Разрешаем почту от доменов в списке relay_from_hosts | |
accept hosts = +relay_from_hosts | |
deny hosts =!+relay_from_hosts | |
# Реализация нашего бан-листа | |
deny hosts = +host_reject | |
message = You are banned. Go away. | |
# еще боримся со спамом и вирусами | |
deny message = We don't accept ".$found_extension". \ | |
You should ZIP it first. | |
demime = bat:btm:cmd:com:cpl:dll:exe:lnk:msi:pif:prf:reg:scr:vbs:url | |
# Если неподошло ни одно правило - чувак явно ищет | |
# открытый релей. Пшёл прочь. :) | |
deny message = "This is not an open relay. Fuck you" | |
# Список доступа для проверки mime частей сообщения | |
acl_check_mime: | |
# Произодим декодирование mime сообщений. Полезно для дальнейшей проверки на | |
# вирусы | |
warn decode = default | |
# Можно очень быстро отсеять сообщения, просто запретив некоторые mime | |
# вложения, чаще всего содержащие вирусы, хотя, конечно, это не панацея | |
deny message = Blacklisted file extension detected | |
condition = ${if match \ | |
{${lc:$mime_filename}} \ | |
{\N(\.wav|\.cpl|\.pif|\.bat|\.scr|\.lnk|\.com)$\N} \ | |
{1}{0}} | |
# Много ли у нас людей, знающих китайский? | |
# А вот китайского спама это поубавит | |
# :) | |
deny message = Sorry, no one speaks chinese here | |
condition = ${if eq{$mime_charset}{gb2312}{1}{0}} | |
accept | |
# Проверка содержимого на вирусы и спам | |
acl_check_data: | |
accept condition = ${if >={$message_size}{500k}{yes}{no}} | |
warn message = X-Spam-Score: $spam_score ($spam_bar) | |
spam = nobody:true | |
warn message = X-Spam-Report: $spam_report | |
spam = nobody:true | |
condition = ${if >{$spam_score_int}{0}{true}{false}} | |
warn message = X-Spam-Status: Yes | |
spam = nobody:true | |
condition = ${if >{$spam_score_int}{50}{true}{false}} | |
deny message = This message scored $spam_score spam points. | |
spam = nobody:true | |
condition = ${if >{$spam_score_int}{70}{true}{false}} | |
# Мы не запрещаем письма со спамом, а просто добавляем заголовок, | |
# содержащий количество спамерских очков, а пользователь на своей | |
# стороне уже просто настраивает свои фильтры. Так мы исключаем жалобы | |
# со стороны пользователей о потерянных письмах | |
#warn message = X-Spam-Score: $spam_score ($spam_bar) | |
#spam = nobody:true | |
# Добавляем заголовки, указывающие, что письма были проверены | |
# spamasssasin'ом | |
#warn message = X-Spam-Scanned: Yes | |
#warn message = X-Spam-Scanner: SpamAssassin running | |
# Вот что-что, а вирусы нам не нужны. | |
deny message = Message rejected: virus found. Your message was successfully trashed. | |
hosts = * | |
malware = * | |
accept | |
###################################################################### | |
# ROUTERS CONFIGURATION # | |
# Specifies how addresses are handled # | |
###################################################################### | |
# THE ORDER IN WHICH THE ROUTERS ARE DEFINED IS IMPORTANT! # | |
# An address is passed to each router in turn until it is accepted. # | |
###################################################################### | |
begin routers | |
# Роутер, осуществляющий поиск по MX записям в DNS | |
dnslookup: | |
driver = dnslookup | |
domains = ! +local_domains | |
transport = remote_smtp | |
ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 | |
no_more | |
# Все останльные роутеры обслуживают доставку локальной почты | |
# Драйвер алиасов пользователя. Обратите внимание на lookup в pgsql базе. Что | |
# интересно, этот lookup работает даже для иерархических алиасов | |
# Также определяются транспорты | |
# для передачи почты в файл (>/path/to/file) и в pipe | |
# (|/usr/local/libexec/slocal) | |
system_aliases: | |
driver = redirect | |
allow_fail | |
allow_defer | |
data = ${lookup pgsql{select alias from aliases \ | |
where mail ='$local_part'}{$value}fail} | |
user = mail | |
group = mail | |
file_transport = address_file | |
pipe_transport = address_pipe | |
#routers переадресация почты | |
userforward: | |
driver = redirect | |
allow_fail | |
allow_defer | |
data = ${lookup pgsql{SELECT recipients FROM userforward \ | |
WHERE local_part='${local_part}'}} | |
############################################################################ | |
# Локальная доставка, если данный пользователь найдем в базе | |
localuser: | |
driver = accept | |
condition = ${lookup pgsql {select uid from \ | |
accounts where login = '$local_part'}{yes}{no}} | |
transport = local_delivery | |
cannot_route_message = Unknown user | |
###################################################################### | |
# TRANSPORTS CONFIGURATION # | |
###################################################################### | |
# ORDER DOES NOT MATTER # | |
# Only one appropriate transport is called for each delivery. # | |
###################################################################### | |
begin transports | |
# Драйвер для доставки через соединения с удаленными smtp серверами | |
remote_smtp: | |
driver = smtp | |
dkim_domain = domain.ru | |
dkim_selector = dkim | |
dkim_private_key = /etc/exim4/dkim/domain.ru.pem | |
# Этот транспорт доставляет почту в локальные maildir'ы. | |
# Путь к maildir хранится | |
# опять же в таблице accounts. Разрешения на директорию 0770 для возможности | |
# работы с данными директориями imap сервера. При этом владельцем является | |
# группа и пользователь из accounts | |
#(потому при вставлении записей в эту таблицу | |
# надо начинать значения uid с достаточно большого числа, например, 2000 и | |
# пересекаться с реальными пользователями оно должно только если реальному | |
# пользователю нужен локальный доступ к maildir'у). | |
# Также из таблицы accounts извлекается данные о размере квоты, и | |
# устанавливается порог в 75% от квоты, когда пользователю посылается указанное | |
# предупреждение об подходе к порогу квоты | |
local_delivery: | |
driver = appendfile | |
directory = ${lookup pgsql{select maildir from \ | |
accounts where login = '$local_part'}{$value}fail} | |
create_directory | |
directory_mode = 0770 | |
maildir_format | |
delivery_date_add | |
envelope_to_add | |
return_path_add | |
group = mail | |
user = mail | |
mode = 0660 | |
no_mode_fail_narrower | |
quota = ${lookup pgsql{select mailquota from \ | |
accounts where login = '$local_part'}{$value}fail}M | |
quota_warn_message = "\ | |
To: $local_part\n\ | |
Cc: admin@domain.ru\n\ | |
From: admin@domain.ru\n\ | |
Subject: Your maildir is going full\n\ | |
This message is automaticaly gnerated by your mail server.\n\ | |
This means, that your mailbox is 75% full. If you would \n\ | |
override this limit new mail would not be delivered to you!\n" | |
quota_warn_threshold = 75% | |
# Транспорт, осуществляющий доставку в pipe | |
address_pipe: | |
driver = pipe | |
return_output | |
# Транспорт, осуществляющий доставку прямо в файл | |
address_file: | |
driver = appendfile | |
delivery_date_add | |
envelope_to_add | |
return_path_add | |
# Этот транспорт используется для автоматического ответа на сообщения | |
#об ошибках | |
address_reply: | |
driver = autoreply | |
###################################################################### | |
# RETRY CONFIGURATION # | |
###################################################################### | |
begin retry | |
# Настройки по умолчанию, которые я не трогал, управляют интервала повторной | |
# передачи сообщений | |
# This single retry rule applies to all domains and all errors. It specifies | |
# retries every 15 minutes for 2 hours, then increasing retry intervals, | |
# starting at 1 hour and increasing each time by a factor of 1.5, up to 16 | |
# hours, then retries every 6 hours until 4 days have passed since the first | |
# failed delivery. | |
# Address or Domain Error Retries | |
# ----------------- ----- ------- | |
* * F,2h,15m; G,16h,1h,1.5; F,4d,6h | |
###################################################################### | |
# AUTHENTICATION CONFIGURATION # | |
###################################################################### | |
# Описания аутентификации | |
begin authenticators | |
# CRAM-MD5 аутентификация, требует наличия пароля в открытом виде, имя | |
# пользователя должно быть в формате user, как оно хранится в таблице | |
# accounts | |
lookup_cram: | |
driver = cram_md5 | |
public_name = CRAM-MD5 | |
server_secret = ${lookup pgsql {select password from accounts where login = replace('$1', '@domain.ru', '');}{$value}fail} | |
server_set_id = $1 | |
# LOGIN аутентификация - не требует хранения пароля в открытом виде, однако, по | |
# сети пароль передается в открытом виде - требуется лишь выполнение условия | |
# server_condition - $1 - имя пользователя, а $2 - пароль. LOGIN безопасен | |
# только при установлении ssl соединения. | |
login: | |
driver = plaintext | |
public_name = LOGIN | |
server_prompts = Username:: : Password:: | |
server_condition = ${lookup pgsql {select login \ | |
from accounts where login = replace('$1', '@domain.ru', '') and password='$2'}{yes}{no}} | |
server_set_id = $1 | |
# End of Exim configuration file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment