LINUX.ORG.RU
ФорумAdmin

Exim принимать / отклонять письма по правилам

 


0

2

Доброго времени суток.

Актуальной задачей в последнее время является блокировка получения почты с определенных доменов или доменных зон (официально - в целях безопасности). Так, многие российские госорганы заблокировали прием сообщений с зарубежных доменов (в частности, .com) либо наоборот, по принципу белого списка, принимают почту только с доменов .ru

По стандарту Exim отклоняет письма на этапе соединения между MX серверами если сервер отправителя в спам базах (либо если из-за технических проблем с DNS разные spamhaus’ы отвечают на все домены что они заблокированы). В некоторых ситуациях идет ответ over quota, в других же письмо может быть формально принято но в ответ уйдет Delivery report с указанием ошибки.

Реально ли реализовать настройками Exim подобные ограничения, если да - то как?

Пример конкретной задачи: заблокировать определенному почтовому ящику, размещенному на сервере, либо определенному почтовому домену (чтобы это не затронуло другие домены, только в крайнем случае это правило можно применять ко всем доменам почта которых обрабатывается на одном сервере) заблокировать прием всех писем с доменов отличных от одного - нескольких выыбранных (белый список) либо наоборот заблокировать один выбранный? Чтобы письма отклонялись и отправитель сразу видел (отчетом своего сервера или ответом моего сервера) что его письмо не было принято?

Ответ на: комментарий от BOOBLIK

Это не шиза, от гугла реально надо избавляться. И по доменам, на данном этапе, самый эффективный вариант по цене/качеству. Банить по настоящему гео надо было начинать 15-20 лет назад (и делать это комплексно а не только в переписке с гос органами), сейчас уже поздно/ещё рано.

И не «враг пишет» а «у некомпетентного гражданина утекают данные за границу, надо мягко подтолкнуть его к правильному решению».

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 4)
Ответ на: комментарий от firkax

И по доменам, на данном этапе, самый эффективный вариант по цене/качеству.

Сделать в exim run на mmdblookup или mmdbinspect с $sender_host_address не велика цена за качественные данные откуда письмо.

yandrey
()
Ответ на: комментарий от yandrey

И что? Технически можно что угодно делать, речь не про это. Это у автора темы задача «как сделать конфиг», но задача сверху - не техническая а политическая, решается поэтапно и не в лоб. Банить заграничные айпи-адреса указа пока не было.

firkax ★★★★★
()

вариант ввести обычную спам фильтрацию с regexp по доменной зоне?
У многих обычно своя фильтрация по спамерам, так просто дополнить нужными/ненужными доменами.

Atlant ★★★★★
()

Спасибо всем кто ответил. Предлагаю обсуждать не шизу а возможные методы реализации. Я сам против таких вещей, но в данный момент надо на почте в одном домене сделать прямую аналогию того что реализовали госорганы (в частности судебная система) РФ - блок по домену.

По IP адресу или GEO мне не подходит. Нужно завайтлистить несколько доменов (корпоративных) заблокировав все остальные, либо наоборот заблеклистить несколько доменов. Как будет эффективнее мы еще сами не понимаем.

Я уже думал над тем чтобы поднять свой локальный spamhaus на уровне dns

  deny    message       = Rejected because $sender_host_address is in a black list at $dnslist_domain\n$dnslist_text
          hosts         = !+whitelist
          dnslists      = ${readfile {/etc/exim4/dnsbl.conf}{:}}

но пока не понимаю где здесь указано что по хостам dnsbl.conf опрашивается IP адрес ($sender_host_address) а не домен отправителя. Видимо можно проще.

begin acl

acl_check_spammers:
  accept  hosts         = +whitelist

  drop    message       = Your host in blacklist on this server.
          log_message   = Host in blacklist
          hosts         = +spammers

  accept

acl_check_mail:	
  deny    condition     = ${if eq{$sender_helo_name}{}}
          message       = HELO is required

  drop    message       = Helo name contains a ip address (HELO was $sender_helo_name) and not is valid
          condition     = ${if match{$sender_helo_name}{\N((\d{1,3}[.-]\d{1,3}[.-]\d{1,3}[.-]\d{1,3})|([0-9a-f]{8})|([0-9A-F]{8}))\N}{yes}{no}}
          condition     = ${if match {${lookup dnsdb{>: defer_never,ptr=$sender_host_address}}\}{$sender_helo_name}{no}{yes}}
          delay         = 45s

  drop    condition     = ${if isip{$sender_helo_name}}
          message       = Access denied - Invalid HELO name (See RFC2821 4.1.3)

  drop    condition     = ${if eq{[$interface_address]}{$sender_helo_name}}
          message       = $interface_address is _my_ address

  accept authenticated = *

  deny    spf           = fail : softfail
	  message	= SPF validation failed: $sender_host_address is not allowed to send mail from ${if def:sender_address_domain{$sender_address_domain}{$sender_helo_name}}
	  log_message	= SPF validation failed ${if eq{$spf_result}{softfail}{ (softfail)}{}}: $sender_host_address is not allowed to send mail from ${if def:sender_address_domain{$sender_address_domain}{$sender_helo_name}}

  deny	  spf		= permerror
	  message	= SPF validation failed: syntax error in SPF record(s) for ${if def:sender_address_domain{$sender_address_domain}{$sender_helo_name}}
	  log_message	= SPF validation failed (permerror): syntax error in SPF record(s) for ${if def:sender_address_domain{$sender_address_domain}{$sender_helo_name}}

  defer	  spf		= temperror
	  message	= temporary error during SPF validation; please try again later
	  log_message	= SPF validation failed temporary; deferred

  warn	  spf		= none : neutral
	  log_message	= SPF validation none/neutral

  warn	  condition	= ${if eq{$sender_host_name}{} {1}}
	  set acl_m_greylistreasons = Host $sender_host_address lacks reverse DNS\n$acl_m_greylistreasons

  accept
	  add_header = :at_start:$spf_received
	  logwrite = SPF validation passed


Я могу сюда просто добавить новый блок с названием acl_some_name: и он будет выполняться? Или для этого его как-то прописать надо в самом начале конфига

acl_smtp_connect = acl_check_spammers
acl_smtp_mail = acl_check_mail
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_data
acl_smtp_mime = acl_check_mime

?

Помогите кто-то с правилом, допустим, заблокировать всю почту с домена gmail.com или разрешить всю почту с любого домена заканчивающегося на .ru

Это реально сделать на уровне одного ящика или одного домена, или будет касаться всех кто использует данный Exim сервер?

И еще как вариант чтобы почта принималась в папку СПАМ но отправителю уходил Delivery report о том что письмо не принято по причине sender is blocked - это реально?

Dima_228
() автор топика
Последнее исправление: Dima_228 (всего исправлений: 2)
Ответ на: комментарий от Dima_228

Delivery report шлёт сервер-отправитель, а не получатель (ну по крайней мере обычно так). Обычно в него включается текст ошибки, отданный сервером-получателем в какой-то момент smtp-сессии, но я не уверен что у всех серверов-отправителей это работает одинаково, лучше с разными проверь что твой текст ошибки попадает в их репорт.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Дошло. Получается что Delivery report можно сделать отправителю только в случае deny либо drop на моем сервере. Значит скрыто получать сообщение (допустим, помещая его в папку SPAM) в то же время отвечая отправителю что сообщение не принято перманентно - невозможно.

С настройкой под конкретный домен, если Exim4 обрабатывает почту нескольких доменов на одном сервере, кажется, можно как-то так:

${if exists{/etc/exim4/domains/$domain/fwd_only}{${lookup{$local_part}lsearch{/etc/exim4/domains/$domain/fwd_only}{true}{false}}}}

то есть если переменную $domain можно использовать в конфиге везде (это я пока не понял) при наличии определенного файла из него можно читать acl

acl_smtp_rcpt = ${if ={25}{$interface_port} {acl_check_rcpt} {acl_check_rcpt_submit} }
acl_smtp_data = /etc/acls/${lookup{$sender_host_address}lsearch{/etc/acllist}{$value}{default}}

(то есть подобное условие if существования файла с переменной $domain указать в значении acl_еще_понять_каком).

Тут https://sysadmin.pm/exim-filters/ прочел про system_filter, разбирается кейс блокирования исходящей почты. В нем можно использовать условие $sender_address contains «@banneddomain.com» с отказом принять сообщение, или так не сработает?

Или проще условие на $sender_address_domain либо $sender_address ставить прямо в acl, который выбирается на основе $domain ? Как лучше?

Можно условием if на $local_part применить определенные правила к одному ящику?

Вижу в примерах много if, но ни одного and / &&. Как-то можно сложные логические условия задавать?

Dima_228
() автор топика
Последнее исправление: Dima_228 (всего исправлений: 2)
Ответ на: комментарий от Dima_228

Можно попробовать отвечать ошибкой уже после того как тебе прислали тело письма, но exim наверно так не умеет, да и не знаю как на такое отреагируют отправители.

firkax ★★★★★
()
Ответ на: комментарий от Dima_228

Первый блин комом. Изменил ACL на RCPT TO на такой чтобы можно было настроить индивидуальные правила для каждого юзера каждого домена (в теории) но чтобы не забивать дефолтным файлом всех юзеров - только при наличии файла используются правила из него, при отсутствии файла используется дефолтное правило acl_check_rcpt которое стояло в конфиге до того как я туда полез.

#acl_smtp_rcpt = acl_check_rcpt
acl_smtp_rcpt = ${if exists{/etc/exim4/domains/$domain/acl_rule_$local_part} {/etc/exim4/domains/$domain/acl_rule_$local_part} {acl_check_rcpt}}

