dnl dnl Использование ratelimit'ов dnl dnl NO - не использовать ratelimit'ы dnl HOST - использовать ratelimit'ы по хостам отправителей dnl AUTH - использовать ratelimit'ы по учетным записям dnl аутентифицировавшихся отправителей dnl AUTH_FAILED - использовать ratelimit'ы по неудачным попыткам аутентификации dnl AUTH_RCPT_UNKNOWN - использовать ratelimit'ы по несуществующим получателям dnl в письмах от аутентифицированных отправителей dnl AUTH_WHEN_NOT_ADVERTISED - использовать ratelimit'ы по хостам, с которых dnl производятся попытки аутентифицироваться тогда, когда SMTP dnl аутентификация не анонсирована dnl MAIL - использовать ratelimit'ы по адресам отправителей dnl RCPT - использовать ratelimit'ы по адресам получателей dnl DEBUG - выводить в файл протокола результаты расчет dnl ratelimit'ов вне зависимости от их превышения dnl define(`confRATELIMIT', `NO')dnl dnl dnl возможно одновременное использование нескольких значений, разделённых пробелами. dnl значение AUTH_RCPT_UNKNOWN может использоваться только в случае использования RCPT в значении confVERIFY_RECIPIENT. dnl dnl настройки ratelimit'ов по хостам отправителей указываются в файле ratelimit-host dnl настройки ratelimit'ов по учетным записям аутентифицировавшихся отправителей указываются в файле ratelimit-auth dnl настройки ratelimit'ов по неудачным попыткам аутентификации указываются в файле ratelimit-host-auth-failed dnl настройки ratelimit'ов по несуществующим получателям в письмах от аутентифицированных отправителей указываются в файле ratelimit-auth-rcpt-unknown dnl настройки ratelimit'ов по адресам отправителей указываются в файле ratelimit-mail dnl настройки ratelimit'ов по адресам получателей указываются в файле ratelimit-rcpt dnl dnl во всех файлах настроек ratelimit'ов данные указываются однотипно в виде: dnl dnl аргумент : лимит, блокировка : действие : сообщение dnl dnl где: dnl аргумент - это адрес хоста отправителя в случае ratelimit-host и dnl ratelimit-host-auth-failed dnl SMTP логин в случае ratelimit-auth dnl адреса отправителя и получателя в случае ratelimit-mail dnl и ratelimit-rcpt dnl лимит - ограничение в виде "количество / период" dnl блокировка - длительность дополнительной блокировки при срабатывании ratelimit dnl действие - действие, применяемое к письму (может отсутствовать) dnl сообщение - сообщение SMTP клиенту dnl dnl адреса хостов можно задавать в виде IP адресов, номеров сетей, имен dnl хостов, в том числе указанных по маске или в виде регулярного dnl выражения. dnl dnl SMTP логины и адреса отправителей и получателей можно указывать в dnl виде полных адресов, масок или регулярных выражений. dnl dnl "лимит" указывается в виде "количество_сообщений / период_времени". dnl "период_времени" указывается в виде 5s, 10m30s, 1h10m и т. д. dnl dnl "блокировка" явлется необязательным параметром. dnl длительность блокировки указывается в таком же виде, как и "период_времени" dnl с помощью параметра "блокировка" можно применять дополнительную блокировку dnl указанной длительности при срабатывании ratelimit. dnl dnl возможные действия: dnl ok - исключение из проверки dnl skip - синоним для ok dnl warn - вывод предупреждения в файл протокола и добавление в письмо поля заголовка dnl reject - отказ в приеме сообщения dnl deny - синоним для reject dnl defer - возврат временной ошибки dnl greylist=XX - добавление XX баллов к счетчику опционального грейлистинга dnl reject=XX - добавление XX баллов к счетчику опционального reject'а dnl delay=XX - задержка на XX секунд перед продолжением обработки сообщения dnl pause=XX - синоним delay=XX dnl dnl при отсутствии явно указанного действия по умолчанию применяется действие defer. dnl dnl при описании действий можно использовать вычисляемые выражения. dnl пример: dnl * : 20 / 10m : defer delay=${eval:${sg{$sender_rate}{\N\..*$\N}{}} - $sender_rate_limit} : Try again later dnl dnl в качестве сообщения SMTP клиенту указывается не столько само dnl сообщение, сколько его уточнение dnl в уточнении сообщения SMTP клиенту можно использовать вычисляемые dnl выражения, например в нем можно использовать переменные $sender_rate, dnl $sender_rate_limit и $sender_rate_period dnl dnl по умолчанию SMTP клиенту возвращаются следующие сообщения: dnl Sender host rate exceeded limit dnl Authenticated sender rate exceeded limit dnl Failed authenticated sender host rate exceeded limit dnl Too many authentication attempts dnl Sender rate exceeded limit dnl Recipient rate exceeded limit dnl dnl далее следует уточнение сообщения. если оно отсутсвует, то dnl используется фраза "Try again later" dnl ifdef(`confRATELIMIT', `ifelse(confRATELIMIT, `NO', `', `dnl dnl #################### CONNECT #################### ifelse(SECTION, `ACL_CHECK_CONNECT', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `dnl # rate limit прошлых попыток аутентификации при отсутствии анонса аутентификации FEATURE(`ratelimit_host_auth_when_not_advertised')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `') ifelse_strstr(` 'confRATELIMIT` ', ` HOST ', `dnl # rate limit коннектов с хостов отправителей warn set acl_m_normalize_action_result = set acl_m_rate_host = ${sg{${lookup{$sender_host_address}iplsearch{CONFDIR/ratelimit-host}{$value}{}}}{\N^\s+\N}{}} condition = ${if eq{$acl_m_rate_host}{}{yes}{no}} condition = ${if eq{$sender_host_name}{}{no}{yes}} set acl_m_rate_host = ${sg{${lookup{$sender_host_name}wildlsearch{CONFDIR/ratelimit-host}{$value}{}}}{\N^\s+\N}{}} warn condition = ${if eq{$acl_m_rate_host}{}{no}{yes}} set acl_m_rate_host = ${if match{$acl_m_rate_host}{\N(?i)^\s*(no|skip)\N}{}{$acl_m_rate_host}} condition = ${if eq{$acl_m_rate_host}{}{no}{yes}} set acl_m_rate_host = ${sg{$acl_m_rate_host}{eval:}{eval╕}} set acl_m_limit = ${extract{1}{,}{${extract{1}{:}{$acl_m_rate_host}}}} set acl_m_limit = ${sg{$acl_m_limit}{eval╕}{eval:}} set acl_m_limit = ${if match{$acl_m_limit}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_limit}}{$acl_m_limit}} # ratelimit = $acl_m_limit / per_conn / strict / ${if isip6{$sender_host_address}{${ipv6denorm:$sender_host_address}/64}{$sender_host_address}} ratelimit = $acl_m_limit / per_conn / strict / ${if isip6{$sender_host_address}{${sg{${ipv6denorm:$sender_host_address}}{\N(:\d+){4}$\N}{:0000:0000:0000:0000}}/64}{$sender_host_address}} set acl_m_action = ${extract{2}{:}{$acl_m_rate_host}} set acl_m_action = ${sg{$acl_m_action}{eval╕}{eval:}} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = Sender host rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} set acl_m_smtp_message = ${extract{3}{:}{$acl_m_rate_host}} set acl_m_smtp_message = Sender host rate exceeded limit.${if eq{$acl_m_smtp_message}{}{Try again later}{$acl_m_smtp_message}} set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', ` warn condition = ${if eq{$acl_m_rate_host}{}{no}{yes}} log_message = DEBUG: Sender host ${if eq{$sender_host_name}{}{}{$sender_host_name }}[$sender_host_address]${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} rate $sender_rate / $sender_rate_limit / $sender_rate_period ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `') FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` HOST ', `') ') dnl ifelse(SECTION, `ACL_CHECK_CONNECT', `') dnl #################### /CONNECT #################### dnl #################### AUTH #################### ifelse(SECTION, `ACL_CHECK_AUTH', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `dnl FEATURE(`ratelimit_host_auth_when_not_advertised')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `') ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `dnl # rate limit прошлых неудачных попыток аутентификации warn set acl_m_normalize_action_result = condition = ${if eq{$acl_c_prerate_host_auth_failed}{yes}{no}{yes}} set acl_m_rate_host_auth_failed = ${sg{${lookup{$sender_host_address}iplsearch{CONFDIR/ratelimit-host-auth-failed}{$value}{}}}{\N^\s+\N}{}} condition = ${if eq{$acl_m_rate_host_auth_failed}{}{yes}{no}} condition = ${if eq{$sender_host_name}{}{no}{yes}} set acl_m_rate_host_auth_failed = ${sg{${lookup{$sender_host_name}wildlsearch{CONFDIR/ratelimit-host-auth-failed}{$value}{}}}{\N^\s+\N}{}} warn condition = ${if eq{$acl_m_rate_host_auth_failed}{}{no}{yes}} set acl_m_rate_host_auth_failed = ${if match{$acl_m_rate_host_auth_failed}{\N(?i)^\s*(no|skip)\N}{}{$acl_m_rate_host_auth_failed}} condition = ${if eq{$acl_m_rate_host_auth_failed}{}{no}{yes}} set acl_m_rate_host_auth_failed = ${sg{$acl_m_rate_host_auth_failed}{eval:}{eval╕}} set acl_m_limit = ${extract{1}{,}{${extract{1}{:}{$acl_m_rate_host_auth_failed}}}} set acl_m_limit = ${sg{$acl_m_limit}{eval╕}{eval:}} set acl_m_limit = ${if match{$acl_m_limit}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_limit}}{$acl_m_limit}} set acl_c_prerate_host_auth_failed = yes # ratelimit = $acl_m_limit / per_cmd / count=0 / readonly / auth_failed-${if isip6{$sender_host_address}{${ipv6denorm:$sender_host_address}/64}{$sender_host_address}} ratelimit = $acl_m_limit / per_cmd / count=0 / readonly / auth_failed-${if isip6{$sender_host_address}{${sg{${ipv6denorm:$sender_host_address}}{\N(:\d+){4}$\N}{:0000:0000:0000:0000}}/64}{$sender_host_address}} set acl_m_action = ${extract{2}{:}{$acl_m_rate_host_auth_failed}} set acl_m_action = ${sg{$acl_m_action}{eval╕}{eval:}} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = ${sg{${sg{${extract{4}{:}{$acl_m_rate_host_auth_failed}}}{\N^\s+\N}{}}}{\N\s+$\N}{}} set acl_m_log_message = Previous failed authenticated sender host rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}}${if eq{$acl_m_log_message}{}{}{: $acl_m_log_message}} set acl_m_smtp_message = ${sg{${sg{${extract{3}{:}{$acl_m_rate_host_auth_failed}}}{\N^\s+\N}{}}}{\N\s+$\N}{}} # set acl_m_smtp_message = Failed authenticated sender host rate exceeded limit.${if eq{$acl_m_smtp_message}{}{Try again later}{$acl_m_smtp_message}} set acl_m_smtp_message = ${if eq{$acl_m_smtp_message}{}{Failed authenticated sender host rate exceeded limit. Try again later}{$acl_m_smtp_message}} set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} set acl_c_auth_attemps = 0 ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `dnl warn condition = ${if eq{$acl_m_rate_host_auth_failed}{}{no}{yes}} log_message = DEBUG: Previous failed authenticated sender host ${if eq{$sender_host_name}{}{}{$sender_host_name }}[$sender_host_address]${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} rate $sender_rate / $sender_rate_limit / $sender_rate_period ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `') FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `') ') dnl ifelse(SECTION, `ACL_CHECK_AUTH', `') dnl #################### /AUTH #################### dnl #################### QUIT #################### ifelse(SECTION, `ACL_CHECK_QUIT', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `dnl FEATURE(`ratelimit_auth_failed')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `') ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `dnl # rate limit попыток аутентификации при отсутствии анонса аутентификации FEATURE(`ratelimit_host_auth_when_not_advertised')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `') ') dnl ifelse(SECTION, `ACL_CHECK_QUIT', `') dnl #################### /QUIT #################### dnl #################### NOTQUIT #################### ifelse(SECTION, `ACL_CHECK_NOTQUIT', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `dnl FEATURE(`ratelimit_auth_failed')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `') ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `dnl # rate limit попыток аутентификации при отсутствии анонса аутентификации FEATURE(`ratelimit_host_auth_when_not_advertised')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `') ') dnl ifelse(SECTION, `ACL_CHECK_NOTQUIT', `') dnl #################### /NOTQUIT #################### dnl #################### MAIL #################### ifelse(SECTION, `ACL_CHECK_MAIL', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `dnl FEATURE(`ratelimit_host_auth_when_not_advertised')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_WHEN_NOT_ADVERTISED ', `') ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `dnl FEATURE(`ratelimit_auth_failed')dnl FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_FAILED ', `') ifelse_strstr(` 'confRATELIMIT` ', ` AUTH ', `dnl # rate limit успешных попыток аутентификации warn set acl_m_rate_auth = set acl_m_normalize_action_result = authenticated = * set acl_m_rate_auth = ${sg{${lookup{$authenticated_id}wildlsearch{CONFDIR/ratelimit-auth}{$value}{}}}{\N^\s+\N}{}} set acl_m_rate_auth = ${if match{$acl_m_rate_auth}{\N(?i)^\s*(no|skip)\N}{}{$acl_m_rate_auth}} condition = ${if eq{$acl_m_rate_auth}{}{no}{yes}} set acl_m_rate_auth = ${sg{$acl_m_rate_auth}{eval:}{eval╕}} set acl_m_limit = ${extract{1}{,}{${extract{1}{:}{$acl_m_rate_auth}}}} set acl_m_limit = ${sg{$acl_m_limit}{eval╕}{eval:}} set acl_m_limit = ${if match{$acl_m_limit}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_limit}}{$acl_m_limit}} ratelimit = $acl_m_limit / per_mail / strict / auth-${authenticated_id} set acl_m_action = ${extract{2}{:}{$acl_m_rate_auth}} set acl_m_action = ${sg{$acl_m_action}{eval╕}{eval:}} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = Authenticated sender rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} set acl_m_smtp_message = ${extract{3}{:}{$acl_m_rate_auth}} set acl_m_smtp_message = Authenticated sender rate exceeded limit.${if eq{$acl_m_smtp_message}{}{Try again later}{$acl_m_smtp_message}} set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `dnl warn condition = ${if eq{$acl_m_rate_auth}{}{no}{yes}} log_message = DEBUG: Authenticated sender $authenticated_id from host ${if eq{$sender_host_name}{}{}{$sender_host_name }}[$sender_host_address]${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} rate $sender_rate / $sender_rate_limit / $sender_rate_period ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `') FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(confRATELIMIT` ', `AUTH ', `') ifelse_strstr(` 'confRATELIMIT` ', ` MAIL ', `dnl # rate limit приёма писем по адресам отправителей warn set acl_m_normalize_action_result = set acl_m_rate_mail = ${sg{${lookup{$sender_address}wildlsearch{CONFDIR/ratelimit-mail}{$value}{}}}{\N^\s+\N}{}} set acl_m_rate_mail = ${if match{$acl_m_rate_mail}{\N(?i)^\s*(no|skip)\N}{}{$acl_m_rate_mail}} condition = ${if eq{$acl_m_rate_mail}{}{no}{yes}} set acl_m_rate_mail = ${sg{$acl_m_rate_mail}{eval:}{eval╕}} set acl_m_limit = ${extract{1}{,}{${extract{1}{:}{$acl_m_rate_mail}}}} set acl_m_limit = ${sg{$acl_m_limit}{eval╕}{eval:}} set acl_m_limit = ${if match{$acl_m_limit}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_limit}}{$acl_m_limit}} ratelimit = $acl_m_limit / per_mail / strict / $sender_address set acl_m_action = ${extract{2}{:}{$acl_m_rate_mail}} set acl_m_action = ${sg{$acl_m_action}{eval╕}{eval:}} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = Sender rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} set acl_m_smtp_message = ${extract{3}{:}{$acl_m_rate_mail}} set acl_m_smtp_message = Sender rate exceeded limit.${if eq{$acl_m_smtp_message}{}{Try again later}{$acl_m_smtp_message}} set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `dnl warn condition = ${if eq{$acl_m_rate_mail}{}{no}{yes}} log_message = DEBUG: Sender ${if eq {$sender_address}{}{<>}{$sender_address}} from host ${if eq{$sender_host_name}{}{}{$sender_host_name }}[$sender_host_address]${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} rate $sender_rate / $sender_rate_limit / $sender_rate_period ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `') FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` MAIL ', `') ') dnl ifelse(SECTION, `ACL_CHECK_MAIL', `') dnl #################### /MAIL #################### dnl #################### RCPT #################### ifelse(SECTION, `ACL_CHECK_RCPT', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` RCPT ', `dnl # rate limit приёма писем по адресам получателей warn set acl_m_normalize_action_result = set acl_m_rate_rcpt = ${sg{${lookup{$local_part@$domain}wildlsearch{CONFDIR/ratelimit-rcpt}{$value}{}}}{\N^\s+\N}{}} set acl_m_rate_rcpt = ${if match{$acl_m_rate_rcpt}{\N(?i)^\s*(no|skip)\N}{}{$acl_m_rate_rcpt}} condition = ${if eq{$acl_m_rate_rcpt}{}{no}{yes}} set acl_m_rate_rcpt = ${sg{$acl_m_rate_rcpt}{eval:}{eval╕}} set acl_m_limit = ${extract{1}{,}{${extract{1}{:}{$acl_m_rate_rcpt}}}} set acl_m_limit = ${sg{$acl_m_limit}{eval╕}{eval:}} set acl_m_limit = ${if match{$acl_m_limit}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_limit}}{$acl_m_limit}} ratelimit = $acl_m_limit / per_rcpt / strict / ${local_part}@${domain} set acl_m_action = ${extract{2}{:}{$acl_m_rate_rcpt}} set acl_m_action = ${sg{$acl_m_action}{eval╕}{eval:}} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = Recipient rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} set acl_m_smtp_message = ${extract{3}{:}{$acl_m_rate_rcpt}} set acl_m_smtp_message = Recipient rate exceeded limit.${if eq{$acl_m_smtp_message}{}{Try again later}{$acl_m_smtp_message}} set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `dnl warn condition = ${if eq{$acl_m_rate_rcpt}{}{no}{yes}} log_message = DEBUG: Recipient $local_part@$domain rate $sender_rate / $sender_rate_limit / $sender_rate_period ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `') FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` RCPT ', `') ') dnl ifelse(SECTION, `ACL_CHECK_RCPT', `') ifelse(SECTION, `ACL_CHECK_RCPT_VERIFY_RECIPIENT', `dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_RCPT_UNKNOWN ', `dnl # rate limit по несуществующим адресам получателей в разрезе SMTP логинов warn set acl_m_rate_auth_rcpt_unknown = set acl_m_normalize_action_result = authenticated = * set acl_m_rate_auth_rcpt_unknown = ${sg{${lookup{$authenticated_id}wildlsearch{CONFDIR/ratelimit-auth-rcpt-unknown}{$value}{}}}{\N^\s+\N}{}} set acl_m_rate_auth_rcpt_unknown = ${if match{$acl_m_rate_auth_rcpt_unknown}{\N(?i)^\s*(no|skip)\N}{}{$acl_m_rate_auth_rcpt_unknown}} condition = ${if eq{$acl_m_rate_auth_rcpt_unknown}{}{no}{yes}} set acl_m_rate_auth_rcpt_unknown = ${sg{$acl_m_rate_auth_rcpt_unknown}{eval:}{eval╕}} set acl_m_limit = ${extract{1}{,}{${extract{1}{:}{$acl_m_rate_auth_rcpt_unknown}}}} set acl_m_limit = ${sg{$acl_m_limit}{eval╕}{eval:}} set acl_m_limit = ${if match{$acl_m_limit}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_limit}}{$acl_m_limit}} set acl_m_action = ${extract{2}{:}{$acl_m_rate_auth_rcpt_unknown}} set acl_m_action = ${sg{$acl_m_action}{eval╕}{eval:}} set acl_m_smtp_message = ${extract{3}{:}{$acl_m_rate_auth_rcpt_unknown}} set acl_m_smtp_message = Too many authentication attempts.${if eq{$acl_m_smtp_message}{}{Try again later}{$acl_m_smtp_message}} warn authenticated = * set acl_m0 = ! verify = recipient/callout=use_sender,120s,defer_ok set acl_m_verify_message = ${sg{$acl_verify_message}{\n}{ }} set acl_m0 = failed condition = ${if eq{$acl_m_rate_auth_rcpt_unknown}{}{no}{yes}} ratelimit = $acl_m_limit / per_cmd / strict / auth-rcpt-unknown-${authenticated_id} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = Authenticated sender unknown recipients rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period${if eq{$acl_c_geo_data}{}{}{ ($acl_c_geo_data)}} set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `dnl warn condition = ${if eq{$acl_m_rate_auth_rcpt_unknown}{}{no}{yes}} log_message = DEBUG: Authenticated sender $authenticated_id unknown recipients rate $sender_rate / $sender_rate_limit / $sender_rate_period ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` DEBUG ', `') deny authenticated = * condition = ${if eq{$acl_m0}{failed}{yes}{no}} message = Unrouteable address: $acl_m_verify_message warn authenticated = * condition = ${if eq{$acl_m0}{failed}{no}{yes}} condition = ${if eq{$acl_m_rate_auth_rcpt_unknown}{}{no}{yes}} ratelimit = $acl_m_limit / per_cmd / count=0 /readonly / auth-rcpt-unknown-${authenticated_id} set acl_m_action = ${if match{$acl_m_action}{\N.+(lookup |[\{\}])\N}{${expand:$acl_m_action}}{$acl_m_action}} acl = acl_normalize_action "$acl_m_action" set acl_m_normalize_action_result = ${if match{$acl_m_normalize_action_result}{\N^\s*$\N}{defer}{$acl_m_normalize_action_result}} set acl_m_normalize_action_result = ${sg{$acl_m_normalize_action_result }{\N\b([^=\s\d]+)(\s)\N}{\$1=00\$2}} set acl_m_log_message = Authenticated sender unknown recipients rate $sender_rate exceeded limit $sender_rate_limit messages per $sender_rate_period set acl_m_smtp_message = ${if match{$acl_m_smtp_message}{\N(^\$|[^\\]\$)\N}{${expand:$acl_m_smtp_message}}{$acl_m_smtp_message}} FEATURE(`ratelimit_actions')dnl ') dnl ifelse_strstr(` 'confRATELIMIT` ', ` AUTH_RCPT_UNKNOWN ', `') ') dnl ifelse(SECTION, `ACL_CHECK_RCPT_VERIFY_RECIPIENT', `') dnl #################### /RCPT #################### ')') dnl ifdef(`confRATELIMIT', `ifelse(confRATELIMIT, `NO', `', `')')