Инструкций по настройке почтового сервера с помощью связки postfix — amavisd-new — dovecot очень много.
И подавляющее большинство из них практически дословно повторяют друг друга, включая ошибки и неточности.
Мне кажется скучным бездумное нажатие кнопок, поэтому я решил оптимизировать стандартную конфигурацию: а что, если построить взаимодействие postfix и amavisd-new не через localhost, а на unix-сокете? Как оказалось, это не так просто, но я это сделал! Инструкция и патч под катом.
Честно говоря, мне вообще не нравится взаимодействие через локальный хост внутри одной машины.
Если вам необходимо организовать обмен данными между двумя приложениями, то гораздо правильнее, безопаснее и менее ресурсоемко сделать это через unix-сокет файловой системы.
Более того, таким образом можно организовать защиту (посредством прав на файловую систему) даже там, где она отсутствует на уровне приложения или протокола.
Итак, путь почты в обсуждаемом соединении выглядит так:
Получается, что нам нужно организовать два соединения: при переходе на фильтрацию и при возврате обратно в MTA. Поскольку сокет создается слушателем, то в первом случае это будет amavisd, а во втором — постфикс.
Начнем со второго, потому что он проще и лучше описан.
Чтобы постфикс создал сокет прослушивания, вам просто нужно указать unix, а не inet, во втором столбце master.cf (столбец типа).
В этом случае в первом столбце указывается путь и имя файла сокета.
Поскольку постфиксные процессы выполняются в chroot (это можно отключить для конкретного процесса, но не следует этого делать), папку необходимо создать внутри домашнего каталога постфикса: /var/spool/postfix. Он будет содержать оба сокета:
Итак, конфигурация постфикса:mkdir /var/spool/postfix/amavis chown amavis:postfix /var/spool/postfix/amavis chmod 770 /var/spool/postfix/amavis
amavis/postfix-in unix y - y - - smtpd
-o smtpd_client_restrictions=$local_clients_only
-o smtpd_helo_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=
-o smtpd_milters=
Точные параметры зависят от ваших настроек, это мой вариант. Здесь есть две проблемы:
- Путь будет относительным к /var/spool/postfix/private, у которого очень строгие права.
- Я не уверен, верно ли это для всех дистрибутивов, но для Ubuntu это верно.
Права на папку лучше не трогать (сокеты всех постфиксных сервисов там есть), лучше просто создать симлинк.
- Помимо сокета, postfix также создает для процесса pid-файл, имя которого автоматически генерируется с использованием маски $type.$name. Где тип будет равен unix, а имя берется из первого столбца master.cf. Получается unux.amavis/postfix-in т.е.
файл в подпапке.
Сам он его не создаст и завершится с ошибкой.
cd /var/spool/postfix/private
ln -s .
/amavis .
mkdir /var/spool/postfix/pid/unix.amavis
Не очень красиво, но и не разрушительно для стандартной структуры папок пакета.
Перезапускаем постфикс и убеждаемся, что файл сокета появился в папке amavis, а файл pid — в pid/unix.amavis. К сожалению, права на сокет 666, но права на папку, которую вы создали ранее, защитят файл от посторонних глаз.
Проверить работу можно командой: netcat -U /var/spool/postfix/amavis/postfix-in
220 mail.example.ru ESMTP Postfix
Отлично, мы справились.
Теперь о восторге.
Во-первых, давайте настроим обратный путь почты через сокет unix, принадлежащий postfix. Это работает из коробки: $forward_method = 'smtp:/var/spool/postfix/amavis/postfix-in';
$notify_method = \$forward_method;
Ну а теперь самое сложное — настройка сокетов в amavisd. Решение можно найти в Интернет , но предлагает использовать один сокет, указанный в параметре $unix_socketname. Я хотел, чтобы мой собственный протокол amavisd-new (AM.PDP) и прием почты происходили через сокеты.
В файле конфигурации по умолчанию упоминается директива @listen_sockets, но для нее нет описания.
Но это в примечания к выпуску , даже с примерами! Правда, розетка всего одна, но что мешает попробовать? Хорошо, как мне установить протокол для сокета (который указан в банке политик)? Во всех примерах просто пишут SOCK. По аналогии с инет-сокетами (где можно указать порт хоста) я предположил, что нужно указать полный путь к файлу сокета.
Вот что произошло: $unix_socketname = undef;
$inet_socket_bind = undef;
$inet_socket_port = undef;
@listen_sockets = ('/var/lib/amavis/amavisd.sock', '/var/spool/postfix/amavis/amavis-in.sock');
$unix_socket_mode = 0660;
%interface_policy = (
'/var/lib/amavis/amavisd.sock' => 'AM.PDP-SOCK',
'/var/spool/postfix/amavis/amavis-in.sock' => 'LMTP-SOCK'
);
$policy_bank{'LMTP-SOCK'} = {
protocol => 'LMTP'
};
$policy_bank{'AM.PDP-SOCK'} = {
protocol => 'AM.PDP',
auth_required_release => 0, # don't require secret-id for release
};
Перезапускаю и проверяю — действительно, оба сокета созданы! Победа? Не совсем, при попытке подключиться к сокету ничего не происходит, а в журнал пишется ошибка, что протокол для него не определен.
Получается, что политика банков к ним не применяется.
Как же так? Мне пришлось зайти в код. Эта поездка принесла две новости – как обычно, хорошую и плохую.
Хорошей новостью является то, что предположение относительно %interface_policy было верным: # load policy banks according to my socket (destination),
# then check for allowed access from the peer (client/source)
#
sub access_is_allowed($;$$$$) {
my($unix_socket_path, $src_addr, $src_port, $dst_addr, $dst_port) = @_;
my(@bank_names);
if (defined $unix_socket_path) {
push(@bank_names, $interface_policy{"SOCK"});
push(@bank_names, $interface_policy{$unix_socket_path});
} elsif (defined $dst_addr && defined $dst_port) {
$dst_addr = '['.
lc($dst_addr).
']' if $dst_addr =~ /:[0-9a-f]*:/i; # IPv6?
push(@bank_names, $interface_policy{$dst_port});
push(@bank_names, $interface_policy{"$dst_addr:$dst_port"});
}
load_policy_bank($_) for @bank_names;
Плохо то, что $unix_socket_path приходит в эту функцию пустым.
Заполняется следующим образом: my $is_ux = $sock && $sock->UNIVERSAL::can('NS_proto') &&
$sock->NS_proto eq 'UNIX';
И оба объекта там пусты.
Изучение документация предложил такой вариант: my $unix_socket_path = $sock->hostpath();
И это сработало! Готовый .
патч можно сказать Здесь .
Остается последний штрих.
Поскольку amavisd создает свой сокет с правами только себе, а доступ другим мы запретили (что верно), то нужно добавить постфикс в группу amavis, чтобы она могла писать в сокет: gpasswd -a postfix amavis
Готовый.
P.S. Патч и описание проблемы я отправил Марку Мартинеку по почте, так как на сайте нет упоминания о баг-трекере.
Веб-сайт Не нашел.
Ответа я до сих пор не получил, но особо на него не рассчитываю — проект выглядит заброшенным (последний релиз был более двух лет назад).
Теги: #*nix #Администрирование сервера #почтовый сервер #postfix #amavisd-new #unix-сокет
-
Книги Для Работы В It-Компаниях
19 Oct, 24 -
Мотивируй Правильно – Раздай Леща
19 Oct, 24 -
Вы Забываете Дни Рождения Своих Друзей?
19 Oct, 24 -
Вы Не Google
19 Oct, 24 -
«Нтв Плюс» Запустит Ip Tv Через Год
19 Oct, 24