Ограничения на пересылку почты отдельным пользователям в postfix


Версия 2.

Ограничения на пересылку почты отдельным пользователям только внутри домена
средствами postfix

Иногда возникает необходимость ограничить пересылку ряду пользователей
электронной почты в мир. Например у нас ряд заявок оформляется в (на наш
отдел) в форме e-mail, тобишь пользователь просит сделать то-то и то-то. Мы
взглянув на проблему даем ответ, реализуемо это или нет. Если реализуемо
сообщаем о том, что это сделано. То бишь получается что все заявки есть,
учтены, ответы даны, можно предоставить отчет руководству в любом виде по
этим вопросам. Но ведь не все имеют право отправки писем в мир. Такова уж
политика компании.

Ну и для примера еще такой мой опыт - один товарищ решил отправить на mail.ru,
на свой почтовый ящик порнушный фильм. 90 метров мелочь, но неприятно.

В общем наша цель ясна - запретить ряду пользователей пересылку почты за
пределы домена или ряда доменов.

И так желание и цельесть. Взглянем, на то, что у нас есть под рукой. Это
настроенный(или не очень) и рабочий (надеюсь) почтовый сервер postfix. В моем
случае это:

root@ipps-1-66 :lf /var/db/pkg/| grep postfix
postfix-2.0.20,1/
root@ipps-1-66 :

Описывать предварительную установку почтового сервера приводить не буду, в
этом просто нет нужды. На том же www.postfix.org в разделе HOW-TO
http://www.postfix.org/docs.html примеров предостаточно, ну или например
поближе на www.opennet.ru вот пример поиска по этой теме
http://www.opennet.ru/cgi-bin/opennet/ks.cgi?mask=postfix

В общем установимся, что сервер вы настроили или сами или основываясь на одном
из HOW-TO, а теперь будем делать ограничения.

И так, мы рассмотрим два случая, первый - хранение пользователей с
ограниченными правами в базе mysql и второй в текстовом файле.
Для начала, прежде чем начать править конфиг, просмотрите внимательно, какие
базы данных поддерживает установленный вами postfix. В моем случае это:

root@ipps-1-66 :postconf -m
static
sdbm
pcre
regexp
environ
proxy
mysql
btree
unix
hash
root@ipps-1-66 :

В вашем случае вывод может отличаться, но если вы решили использовать для
хранения mysql, то убедитесь что в приведенном списке он присутствует.

В общем приступаем.

Если база пользователей находиться в mysq, нам потребуется внести следующие
изменения в файл main.cf:

check_sender_access = mysql:/usr/local/etc/postfix/restricted_senders
check_recipient_access = mysql:/usr/local/etc/postfix/local_domains
smtpd_recipient_restrictions =
check_sender_access ,permit_mynetworks,reject_unauth_destination
smtpd_restriction_classes = local_only
local_only = check_recipient_access, reject_unauth_destination


или можно второй вариант:

smtpd_recipient_restrictions =check_sender_access
mysql:/usr/local/etc/postfix/restricted_senders, permit_mynetworks,
reject_unauth_destination
smtpd_restriction_classes = local_only
local_only = check_recipient_access
mysql:/usr/local/etc/postfix/local_domains, reject_unauth_destination

Должен сказать, что первый вариант мне более предпочтителен - все расписано,
откуда и куда, но и второй имеет место быть. Может кому будет удобнее именно
так.

Содержимое /usr/local/etc/postfix/restricted_senders

user = postfix
password = postfix
dbname = mail
table = restricted_senders
select_field = permission
where_field = usermail
hosts = localhost

Содержимое /usr/local/etc/postfix/local_domains

user = postfix
password = postfix
dbname = mail
table = local_domains
select_field = result
where_field = domain
hosts = localhost

Расмотрим значения каждого из параметров:

- user - имя пользователя для подключения к mysql
- password - соответственно пароль
- dbname - имя базы
- table - таблица
- select_field - поле в котором ищем
- where_field - правила отбора
- hosts - хост на котором крутиться база

А теперь создадим сами таблицы и их содержимое:

create table restricted_senders (
usermail varchar(255) primary key,
permission varchar(128)
);
create table local_domains (
domain varchar(255) primary key,
result varchar(8)
);

Вносим нужные нам данные. Для начала укажем какому именно пользователю
перекрывается доступ в мир:

insert into restricted_senders values ('pupkin@xxx.com.ua','local_only');

теперь укажем, куда он может отправлять почту

insert into restricted_senders values ('xxx.com.ua','OK');

Сюда можно внести несколько доменов, и все они будут доступны пользователю с
правами local_only, а вот в мир он уже ничего не отправит.

Все, теперь можем по выбору сделать или

root@ipps-1-66: postfix reload
или
root@ipps-1-66: postfix stop && postfix start

Да, обращу внимание на то что если вы сделаете например так:

root@ipps-1-66: postconf | grep smtpd_restriction_classes

то увидите:
smtpd_restriction_classes =

Но беспокоится не стоит, все будет нормально, для вящей убедительности
достаточно отправить письмо в мир и внутри домена и возрадоваться своим
успехам.

Ну вот в принципе и все для mysql, кто не желает пользоваться оным, можем все
наши правила разместить в обычном текстовом файле.
И так рассмотрим теперь такой вариант, хотя он принципиальных отличий не
имеет.

Добавляем содержимое в main.cf

