http://linux.ufaras.ru/SendmailACL.html ----------------------------------------- LOCAL_CONFIG Ksyslog syslog Kallow hash /etc/mail/allow Kdeny hash /etc/mail/deny C{OnlyLocal}OK NOR F{Group1}/etc/mail/group1 F{Group2}/etc/mail/group2 F{Group3}/etc/mail/group3 LOCAL_RULESETS SLocal_check_rcpt # ПОЛИТИКА: Все, что не разрешено, то запрещено! # Это локальный набор правил, обрабатывающий адрес получателя. # На вход в Local_check_rcpt подается заключенный в угловые скобки адрес получателя. # Сначала разберемся с бездоменными локальными получателями. # Помечаем любого получателя меткой R$+ $: $1 # Освобождаем от метки доменных получателей R<$+@$+> $: <$1@$2> # С меткой остались только бездоменные получатели, и мы присоединяем # полностью разрешенное имя хоста, которое определяется # следующим образом: сначала вызывается команда gethostname, # которая дает имя хоста, это имя хоста затем передается команде gethostbyname, # которое должно вернуть каноническое имя хоста (см. op.me). # Позаботьтесь самостоятельно о том, # чтобы это имя попало в класс $=w - перечень всех доменных имен, под которыми известен хост. # Потому что в дальнейшем для определения локальности почты я буду пользоваться именно этим классом # R<$+> $: <$1@$j> # Теперь "все сестры с серьгами", а получатели с доменами, можно от метки освободиться R<$+> $: <$1> #Добавляем адрес отправителя - $&f R$* $: $(syslog syslog:last: $1 $) $1 R$* $: $&f $| $1 R$* $: $(syslog syslog:last1: $1 $) $1 # Все неправильности (несуществующий или неразрезолвленный домен, запреты в access, etc) с эл.адресом отправителя уже обработаны в check_mail, поэтому мы их не обрабатываем. # Для пользователей delay_check эти проверки не провожу, иначе никогда этот набор не закончу. # Канонизируем адреса отправителя и получателя R$* $| $* $: $2 $| $>Parse0 $>3 $1 R$* $| $* $: $2 $| $>Parse0 $>3 $1 # Отлупы мэйлер-даемона пропускаем R<@> $| $* $@ OK R$+<@$+> $| $+<@$+> $: $1<@$2> $| $3<@$4> R$+<@$+.> $| $+<@$+.> $: $1<@$2.> $| $3<@$4.> R$+ $#error $: "553 5.1.8 Domain of sender/recipient address does not exist." # Блокировки для виртуальных доменов. # Пока не знаю, как это втолкнуть в CheckACL - ведь я туда не передаю домен локального отправителя # И не хотелось бы с ним там таскаться #$+<@apache.anrb.ru.> $| $+<@mail.ru.> $#error $: 553 You are not allowed to send to this recipient -Nooo R$* $: $(syslog syslog:last2: $1 $) $1 # Добавляем макрос $&{auth_authen} - свидетельство имевшей место smtp-авторизации # Если отправитель использовал smtp-авторизацию, то значение макроса совпадет с именем клиента. # R$+ $: <$&{auth_authen}> $1 R$* $: $(syslog syslog:last3: $1 $) $1 # Если отправитель использовал smtp-авторизацию, то в угловых скобках что-то будет (<$+>) # Ели при этом почта предназначена локальному клиенту (домен принадлежит классу w), # то пропускаем письмо дальше R<$+> $+<@$+> $| $+<@$=w.> $@ OK R$* $: $(syslog syslog:last4 $1 $) $1 # Если отправитель авторизовался, но отправляет письмо внешнему клиенту # (случай с локальными получателями обработан предыд. правилом), то отправляем # использованное локальным отправителем для авторизации имя и адрес внешних получателя # в CheckACL для проверки наличия прав для отправки письма # В этом случае использованный отправителем эл.адрес нас не интересует, самое главное, он авторизовался. # R<$+> $+<@$+> $| $+<@$+> $: $>CheckACL From:$1:$4<@$5> ROK $@ OK #### delay_check: #Если отправитель авторизовался, но не указал домен в эл. адресе, то мы его спросим, зачем он нам морочит голову #### delay_check: R<$+> $+ $| $+ $# error $: "553 Where is your mail domain?" # Кто остался не охваченым нашими правилами в случае smtp-авторизации R<$-> $* $: $(syslog syslog:problem0: <$1>$2 $) <$1>$2 #R<$*> $* $: $(syslog syslog:problem000: <$1>$2 $) <$1>$2 # А это отправители без smtp-авторизации R<>$* $: $(syslog syslog:no-auth: $1 $) $1 # Избавляемся от признака smtp-авторизации R<$*>$* $: $2 # Проверяем локальность IP-адреса. # Добавляем IP-адрес отправителя - $&{client_addr} R$+ $: $&{client_addr} $| $1 R$* $: $(syslog syslog:last6: $1 $) $1 # Пометим словом почту с непосредственно с нашего сервера R 127.0.0.1 $| $+ $: $| $1 R$* $: $(syslog syslog:last60: $1 $) $1 # Пометим словом почту с ip-адресов, указанных в /etc/mail/relay-domains R $=R $* $| $+ $: $| $3 R$* $: $(syslog syslog:last600: $1 $) $1 # Анализируем файл /etc/mail/access: R $-.$-.$-.$- $| $+ $: <$(access $1.$2.$3.$4 $:$1.$2.$3 $)> $| $5 R$* $: $(syslog syslog:last61: $1 $) $1 R<$-.$-.$-> $| $+ $: <$(access $1.$2.$3 $:$1.$2 $)> $| $4 R$* $: $(syslog syslog:last62: $1 $) $1 R<$-.$-> $| $+ $: <$(access $1.$2 $:NOR $)> $3 # Проверяем результаты просмотра файла /etc/mail/access. # Взято из Scheck_mail sendmail.cf: # check results R $* $#discard $: discard R<> $* $#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later." ## delay_check: R $* $#error $@ quarantine $: $1 ## delay_check: R $* $#error $@ 5.7.1 $: "550 Access denied" ## delay_check: R $* $#error $@ $1.$2.$3 $: $4 ## delay_check: R $* $#error $: $1 #Если отправителю разрешено релеить (из access правило вернулось с меткой ), #и домены отправителя и получателя - локальные (принадлежат классу w, $=w) - пропускаем письмо R $| $+<@$=w.> $| $+<@$=w.> $@ OK R$* $: $(syslog syslog:last7: $1 $) $1 # Если отправителю разрешено релеить, # домен отправителя - локальные (принадлежат классу w, $=w), # а домен получателя любой другой кроме локального (локальщики с доменом уже пропущены предыдущим правилом) # - отправляем имя локального отправителя ($1) без домена и адрес внешнего получателя полностью $3<@$4> # в набор правил CheckACL R $| $+<@$=w.> $| $+<@$+> $: $>CheckACL From:$1:$3<@$4> R$* $: $(syslog syslog:last8: $1 $) $1 ROK $@ OK # Если отправителю разрешено релеить (из access правило вернулось с меткой ), # а домен отправителя нелокальный (локальные домены уже обработаны тремя предыдущими правилами, домен получателя нас не интересует и мб любым) # - запрещаем такую почту. # Мы разрешаем локальному юзеру указывать посторонний домен # только в случае использования им smtp-авторизации, # ведь в этом случае он предоставляет нам свое автризационное имя для проверки в ACL. R $| $+<@$+> $| $+<@$+> $#error $: "553 Non valid local domain name." R$* $: $(syslog syslog:last12: $1 $) $1 #### delay_check: # Не разрешаем бездоменных отправителей из локальной сети. #### delay_check: # Все доменные отправители уже обработаны предыд. правилами #### delay_check: R $| $+ $| $+<@$+> $# error $: "553 Where is your mail domain?" # Там кто-то остался из релейщиков? R $* $: $(syslog syslog:problem1: $1 $) $1 # Избавляемся от IP-адреса, он нам больше не понадобится # Вообще-то это правило лишнее, потому что после прохода через файл /etc/mail/access, # ip-адрес преобразуется в один из ключей: RELAY, OK, DISCARD, etc, и в явном виде больше использоваться не будет. # Но мы подстрахуемся, предварительно записав сообщение о казусе в лог R$-.$-.$-.$- $| $* $: $(syslog syslog:problem2: $1.$2.$3.$4 $5 $) $1.$2.$3.$4 $5 R$-.$-.$-.$- $| $* $: $5 R$* $: $(syslog syslog:last13: $1 $) $1 # Вроде бы всех, кто имеет право релеить почту, мы обработали. # Всех, кто был заблокирован в /etc/mail/access, мы тоже обработали. # Остались те, у кого в качестве ключа в access стоит ОК, # и те, кто вообще не упомянут в access (). # Эти две последние группы имеют право отправлять почту только нашим локальным клиентам. # Но на всякий случай мы сделаем проверку, а вдруг кто остался непомеченным # И заодно запретим внешнюю() почту, подписанную нашим доменом ($=w). R $+<@$=w.> $| $+<@$+> $#error $: "553 Please use your own domain name." R$+ $: $1 R$* $: $(syslog syslog:last131: $1 $) $1 R <$={OnlyLocal}> $+ $: $2 R $+ $: $(syslog syslog:problem3: $1 $) $1 # После всех манипуляций у нас должна остаться пара внешний отправитель:локальный получатель # $+<@$+> $| $+<@$=w.> # Если получатель локальный ($=w), то отправляем тройку To:лок.получатель:внеш.отправитель в # набор правил CheckACL. R$+<@$+> $| $+<@$=w.> $: $>CheckACL To:$3:$1<@$2> R$* $: $(syslog syslog:last14: $1 $) $1 ROK $@ OK R$* $: $(syslog syslog:last140: $1 $) $1 #### А этот куда намылился? Внешниий IP, в smtp-авторизации не замечен, внешний получатель - #### а мы не OPEN RELAY! #### Вообще-то этого перца прекрасно заблокирует и сам sendmail, но позже. #### А если это можно сделать раньше, то почему бы это не сделать сразу. R$+<@$+> $| $+<@$+> $#error $: "553 Go away. We are not open relay!" R$* $: $(syslog syslog:last15: $1 $) $1 #### delay_check: # Бездоменный отправитель. Его также потом заблокирует основной набор правил check_mail, #### delay_check: # но мы сделаем это раньше. #### delay_check: R$+ $| $+ $#error $: "553 Where is your domain name?" #Кто остался не охваченым нашими правилами R$* $: $(syslog syslog:problem5: $1 $) $1 SCheckACL # Итак, вот набор правил, непосредственно проверяющий права пар пользователей, # прописанные в файлах /etc/mail/allow(deny). # На вход этому набору правил подается метка To: или From:, указывающая # на направление движения почты относительно локального пользователя, и пара # локальный пользователь:внешний пользователь. # Эта пара (лок.отправитель:внеш.получатель или лок.получатель:внеш.отправитель) # может быть задана пятью способами. # Первый: локальный юзер или группа:внешний e-mail # Второй: локальный юзер или группа:внешний почтовый домен # Третий: локальный юзер или группа:весь внешний мир # Четвертый: все локальные юзеры:внешний e-mail # Пятый: все локальные юзеры:внешний почтовый домен # Так как по условию задачи файл /etc/mail/allow имеет приоритет перед /etc/mail/deny, # то сначала проверяем, разрешено ли паре общение, и только потом, не запрещено ли оно. # По умолчанию, все не разрешено - запрещено. # Поэтому последним правилом в наборе CheckACL стоит правило, запрещающее все, # что не попало в вышестоящие разрешения #R $#error $: "553 You cannot send any mail to this recipient." # 1. Сначала разберемся с парами лок.отправитель:внеш.e-mail внеш.получателя или лок.получатель:e-mail внеш.отправителя # По условию задачи права этой пары имеют преимущество перед остальныит ограничениями # 1.1.1 Указана ли пара в файле allow? R$* $: $(syslog syslog:ACL0: $1 $) $1 R$+ $: $(allow $1 $) R$* $: $(syslog syslog:ACL1-1-1: $1 $) $1 # Да - пропускаем письмо дальше RALLOW $@ OK # Нет - продолжаем # 1.1.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:внеш.получатель(отправитель) в файле allow? R$+ : $={Group1} : $+ $: <$(allow $1:group1:$3 $:NOAL $)> $1:$2:$3 R$* $: $(syslog syslog:ACL1-1-2: $1 $) $1 # Да - пропускаем письмо дальше R $+ $@ OK # Нет - избавляемся от метки R $+ $: $1 R$* $: $(syslog syslog:ACL1-1-2: $1 $) $1 # 1.1.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:внеш.получатель(отправитель) в файле allow? R$+ : $={Group2} : $+ $: <$(allow $1:group2:$3 $:NOAL $)> $1:$2:$3 R$* $: $(syslog syslog:ACL1-1-3: $1 $) $1 R $+ $@ OK R $+ $: $1 # 1.2.1. Указана ли пара в файле deny? R$+ $: $(deny $1 $) R$* $: $(syslog syslog:ACL1-2-1: $1 $) $1 # Да - блокируем RDENY $#error $: "553 You cannot send any mail to this recipient." # Нет - продолжаем # 1.2.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:внеш.получатель(отправитель) в файле deny? R$+ : $={Group1} : $+ $: <$(deny $1:group1:$3 $:NODEN $)> $1:$2:$3 R$* $: $(syslog syslog:ACL1-2-2: $1 $) $1 # Да - блокируем R $+ $#error $: "553 You cannot send any mail to this recipient." # Нет - избавляемся от метки R $+ $: $1 R$* $: $(syslog syslog:ACL1-2-2: $1 $) $1 # 1.2.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:внеш.получатель(отправитель) в файле deny? R$+ : $={Group2} : $+ $: <$(deny $1:group2:$3 $:NODEN $)> $1:$2:$3 R$* $: $(syslog syslog:ACL1-2-3: $1 $) $1 R $+ $#error $: "553 You cannot send any mail to this recipient." R $+ $: $1 R$* $: $(syslog syslog:ACL1-2-3: $1 $) $1 # 2. Теперь разберемся с парами лок.юзер:домен внешнего получателя(отправителя) # # 2.1.1 Прописана ли эта пара в файле allow? R$+:$+:$+<$+> $: <$(allow $1:$2:<$4> $:NOAL $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL2-1-1: $1 $) $1 R $+ $@ OK R $+ $: $1 R$* $: $(syslog syslog:ACL2-1-1: $1 $) $1 # 2.1.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:домен внеш.получателя(отправителя) в файле allow? R$+ : $={Group1} : $+<$+> $: <$(allow $1:group1:<$4> $:NOAL $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL2-1-2: $1 $) $1 R $+ $@ OK R $+ $: $1 # 2.1.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:домен внеш.получателя(отправителя) в файле allow? R$+ : $={Group2} : $+<$+> $: <$(allow $1:group2:<$4> $:NOAL $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL2-1-3: $1 $) $1 R $+ $@ OK R $+ $: $1 # 2.2.1. Проверяем, а не запрещена ли часом пара лок.юзер:внешний_почтовый_домен в файле deny? R$+:$+:$+<$+> $: <$(deny $1:$2:<$4> $:NODEN $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL2-2-1: $1 $) $1 # Да - блокируем R $+ $#error $: "553 You cannot send any mail to this domain." R $+ $: $1 # 2.2.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:домен внеш.получателя(отправителя) в файле deny? R$+ : $={Group1} : $+<$+> $: <$(deny $1:group1:<$4> $:NODEN $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL2-2-2: $1 $) $1 R $+ $#error $: "553 You cannot send any mail to this domain." R $+ $: $1 # 2.2.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:домен внешнего получателя(отправителя) в файле deny? R$+ : $={Group2} : $+<$+> $: <$(deny $1:group2:<$4> $:NODEN $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL2-2-3: $1 $) $1 R $+ $#error $: "553 You cannot send any mail to this domain." R $+ $: $1 # 3. Следующая пара - локальный юзер:получатель(отправитель)_all. # 3.1.1. Проверяем, указана ли эта пара в файле allow: # (проверка в deny будет избыточной, тк политика по умолчанию - # все, что не разрешено, то запрещено). R$+:$+:$+ $:<$(allow $1:$2:all $:NOAL $)> $1:$2:$3 R$* $: $(syslog syslog:ACL3-1-1: $1 $) $1 R $+ $@ OK R $+ $: $1 # 3.1.2. Если лок. юзер принадлежит группе Group1, указана ли пара лок.группа:all в файле allow? R$+ : $={Group1} : $+ $: <$(allow $1:group1:all $:NOAL $)> $1:$2:$3 R$* $: $(syslog syslog:ACL3-1-2: $1 $) $1 R $+ $@ OK R $+ $: $1 # 3.1.3. Если лок. юзер принадлежит группе Group2, указана ли пара лок.группа:all в файле allow? R$+ : $={Group2} : $+ $: <$(allow $1:group2:all $:NOAL $)> $1:$2:$3 R$* $: $(syslog syslog:ACL3-1-3: $1 $) $1 R $+ $@ OK R $+ $: $1 # 4. Еще одна пара - любой локальный юзер:e-mail внешнего получателя(отправителя). # 4.1. Проверяем, указана ли эта пара в файле allow R$+:$+:$+ $:<$(allow $1:all:$3 $:NOAL $)> $1:$2:$3 R$* $: $(syslog syslog:ACL4-1: $1 $) $1 R $+ $@ OK R $+ $: $1 R$* $: $(syslog syslog:ACL4-1: $1 $) $1 # 4.2. Проверяем, указана ли эта пара в файле deny R$+:$+:$+ $:<$(deny $1:all:$3 $:NODEN $)> $1:$2:$3 R$* $: $(syslog syslog:ACL4-2: $1 $) $1 R $+ $#error $: "553 You cannot send any mail to this user." R $+ $: $1 R$* $: $(syslog syslog:ACL4-2: $1 $) $1 # 5. Последняя пара - любой локальный юзер:домен внешнего получателя(отправителя). # 5.1. Проверяем, указана ли эта пара в файле allow R$+:$+:$+<$+> $:<$(allow $1:all:<$4> $:NOAL $)> $1:$2:$3<$4> R$* $: $(syslog syslog:ACL5-1: $1 $) $1 R $+ $@ OK # 5.2. Проверяем, указана ли эта пара в файле deny - излишнее, так как политика # и так запретит все, что не разрешено. #R$+:$+:$+<$+> $:<$(deny $1:all:<$4> $:NODEN $)> #R$* $: $(syslog syslog:ACL5-2: $1 $) $1 #R $#error $: "553 You cannot send any mail to this domain." ## Заключение. Нет - блокируем письмо R $#error $: "553 You cannot send any mail to this recipient." # Кто-нибудь остался не охваченым нашими правилами? R$* $: $(syslog syslog:problem4: $1 $)