Created
September 14, 2017 18:43
-
-
Save grigorescu/eee2024c88d6c6cc6e29702d247d8166 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@load base/frameworks/sumstats | |
@load base/protocols/smtp | |
module SMTP; | |
export { | |
redef enum Notice::Type += { | |
## Generated if a user is sending mail to too many recipients | |
ExcessiveRecipients | |
}; | |
const excessive_limit = 100.0 &redef; | |
const excessive_interval = 120min &redef; | |
global excessive_whitelist: set[string] = { | |
} &redef &synchronized; | |
} | |
function format_crl_samples(samples: vector of SumStats::Observation): string | |
{ | |
local ret = "SMTP Message samples\n---------------------"; | |
for ( i in samples ) | |
ret += "\n" + samples[i]$str; | |
return ret; | |
} | |
event bro_init() &priority=3 | |
{ | |
local r1 = SumStats::Reducer( | |
$stream="recipients", | |
$apply=set(SumStats::UNIQUE, SumStats::SAMPLE), | |
$num_samples=5, | |
$unique_max=double_to_count(excessive_limit+2) | |
); | |
SumStats::create([$name = "counting recipients", | |
$epoch = excessive_interval, | |
$threshold = excessive_limit, | |
$reducers = set(r1), | |
$threshold_val(key: SumStats::Key, result: SumStats::Result) = { | |
return result["recipients"]$unique + 0.0; | |
}, | |
$threshold_crossed(key: SumStats::Key, result: SumStats::Result) = { | |
local r = result["recipients"]; | |
NOTICE([ | |
$note=ExcessiveRecipients, | |
$msg=fmt("%s has sent mail to more than %d recipients in %s", key$str, r$unique, excessive_interval), | |
$sub=key$str, | |
$email_body_sections=vector(format_crl_samples(r$samples)), | |
$identifier=cat(key$str) | |
]); | |
} | |
]); | |
} | |
event SMTP::log_smtp(rec: SMTP::Info) | |
{ | |
#skip this if it is not an outbound email | |
#or if it is going to a neighbor site | |
if(!Site::is_local_addr(rec$id$orig_h)) | |
return; | |
if(Site::is_neighbor_addr(rec$id$resp_h)) | |
return; | |
if(!rec?$mailfrom || rec$mailfrom in excessive_whitelist) | |
return; | |
if(!rec?$rcptto) | |
return; | |
for(recp in rec$rcptto) { | |
SumStats::observe("recipients", SumStats::Key($str=rec$mailfrom), SumStats::Observation($str=recp)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment