# HG changeset patch # User Carl Byington # Date 1342884844 25200 # Node ID be939802c64e70418c17ac18e30d1c17e7425486 # Parent 7a16904fec66e2629bff8eccaaca5244175dc1d9 add recipient rate limits by email from address or domain diff -r 7a16904fec66 -r be939802c64e dnsbl.conf --- a/dnsbl.conf Sun Jul 01 10:34:43 2012 -0700 +++ b/dnsbl.conf Sat Jul 21 08:34:04 2012 -0700 @@ -7,7 +7,7 @@ content on { filter sbl-xbl.spamhaus.org "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s"; uribl multi.surbl.org "Mail containing %s rejected - surbl; see http://www.rulesemporium.com/cgi-bin/uribl.cgi?bl0=1&domain0=%s"; - #uribl black.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; + #uribl multi.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; ignore { include "hosts-ignore.conf"; }; tld { include "tld.conf"; }; cctld { include "cctld.conf"; }; @@ -28,12 +28,15 @@ "<>" black; }; - // hourly recipient rate limit by smtp auth client id + // hourly recipient rate limit by smtp auth client id, + // or unauthenticated mail from address // default hourly limit is 30 // daily limits are 4 times the hourly limit rate_limit 30 4 { // default #fred 100; // override default limits #joe 10; // "" + #sam@somedomain.tld 500; + #@otherdomain.tld 100; }; }; @@ -49,7 +52,7 @@ content on { filter sbl-xbl.spamhaus.org "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s"; uribl multi.surbl.org "Mail containing %s rejected - surbl; see http://www.rulesemporium.com/cgi-bin/uribl.cgi?bl0=1&domain0=%s"; - #uribl black.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; + #uribl multi.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; ignore { include "hosts-ignore.conf"; }; tld { include "tld.conf"; }; cctld { include "cctld.conf"; }; diff -r 7a16904fec66 -r be939802c64e src/context.cpp --- a/src/context.cpp Sun Jul 01 10:34:43 2012 -0700 +++ b/src/context.cpp Sat Jul 21 08:34:04 2012 -0700 @@ -843,8 +843,22 @@ int CONTEXT::find_rate(const char *user) { if (rcpt_per_hour.empty()) return default_rcpt_rate; - rcpt_rates::iterator i = rcpt_per_hour.find(user); - return (i == rcpt_per_hour.end()) ? default_rcpt_rate : (*i).second; + rcpt_rates::iterator i = rcpt_per_hour.find(user); // look for authen id, or sender user@email limiting + if (i != rcpt_per_hour.end()) return (*i).second; // found authen id, or user@email limiting + const char *f = strchr(user, '@'); + if (!f) return default_rcpt_rate; + i = rcpt_per_hour.find(f); // look for @domain limiting + if (i != rcpt_per_hour.end()) return (*i).second; // found @domain limiting + return default_rcpt_rate; +} + + +bool CONTEXT::is_unauthenticated_limited(const char *user) { + rcpt_rates::iterator i = rcpt_per_hour.find(user); // look for sender user@email limiting + if (i != rcpt_per_hour.end()) return true; // found user@email limiting + const char *f = strchr(user, '@'); + i = rcpt_per_hour.find(f); // look for sender @domain limiting + return (i != rcpt_per_hour.end()); // found @domain limiting } diff -r 7a16904fec66 -r be939802c64e src/context.h --- a/src/context.h Sun Jul 01 10:34:43 2012 -0700 +++ b/src/context.h Sat Jul 21 08:34:04 2012 -0700 @@ -209,6 +209,7 @@ void set_daily_multiple(int multiple) {rcpt_daily_multiple = multiple;}; void add_rate(const char *user, int limit) {rcpt_per_hour[user] = limit;}; int find_rate(const char *user); + bool is_unauthenticated_limited(const char *user); int get_daily_multiple() {return rcpt_daily_multiple;}; void add_to(const char *to) {env_to.insert(to);}; diff -r 7a16904fec66 -r be939802c64e src/dnsbl.cpp --- a/src/dnsbl.cpp Sun Jul 01 10:34:43 2012 -0700 +++ b/src/dnsbl.cpp Sat Jul 21 08:34:04 2012 -0700 @@ -1143,9 +1143,9 @@ uint pp = p - priv.client_name; priv.client_dns_name = strdup(priv.client_name); priv.client_dns_name[pp] = '\0'; - char text[500]; - snprintf(text, sizeof(text), "found simple dns client name %s", priv.client_dns_name); - my_syslog(text); + //char text[500]; + //snprintf(text, sizeof(text), "found simple dns client name %s", priv.client_dns_name); + //my_syslog(text); } } if (spamc != spamc_empty) { @@ -1194,6 +1194,21 @@ smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"recipient can not reply due to blacklisting"); return SMFIS_REJECT; } + if (!priv.authenticated && dc.default_context->is_unauthenticated_limited(priv.mailaddr)) { + int hourly, daily; + incr_rcpt_count(priv.mailaddr, hourly, daily); + int h_limit = dc.default_context->find_rate(priv.mailaddr); + int d_limit = dc.default_context->get_daily_multiple() * h_limit; + if (debug_syslog > 1) { + char msg[maxlen]; + snprintf(msg, sizeof(msg), "unauthenticated address %s (%d %d recipients, %d %d limits)", priv.mailaddr, hourly, daily, h_limit, d_limit); + my_syslog(&priv, msg); + } + if ((hourly > h_limit) || (daily > d_limit)){ + smfi_setreply(ctx, (char*)"550", (char*)"5.7.1", (char*)"recipient rate limit exceeded"); + return SMFIS_REJECT; + } + } if (priv.authenticated) { int hourly, daily; incr_rcpt_count(priv.authenticated, hourly, daily); diff -r 7a16904fec66 -r be939802c64e xml/dnsbl.in --- a/xml/dnsbl.in Sun Jul 01 10:34:43 2012 -0700 +++ b/xml/dnsbl.in Sat Jul 21 08:34:04 2012 -0700 @@ -186,9 +186,13 @@ specified limit. - This milter can also impose hourly rate limits on the number of - recipients accepted from SMTP AUTH connections, that would otherwise be - allowed to relay thru this mail server with no spam filtering. + This milter can also impose hourly and daily rate + limits on the number of recipients accepted from SMTP + AUTH connections, that would otherwise be allowed to + relay thru this mail server with no spam filtering. If + the connection does not use SMTP AUTH, the rate limits + may be specified by the mail from email address or + domain. Consider the case of a message from A to B passing thru this milter. If @@ -732,7 +736,7 @@ content on { filter sbl-xbl.spamhaus.org "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s"; uribl multi.surbl.org "Mail containing %s rejected - surbl; see http://www.rulesemporium.com/cgi-bin/uribl.cgi?bl0=1&domain0=%s"; - #uribl black.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; + #uribl multi.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; ignore { include "hosts-ignore.conf"; }; tld { include "tld.conf"; }; cctld { include "cctld.conf"; }; @@ -753,12 +757,15 @@ "<>" black; }; - // hourly recipient rate limit by smtp auth client id + // hourly recipient rate limit by smtp auth client id, + // or unauthenticated mail from address // default hourly limit is 30 // daily limits are 4 times the hourly limit rate_limit 30 4 { // default #fred 100; // override default limits #joe 10; // "" + #sam@somedomain.tld 500; + #@otherdomain.tld 100; }; }; @@ -774,7 +781,7 @@ content on { filter sbl-xbl.spamhaus.org "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s"; uribl multi.surbl.org "Mail containing %s rejected - surbl; see http://www.rulesemporium.com/cgi-bin/uribl.cgi?bl0=1&domain0=%s"; - #uribl black.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; + #uribl multi.uribl.com "Mail containing %s rejected - uribl; see http://l.uribl.com/?d=%s"; ignore { include "hosts-ignore.conf"; }; tld { include "tld.conf"; }; cctld { include "cctld.conf"; }; @@ -790,7 +797,7 @@ generic "^dsl.static.*ttnet.net.tr$|(^|[x.-])(ppp|h|host)?([0-9]{1,3}[x.-](Red-|dynamic[x.-])?){4}" "your mail server %s seems to have a generic name"; - white_regex ".*=example.com=user@yourhostingaccount.com"; + white_regex "=example.com=user@yourhostingaccount.com$"; env_to { # !! replace this with your domain names