Debian, exim4. Настраиваем SMTP сервер для нашего веб-сервера

Опубликовано:

В данной статье я рассмотрю один из самых быстрых способов настройки smtp-демона для нашего вебсервера. Если вам нужен сервер, который ещё и должен принимать почту — проходите мимо. Эта статья подойдёт для тех, кто принимает почту гуглом или яндексом (на своём домене, само собой), но не хочет дергать их SMTP серверы, чтобы слать письма.

Внимание! Этот мануал описывает то, как настроить SMTP сервер (сервер отправки писем), отправить письмо через который можно только с того же сервера (то есть с localhost). При этом не будет требоваться никакой авторизации! Будьте внимательны.

lamp-server:~# apt-get install exim4
lamp-server:~# dpkg-reconfigure exim4-config
 Отвечаем на вопросы:
 General type of mail configuration: internet site; mail is sent and received directly using SMTP
 System mail name: желательно вписываем сюда обратную зону для вашего IP интерфейса eth0. Либо просто full hostname сервера (mail.debian.pro, например)
 IP-addresses to listen on for incoming SMTP connections: 127.0.0.1
 Other destinations for which mail is accepted: оставляем пустым. Это список локальных доменов — нам он не нужен.
 Domains to relay mail for: если не знаете зачем оно, то оставляйте пустое поле
 Machines to relay mail for: аналогично, если не знаем — оставляем пустым
 Keep number of DNS-queries minimal (Dial-on-Demand)? No
 Delivery method for local mail: неважно что
 Split configuration into small files? Yes
 Ещё могут спросить, кому перенаправлять почту локального админа. Впишите свою почту, например — туда будут отправляться письма от крона.

Если необходимо настроить отправку почты с нашего сервера через почту для доменов от Яндекса.

Type Machine handling outgoing mail for this host (smarthost): smtp.yandex.ru:587

прописываем пароль для ящика в файле /etc/exim4/passwd.client:

smtp.yandex.ru:no-reply@yandex.ru:СВОЙ_ПАРОЛЬ

Если   почтовый сервер яндекс ругается, что нужно заполненное поле FROM. Прописываем его в файле /etc/exim4/conf.d/rewrite/00_exim4-config_header:

begin rewrite *@* no-reply@yandex.ru Ffr

Теперь вы можете отправлять письма при помощи апача (чуть позже опишу как настроить) или командой вида echo «Testing Exim» | mail -s Test vlad@debian.pro

Ну и да — не стоит спамить 😉
Так же не используйте этот метод для тех случаев, когда доступ к серверу по ssh (или даже по ftp в каталоги, доступные по http) имеют доступ люди, которые могут начать спамить.

Как ограничить список ящиков, которым можно отправлять письма с сервера

В конце выбираем «Split configuration into small files: yes» — так удобнее будет.

Теперь создаём необходимые нам файлы:

root@server:~# touch /etc/exim4/allowed.domains; touch /etc/exim4/allowed.mails
 root@server:~# touch /etc/exim4/conf.d/router/01_exim4-outgoing-filter

В файл /etc/exim4/conf.d/router/01_exim4-outgoing-filter пишем правила, которые будут применяться к исходящей почте:

check_outgoing_from_header:
 driver = redirect
 domains = ! +local_domains
 condition = ${if !match {$header_from:}{$sender_address}}
 allow_fail
 data = :fail: You can not send mail from here with From: $header_from as sender: $sender_address
check_outgoing:
 driver = redirect
 domains = ! +local_domains
 senders = ! : ! *@lsearch;/etc/exim4/allowed.domains : ! lsearch;/etc/exim4/allowed.mails
 allow_fail
 data = :fail: You can not send mail from this mailbox from this server.

Если вы всё же выбрали «Split configuration into small files: no», то эти правила нужно вписать сразу после строчки

begin routers

в конфиге exim.

Это правило позволит отправлять только почту с любых ящиков доменов, которые перечислены в файле /etc/exim4/allowed.domains, или ящиков, перечисленных в файле /etc/exim4/allowed.mails. Обратите внимание на «или» — если домен написан в первом файле, то во втором смысле перечислять его ящики нет смысла. А если вам нужно разрешить отправку только с одного ящика домена — то не нужно писать его в allowed.domains, нужно написать конкретный ящик в allowed.mails

Ящики и домены нужно писать целиком (без регулярок, звездочек и прочего) по одному на строчку:

