[Карта]                      [Начало]                      [Sendmail-ссылки]                      [Синтаксис]                      [Типовые задачки]                      [Задачки по маршрутизации]                      [Задачки по маcкарадингу]                      [SendmailACL]                      [Spamooborona]                      [VadeRetro]                      [Regex]                      [Тонкости]                      [Недок.особен.]                      [Несущ.юзеры]                      [Прячемся!]                      [RFC1893.Цитаты]                      [ТП.Эмоции]                      [Антиспам&Разум]                     

Боремся с перебором почтовых ящиков.


Теорию по поводу несуществующих юзеров можно посмотреть здесь.

Итак, заблокируем перебор имен почтовых ящиков (наложение ограничения на число отказов "User unknown")
Рассмотрим 3 случая, когда:
  • 1. почтовые пользователи являются системными;
  • 2. почтовые пользователи не являются системными;
  • 3. почтовые пользователи являются транзитными.


  • В первом случае получатели письма являются не только локальными для данного почтовика, но и системными, то есть они прописаны в /etc/passwd.
    Во втором случае локальные получатели не являются системными, а информация о них хранится, например, в БД.
    В третьем случае мы имеем дело с mx-ом, который должен пересылать почту на основной почтовик. MX ничего не знает о транзитных получателях.

    1. Век живи - век учись, оказывается, у sendmail уже есть встроенный макрос nbadrcpts, который содержит количество неопознанных получателей. Благодаря этому, проверка оказывается весьма лаконичной:
    LOCAL_CONFIG
    D{Allowed_Unknown_Rcpts}5
    Ksyslog syslog
    LOCAL_RULESETS
    HFrom:                   $>CheckFrom
    R$*                   $: $(arith l $@ $&{nbadrcpts} $@ $&{Allowed_Unknown_Rcpts} $)
    Запишем для контроля значения в лог
    RFALSE                   $: $(syslog syslog:CheckFrom:FALSE:Internal:$&{nbadrcpts} - Allowed.Un.Rec:$&{Allowed_Unknown_Rcpts} $) FALSE
    RFALSE                   $#error $: 553 Unknown users rate exceeds.

    Таким образом, рассылка будет запрещена, если количество неопознанных объектов среди получателей превышает 5 адресов.

    2. В этом случае невозможно воспользоваться внутренними макросами sendmail - $&{nrcpts}(кол-во реальных получателей письма) & $&{nbadrcpts}(количество несуществующих получателей). Значит, придется прописывать получателей в отдельном файле, мы используем для этих целей файл /etc/mail/access.
    Эта задача состоит из двух:
    1) нужно определить, знает ли о таком получателе наша почтовая система;
    2) если пользователь не известен, то посчитать, какой он по счету за данную сессию и на основании этого числа принять решение о принятии/блокировке почты.

    Поскольку в явном виде "User unknown" в sendmail.cf мы не увидим, поэтому для проверки на количество неверно заданных получателей мы добавим собственный набор правил в Local_check_rcpt.
    Для начала редактируем /etc/mail/access, прописав в нем всех своих локальных клиентов и последней строкой запретив все остальные имена.
    Напоминаю: для того, чтобы sendmail обращался к этому файлу необходимо в sendmail.mc включить строку FEATURE(access_db)
    А для того, чтобы можно было блокировать получение почты локальными клиентами, необходимо еще добавить FEATURE(blacklist_recipients).
    Иначе будете ССЗБ.

    #Разрешаем получение почты локальными(но не системными) пользователями user1, user2, etc

    To:user1@domain.ru                   [TAB]                   OK
    To:user2@domain.ru                   [TAB]                    OK
    ....
    #Запрещаем почту для всех остальных вариантов имен почтовых ящиков :
    To:domain.ru                   [TAB]                   ERROR:"550 User unknown"

    Решаем вторую задачу: нужно посчитать количество неопознанных юзеров за одну сессию.
    Редактируем sendmail.cf
    LOCAL_CONFIG
    Ksyslog syslog
    Kstorage macro
    Допустимое количество неопознанных юзеров за сессию - 3
    D{Allowed_U_nr}3
    Начальное значение счетчика неопознанных юзеров.
    D{Unknown_Rcpts}0

    LOCAL_RULESETS
    SLocal_check_rcpt
    #Канонизируем адрес получателя
    R$*                    $: $>3 $1

    #Почту для локальных пользователей отправляем на дальнейшую проверку в CheckLocalUser, при этом освобождаемся от доменной части - она нам пока не понадобится
    R$+<@$=w.>                    $: $>CheckLocalUser $1
    #Если в CheckLocalUser проверка была успешной, то на выходе мы получим OK, и такую почту пропускаем дальше
    #(Недостаток след. строки в том, что почта для пользователя OK станет приниматься вашим сервером,
    #даже если такого пользователя нет.
    #Поэтому небходимо в /etc/mail/access добавить строку: To:OK@      [TAB]      550 Unknown user
    #обращаю внимание на обязательность знака @ в предыд. строке - он сигналит sendmail о том, что это имя
    #_локального_ пользователя (Please note: a local username must be now tagged with an @
    #(this is consistent with the check of the sender address, and hence it is possible to distinguish between
    #hostnames and usernames)))
    ROK                   $@ OK

    #Пропускаем почту с внешними доменными именами
    R$+<@$+>                    $@ OK

    #Остались адреса локальных получателей, у которых отсутствует доменная часть (это возможно сделать в sendmail -bs, telnet & TheBat)
    #Отправляем их на дальнейшую проверку в CheckLocalUser
    R$+                    $: $>CheckLocalUser $1
    ROK                   $@ OK

    #Контрольная провека - кто остался неохваченным нашими правилами
    R$*                   $: $(syslog syslog:RCPT_PROBLEM1: $1 $) $1

    SCheckLocalUser

    #Проверяем наличие подобного адреса в access
    R$*                   $: $(access $1@domain.ru $)
    #Если он присутствует - пропускаем
    ROK                   $@ OK
    #Нет - увеличиваем число несуществующих клиентов в данной сессии на 1
    R$*                   $: $(arith + $@ $&{Unknown_Rcpts} $@ 1 $)
    #Присваиваем макросу {Unknown_Rcpts} полученное значение
    R$*                    $: $(storage {Unknown_Rcpts} $@ $1 $)

    HFrom:                $>CheckFrom
    SCheckFrom
    #Проверяем, не превышает ли число несуществующих клиентов заявленное выше значение
    R$+                    $: $(arith l $@ $&{Unknown_Rcpts} $@ $&{Allowed_U_nr} $)
    # Clear the macros {Unknown_Rcpts} for the next message
    R$*                   $: $(storage {Unknown_Rcpts} $) $1
    #Превышает - запрещаем письмо
    RFALSE                   $#error $: 553 Sorry, too many unknown users ...


    3. Решение для транзитной почты аналогично предыдущему за исключением мелких, но важных деталей: ключа RELAY, имени транзитного домена и в access, и в нашем наборе правил.
    Редактируем access.
    Зная о вот такой замечательной возможности sendmail, разрешаем получение почты транзитными пользователями user1, user2, etc

    To:user1@transit.ru                    [TAB]                   RELAY
    To:user2@transit.ru                    [TAB]                   RELAY
    ....
    #Запрещаем почту для всех остальных вариантов имен почтовых ящиков :
    To:transit.ru                   [TAB]                   ERROR:"550 User unknown"

    Редактируем sendmail.mc
    LOCAL_CONFIG
    Ksyslog syslog
    Kstorage macro
    #Максимально допустимое число несущ. транзитных получателей
    D{Allowed_Unknown_Rcpts}3
    #Макрос, накапливающий число несущ. транзитных получателей
    D{Unknown_Rcpts}0

    SLocal_check_rcpt
    #Канонизируем адрес получателя
    R$*                   $: $>3 $1

    #Почту для транзитных пользователей отправляем на дальнейшую проверку в CheckTransitUser, при этом освобождаемя от доменной части - она нам пока не понадобится
    R$+<@transit.ru.>                   $: $>CheckTransitUser $1
    #Если в CheckTransitUser проверка была успешной, то на выходе мы получим OK, и такую почту пропускаем дальше
    #(Недостаток след. строки в том, что почта для пользователя OK станет приниматься вашим сервером, даже если такого пользователя нет.
    #Поэтому небходимо в /etc/mail/access добавить строку: OK@ [TAB] 550 Unknown user)
    ROK                    $@ OK

    #Остальную почту тоже пропускаем
    R$+                   $@ OK

    SCheckTransitUser
    R$*                   $: $(access To:$1@transit.ru $)
    RRELAY                   $@ OK
    R$*                    $: $(arith + $@ $&{Unknown_Rcpts} $@ 1 $)
    R$*                   $: $(storage {Unknown_Rcpts} $@ $1 $)

    HFrom:                   $>CheckFrom
    SCheckFrom
    R$*                   $: $(arith l $@ $&{Unknown_Rcpts} $@ $&{Allowed_Unknown_Rcpts} $)
    # Clear the macros {Unknown_Rcpts} for the next message
    R$*                   $: $(storage {Unknown_Rcpts} $) $1
    RFALSE                   $: $(syslog syslog:CheckFrom:FALSE: Unk.Rec.:$&{Unknown_Rcpts}-Allowed.Unk.Rec:$&{Allowed_Unknown_Rcpts} $) FALSE
    RFALSE                    $#error $: 553 Sorry, too many unknown users...

    В среднем на одно такое "переборное" спам-письмо приходится 4-5 реальных получателей. То есть, если отлуп случился 100 раз за сутки, то его не получили от 400 до 500 получателей.
    Страница кардинально переписана 30 ноября 2007