Имеется 2 юзера: user1 и user2. На первого есть файл с кастомным правилом, на второго нет. Первый юзер перестал принимать письма:

attempt to use tainted ACL text "/etc/exim4/domains/test.mydomain.com/acl_rule_user1"
temporarily rejected RCPT <user1@test.mydomain.com>: internal configuration error

но при этом видно что acl_smtp_rcpt корректно разворачивается в путь, этот файл находит (а для юзера 2 не находит потому используется дефолтное значение. По запросу attempt to use tainted ACL text в кавычках гугл выдает ровно 1 не релевантный результат…

Написано в доках что значение is expanded before use, далее If the string begins with a slash, Exim uses it as a filename, and reads its contents as an ACL. То есть сначала подставляются переменные, потом это рассматривается как строка, и если она как в моем случае начинается со слеша - правило читается из файла.

internal configuration error возникает независимо от содержимого файла: это может быть даже одно слово accept. Права на файл правильные, те же что accounts, aliases и прочие рядом. В чем может быть проблема?

Dima_228
() автор топика
Последнее исправление: Dima_228 (всего исправлений: 1)
Ответ на: комментарий от Dima_228

tainted строки это такой костыль для безопасности: всё, что пришло по сети, exim считает потенциально вредоносным (tainted) и запрещает использовать эти строки в качестве путей к файлам. В данном случае у тебя это строки $domain и $local_part. Прописать в конфиге, что ты об этом в курсе и считаешь строку достаточно проверенной, невозможно, но проблема таки решаема. Я уже отвечал про это в другой теме, вот ссылка: Ошибка Exim: Tainted filename for search: '/etc/exim4/domains/site.com/aliases' (комментарий)

firkax ★★★★★
()
Ответ на: комментарий от firkax

Блин, о безопасности я как-то не подумал. Но то что Вы пишете не очевидно и вроде не описано в мануале. Действительно ни логин, ни домен не следует указывать в пути к файлу, однако, $domain в моем дефолтном конфиге от панели используется чуть менее чем везде в путях ко всяким форвардам и алиасам.

Perl не вариант. Как бы не пришлось все таки делать через contains, только я все еще не понял как сделать в if условие AND / &&

acl_smtp_rcpt = ${if exists{/etc/exim4/domains/$domain/acl_rule} {/etc/exim4/domains/$domain/acl_rule} {acl_check_rcpt}}

Попробовал вот так (без логина юзера) - используется везде дефолтный acl_check_rcpt, хотя файл acl_rule существует. Ошибка tainted не возникает. Буду пробовать файл с логинами и параметром да или нет второй колонкой…

Dima_228
() автор топика
Последнее исправление: Dima_228 (всего исправлений: 1)
Ответ на: комментарий от Dima_228

Вот как должно выглядеть это извращение для того чтобы на каждого юзера простым созданием файла можно было сделать дополнительные ACL правила (если файла нет - используется обработчик по умолчанию acl_check_rcpt.

acl_smtp_rcpt = ${if exists{/etc/exim4/domains/${lookup{$domain}dsearch{/etc/exim4/domains/}}/acl_${extract{1}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/${lookup{$domain}dsearch{/etc/exim4/domains/}}/accounts}}}}} {/etc/exim4/domains/${lookup{$domain}dsearch{/etc/exim4/domains/}}/acl_${extract{1}{:}{${lookup{$local_part}lsearch{/etc/exim4/domains/${lookup{$domain}dsearch{/etc/exim4/domains/}}/accounts}}}}} {acl_check_rcpt}}

Для ситуации отдельного обработчика на домен решение вот

acl_smtp_rcpt = ${if exists{/etc/exim4/domains/${lookup{$domain}dsearch{/etc/exim4/domains/}}/acl} {/etc/exim4/domains/${lookup{$domain}dsearch{/etc/exim4/domains/}}/acl} {acl_check_rcpt}}

(Не совсем сам пришел к этому решению, но учитывая совет firkax нашел подходящие почти готовые коды в конфигах. Это все к панели Vesta / Hestia / Myvesta, как и в теме на которую ссылались выше.)

В файле сделанном под определенного юзера уже два варианта - deny по условию, ниже accept либо наоборот, accept по условию ниже deny остальное просто удалил нафиг. Кажется, работает как надо. Скорее всего проблема решена, всем спасибо.

Dima_228
() автор топика

Так, многие российские госорганы заблокировали прием сообщений с зарубежных доменов (в частности, .com) либо наоборот, по принципу белого списка, принимают почту только с доменов .ru

Столяров еще и yandex.ru заблокировал

rtxtxtrx
()
Ответ на: комментарий от rtxtxtrx

Yandex клоуны, раньше можно было привязать телефон к аккаунту и удалить его, а сейчас удалить (отвязать) физически невозможно. А кто такой Столяров я вообще не имею понятия :-)

Dima_228
() автор топика