root@server:~# cat /etc/exim4/allowed.domains
 adminunix1.ru
 adminunix2.ru
 root@server:~# cat /etc/exim4/allowed.mails
 noreply@adminunix3.ru
 robot@adminunix3.ru
 webmaster@adminunix3.ru

Проверить можно так:

root@server:~# echo test | sendmail -f noreply@somepieceofshit.com youremail@adminunix.ru

где noreply@somepieceofshit.com — адрес отправителя, а youremail@adminunix.ru — адрес получателя.

В /var/log/exim4/mainlog в ответ на это вы увидите что-то в духе:

2014-11-20 17:10:47 1VphsU-0007JA-Vr ** youremail@adminunix.ru R=check_outgoing: You can not send mail from this mailbox from this server.

Как работают эти правила. Для начала стоит упомянуть, что у писем есть 2 важных заголовка — smtp.sender и header From:. smtp.sender, по сути, smtp-аккаунт, с которого происходит отправка письма. Поле From может содержать произвольную чушь, в том числе и совершенно левый ящик. Например, можно отправить письмо с smtp-аккаунта blah@someshit.com, но в поле From поставить admin@gmail.com. Чтобы посмотреть, кто реально отправил письмо — нужно будет лезть в его исходники. Большинство почтовых провайдеров при несовпадении этих полей кладёт такое письмо в спам. А спамеры, в свою очередь, шлют тонны писем с несовпадающими заголовками. Кхе.
Собственно, правило check_outgoing_from_header проверяет, чтобы в заголовке From содержалось имя smtp-аккаунта. Тут стоит упомянуть, что заголовок From: в нормальном письме выглядит примерно так — «inkvizitor68sl <root@vlad.pro>» (то есть помимо ящика содержит и имя/фамилию отправителя/ник или какую-нибудь другую чушь, которую он соизволит вписать туда). Именно поэтому, полагаться здесь на точное совпадение полей нельзя.

Второе правило (check_outgoing) проверяет, что значение поля sender (он же — smtp.sender, он же — smtp.name) подходит под одно из трех правил. Первое — sender пустой (сюда входят письма, сгенерированные самим почтовым сервером — например, отлупы о недоставке писем). Второе — sender совпадает с шаблоном *@любойдоменизспискаallowed.domains. Третье — поле sender целиком (пользователь@домен) указано в allowed.mails.

Так же учитывайте, что строчка в конфиге apache2 для вхоста вида:

php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f noreply@adminunix.ru"

выставляет значения поля sender в noreply@adminunix.ru (при том обойти это из самих скриптов уже не получится, только через htaccess). Поэтому, если ваша CMS шлет письма от ящика, отличного от указанного в этом месте — письма слать она перестанет.

Само собой, такая защита обходится (достаточно начать рассылать спам от «доверенных» ящиков) — авторизации всё ещё не требуется. Но мы можем в любой момент выключить ящик до того момента, пока не разберемся, что послужило источником спама на сервере.

В файле конфигурации php поправим sendmail_path.

В Debian: /etc/php5/apache2/php.ini или /etc/php4/apache2/php.ini

< в других дистрибутивах >

sendmail_path = /usr/sbin/exim4 -t

Правильная настройка SPF

Если кратко, то SPF — это способ борьбы со спамом.

Мы собираемся отправлять почту с сервера, PTR IP которого не равен одной из MX-записей сервера, а так же в большинстве случаев PTR IP не равен самому нашему домену (не всегда хостеры соглашаются менять PTR). В этом случае вероятность попадания писем в спам повышается. Но есть хороший способ ее понизить: указать правильно запись SPF нашего домена.

SPF-запись — это обыкновенная запись доменной зоны, имеющая тип TXT. Узнать текущее ее значение для домена можно с помощью команды host в Linux:

$ host -t TXT adminunix.ru
 adminunix.ru TXT record currently not present

В данном примере SPF-запись не задана. Зададим ее. С моего домена почта может отправляться с серверов Gmail и с моего сервера. Для начала узнаем, какой PTR моего сайта (adminunix.ru):

$ nslookup adminunix.ru
 Server:      194.224.52.4
 Address:     194.224.52.4#53
 Non-authoritative answer:
 Name:     adminunix.ru
 Address:  93.174.6.118

IP-адрес моего сервера 93.174.6.118. Узнаем PTR:

$ nslookup 93.174.6.118
 Server:      194.224.52.4
 Address:     194.224.52.4#53
 Non-authoritative answer:
 118.6.174.93.in-addr.arpa name = server.adminunix.ru.

Видно, что PTR IP, к которому привязан мой домен (IP моего сервера) — server.adminunix.ru.

v=spf1 a mx ptr include:_spf.google.com ~all

По порядку:

v=spf1 — версия SPF (первая);
a — разрешение отправлять почту с IP, указанного в A-записи домена (собственно с сервера, на который ваш домен ссылается);
mx — разрешение отправлять почту с IP, указанных в MX-записях домена (в нашем случае сервера Gmail);
ptr — разрешение отправлять почту с IP, PTR-запись которых содержит ваш домен (т.е. сам домен и поддомены);
include:_spf.google.com — подключение разрешений для серверов отправки почту Gmail (совсем не обязательно почта будет слаться с серверов, указанных в MX-записи);
~all — нейтральная реакция на всю остальную почту; здесь можно указать -all, что будет значить, что почта, не попадающая под эти правила, — спам.
Если вы хотите отправлять почту с сервера, не попадающего под все эти правила, его можно указать по IP или домену PTR, например:

v=spf1 a mx ptr ptr:example.com include:_spf.google.com ~all

Запись указывается для вашего домена соответствующим образом, который определяет владелец DNS-сервера. Обычно сервером заведует хостер и предоставляет возможность вносить изменения в DNS-зоны через панель хостинга. Либо сам по запросу в саппорт меняет запись. В зональном файле должна появиться запись вида:

adminunix.ru.      TXT      v=spf1 a mx ptr include:_spf.google.com ~all

После обновления зоны host выдаст следующее:

$ host -t TXT adminunix.ru
adminunix.ru      TXT      »v=spf1 a mx ptr include:_spf.google.com ~all»

PHP mail ()

После всей этой настройки функция mail () в PHP начнет слать почту через ваш локальный сервер на законных основаниях для антиспам-ботов. Но косяк будет в том, что в поле отправителя будет фигурировать адрес системного пользователя www-data@localdomain. Нас это не устраивает. Чтобы почта правильно слалась из mail (), необходимо использовать ее дополнительный параметр.

bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )

Именно $additional_parameters нас и интерисует. В него надо передавать реального отправителя:

mail ($to, $subject, $message, $additional_headers, $additional_parameters.» -frealsender@adminunix.ru»);

Указывается отправитель слитно с параметром -f.

Теперь отправленные через mail () письма будут абсолютно адекватны (при условии, что вы указываете все нужные SMTP-заголовки, вроде “FROM:”, “TO:” и т.д.).

А если несколько сайтов с разными IP (настройка Exim для отправки писем с разных IP)?

Мы хотим использовать локальный SMTP-сервер для отправки почты со всех сайтов на сервере. Никаких проблем нет, если настроен Exim правильно (см. выше). Но проблема появляется, если разные сайты работают на разных IP. Мы не хотим в почте «палить» то, что все наши сайты живут на одном сервере. Но Exim по умолчанию шлет всю почту с основного (первого) IP сетевого интерфейса, а этот IP всем получателям в SMTP-заголовках “Received:” письма. Кроме того, там указывается и имя сервера, которые мы в случае с разными сайтами на сервере выбрали нейтральными.

Чтобы не «палить» IP сервера, нужно отсылать письмо на удаленный сервер с IP, равного A-записи домена сайта. Делается это несложно путем изменения конфига Exim. Внесем изменения в настройки транспорта SMTP Exim. Если вы выбрали монолитный конфиг, то нужно отредактировать файл:

# nano /etc/exim4/exim4.conf.template

local_interfaces = a.a.a.a : b.b.b.b : c.c.c.c : d.d.d.d
smtp_active_hostname = ${lookup{$interface_address}lsearch{/etc/exim4/domain2ip}{$value}}
smtp_banner = «$smtp_active_hostname ESMTP $tod_full»

#mcedit /etc/exim4/conf.d/transport/30_exim4-config_remote_smtp

Находим в файле строку “remote_smtp:” (поиск в nano — F6). Добавляем в конец этого блока:

interface = «${lookup{$sender_address_domain}lsearch{/etc/exim4/domain2ip}{$value}}»
helo_data = «$sender_address_domain»