check_sender_access = hash:/usr/local/etc/postfix/restricted_senders
check_recipient_access = hash:/usr/local/etc/postfix/local_domains
smtpd_recipient_restrictions =
check_sender_access ,permit_mynetworks,reject_unauth_destination
smtpd_restriction_classes = local_only
local_only = check_recipient_access, reject

или опять таки второй вариант:

smtpd_recipient_restrictions =check_sender_access
hash:/usr/local/etc/postfix/restricted_senders, permit_mynetworks,
reject_unauth_destination
smtpd_restriction_classes = local_only
local_only = check_recipient_access hash:/usr/local/etc/postfix/local_domains,
reject_unauth_destination

Создаем указанные файлы, с нужным содержимым:

root@ipps-1-66 : touch /usr/local/etc/postfix/restricted_senders
root@ipps-1-66 : ee /usr/local/etc/postfix/restricted_senders
pupkin@xxx.com.ua local_only

Объясним. Первое поля - e-mail пользователя с ограниченными правами пересылки,
а второе указывает, что пересылать почту он может только локально

Создадим файл, где будет список локальных доменов:

root@ipps-1-66 : touch /usr/local/etc/postfix/local_domains
root@ipps-1-66 : ee /usr/local/etc/postfix/local_domains
xxx.com.ua OK

Опять же, список может не ограничиваться одним только доменом, их может быть
несколько.

Теперь рассмотрим вариант, когда нужно закрыть дополнительно доступ и из мира
на ряд ящиков. В принципе это почти тот же случай, только несколько на
оборот. И так, начинаем делать.

Для начала мой любимый mysql:

smtpd_recipient_restrictions =
mysql:/usr/local/etc/postfix/protected_destinations, check_sender_access
mysql:/usr/local/etc/postfix/restricted_senders,
permit_mynetworks,reject_unauth_destination
smtpd_restriction_classes = local_only,insiders_only
local_only = check_recipient_access
mysql:/usr/local/etc/postfix/local_domains, reject_unauth_destination
insiders_only = check_sender_access mysql:/usr/local/etc/postfix/insiders, reject

Здесь стоит обратить внимание на то, что первый предложенный выше мной вариант
ограничения на пересылку в мир в паре с ограничениями на прием работать не
будет, увы. Что ж нет в мире совершенства. Но мы воспользуемся этим вторым
вариантом.

Так же обращу внимание на последнюю строку:

insiders_only = check_sender_access mysql:/usr/local/etc/postfix/insiders, reject

Почему? потому что заключительный параметр очень важен в данном случае, если
вы поставите, например reject_unauth_destination, то почта будет исправно
доходить до пользователя, а ведь нам этого не нужно, правда?

Теперь опишем содержимое файлов:

/usr/local/etc/postfix/insiders
user = postfix
password = postfix
dbname = mail
table = insiders
select_field = result
where_field = domain
hosts = localhost

/usr/local/etc/postfix/protected_destinations
user = postfix
password = postfix
dbname = mail
table = protected_destinations
select_field = permissions
where_field = mailuser
hosts = localhost

Ну, объяснять думаю не стоит, посему перейдем к созданию таблиц и внесению
данных:

create table protected_destinations (
mailuser varchar(255) primary key,
permissions varchar(128)
);
create table insiders (
domain varchar(255) primary key,
result varchar(8)
);

Так, создали, теперь вносим данные, ну проделаем это все над тем же нашим
пользователем по имени pupkin - бедный церковноприходской учебник математики:

insert into protected_destinations ('pupkin@xxx.com.ua','insiders_only');

теперь укажем, откуда он может получать почту

insert into restricted_senders values ('xxx.com.ua','OK');

Проверим, что же у нас получилось:

root@ipps-1-66 :telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.owe.
Escape character is '^]'.
220 ipps-1-66.xxx.com ESMTP Postfix (2.0.20)
mail from: pupkin@owe.com.ua
250 Ok
rcpt to: skif@xx.ua
454 <skif@xx.ua>: Relay access denied

Вот оно! за пределы домена мы ничего отправить не могем....

rcpt to: skif@xxx.com.ua
250 Ok
data
354 End data with <CR><LF>.<CR><LF>
Subject: test
test
.
250 Ok: queued as 345BFC2A60
quit
221 Bye
Connection closed by foreign host.
root@ipps-1-66 :

А по домену почта гуляет просто на ура.

Что ж проверим нашего пользователя на получение почты из мира:

skif@ostwest :telnet ipps-1-66.xxx.com 25
Trying xxx.xxx.xxx.xxx...
Connected to ipps-1-66.xxx.com.
Escape character is '^]'.
220 ipps-1-66.xxx.com ESMTP Postfix (2.0.20)
mail from: skif@xx.ua
250 Ok
rcpt to: pupkin@xxx.com.ua
450 <pupkin@xxx.com.ua>: Recipient address rejected: Access denied
quit
221 Bye
Connection closed by foreign host.

Думаю комментарии излишни. Пользователь отныне может шалить только в пределах
отведенных ему ресурсов.

Вот в принципе и все несложные манипуляции. Ограничиваться только этим конечно
не стоит, можно придумать и реализовать много разного и полезного и postfix
предоставляет большие возможности к этому.

Чижиков Владимир (Skif)

Написано по мотивам:

http://www.postfix.org/RESTRICTION_CLASS_README.html - кстати, отнеситесь
несколько предвзято к этому документу ибо после манипуляций как там указано у
меня postfix отказался принимать все соединения.
и примеров идущих в комплекте с postfix, в частности:
/usr/local/etc/postfix/sample-smtpd.cf

Обновлено: 13.03.2015