LINUX.ORG.RU
ФорумAdmin

настройка Ratelimit модуля в rspamd

 


0

1

Возможно ли с помощью модуля Ratelimit в rspamd настроить такое:

1. Ограничить кол-во отсылаемых писем с одного IP до 2000 в час 2. При превышении этого лимита письма отклоняюся

Если это возможно, то достаточно ли задать только значения параметров to, to_ip и to_ip_from в /etc/rspamd/modules.d/ratelimit.conf:

ratelimit {
    rates {
        # Limit for all mail per recipient (rate 34 per minute)
        to = "34 / 1min";
        # Limit for all mail per one source ip (rate 34 per minute)
        to_ip = "68 / 2min";
        # Limit for all mail per one source ip and from address (rate 34 per minute)
        to_ip_from = "34 / 1min";
        # Limit for all bounce mail (rate 10 per hour)
        bounce_to = "10 / 1h";
        # Limit for bounce mail per one source ip (rate 5 per hour)
        bounce_to_ip = "5 / 1h";
        # Limit for all mail per authenticated user (rate 5 per minute)
        user = "5 / 1min";
    }
    # If symbol is specified, then it is inserted instead of setting result
    symbol = "R_RATELIMIT";
    whitelisted_rcpts = "postmaster,mailer-daemon";
    max_rcpt = 5;

    .include(try=true,priority=5) "${DBDIR}/dynamic/ratelimit.conf"
    .include(try=true,priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/ratelimit.conf"
    .include(try=true,priority=10) "$LOCAL_CONFDIR/override.d/ratelimit.conf"
}

Если у вас почтовиком работает postfix, то у него есть более простое средство всего в три строки:

anvil_rate_time_unit = 
smtpd_client_message_rate_limit = 
smtpd_client_event_limit_exceptions = 

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

К сожалению работает Exim, текущая конфигурация:

primary_hostname = d-xsmtp02-de.localdomain1.com

domainlist local_domains = @ : localhost
domainlist relay_to_domains =
domainlist relay_domains_restricted = lsearch;/etc/exim/restricted_destination_domains
hostlist   relay_from_hosts = localhost : net-iplsearch;/etc/exim/OPS_Relay_Hosts_All1
hostlist   relay_from_hosts_restricted = net-iplsearch;/etc/exim/OPS_Relay_Hosts_All2
hostlist   Unqualified_Senders = net-iplsearch;/etc/exim/Unqalified_Senders
domainlist domains_No_TLS = lsearch;/etc/exim/domains_No_TLS

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

av_scanner = clamd:/var/run/clamd.exim/clamd.sock

tls_advertise_hosts = *
tls_certificate = /etc/pki/tls/certs/exim.pem
tls_privatekey = /etc/pki/tls/private/exim.pem

daemon_smtp_ports = 25 : 465 : 587
tls_on_connect_ports = 465

qualify_domain = localdomain1.com

qualify_recipient = localdomain1.com

never_users = root

host_lookup = *

auth_advertise_hosts =

prdr_enable = true
 sender_unqualified_hosts = *
 recipient_unqualified_hosts = *

log_selector = +address_rewrite +all_parents +arguments +connection_reject +delay_delivery +deliver_time +delivery_size +dnslist_defer +incoming_interface +incoming_port +lost_incoming_connection +queue_time +queue_time_overall +queue_run +received_sender +received_recipients +rejected_header +retry_defer +sender_on_delivery +size_reject +skip_delivery +smtp_confirmation +smtp_connection +smtp_incomplete_transaction +smtp_protocol_error +smtp_syntax_error +subject +tls_cipher +tls_peerdn +tls_certificate_verified +received_recipients +host_lookup_failed

ignore_bounce_errors_after = 2d

timeout_frozen_after = 7d

split_spool_directory = true

keep_environment = ^LDAP
add_environment = PATH=/usr/bin::/bin
smtp_accept_max_per_connection = 2000
smtp_accept_queue_per_connection = 2000
remote_max_parallel = 50
queue_run_max = 50
smtp_accept_max = 2000
disable_ipv6=true
#smtp_max_synprot_errors = 15

begin acl

acl_check_mail:

  # Hosts are required to say HELO (or EHLO) before sending mail.
  # So don't allow them to use the MAIL command if they haven't
  # done so.

  deny condition = ${if eq{$sender_helo_name}{} {1}}
       message = Nice boys say HELO first

  # Use the lack of reverse DNS to trigger greylisting. Some people
  # even reject for it but that would be a little excessive.

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

  accept

acl_check_rcpt:

  accept  hosts = :
          control = dkim_disable_verify

  deny    message       = Restricted characters in address
          domains       = +local_domains
          local_parts   = ^[.] : ^.*[@%!/|]

  deny    message       = Restricted characters in address
          domains       = !+local_domains
          local_parts   = ^[./|] : ^.*[@%!] : ^.*/\\.\\./

  accept  local_parts   = postmaster
          domains       = +local_domains

  require verify        = sender

  accept  hosts = +relay_from_hosts_restricted
          endpass
          message = $sender_fullhost is not authorized to send to $domain
          domains = +relay_domains_restricted

 #        defer ratelimit = 15 /1h / strict / $sender_host_address 
  #        message = Sender rate exceeds $sender_rate_limit messages per $sender_rate_period
  #        log_message = Local sender rate limit $sender_rate / $sender_rate_period
  accept  hosts         = +relay_from_hosts
  #        defer ratelimit = 15 /1h / strict / $sender_host_address
  #        message = Sender rate exceeds $sender_rate_limit messages per $sender_rate_period
  #        log_message = Local sender rate limit $sender_rate / $sender_rate_period

          control       = submission
          control       = dkim_disable_verify

  accept  authenticated = *
          control       = submission
          control       = dkim_disable_verify

  # Insist that a HELO/EHLO was accepted.

  require message       = nice hosts say HELO first
          condition     = ${if def:sender_helo_name}

  require message = relay not permitted
          domains = +local_domains : +relay_to_domains

  require verify = recipient

  accept

acl_check_data:

  # Deny if the message contains an overlong line.  Per the standards
  # we should never receive one such via SMTP.
  #
  deny    message    = maximum allowed line length is 2300 octets, \
                       got $max_received_linelength
          condition  = ${if > {$max_received_linelength}{2300}}

  warn    condition  = ${if !def:h_Message-ID: {1}}
          set acl_m_greylistreasons = Message lacks Message-Id: header. Consult RFC2822.\n$acl_m_greylistreasons

  accept


acl_check_mime:

  # File extension filtering.
  deny message = Blacklisted file extension detected
       condition = ${if match \
                        {${lc:$mime_filename}} \
                        {\N(\.exe|\.pif|\.bat|\.scr|\.lnk|\.com)$\N} \
                     {1}{0}}

  accept

begin routers

pp_aliases:
  driver        = redirect
  require_files = /etc/exim/localdomain1.com-aliases
  qualify_preserve_domain
  allow_fail
  data          = ${expand:${lookup {$local_part} lsearch* {/etc/exim/localdomain1.com-aliases}}}

dnslookup:
  debug_print = "Routing Mail: dnslookup for $local_part@$domain with TLS"
  driver = dnslookup
  domains = ! +local_domains : ! +domains_No_TLS
  transport = remote_smtp
  ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
# if ipv6-enabled then instead use:
# ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
  no_more

dnslookup_No_TLS:
  debug_print = "Routing Mail: dnslookup for $local_part@$domain without TLS"
  driver = dnslookup
  domains = +domains_No_TLS
  transport = remote_smtp
  ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8
# if ipv6-enabled then instead use:
# ignore_target_hosts = <; 0.0.0.0 ; 127.0.0.0/8 ; ::1
  no_more

system_aliases:
  driver = redirect
  allow_fail
  allow_defer
  data = ${lookup{$local_part}lsearch{/etc/aliases}}
# user = exim
  file_transport = address_file
  pipe_transport = address_pipe

userforward:
  driver = redirect
  check_local_user
# local_part_suffix = +* : -*
# local_part_suffix_optional
  file = $home/.forward
  allow_filter
  no_verify
  no_expn

  check_ancestor
  file_transport = address_file
  pipe_transport = address_pipe
  reply_transport = address_reply

procmail:
  driver = accept
  check_local_user
  require_files = ${local_part}:+${home}/.procmailrc:/usr/bin/procmail
  transport = procmail
  no_verify

localuser:
  driver = accept
  check_local_user
# local_part_suffix = +* : -*
# local_part_suffix_optional
  transport = local_delivery
  cannot_route_message = Unknown user

begin transports

remote_smtp_tls:
  driver = smtp
  hosts_require_tls = *
 # message_size_limit = ${if > {$max_received_linelength}{998} {1}{0}
remote_smtp:
  driver = smtp

remote_msa:
  driver = smtp
  port = 587
  hosts_require_auth = *

procmail:
  driver = pipe
  command = "/usr/bin/procmail -d $local_part"
  return_path_add
  delivery_date_add
  envelope_to_add
  user = $local_part
  initgroups
  return_output

local_delivery:
  driver = appendfile
  file = /var/mail/$local_part
  delivery_date_add
  envelope_to_add
  return_path_add
  group = mail
  mode = 0660

address_pipe:
  driver = pipe
  return_output

address_file:
  driver = appendfile
  delivery_date_add
  envelope_to_add
  return_path_add

address_reply:
  driver = autoreply

begin retry

localdomain1.com      *           F,4h,2m;  G,16h,1h,1.5; F,4d,6h
*                      *           F,2h,15m; G,16h,1h,1.5; F,4d,6h


begin rewrite

begin authenticators

# End of Exim configuration file

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

Как теперь правильно интегрировать Exim с rspamd, если проверка на спам вообще не нужна? Оставить в exim.conf только строку:

spamd_address = 127.0.0.1 11333 variant=rspamd

и не указывать никакого ACL типа указанного на официальной сайте rspamd :

acl_check_spam:
  # do not scan messages submitted from our own hosts
  # +relay_from_hosts is assumed to be a list of hosts in configuration
  accept hosts = +relay_from_hosts

  # do not scan messages from submission port (or maybe you want to?)
  accept condition = ${if eq{$interface_port}{587}}

  # skip scanning for authenticated users (if desired?)
  accept authenticated = *

  # scan the message with rspamd
  warn spam = nobody:true
  # This will set variables as follows:
  # $spam_action is the action recommended by rspamd
  # $spam_score is the message score (we unlikely need it)
  # $spam_score_int is spam score multiplied by 10
  # $spam_report lists symbols matched & protocol messages
  # $spam_bar is a visual indicator of spam/ham level

  # use greylisting available in rspamd v1.3+
  defer message    = Please try again later
        condition  = ${if eq{$spam_action}{soft reject}}

  deny  message    = Message discarded as high-probability spam
        condition  = ${if eq{$spam_action}{reject}}

  # Remove foreign headers
  warn remove_header = x-spam-bar : x-spam-score : x-spam-report : x-spam-status

  # add spam-score and spam-report header when "add header" action is recommended by rspamd
  warn
    condition  = ${if eq{$spam_action}{add header}}
    add_header = X-Spam-Score: $spam_score ($spam_bar)
    add_header = X-Spam-Report: $spam_report

  # add x-spam-status header if message is not ham
  warn
    ! condition  = ${if match{$spam_action}{^no action\$|^greylist\$}}
    add_header = X-Spam-Status: Yes

  # add x-spam-bar header if score is positive
  warn
    condition = ${if >{$spam_score_int}{0}}
    add_header = X-Spam-Bar: $spam_bar

  accept

Или все таки указывать этот ACL, но убрать строки, добавляющие X-Spam заголовки, greylisting и оставить только такое:

acl_check_spam:
  # do not scan messages submitted from our own hosts
  # +relay_from_hosts is assumed to be a list of hosts in configuration
  accept hosts = +relay_from_hosts

  # do not scan messages from submission port (or maybe you want to?)
  accept condition = ${if eq{$interface_port}{587}}

  # skip scanning for authenticated users (if desired?)
  accept authenticated = *

accept

?

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

для начала хоть немного понять, как работает конфиг exim.

1. https://www.exim.org/exim-html-current/doc/html/spec_html/ch-access_control_l...

у него есть вполне себе широкий набор параметров рейтлимитов. вам достаточно в начале acl_check_data добавить что-то типа

  defer message = Sender rate exceeds $sender_rate_limit \
               messages per $sender_rate_period
        ratelimit = 2000 / 1h / leaky / $sender_host_address

сходу: подключать для этого внешний фильтр ну если только один фильтр для нескольких релаев, чтобы централизированно лимитить кластер. К сожалению екзим не умеет вести дб лимитов в удаленной базе (шарить /var/spool/exim/db/* серьезно не рассматриваю)

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

2. если подключать spamd_address = 127.0.0.1 11333 variant=rspamd

то надо обрабатывать его екзит коды, т.е. оставить как минимум

 # scan the message with rspamd
  warn spam = nobody:true
  # This will set variables as follows:
  # $spam_action is the action recommended by rspamd
  # $spam_score is the message score (we unlikely need it)
  # $spam_score_int is spam score multiplied by 10
  # $spam_report lists symbols matched & protocol messages
  # $spam_bar is a visual indicator of spam/ham level

  # use greylisting available in rspamd v1.3+
  defer message    = Please try again later
        condition  = ${if eq{$spam_action}{soft reject}}

  deny  message    = Message discarded as high-probability spam
        condition  = ${if eq{$spam_action}{reject}}

далее в самом фильтре отключить все нафиг, кроме рейтлимитов, которые и должны делать defer

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

Спасибо, вчера пробовал оганичивать лимит только Exim_ом, проверил-работает.

Вообще хочется попробовать на реальной нагрузке оба варианта - и с rspamd+Exim и ratelimit, встроенный в Exim и выбрать из них оптимальное. Сейчас я хочу просто подружить Exim и rsapmd для 1 варианта (rpamd+Exim), но проверку спама не проводить, добиться только работы ratelimit модуля...

Ну т.е. надо подправить ACL, указанный выше с официального сайта rspamd для работы Exim в связке с rspamd и redis...

Pls. HELP!

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

Возможно ли просто указать параметр в exim.conf:

spamd_address = 127.0.0.1 11333 variant=rspamd

и вообще не указывать ACL для проверки спама? мне ведь нужен только работающий модуль ratelimit от rspamd...

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

на данном этапе я не считаю для себя нужным этот фильтр в екзиме. поэтому разбираться с его конфигом без меня. я, например, делаю рейтлимит через екзим и его redis lookup в редис кластере для централизованного ограничения, мне хватает функционала exim.

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

нет. повторяю, как минимум

warn spam = nobody:true
defer message    = Please try again later
        condition  = ${if eq{$spam_action}{soft reject}}

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

ну т.е. так пойдет?

spamd_address = 127.0.0.1 11333 variant=rspamd

acl_check_spam:

  # scan the message with rspamd
  warn spam = nobody:true

  # use greylisting available in rspamd v1.3+
  defer message    = Please try again later
        condition  = ${if eq{$spam_action}{soft reject}}

accept
gigantischer
() автор топика
Ответ на: комментарий от gigantischer

нет, кажется так?

spamd_address = 127.0.0.1 11333 variant=rspamd

acl_check_spam:

  # scan the message with rspamd
  warn spam = nobody:true

  # use greylisting available in rspamd v1.3+
  defer message    = Please try again later
        condition  = ${if eq{$spam_action}{soft reject}}

  deny  message    = Message discarded as high-probability spam
        condition  = ${if eq{$spam_action}{reject}}

accept
gigantischer
() автор топика
Ответ на: комментарий от anonymous

попробовал как Вы подсказали, указал:

acl_smtp_mail = acl_check_mail
acl_smtp_rcpt = acl_check_rcpt
acl_smtp_data = acl_check_spam
acl_smtp_mime = acl_check_mime

acl_check_spam:
  accept hosts = +relay_from_hosts

  accept condition = ${if eq{$interface_port}{587}}

  accept authenticated = *

  # scan the message with rspamd
  warn spam = nobody:true

  # use greylisting available in rspamd v1.3+
  defer message    = Please try again later
        condition  = ${if eq{$spam_action}{soft reject}}

  deny  message    = Message discarded as high-probability spam
        condition  = ${if eq{$spam_action}{reject}}

  accept

но письма отправляются полностью - ratelimit не срабатывает...

gigantischer
() автор топика
Ответ на: комментарий от anonymous

закомментировал 3 accept_a, теперь в логе Exim появились строки перед отправкой письма:

2018-06-20 15:06:54 1fVbt0-000EmS-FZ spam acl condition: spamd: failed to connect to any address for 127.0.0.1: Permission denied
2018-06-20 15:06:54 1fVbt0-000EmS-FZ spam acl condition: all spamd servers failed
2018-06-20 15:06:54 1fVbt0-000EmS-FZ H=(domain.tk) [ip-address] Warning: ACL "warn" statement skipped: condition test deferred

при этом ratelimit по прежнему не срабатывает -все письма доходят...

gigantischer
() автор топика
Ответ на: комментарий от anonymous

спасибо, отключил selinux, исчезли указанные 2 сообщения, но ratelimit так и не сработал, письма продолжают доходить...

Как можно протестить вообще взаимодействие между Exim и rsapmd? Ну я не знаю tcpflow или как?

gigantischer
() автор топика
Ответ на: комментарий от anonymous

сейчас в rspamd логе увидел строку с R_RATELIMIT(0.00):

2018-06-20 17:29:13 #58535(normal) <4fd69c>; task; rspamd_task_write_log: id: <5b2a64b8.26LkpCTqo6upq+fm%postmaster@domain.tk>, qid: <1fVe6i-000FF5-V4>, ip: 192.168.42.1, from: <postmaster@domain.tk>, (default: F (no action): [1.10/15.00] [MID_CONTAINS_FROM(1.00){},MIME_HTML_ONLY(0.20){},MIME_GOOD(-0.10){text/plain;},FROM_EQ_ENVFROM(0.00){},FROM_NO_DN(0.00){},RCPT_COUNT_ONE(0.00){1;},RCVD_COUNT_ONE(0.00){1;},RCVD_NO_TLS_LAST(0.00){},R_RATELIMIT(0.00){bounce_to_ip(27:_:s27rt@vivaldi.net:192.168.42.1);to(1666:s27rt@vivaldi.net);bounce_to(27:_:s27rt@vivaldi.net);to_ip_from(1666:s27rt@vivaldi.net:192.168.42.1:postmaster@domain.tk);to_ip(833:s27rt@vivaldi.net:192.168.42.1);},TO_DN_NONE(0.00){},TO_MATCH_ENVRCPT_ALL(0.00){}]), len: 593, time: 93.015ms real, 13.251ms virtual, dns req: 0, digest: <8715b7b58c747a49e371ba0b02b7de8f>, rcpts: <s27rt@vivaldi.net>, mime_rcpts: <slawa@vivaldi.net>
2018-06-20 17:29:13 #58535(normal) <4fd69c>; task; rspamd_protocol_http_reply: regexp statistics: 0 pcre regexps scanned, 1 regexps matched, 174 regexps total, 90 regexps cached, 0B bytes scanned using pcre, 679B bytes scanned total
2018-06-20 17:35:38 #58534(controller) <pr5857>; map; http_map_finish: data is not modified for server updates.rspamd.com, next check at Wed, 20 Jun 2018 14:40:38 GMT
2018-06-20 17:42:38 #58534(controller) <pr5857>; map; http_map_finish: data is not modified for server updates.rspamd.com, next check at Wed, 20 Jun 2018 14:47:38 GMT

При этом лимиты не нулевые:

$ rspamadm configdump
ratelimit {
    whitelisted_rcpts = "postmaster,mailer-daemon";
    symbol = "R_RATELIMIT";
    rates {
        to_ip = "3 / 2min";
        to = "2 / 1min";
        bounce_to = "2 / 1h";
        to_ip_from = "1 / 1min";
        user = "1 / 1min";
        bounce_to_ip = "1 / 1h";
    }
    max_rcpt = 5;
    info_symbol = "R_RATELIMIT_INFO";
    enabled = true;
}

Ой, кажется нулевой RATELIMIT потому, что postmaster присутствует в значении whitelisted_rcpts модуля ratelimit?

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

Теперь если я отправляю почту от postmaster@domain.tk наружу я вижу в логе параметр R_RATELIMIT(0.00), а когда я отправляю от адреса типа user@domain.tk этого параметра нет в логе.

Как правильно временно исключить адрес postmaster@domain.tk из whitelisted_rcpts модуля ratelimit? Пробовал просто указать в /etc/rspamd/local.d/ratelimit.conf строку

whitelisted_rcpts = "mailer-daemon";

но тогда в логе rspamd:

2018-06-22 10:55:28 #19477(normal) <4856d6>; task; lua_metric_symbol_callback: call to (R_RATELIMIT) failed (2): /usr/share/rspamd/lua//ratelimit.lua:339: attempt to index field 'whitelisted_rcpts' (a nil value); trace: [1]:{/usr/share/rspamd/lua//ratelimit.lua:339 - fun [Lua]}; [2]:{/usr/share/rspamd/lib/fun.lua:30 - call_if_not_empty [Lua]}; [3]:{/usr/share/rspamd/lib/fun.lua:654 - any [Lua]}; [4]:{/usr/share/rspamd/lua//ratelimit.lua:339 - <unknown> [Lua]};

Аналогично если создать файл /etc/rspamd/override.d/ratelimit.conf с 1 параметром:

whitelisted_rcpts = "mailer-daemon";

появляется та же ошибка call to (R_RATELIMIT) failed (2)...

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

при этом

$ rspamadm configdump

ratelimit {
    whitelisted_rcpts = "mailer-daemon";
    symbol = "R_RATELIMIT";
    rates {
        to_ip = "3 / 2min";
        to = "2 / 1min";
        bounce_to = "2 / 1h";
        to_ip_from = "1 / 1min";
        user = "1 / 1min";
        bounce_to_ip = "1 / 1h";
    }
    max_rcpt = 5;
    info_symbol = "R_RATELIMIT_INFO";
    enabled = true;
}

gigantischer
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.