Это значит, что при отправке письма нужно определить домен отправителя почты (для sender@adminunix.ru это adminunix.ru) и отправить почту с IP, к которому этот домен привязан. Само собой разумеется, что домен должен быть привязан к серверу, где установлен Exim.

Так же нужно создать файл в любом месте файл привязки доменов к IP (у домена может быть несколько IP, так что просто lookup-ить его не прокатит). Я выбрал для файла место: /etc/exim4/domain2ip

# nano /etc/exim4/domain2ip

Туда вводим наши домены по шаблону:

adminunix.ru: 123.123.123.123
vasya.ws: 123.123.123.124

Не забудьте дописать домен в файл в случае появления нового сайта.
Кстати, строку helo_data = «$sender_address_domain» можно добавить в файл даже если у вас один IP на все сайты. Тогда в команде HELLO SMTP-протокола (а, следовательно, и в заголовках писем) будет фигурировать ваш домен.

Идея с указанием интерфейса взята отсюда: http://www.directadmin.com/forum/showthread.php?t=36468

Проверка

Остается проверить, чтобы все ваши настройки работали верно. Для этого просто отправим письмо с локального сервера через консоль.

$ mail -a «From:feedbee@adminunix.ru» -s Test feedbee@gmail.com — -ffeedbee@adminunix.ru
Test
Cc:

Проверяем отосланное письмо в ящике получателя:

А вот текст SMTP-протокола:

Delivered-To: feedbee@gmail.com
 Received: by 10.236.109.139 with SMTP id s11cs13826yhg;
 Wed, 24 Nov 2010 02:18:14 -0800 (PST)
 Received: by 10.227.145.134 with SMTP id d6mr9025492wbv.195.1290593893066;
 Wed, 24 Nov 2010 02:18:13 -0800 (PST)
 Return-Path: feedbee@adminunix.ru
 Received: from adminunix.ru (server.adminunix.ru [93.174.6.118])
 by mx.google.com with ESMTP id b7si11085685wer.164.2010.11.24.02.18.12;
 Wed, 24 Nov 2010 02:18:12 -0800 (PST)
 Received-SPF: pass (google.com: domain of feedbee@adminunix.ru designates 93.174.6.118 as permitted sender) client-ip=93.174.6.118;
 Authentication-Results: mx.google.com; spf=pass (google.com: domain of feedbee@adminunix.ru designates 93.174.6.118 as permitted sender) smtp.mail=feedbee@adminunix.ru
 Received: from root by server.adminunix.ru with local (Exim 4.69)
 (envelope-from <feedbee@adminunix.ru>)
 id 1PLCQW-0006KD-Pc
 for feedbee@gmail.com; Wed, 24 Nov 2010 10:18:12 +0000
 To: feedbee@gmail.com
 Subject: Test
 From:feedbee@adminunix.ru
 Message-Id: E1PLCQW-0006KD-Pc@server.adminunix.ru
 Date: Wed, 24 Nov 2010 10:18:12 +0000

Test

P.S. Чтобы отправленная почта не попадала в спам, отправляйте письма только от имени реально существующих на серверах Gmail адресов на ваших доменах. Туда же повалятся уведомления о недоставках.

Чтобы при отправке писем root'у, как это любят делать многие утилиты (например smartd), письмо уходило не на root@example.org, а на admin@adminunix.ru. Я изменил /etc/aliases:

# cat /etc/aliases
 # /etc/aliases
 mailer-daemon: postmaster
 postmaster: root
 nobody: root
 hostmaster: root
 usenet: root
 news: root
 webmaster: root
 www: root
 ftp: root
 abuse: root
 noc: root
 security: root
 root: admin@adminunix.ru

В файл /etc/exim4/conf.d/rewrite/00_exim4-config_header пишем правила,

root@example.org admin@adminunix.ru rTbtc

перезапускаем exim

service exim4 restart
 # exim -brw root
 sender: root@example.org
 from: root@example.org
 to: admin@adminunix.ru
 cc: admin@adminunix.ru
 bcc: admin@adminunix.ru
 reply-to: admin@adminunix.ru
 env-from: admin@adminunix.ru
 env-to: admin@adminunix.ru

А для затирания Received из заголовков писем с ip серверов которые коннектятся к нашему почтовику надо добавить вот эту строчку:

/etc/exim4/conf.d/transport/30_exim4-config_remote_smtp_smarthost

headers_remove = Received

Понравилась статья, расскажи о ней друзьям, нажми кнопку!