Применение ограничений (smtpd_*_restrictions) в Postfix
Сразу оговорюсь, статья не моя, взята отсюда. Копирую к себе с целью сохранения важного материала, т.к. некоторый контент имеет тенденцию исчезать с просторов Internet’а. После прочтения данного материала у меня наконец-то в голове полностью все встало на места в понимании работы Postfix! |
Данный материал является вольным переводом части 11-й главы («Blocking Unsolicited Bulk Email») книги “Postfix”, Kyle D.Dent, O’ Reilly, ISBN 0–596–00212–2, и переосмыслением документации postfix (man 5 postconf, README_FILES) см. данный материал.
Оглавление документа
- Правила для ограничений на подключение (smtpd_client_restrictions) и рекомендации по их использованию.
- Общие рекомендации по настройке ограничений.
- Принципы построения ограничений на соединение.
В postfix (v2.2) имеется 7 (какое приятное число! :)) ограничений, работающих на уровне smtpd, т.е. ДО проверки заголовков и тела писем. Эффективное использование этих ограничений резко снижает трафик почтового сервера, поскольку письма могут отбрасываться еще на этапе RCPT, т.е. дело не доходит даже загрузки тела письма!
Вот все ограничения в порядке их отработки postfix’ом со значениями по умолчанию и входными данными для проверки:
1. smtpd_client_restrictions (empty) – IP-адрес и (если возможно) доменное имя клиентского компьютера (или другого почт.сервера), который соединяется с сервером postfix для отправки письма.
2. smtpd_helo_restrictions (empty) – имя компьютера и (если возможно) его IP-адрес по имени, переданному в команде HELO/EHLO hostname.
3. smtpd_etrn_restrictions (empty) – то же, что и для 1), 2).
4. smtpd_sender_restrictions (empty) – адрес отправителя, указанный в команде MAIL FROM:<sender>
.
5. smtpd_recipient_restrictions (permit_mynetworks, reject_unauth_destination) – адрес получателя, указанный в команде RCPT TO:<recipient>
.
6. smtpd_data_restrictions (empty) – то же, что и для 1)…5) +специальные правила (см.далее).
7. smtpd_end_of_data_restrictions (empty) – то же, что и для 1)…6).
Именно так они и срабатывают: (1)->(2)->(3)->…->(7). Каждое ограничение может состоять из набора правил, либо относящихся ТОЛЬКО к данному ограничению, либо ОБЩИХ ПРАВИЛ (generic), либо правил, относящихся к ограничению, стоящему СЛЕВА (ВЫШЕ) в порядке их обработки. Например, в ограничении sender_restrictions допускается использовать правила, предназначенные как собственно для ограничения sender_restrictions, так и, например, для client_restrictions, и helo_restrictions.
Правила в каждом ограничении работают в том порядке, каком они для данного ограничения прописаны – последовательно друг за другом.
Все правила по результатам проверки (за исключением правил вида check_.*_access, которые могут и больше – (см.далее!) возвращают либо REJECT, либо OK, либо DUNNO.
Если правило вернуло REJECT, никаких проверок в данном ограничении больше не проводится, и, более того, никаких других проверок в последующих ограничениях не проводится также. Письмо отбрасывается! На самом деле, происходит рассоединение с клиентским компьютером или другим почтовым сервером с выдачей ему соответствующего кода завершения).
Если правило вернуло OK, проверка считается успешной, и все остальные правила В ДАННОМ ОГРАНИЧЕНИИ не проверяются. Происходит переход на следующее ограничение.
Если правило вернуло DUNNO, проверка продолжается в следующем правиле для данного ограничения. Если ВСЕ правила пройдены с результатом DUNNO, считается, что проверка для данного ограничения завершилась УСПЕШНО, и происходит переход на следующее ограничение.
Следует отметить следующее:
1) Правила, начинающиеся с reject_.* возвращают либо REJECT, либо DUNNO.
2) Правила, начинающиеся с permit_.* возвращают либо OK, либо DUNNO.
3) Правила, вида check_.*_access могут возвращать REJECT, OK или DUNNO, а кроме того, цифровые коды – 4NN «временные трудности, попробуете послать письмо позже», 5NN «тяжелая проблема у меня или, скорее всего, у Вас», либо «видеть Вас не желаю, и не шлите мне ничего».
Еще в check_.*_access могут указываться последующие действия для менеджера очередей postfix (qmgr) – FILTER, HOLD, REDIRECT, отложенные reject и permit (DEFER_IF_REJECT и DEFER_IF_PERMIT), «глотание» писем без их реальной доставки (DISCARD), и другие интересные вещи… Все это здорово, и, возможно, где-то даже применяется, но в рассматриваемом контексте (а именно, борьба со спамом и ограничения по доступу) будем учитывать только REJECT, OK или DUNNO.
Общий подход таков, что если на выходе check_.*_access получается что-нибудь отличное от явных REJECT, OK или DUNNO, то это – DUNNO, кроме случаев DEFER_IF_REJECT и DEFER_IF_PERMIT. Цифровые коды любого вида кроме 4NN и 5NN трактуются как OK, а 4NN и 5NN считаются за REJECT, как и DISCARD. DEFER_IF_REJECT обычно используют, когда возникают проблемы в «белых списках», т.е., например, Вы вроде правильно указали, что с данного сервера письма должны приниматься, а они все равно не проходят из-за каких-либо дальнейших правил или ограничений. В этом случае клиенту (другому почтовому серверу) сообщается о временной проблеме (т.е. «попробуйте позже»). DEFER_IF_PERMIT используется с точностью наоборот, т.е. когда возникают проблемы с «черными списками».
Ну вот, остается только привести правила, относящиеся к каждому ограничению. Вот они (2.2 означает, что данное правило поддерживается, начиная с версии 2.2.x):
0) общие правила (generic):
check_policy_service
defer
defer_if_permit
defer_if_reject
permit
reject
warn_if_reject
1) smtpd_client_restrictions:
check_ccert_access (2.2)
check_client_access
permit_inet_interfaces (2.2)
permit_mynetworks
permit_sasl_authenticated
permit_tls_all_clientcerts (2.2)
permit_tls_clientcerts (2.2)
reject_rbl_client
reject_rhsbl_client
reject_unknown_client
2) smtpd_helo_restrictions:
check_helo_access
check_helo_mx_access
check_helo_ns_access
reject_invalid_hostname
reject_non_fqdn_hostname
reject_unknown_hostname
+ generic
+ smtpd_client_restrictions
3) smtpd_etrn_restrictions:
check_etrn_access
+ generic
+ smtpd_client_restrictions
+ smtpd_helo_restrictions
4) smtpd_sender_restrictions:
check_sender_access
check_sender_mx_access
check_sender_ns_access
reject_authenticated_sender_login_mismatch
reject_non_fqdn_sender
reject_rhsbl_sender
reject_sender_login_mismatch
reject_unknown_sender_domain
reject_unlisted_sender
reject_unverified_sender
+ generic
+ smtpd_client_restrictions
+ smtpd_helo_restrictions
+ smtpd_etrn_restrictions
5) smtpd_recipient_restrictions:
check_recipient_access
check_recipient_mx_access
check_recipient_ns_access
permit_auth_destination
permit_mx_backup
reject_non_fqdn_recipient
reject_rhsbl_recipient
reject_unauth_destination
reject_unknown_recipient_domain
reject_unlisted_recipient
reject_unverified_recipient
+ generic
+ smtpd_client_restrictions
+ smtpd_helo_restrictions
+ smtpd_etrn_restrictions
+ smtpd_sender_restrictions
6) smtpd_data_restrictions:
reject_multi_recipient_bounce
reject_unauth_pipelining
+ generic
+ smtpd_client_restrictions
+ smtpd_helo_restrictions
+ smtpd_etrn_restrictions
+ smtpd_sender_restrictions
+ smtpd_recipient_restrictions
7) smtpd_end_of_data_restrictions (2.2):
+ generic
+ smtpd_client_restrictions
+ smtpd_helo_restrictions
+ smtpd_etrn_restrictions
+ smtpd_sender_restrictions
+ smtpd_recipient_restrictions
+ smtpd_data_restrictions
Таким образом, postfix позволяет полностью контролировать весь сеанс соединения, начиная от момента подключения (smtpd_client_restrictions), вплоть до окончания соединения (smtpd_end_of_data_restrictions, v2.2).
Логично было бы обрывать сеанс чем раньше, тем лучше, экономя входящий трафик. Скажем, сразу после того, как IP-адрес клиентского компьютера (или другого почтового сервера) был вычислен как спамерский (например, через базы rbl). Но… как считают разработчики postfix, существует достаточно большое количество клиентских программ, которые не обращают внимания на сообщения почтового сервера до команды RCPT TO.
Поэтому разработчики предусмотрели специальный параметр, smtpd_delay_reject, включение которого указывает postfix’у отрабатывать весь сеанс, от установления соединения до RCPT TO включительно НЕ ГЛЯДЯ НИ НА КАКИЕ ОГРАНИЧЕНИЯ, и лишь после этого запускать проверки (1)->…->(5).
Побочным эффектом такого поведения является возможность (все таки!:)) в ограничениях, находящихся ЛЕВЕЕ, использовать правила из ограничений, находящихся ПРАВЕЕ, в порядке следования. Однако, сам ПОРЯДОК обработки ограничений при этом ОСТАЕТСЯ ПРЕЖНИМ!
Остается добавить только, что параметр smtpd_delay_reject по умолчанию включен (=yes)… и это является еще одним дополнительным источником неправильного понимания работы ограничений. :)
Правила для ограничений на подключение (smtpd_client_restrictions) и рекомендации по их использованию.
ЗАМЕЧАНИЕ: Ссылки на конфигурационные параметры в дальнейшем будут обозначаться как $<имя_параметра>. Текущее значение параметра можно получить так:
postconf <имя_параметра>. Например, чтобы посмотреть чему равно $myhostname, наберите: postconf myhostname
Входным аргументом, по которому работают правила в smtpd_client_restrictions, является «адрес клиента»: IP-адрес компьютера или другого почтового сервера (далее – просто «клиент»), который собирается отправить письмо через сервер postfix.
(1) Правила вида reject_.*:
reject_unknown_client – REJECT, если адрес клиента неправильно прописан в DNS: отсутствует или неправильно указан прямой адрес клиента (имя->адрес, запись типа A), или обратный адрес (адрес->имя, запись типа PTR).
reject_rbl_client rbl_domain.tld[=d.d.d.d] – REJECT, если обратный адрес клиента совпадает с записью типа А в указанном антиспаммерном домене rbl. Необязательная часть [=d.d.d.d] (в некоторых доменах) может служить, например, для тестовых целей, либо для предоставления других сервисов (подробнее о доменах rlb – далее).
reject_rhsbl_client rbl_domain.tld[=d.d.d.d] – то же самое, что и предыдущее правило, но проверяется прямой адрес клиента.
(2) Правила вида permit_.*:
permit_mynetworks – OK, если адрес клиента находится в той же сети, что сервер postfix, либо принадлежит диапазону адресов сетей, указанных в $mynetworks.
permit_sasl_authenticated – OK, если клиент успешно прошел аутентификацию через SASL (в клиентской программе введено правильное имя пользователя и пароль).
В postfix v2.2 добавлены еще 3 правила:
permit_inet_interfaces – OK, если адрес совпадает с сетевыми адресами, указанными в $inet_interfaces.
permit_tls_all_clientcerts – OK, если распознан любой клиентский сертификат.
permit_tls_clientcerts – OK, если распознан клиентский сертификат И этот сертификат есть в списке, указанном в параметре $relay_clientcerts.
(3) Правила вида check_.*_access:
check_client_access <тип_таблицы>:<имя_таблицы> – гм…:) конечно, можно написать «просто», как в man 5 postconf + man 5 access: «postfix просматривает таблицу на совпадение шаблонов по имени клиента, его родительскому домену, IP-адресу клиента и его сетей (последовательно обрезая наименее значимый октет), и в случае, когда таковое совпадение происходит, отрабатывает соответствующее действие (REJECT, OK или DUNNO)”.
Но мы же должны понимать, как это работает, чтобы уметь пользоваться, правильно?
Итак… Таблицы бывают разных типов. Список этих типов, поддерживаемых Вашим сервером, можно получить по команде postconf -m, а тип по умолчанию устанавливается параметром $default_database_type. Наиболее популярны таблицы типа cidr, hash, pcre и regexp. На серверах с централизованной системой хранения пользовательских аккаунтов используются таблицы для доступа к различным базам данных: ldap, mysql, pgsql. Остальные типы можно смело отнести к экзотике.
Несмотря на обилие типов таблиц, они делятся всего на 2 вида: таблицы регулярных выражений (в дальнейшем – «регулярные»), и индексные, которые состоят из пар <значение> <действие>. К первому виду из перечисленных относятся таблицы типов pcre и regexp, остальные (даже те, которые работают с базами данных!) – ко второму. Таблицы типа cidr тоже относятся к индексным, но работают только с IP-адресами.
В smtpd_client_restrictions к таблице любого вида postfix производит доступ несколько раз, если только результат предыдущего обращения к этой таблице не был REJECT или OK.
В таблице ниже знаком ‘+’ отмечено с какими аргументами и к какого вида таблицам postfix производит доступ. Например, к регулярным таблицам он (максимально) обратиться всего 2 раза – с аргументом cli.ent.dom.ain.tld и net.work.addr.ess, а вот к доступ к индексным таблицам может быть выполнен целых 6 раз (и более!).
Аргумент просмотра | регулярные | cidr | индексные | Примечание |
cli.ent.dom.ain.tld | + | + | 1 | |
[.]ent.dom.ain.tld | + | + | 1,2 | |
[.]dom.ain.tld | + | + | 1,2 | |
[.]ain.tld | + | + | 1,2 | |
[.]tld | + | + | 1,2 | |
net.work.addr.ess | + | + | + | |
net.work.addr | + | + | + | |
net.work | + | + | + | |
net | + | + | + |
Примечания:
1. Доступ осуществляется, если только возможно получить доменное имя клиента по его адресу (запись типа PTR) из запроса к реверсной зоне DNS.
2. Разработчики postfix рекомендуют для поддоменов использовать точку, например если мы хотим запретить доступ со всех поддоменов домена ‘dom1’ вида x.y.z.dom1.tld в таблице нужно указать:
.dom1.tld REJECT
Но, обратите внимание на параметр $parent_domain_matches_subdomains. Если в его списке есть ‘smtpd_access_maps’, это означает, что ваш сервер будет искать ДРУГИЕ строчки, без точки вначале, т.е. записи вида:
dom1.tld REJECT
check_ccert_access <тип_таблицы>:<имя_таблицы> – после того, как сертификат клиента проверен, postfix будет просматривать указанную таблицу на совпадение подписи сертификата (fingerprint) и выполнять соответствующее действие (REJECT, OK или DUNNO).
Небольшое отступление.
Почему там много внимания уделяется именно ограничениям на подключение (smtpd_client_restrictions)? Все просто.
Во-первых, правила в этих ограничениях срабатывают раньше всех остальных, и если на этом этапе удастся отбросить бОльшую часть ненужных соединений, это здОрово сократит все дальнейшие проверки.
Во-вторых, только в этих правилах используется наиболее правдоподобная информация – IP-адрес клиента, подделка которого хотя и возможна, но достаточно затруднительна.
Общие рекомендации по настройке ограничений.
1) Установите параметр $soft_bounce = yes. Это приведет к тому, что ответы с кодами 5XX (тяжелая, постоянная ошибка) будут преобразовываться в 4XX (временная ошибка). Соответственно, почтовые серверы будут пытаться доставить сообщения на Ваш postfix позже. В это время Вы сможете проанализировать логи и убедиться, так ли, как надо, работают Ваши правила. Если все нормально – установите $soft_bounce = no.
2) Перед новым правилом вида reject_.* поставьте warn_if_reject, например:
smtpd_recipient_restrictions = |
. . . |
warn_if_reject reject_rbl_client dnsbl.sorbs.net, |
. . . |
Это приведет к тому, что в логах будет видно срабатывание этого правила, но сами сообщения отбрасываться не будут. После отладки опцию warn_if_reject перед правилом надо убрать.
Использование такого подхода при отладке правил на работающем сервере позволит не потерять ни одного сообщения, предназначенного Вашим клиентам. “Ничего не бойся!”. :)
Принципы построения ограничений на соединение.
Многие начинающие администраторы устанавливают первым правилом permit_mynetworks:
smtpd_recipient_restrictions = permit_mynetworks, ...
Это, конечно, работает, и не требует особых усилий при настройке, но… А если в Вашей сети (сетях) найдется недобросовестный спамер? Или просто компьютер Вашего пользователя окажется зараженным почтовым трояном? Или… Да мало ли, что может произойти!
«Никому не верь!» – это главный принцип, которого необходимо придерживаться, чтобы Ваш сервер в скором времени не попал в блэк-листы в качестве открытого релея или источника спама.
Лучше всего сразу установить жесткую политику: все пользователи при отправке писем должны регистрироваться. По меньшей мере – путем указания своего имени и пароля. Еще лучше, если к этому добавить сертификацию и соединение по TLS, но это уже на Ваше усмотрение.
Первым правилом всегда должно быть правило вида check_client_access! Оно должно служить ТОЛЬКО для «отбрасывания» клиентов, с которыми возникли проблемы – спамеры, завирусованные компьютеры, неплательщики услуг (для ISP), и т.п. Какую таблицу (регулярную или индексную) в этом правиле использовать – это на Ваше усмотрение. Может быть подряд даже несколько правил check_client_access с таблицами разного типа.
Следующим правилом можно ставить permit_sasl_authenticated, тем самым разрешая отправлять всю почту зарегистрированным клиентам. Не имеет смысла проверять Ваших клиентов через спам-листы, так как в спам-листы, если что, все равно попадет Ваш сервер, а не клиенты.
Если разумно ограничить параметр $mynetworks, далее можно указать permit_mynetworks. Правильнее всего, если в $mynetworks будут только адреса собственных сетевых интерфейсов почтового сервера плюс 127.0.0.0/8. Можно также указать адреса других почтовых серверов, для которых Ваш сервер является релеем, но это решение во многом спорно. Для обмена почтой с релейными серверами лучше использовать TLS и сертификаты. Соответственно, тогда необходимо правило check_ccert_access.
Все остальные правила относятся к «чужим» клиентам, т.е. серверам, с которых сообщения приходят к клиентам Вашего сервера.