; karma.ini, see 'haraka -h karma' ; Redis: karma's high speed key/value store for concurrency, IP history, ; and AS history [redis] host = 172.200.0.102 port = 6379 db = 1 ; karma IP history is expired after this many days. This value is refreshed ; at every connection. Frequent senders may never expire. expire_days = 60 [asn] ; track karma for AS? (network neighborhood) enable=true ;report_as=asn [tarpit] delay=0 ; If you make the remote wait too long, they drop the connection. ; 'max' limits how long to make remotes wait between responses. max=4 ; max_msa: applied for connections to port 587 and 465, when Haraka is acting ; as a Message Submission Agent for roaming users. ; max_msa=1 max_msa=1 [thresholds] ; negative: the threshold below which a connection is denied/rejected ; Be conservative to avoid false positives! negative=-8 ; score above which connections are considered 'good' positive=2 ; karma history = good - bad connections. A negative score means a sender has ; sent more bad than good messages. IPs are not subject to the penalty box ; until they have made > 5 connections and achieved a score lower than this. history_negative=-3 [deny] ; hooks to disconnect on. When the score is below [threshholds]negative, ; deny the connection on these hooks: ;hooks=connect,unrecognized_command,helo,ehlo,mail,rcpt,data,data_post hooks=unrecognized_command,data,data_post,queue ;message=very bad karma score: {score} ;message=https://example.com/logs/{uuid} [deny_excludes] ; karma captures and scores deny requests from other plugins, permitting finer ; control over connection handling. For plugins that should be able to reject ; the connection, add their name to the plugin list: plugins=send_email, tls, access, helo.checks, data.headers, rspamd, spamassassin, avg, clamd, attachment ; hooks whose DENY rejections should be not be captured. hooks=rcpt, queue [spammy_tlds] ; award negative karma to spammy TLDs ; caution, awarding karma > msg_negative_limit may blacklist that TLD work=-4 rocks=-3 ninja=-3 info=-2 biz=-2 pw=-2 me=-1 us=-5 eu=-4 link=-3 science=-6 top=-4 ru=-2 club=-3 stream=-3 bid=-3 trade=-3 [tls] ; awards based on whether the sender opportunistically encrypted ; spammy senders usually do not. Plenty (~1/4) of ham senders don't either ; use with caution. set=0 unset=0 ; CONNECTION / NOTE AWARDS ; ; NOTICE: Generic awards are mostly deprecated in favor of [asn_awards] and ; [result_awards]. These still exist because there are connection properties ; that can't yet be scored any other way. ; ; karma can award points by inspecting connection objects and notes ; saved by other plugins. ; ; syntax: lo.ca.tion = N [if condition VAL] ; ; location: an object or attribute in the connection or transaction object. ; Use the transaction prefix to check only the transaction note. ; N: a numeric karma score to award: + to praise, - to smite ; VAL: the value to use in the conditional match ; ; conditions: ; if match // performs a case insensitive regex match on VAL ; if equals // performs an === comparison ; if gt // performs a greater-than comparison ; if lt // performs a less-than comparison ; if length (gt|lt) // matches against array length ; if in // matches in arrays [awards] relaying = 6 early_talker = -3 ; ASN AWARDS ; Award karma points to specific ASNs. This is much shorter than writing ; result_awards and I score many ASNs. I score an ASN by analyzing the ; past 30 days of traffic. An ASN that sends mostly spam would get an ; award sufficient to "tip the scales" of any indetermine message ; towards spam and vise versa for hammy senders. [asn_awards] ;55286 = -6 ;33182 = -4 ;46717 = -4 ;13332 = -4 ;200002 = -4 ; RESULT AWARDS ; karma subscribes to each connections result store. Any plugin that saves ; results can thus have those results scored by karma. ; ; Example: ; in a plugin named 'example-pi', a result is saved: ; connection.results.add(plugin, { pass: 'someval' }); ; ; in karma.ini, these rules match and assign +1 karma point each: ; 000 = example-pi | pass | eq | someval | 1 ; 001 = example-pi | pass | match | omeva | 1 ; ; result awards have the folowing syntax: ; unique ID = plugin name | property | operator | value | award | reason | remedy ; ; operators: equal, match, gt, and lt. ; award: any integer (negative values smite, positive values praise) ; reason: an optional human readable reason for the award [result_awards] ;geoip.too_far = -1 001 = geoip | distance | gt | 4000 | -1 | Geographic distance is unusual for ham 002 = geoip | distance | gt | 8000 | -1 | Geographic distance is unusual for ham 003 = karma | fail | equals | env_user_match | -2 | Envelope sender doesn't match message sender 004 = karma | history | lt | -1 | -1 | IP reputation is poor 005 = karma | history | lt | -3 | -1 | IP reputation is very poor 006 = karma | pass | equals | all_good | 2 | IP reputation is good 007 = karma | fail | equals | all_bad | -2 | IP reputation is spam-only ; based on ASN history 008 = karma | pass | equals | asn | 1 | ASN reputation is good 009 = karma | fail | equals | asn | -1 | ASN reputation is bad 010 = karma | pass | equals | asn_all_good | 2 | ASN reputation is very good 011 = karma | fail | equals | asn_all_bad | -2 | ASN reputation is very bad 012 = karma | fail | equals | rfc5321.MailFrom | -1 | RFC Ignorant MTA | Use a RFC compliant MTA 013 = karma | fail | equals | rfc5321.RcptTo | -1 | RFC Ignorant MTA | Use a RFC compliant MTA 020 = asn | pass | equals | karma | 1 | ASN reputation is good 021 = asn | fail | equals | karma | -1 | ASN reputation is bad 022 = asn | pass | equals | asn_all_good | 2 | ASN reputation is ham-only 023 = asn | fail | equals | asn_all_bad | -2 | ASN reputation is spam-only ;030 = connect.p0f | os_name | match | freebsd | 1 | FreeBSD 031 = connect.p0f | os_name | match | windows | -1 | Windows OS, likely infected by malware | Don't use Windows as MTA 032 = connect.p0f | os_flavor | equals | XP | -2 | Windows XP, likely infected by malware | Upgrade to a supported OS ; give back the point penalized for running windows 080 = fcrdns | fcrdns | match | outlook.com | 1 084 = fcrdns | fail | match | ptr_valid | -4 | FCrDNS has no valid PTR | Set up https://en.wikipedia.org/wiki/Forward-confirmed_reverse_DNS 085 = fcrdns | fail | match | valid_tld | -6 | FCrDNS has no valid TLD | Set up https://en.wikipedia.org/wiki/Forward-confirmed_reverse_DNS 086 = fcrdns | fail | equals | has_rdns | -6 | FCrDNS has no rDNS | Set up https://en.wikipedia.org/wiki/Forward-confirmed_reverse_DNS 087 = fcrdns | ip_in_rdns | equals | true | -1 | FCrDNS has IP in rDNS | Configure proper hostnames for your MTA 088 = fcrdns | generic_rdns | equals | true | -1 | FCrDNS host is generic ; well known senders 089 = fcrdns | fcrdns | match | google.com | 2 | FCrDNS Well Known Sender 090 = fcrdns | fcrdns | match | twitter.com | 2 | FCrDNS Well Known Sender 100 = access | whitelist | equals | true | 9 | Policy Whitelist 101 = access | blacklist | equals | true | -7 | Policy Blacklist | Unsubscribe the user, stop spamming them. 102 = access | pass | equals | connect.rdns_access.whitelist | 8 103 = access | pass | equals | mail_from.access.whitelist | 8 104 = access | pass | equals | rcpt_to.access.whitelist | 8 ; Scores for specific DNSBLs 111 = dnsbl | fail | equals | b.barracudacentral.org | -7 | DNS Blacklist | Disinfect your host/network 112 = dnsbl | fail | equals | truncate.gbudb.net | -5 | DNS Blacklist | Disinfect your host/network 113 = dnsbl | fail | equals | psbl.surriel.com | -6 | DNS Blacklist | Disinfect your host/network 114 = dnsbl | fail | equals | bl.spamcop.net | -3 | DNS Blacklist | Disinfect your host/network 115 = dnsbl | fail | equals | dnsbl-1.uceprotect.net | -3 | DNS Blacklist | Disinfect your host/network 116 = dnsbl | fail | equals | zen.spamhaus.org | -5 | DNS Blacklist | Disinfect your host/network 117 = dnsbl | fail | equals | xbl.spamhaus.org | -6 | DNS Blacklist | Disinfect your host/network 118 = dnsbl | fail | equals | cbl.abuseat.org | -5 | DNS Blacklist | Disinfect your host/network 119 = dnsbl | fail | equals | dnsbl.justspam.org | -1 | DNS Blacklist | Disinfect your host/network 130 = helo.checks | fail | match | valid_hostname | -1 | HELO host invalid | Use valid HELO hostname 131 = helo.checks | pass | match | forward_dns | 1 | HELO host has forward DNS 132 = helo.checks | skip | match | forward_dns | -1 | HELO host skipped 133 = helo.checks | fail | match | forward_dns | -1 | HELO host fails forward DNS | Use valid HELO hostname 134 = helo.checks | fail | match | dynamic | -1 | HELO host has dynamic name 135 = helo.checks | fail | match | reverse_dns | -1 | HELO host missing rDNS ; SPF survey in March 2014: over 95% of ham has SPF Pass ; over 60% of spam has SPF Pass ; None, Pass, Fail, SoftFail, Neutral, TempError, PermError 150 = spf | result | equals | Fail | -4 | SPF fail | Update SPF record 151 = spf | result | equals | SoftFail | -3 | SPF soft fail | Maintain DNS properly 152 = spf | result | equals | Neutral | -1 | SPF neutral | Set up SPF records 153 = spf | result | equals | TempError | -2 154 = spf | result | equals | PermError | -2 160 = auth | fail | match | auth | -4 | Authentication failure 161 = auth/auth_base | fail | match | auth | -4 | Authentication failure 162 = auth | pass | match | auth | 9 | Authentication success ; 163 = auth/auth_vpopmaild | success | equals | false | -4 | Authentication failure 168 = mail_from.is_resolvable | fail | length | gt 0 | -8 | Mail From host DNS failure 169 = mail_from.is_resolvable | pass | equals | implicit_mx | -4 | Envelope From host has no MX 170 = rcpt_to.qmail_deliverable | fail | gt | 0 | -1 | Invalid envelope recipient ;171 = rcpt_to.qmail_deliverable | pass | gt | 0 | 1 | Valid Envelope recipient 172 = rcpt_to.in_host_list | fail | gt | 0 | -1 | Invalid envelope recipient ;173 = rcpt_to.in_host_list | pass | gt | 0 | 1 | Valid Envelope recipient 181 = data.headers | fail | match | from_match | -1 | Envelope From does not match Message From: 182 = data.headers | pass | match | from_match | 1 | Envelope From matches Message From: 183 = data.headers | fail | equals | UA | -1 | Uncommon MUA 184 = data.headers | fail | match | direct-to-mx | -1 | Not relayed 185 = data.headers | fail | match | missing | -1 | Missing a required header 190 = data.uribl | fail | equals | fresh15.spameatingmonkey.net | -2 | URI blacklist: fresh15.spameatingmonkey.net 191 = data.uribl | fail | equals | dbl.spamhaus.org | -2 | URI blacklist: dbl.spamhaus.org 192 = data.uribl | fail | equals | multi.uribl.com | -2 | URI blacklist: multi.uribl.com 193 = data.uribl | fail | equals | multi.surbl.org | -2 | URI blacklist: multi.surbl.org 194 = data.uribl | fail | match | rdns | -2 | URI Blacklist | Don't send spam 195 = data.uribl | fail | match | helo | -2 | URI Blacklist | Don't send spam 196 = data.uribl | fail | match | ehlo | -2 | URI Blacklist | Don't send spam 197 = data.uribl | fail | match | envfrom | -2 | URI Blacklist | Don't send spam 198 = data.uribl | fail | match | from | -2 | URI Blacklist | Don't send spam 199 = data.uribl | fail | match | replyto | -2 | URI Blacklist | Don't send spam 200 = data.uribl | fail | match | body | -2 | URI Blacklist | Don't send spam 201 = data.uribl | fail | match | msgid | -2 | URI Blacklist | Don't send spam 205 = bounce | fail | equals | single_recipient | -8 | Invalid bounce 206 = bounce | fail | equals | empty_return_path | -8 | Invalid bounce 207 = bounce | fail | equals | bad_rcpt | -8 | Invalid bounce 210 = clamd | fail | match | executable | -4 | Clam AntiVirus Executable 211 = clamd | fail | match | structured | -2 | Clam AntiVirus Structured 212 = clamd | fail | match | encrypted | -4 | Clam AntiVirus Encrypted Archive 213 = clamd | fail | match | pua | -4 | Clam AntiVirus Potentially Unwanted Application 214 = clamd | fail | match | ole2 | -5 | Clam AntiVirus OLE2 215 = clamd | fail | match | safebrows | -4 | Clam AntiVirus SafeBrowsing 216 = clamd | fail | match | unofficial | -4 | Clam AntiVirus UNOFFICIAL 217 = clamd | fail | match | phish | -3 | Clam AntiVirus Phishing 218 = clamd | fail | match | spam | -2 | Clam AntiVirus Spam ;219 = clamd | pass | equals | clean | 1 | Clam AntiVirus Executable 230 = rspamd | is_spam | equals | true | -2 | rspamd detected as spam 231 = rspamd | action | equals | greylist | -1 | rspamd suggested greylist 232 = rspamd | score | lt | 0 | 1 | rspamd positive score 233 = rspamd | score | gt | 6 | -1 | rspamd moderate score 234 = rspamd | score | gt | 10 | -1 | rspamd high score 235 = rspamd | is_spam | equals | false | 1 | rspamd detected as ham 251 = spamassassin | hits | lt | 0 | 1 | 252 = spamassassin | hits | lt | -2 | 1 | 253 = spamassassin | hits | lt | -5 | 1 | 254 = spamassassin | hits | lt | -10 | 2 | 255 = spamassassin | hits | lt | -20 | 5 | 256 = spamassassin | hits | gt | 1 | -1 | 257 = spamassassin | hits | gt | 2 | -1 | 259 = spamassassin | hits | gt | 3 | -2 | 260 = spamassassin | flag | equals | Yes | -5 | SpamAssassin detected as spam ;261 = spamassassin | hits | gt | 6 | -2 | ;263 = spamassassin | hits | gt | 8 | -2 | 264 = spamassassin | hits | gt | 9 | -2 | 265 = spamassassin | hits | gt | 20 | -10 | 280 = known-senders | pass | length | gt 0 | 5 | Known Sender 281 = limit | fail | length | gt 0 | -3 | Exceeding rate limits