Я предпринимаю шаги по усилению защиты моего SMTP-сервера исходящей почты. Я хочу запретить пользователям подделывать адрес отправителя.
При отправке электронной почты с постфиксным SMTP отправитель идентифицируется тремя способами:
From:
заголовок - как определено в RFC 822MAIL FROM
адрес - как определено в RFC 821Глядя в руководство, я считаю, что reject_sender_login_mismatch и reject_unlisted_sender вместе гарантирует, что MAIL FROM
адрес электронной почты, связанный с логином postifx. Это 2 и 3 совпадения.
Я застрял в том, как обеспечить совпадение всех трех. Я счастлив, если результат просто переписывает сообщение, а не отклоняет, но все будет хорошо. Однако я не вижу способа сделать это. Я это вижу уборка добавит недостающий From:
заголовок, но я не вижу возможности проверить и переписать его.
Спасибо тем, кто указал еще один похожий вопрос. К сожалению, это не помогло, так как на этот вопрос есть два ответа: один очень расплывчатый, другой кажется неправильным.
Я потратил некоторое время на изучение этого и не могу найти чистый постфиксный способ. Единственное предложение использовать header_checks
похоже, не работает, потому что вы не можете (AFAIK) сопоставить один заголовок с другим.
Можно написать свою собственную программу / сценарий для выполнения проверки за вас и использовать ее как content_filter.
Вот упрощенная версия того, что я использую, написанное на python. Это читает письмо от stdin, принимающего MAIL from
и RECPT to
адреса как аргументы. Он проверяет From:
заголовок против MAIL from
и заменяет его, если они не совпадают. Я сохраняю это как /usr/share/mail_filter/filter.py
:
#! /usr/bin/python3
import sys
import subprocess
import email.parser
import email.policy
parser = email.parser.BytesParser(policy=email.policy.default)
message = parser.parse(sys.stdin.buffer)
envelope_from = sys.argv[1]
envelope_to = sys.argv[2]
# This if statement checks envelope from against message from
if message['From'].addresses[0].addr_spec != envelope_from:
print(f"Replacing sender {message['from']} with {envelope_from}", file=sys.stderr)
message.replace_header('From', envelope_from)
# sendmail -G -i -f sender@sender_domain.tld recipient@recipient_domain.tld
sendmail = subprocess.Popen(["/usr/sbin/sendmail", "-Gif", envelope_from, envelope_to], stdin=subprocess.PIPE)
with sendmail.stdin:
sendmail.stdin.write(message.as_bytes())
# If sendmail returns an error, cascade it back to postfix
sys.exit(sendmail.wait())
Обновлено /etc/postfix/master.cf
:
# added the -o content_filter...
smtp inet n - y - - smtpd
-o content_filter=filter:dummy
# Added this entire service
filter unix - n n - 10 pipe
flags=Rq user=filter null_sender=
argv=/usr/share/mail_filter/filter.py ${sender} ${recipient}
Обратите внимание, что это ссылается на расположение сценария из шага 1 и пользователя, определенного в шаге 3.
Я добавил пользователя ОС filter
в группе с доступом к использованию sendmail
.
useradd --system --gid postdrop filter
В соответствии с инструкции простые фильтры (переход вперед с использованием sendmail
) может применяться только к клиентам SMTP и не может фильтровать сообщения, отправленные через sendmail. Если это проблема для вас, вам нужно будет написать расширенный фильтр содержимого.