1Sentinel 1.7b
2-------------
3
4 This milter I wrote mostly for myself as it relieves my sysadmin's
5live considerably. If somebody else wants to use it, go ahead. But just
6keep in mind this program is WITHOUT ANY WARRANTY, use this at your own
7risk. Though this milter is stable enough on sparc Solaris7/8. I've never
8had a chance to try it somewhere else under more or less solid loading.
9It can be compiled in FreeBSD and Linux as well. So if somebody wants to
10try it on any platforms different from Solaris7/8 just let me know about
11results. Although "rbl" feature in this release doesn't work for FreeBSD.
12I'm still looking for reentrant gethostbyname() implementation for FreeBSD.
13If somebody has some ideas, just let me know. Also I didn't have enough
14time to shape it as a package. Probably I'll do it in the future.
15
16
17 I think whoever is going to use it knows how to integrate Milter with
18sendmail. It is documented very well on http://www.sendmail.org
19So this README just explains how to operate Sentinel.
20
21Usage: sentinel -p port [-c config] [-v[1-3]] -d
22 or
23 sentinel -p port [-c config] [-v[1-3]]
24 or
25 sentinel -t [-c config] [-f message] [-v[1-3]]
26
27where
28 -p port - a port description according to libmilter specification
29 unix:/var/run/smmsp/sentinel.socket for example
30
31 -c config - a configuration file location (/etc/mail/sentinel.cf by default)
32
33 -d - run as a daemon
34
35 -t - test a configuration file and return
36
37 -f message - a message file location for testing your configuration on
38 a real message. This option will simulate all SMFI calls like for a real
39 message with complete debug/log output on STDOUT. Three additional headers
40 are supported for a message in order to simulate mlfi_connect/mlfi_envfrom/mlfi_rcpt
41 calls. Just place Connection/EnvelopeFrom/EnvelopeRcpt headers at the begining
42 of a message in order to simulate "connection" and "mail from"/"rcpt to" smtp
43 commands like below:
44 ---
45 Connection: 211.239.127.9
46 EnvelopeFrom: foo@bar-list.com
47 EnvelopeRcpt: person1@company.com
48 EnvelopeRcpt: person2@company.com
49 ...
50 EnvelopeRcpt: personn@company.com
51 Received: from relay.bar-list.com (relay.bar-list.com [192.112.214.7])
52 by mx1.mycompany.com (....)
53 ....
54 ---
55 This option might help you to debug your regular expressions and understand
56 your configuration better ;) Also it'll help you to understand how Sentinel
57 is working.
58
59 -v - verbose or debug level. Global parameter "debug" need to be specified
60 to have appropriate destination for debug records. Syslog is by default.
61
62Use signal USR1 to reload a configuration in fly.
63
64The simple configuration file might look as described below:
65
66sentinel.cf
67############################################################################
68## global chapter ##
69[global]
70tmp:/var/tmp
71log:/var/log/sentinel.log
72debug:/var/log/sentinel.debug
73user:smmsp
74group:smmsp
75max_nofiles:512
76max_soconn:64
77
78## hosts chapter ##
79[hosts]
80smtp1:smtp1:reject:/^64\.32\.18\.3[4-9]/
81smtp2:smtp2:reject:/somewhere\.net/i
82
83## headers chapter ##
84[headers]
85From: from1:from1:spam:/Vladimir\.Lenin@gorki.com/i
86 from2:from2:spam:/Alexandr\.Trotsky@zimney.com/i
87
88EnvelopeRcpt: rcpt1:rcpt1:accept:/autoparser@mycompany\.com/i
89
90EnvelopeFrom: efrom1:efrom1:discard:/somebody@tryToSpamUs\.com/i
91
92To: to1:to1,rcvd1:spam:/undisclosed\.recipients@mycompany\.com/i
93 to2:to2,rcvd1:spam:/user@mycompany\.com/i
94
95Received: rcvd1:rcvd1:null:/by[ ]+mx0[1-9]+\.mycompany\.com/i
96 rcvd2:rcvd2:spam:/\.nas[0-9]+\.dialup.somewhere1\.in\.the\.inet\.net/i
97 rcvd3:rcvd3:spam:/\.nas[0-9]+\.dialup.somewhere2\.in\.the\.inet\.net/i
98
99Subject: subj1:subj1:spam:/^adv:|save money|lose weight|save up to/i
100 subj2:subj2:spam:/adult|pussy|pussies|sex/i
101
102## attachments chapter ##
103[attachments]
104## reject all unsafe attachments from outside, some of them from inside as well
105## all attachments below are according to microsoft
106## http://support.microsoft.com/support/kb/articles/Q262/6/17.ASP
107att01:att01,rcvd1:virus:/\.ade$/i
108att02:att02,rcvd1:virus:/\.adp$/i
109att03:att03,rcvd1:virus:/\.bas$/i
110att04:att04,rcvd1:virus:/\.bat$/i
111att05:att05,rcvd1:virus:/\.chm$/i
112att06:att06,rcvd1:virus:/\.cmd$/i
113att07:att07,rcvd1:virus:/\.com$/i
114att08:att08,rcvd1:virus:/\.cpl$/i
115att09:att09,rcvd1:virus:/\.crt$/i
116att10:att10,rcvd1:virus:/\.exe$/i
117att11:att11,rcvd1:virus:/\.hlp$/i
118att12:att12,rcvd1:virus:/\.hta$/i
119att13:att13,rcvd1:virus:/\.inf$/i
120att14:att14,rcvd1:virus:/\.ins$/i
121att15:att15,rcvd1:virus:/\.isp$/i
122att16:att16,rcvd1:virus:/\.js$/i
123att17:att17,rcvd1:virus:/\.jse$/i
124att18:att18,rcvd1:virus:/\.lnk$/i
125att19:att19,rcvd1:virus:/\.mdb$/i
126att20:att20,rcvd1:virus:/\.mde$/i
127att21:att21,rcvd1:virus:/\.msc$/i
128att22:att22,rcvd1:virus:/\.msi$/i
129att23:att23,rcvd1:virus:/\.msp$/i
130att24:att24,rcvd1:virus:/\.mst$/i
131att25:att25,rcvd1:virus:/\.pcd$/i
132att26:att26:virus:/\.pif$/i
133att27:att27,rcvd1:virus:/\.reg$/i
134att28:att28:virus:/\.scr$/i
135att29:att29,rcvd1:virus:/\.sct$/i
136att30:att30,rcvd1:virus:/\.shs$/i
137att31:att31,rcvd1:virus:/\.shb$/i
138att32:att32,rcvd1:virus:/\.url$/i
139att33:att33:virus:/\.vb$/i
140att34:att34:virus:/\.vbe$/i
141att35:att35:virus:/\.vbs$/i
142att36:att36,rcvd1:virus:/\.wsc$/i
143att37:att37,rcvd1:virus:/\.wsf$/i
144att38:att38,rcvd1:virus:/\.wsh$/i
145
146## mime types chapter ##
147[mime types]
148mime1:mime1:virus:/^application/x-javascript$/i
149
150## body chapter ##
151[body]
152body1:body2:offense:/fuck|shit/i
153
154## action chapter ##
155[actions]
156## all actions are here ##
157spam:reject:The message was classified as SPAM.
158reject:reject:This host is blacklisted in our company
159virus:reject:The attachment of the message was classified as unsafe.
160offense:reject:The content of the message consists an offensive words.
161discard:discard
162accept:accept
163null:null
164
165####################################################################
166
167The format of a configuration file is next:
168
169[chapter 1]
170statement 1
171statement 2
172.
173.
174.
175statement n
176
177[chapter 2]
178statement 1
179statement 2
180.
181.
182.
183statement n
184.
185.
186.
187[chapter n]
188statement 1
189statement 2
190.
191.
192.
193statement n
194
195"statement n" might be either parameter/event/action statement for a particular chapter
196or directive "INCLUDE". Directive "INCLUDE" has next syntax:
197
198INCLUDE full_path_to_included_file
199
200For example:
201
202INCLUDE /etc/mail/sentinel/attachments.cf
203
204All "INCLUDE" files just continue a configuration right from "INCLUDE" point.
205Nested "INCLUDE"'s, when included has also "INCLUDE" directive, are allowed.
206
207Below are next chapter names that available in current version:
208
209[global]
210[hosts]
211[headers]
212[attachments]
213[mime types]
214[body]
215[actions]
216
217All chapters but "global" and "actions" have next format:
218
219event:events:actions:regex
220
221where:
222 - event - an event name that will be registered for a message in case
223 a regular expression is matched (context dependable).
224 - events - comma separated list of all events that must be registered
225 (or must not in case "negative" event) for a message in order
226 to process "actions". Symbol "!" is a sign of "negative event".
227
228 Sample:
229 --
230 addr2:addr2,!addr1:ordb(rejectordb):/^(\d+)\.(\d+)\.(\d+)\.(\d+)/
231 --
232 that means "run an action ordb(rejectordb) only if event addr2
233 is matched and event addr1 isn't matched". In other words:
234 --
235 if (addr2 == true && addr1 == false)
236 then
237 run ordb(rejectordb)
238 endif
239 --
240 Multiple negative events are allowed in a list.
241
242 Sample:
243 --
244 addr2:addr2,!addr1,!addr3:ordb(rejectordb):/^(\d+)\.(\d+)\.(\d+)\.(\d+)/
245 --
246 that means:
247 if (addr2 == true && addr1 == false && addr3 == false)
248 then
249 run ordb(rejectordb)
250 endif
251 --
252 - actions - comma separated list of all action that will be processed
253 in case all "events" are registered and all "negative events"
254 are not registered.
255 - regex - regular expression for current event. This version supports
256 extended regular expressions. Two options are available for regex:
257 i - case insensitive
258 n - negative, that means NOMATCH must return MATCH result
259 s - check against html content, which has stripped html tags.
260 d - decode html numeric entities, like "&#nnn;"
261 An option "s" may be helpful against such tricks in html contens as
262 "via<!--he-he-->gra". If you defined your regex like "/viagra|valium|xanax/is",
263 then it'll be running against stripped html content (html content without
264 html tags). It means all html tags will be taken out from html content
265 before to run appropriate regular expression. Of course, it's working for
266 "text/html" only. This optiion will be ignored in case of "text/plain" content".
267 An option "d" is also helpful in case spammers try to hide real content in sequences
268 "&#nnn;". For example, if you defined your regex like "/viagra|valium|xanax/d",
269 then it'll be running against decoded html content (html content without numeric entities).
270 Therefore, the sequences "&#nnn;" will be decoded before to run either regex or body ACL's.
271 You can combine this option with option "s". Of course, it's working for "text/html" only.
272 This option will be ignored in case of "text/plain" content. Below is an example how to run
273 ACL against HTML content with stripped tags and decoded numeric entities:
274 --
275 [body]
276 body1:body1:tabooBody:/.*/ds
277 ...
278 [actions]
279 tabooBody:acl:/etc/mail/milter/tabooBody.lst
280 --
281 where tabooBody.lst is something like below:
282 --
283 viagra
284 Online Pharmacy
285 xanox
286 phentermine
287 prozac
288 valium
289 Vicodin
290 ...
291 --
292 An expression must be delimited by // if you want to use these
293 options. There are some perl-like extentions that are actualy
294 "Alpha Regex Metasymbols":
295 \w - match any "word" character (alphanumerics plus "_");
296 \d - match any digit character;
297 \s - match any whitespace character;
298 \n - match the newline character;
299 \r - match the return character;
300 \t - match the tab character.
301 I don't see any necessity to implement "\W", "\D" and "\S"
302 metasymbols as well. They might be easy defined in your regular
303 expressions as "[^\w]", "[^\d]" and "[^\s]" accordingly.
304
305 Sample:
306 subj1:rblpfx,rcvd1,ordb:/^RBL:/in
307
308 "[global]" chapter.
309
310The syntax for a chapter "[global]" is next:
311<parameter name>:<parameter value>
312Currently next parameters can be defined here:
313
314tmp - where is a temporary files location. Very important if you are going
315 to use "program" action. In this case there should be enough space
316 for temporary files in order to accommodate decoded attachments.
317
318log - where is a logfile location in order to log all actions by sentinel.
319 Must have write permissions for an user "user" (see below). You can either
320 specify "syslog" there or just omit this parameter if you want all log
321 info was recorded by syslog. Syslog is by default. Look for "mail.info"
322 destination in your syslog.conf
323
324debug - where is a debugfile location in order to record all debug info there.
325 Must have write permissions for an user "user" (see below). You can either
326 specify "syslog" there or just omit this parameter if you want all debug
327 info was recorded by syslog. Syslog is by default. Look for "mail.debug"
328 destination in your syslog.conf
329
330user - milter will be running under this account perm.
331
332group - milter will be running under this group perm.
333
334max_nofiles - max number of file descriptors. Important for heavy loaded systems.
335 Can be used as the fix for next possible problems:
336 - "libthread panic: cannot create new lwp";
337 - "too many open files".
338
339max_soconn - backlog value for smfi_sebacklog(). It's using as backlog parameter
340 for listen(). Don't use it if you don't understand what you are
341 doing. The default value in libmilter is 20 for most of systems.
342 Could be useful for heavy loaded systems.
343
344max_parse_txt - this parameter tells sentinel not to process "body" rules for
345 "text/plain" or "text/html" message part if content length for
346 this part is greater than "max_parse_txt". This parameter must
347 be specified in bytes. The deafult value is 1M.
348
349
350 "[actions]" chapter.
351
352Actually all actions that are described here can be available for events in
353chapters "[hosts]", "[headers]", "[attachments]", "[mime types]", "[body]".
354The syntax for chapter "[actions]" is next:
355
356<action name>:<function>:<an argument for a finction>
357
358where
359 <action name> - any name you want
360
361 <function> - one of the next functions that available in the current release:
362
363 null - null operator, that means do nothing but just register an event.
364 Sample: null:null
365
366 accept - accept a message without any further checking. Don't need any arguments.
367 This type is a highest priority type. If you defined some rules with
368 "accept" type, a message will be accepted, no matter what kind of events
369 were triggered before.
370 Sample: accept:accept
371
372 reject - reject a message. An argument will be passed to 554 4.7.1 DSN diagnostic.
373 An argument will be processed as a pattern relatively to a context from
374 where this action was called (headers, hosts, body reg. expressions).
375 You can use next subexpressions:
376 ${0} - whole string that was submitted for an expression
377 (for example "subject" header)
378 ${1} .. ${nn} - subexpressions according to parenthesized
379 subexpressions (delimited by () regular expressions)
380 in appropriate regular expression.
381 $file - attached file name in context of "[attachments]" chapter.
382 Samples:
383 spam:reject:The message was classified as SPAM.
384 rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}). Please contact postmaster@netapp.com in case any business related issues.
385 virus:reject:The attachment "$file" of the message was classified as unsafe.
386
387 discard - just discard a message without any notifications.
388 Don't need any arguments.
389 Sample:
390 discard:discard
391
392 addrcpt - add an recipient for a message. A recipient must be specified
393 as an argument.
394 Sample:
395 addrobot:addrcpt:robot@mycompany.com
396
397 delrcpt - remove an recipient. Don't need any argument. Make sense only
398 in "headers" chapter and only for "EnvelopeRcpt" header. Will
399 remove current recipient for an event in "EnvelopeRcpt".
400 Sample:
401 delrcpt:delrcpt
402
403 chgrcpt - change an recipient. A new recipient must be specified as argument.
404 Make sense only in "headers" chapter and only for "EnvelopeRcpt"
405 header. Will change a current recipient for an event in "EnvelopeRcpt".
406 Sample:
407 chg_domain:chgrcpt:${1}@newdomain.com
408
409 addhdr - add a header for a message. A header name and value must be specified
410 as arguments
411 Sample:
412 xfilter:addhdr:X-Filter: this message was checked by Sentinel
413
414 delhdr - remove a header for a message. Don't need any arguments. Will remove
415 a current header for a first matched regular expression in an event
416 list for a header that defined in "headers" chapter.
417 Sample:
418 delhdr:delhdr
419
420 chghdr - change a header. A new value for a header must be specified as an argument.
421 Make sense only in "headers" chapter. Will change a current header for a
422 first matched regular expression in an event list for a header that defined
423 in "headers" chapter.
424 Sample:
425 rblpfx:chghdr:RBL: ${0}
426
427 quarantine - save message in quarantine directory. Quarantine directory must be specified
428 as an argument. A message will be saved as a file with name event_name.queue_id,
429 where event_name is an event from where this action was called, and queue_id
430 is sendmail queue ID for a message. Default action after a message will be
431 saved is just to discard if an argument is not specified (see arguments for
432 actions program/rbl/quarantine below). You can use formatted string as a
433 directory specification. Only last subdirectory in the path will be created
434 according to your formatted string. Next date/time formatted symbols can be
435 used for last subdirectory in your directory path specification:
436 %a - locale's abbreviated weekday name;
437 %A - lLocale's full weekday name;
438 %b - Locale's abbreviated month name;
439 %B - Locale's full month name;
440 %c - Locale's appropriate date and time representation;
441 %d - day of month [1,31]; single digits are preceded by 0;
442 %D - date as %m/%d/%y;
443 %e - day of month [1,31]; single digits are preceded by a space;
444 %g - week-based year within century [00,99];
445 %G - week-based year, including the century [0000,9999];
446 %h - locale's abbreviated month name;
447 %H - hour (24-hour clock) [0,23]; single digits are preceded by 0;
448 %I - hour (12-hour clock) [1,12]; single digits are preceded by 0;
449 %j - day number of year [1,366]; single digits are preceded by 0;
450 %k - hour (24-hour clock) [0,23]; single digits are preceded by a blank;
451 %l - hour (12-hour clock) [1,12]; single digits are preceded by a blank;
452 %m - month number [1,12]; single digits are preceded by 0;
453 %M - minute [00,59]; leading 0 is permitted but not required;
454 %p - locale's equivalent of either a.m. or p.m.;
455 %r - appropriate time representation in 12-hour clock format with %p;
456 %R - time as %H:%M;
457 %S - seconds [00,61];
458 %T - time as %H:%M:%S;
459 %u - weekday as a decimal number [1,7], with 1 representing Monday;
460 %U - week number of year as a decimal number [00,53], with Sunday as the first day of week 1;
461 %w - weekday as a decimal number [0,6], with 0 representing Sunday;
462 %W - week number of year as a decimal number [00,53], with Monday as the first day of week 1;
463 %x - locale's appropriate date representation;
464 %X - locale's appropriate time representation;
465 %y - year within century [00,99];
466 %Y - year, including the century (for example 1993);
467 Samples:
468 qrtDiscard:quarantine:/var/spool/quarantine
469 or
470 qrtDiscard:quarantine:/var/spool/quarantine/%Y%m%d
471
472 qrtReject:quarantine(spam):/var/log/quarantine
473 or
474 qrtReject:quarantine(spam):/var/log/quarantine/%Y%m%d
475
476 program - call an external program. This action make sense only in "attachments"
477 chapter. An argument is a program name with all required parameters.
478 An argument must be specified as a pattern with "$file" subexpression.
479 This action will call an "argument" if it's specified or just reject
480 action if it isn't. An argument or reject action will be called only
481 in case non zero return code.
482 Samples:
483 vscan:program:/usr/local/sbin/vscan -b -f $file
484 vscan:program(virus):/usr/local/sbin/vscan -b -f $file
485
486 where "virus" action was defined as:
487
488 virus:reject:The attachment "$file" of the message was classified as unsafe.
489
490 strip - strip an attached file. An argument is a diagnostic text message that
491 will be instead of attached file. A subexpression "$file" can be specified
492 in argument string.
493 Sample:
494 stripatt:strip:The attached file "$file" was stripped.
495
496 rbl - Remote Blackhole List. DNS lookup in RBL database will be done according
497 to an argument. Actually this is an argument for gethostbyname call.
498 Next subexpressions may be specified: ${0}, ${1} .. ${nn}. A message
499 will be just rejected in case defined name will be found in RBL.
500 Of course this is just default behavior when no arguments is specified
501 for "rbl" action (see arguments for actions "progarm,rbl,resolv,quarantine" below).
502 Samples:
503 ordb:rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
504 ordb(rejectordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
505
506 where "rejectordb" might be defined as:
507
508 rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}). Please contact postmaster@mycompany.com in case any business related issues.
509
510 resolv - try to resolve name and compare results with second parameter (if defined).
511 This action can accept 1 or 2 arguments. If only one argument defined, "resolv"
512 will return "reject" by default or run an action in parentheses in case specified
513 name is not resolved. If second argument is defined, which expects to be an IP
514 address, "resolv" will try to compare it with each with each address of resolved
515 name. It will return "reject" by default or run an action in parentheses if there
516 is no specified IP in results of resolving. First and second arguments must be
517 separated by comma in an action definition (see an example below).
518 Samples:
519 [headers]
520 Received:
521 rcvd2:rcvd2:helo(quarantine):/^from\s+([^ \t]+)\s+\((unknown\s+)?\[(\d+\.\d+\.\d+\.\d+)\]\)\s+by\s+mx[1-3]\.mycompany\.com/i
522
523 [actions]
524 helo(quarantine):resolv:${1}, ${3}
525 acl - Access Control List allows to define external (outside of sentinel.cf) lists,
526 which can be utilized as whitelists, blacklists, banned URL's lists, and etc.
527 These external lists are regular text files, which consist one entry per string.
528 Entries may be domains, addresses, url's, and etc. It depends of context from which
529 particular "acl" will be called. For example, if you defined an "acl" to be called
530 from header's context, then such "acl" must refer to a list of domains/addresses.
531 In case you want to define an external list as banned URL's list, you must call
532 appropriate "acl" from "body" context ("body" chapter). Just keep in mind, you
533 can't use regular expression inside such lists. Sentinel will check all entries
534 in such lists as case insensitive string occurrences in appropriate context (headers,
535 text or html message body). It means incomplete domain name like "dailypromo.com"
536 will trigger an event for "From" header like "<offers@mail.dailypromo.com>".
537 Samples:
538 Lets say you defined blacklist in /etc/mail/milter/blacklist.lst, which consists:
539 --
540 apslist526.com
541 backpackgirl
542 cupidsclock
543 cdsteals.com
544 DailyDealDepot.com
545 ebanat.com
546 hotbot.com
547 vmadmin.com
548 VIRTUAL0.NET
549 SMTP0.NET
550 IREAYE.NET
551 sepis4556@yahoo.com
552 --
553 Then you need to define "acl" action for this list like below:
554 --
555 [actions]
556 accept:accept
557 quarantine:quarantine:/var/spool/quarantine/sentinel/%Y%m%d
558 blacklist(quarantine):acl:/etc/mail/milter/blacklist.lst
559 whitelist(accept):acl:/etc/mail/milter/whitelist.lst
560 --
561 which can be utilized in "headers" chapter, like below:
562 --
563 [headers]
564 From: from1:from1:blacklist(quarantine):/.*/
565 ...
566 ...
567 EnvelopeFrom: efrom1:efrom1:blacklist(quarantine):/.*/
568 efrom2:efrom2:whitelist(accept):/.*/
569 --
570 In case of "whitelist" an example above shows "whitelist(accept)"
571 action for /etc/mail/milter/whitelist.lst whitelist.
572 Or lets say you defined /etc/mail/milter/bannedurl.lst as below:
573 --
574 beefupyourpenis
575 cool-host
576 quickhost.bz
577 verycoolcars
578 secretsexads
579 freelivewebcamteens
580 --
581 In this case you can utilize this list like in example below:
582 --
583 [body]
584 body1:body1:bannedurl(quarantine):/.*/
585 ...
586 ...
587 [actions]
588 quarantine:quarantine:/var/spool/quarantine/sentinel/%Y%m%d
589 bannedurl(quarantine):acl:/etc/mail/milter/bannedurl.lst
590 --
591 Just keep in mind, if you want to utilize regular expressions, then you have to use
592 them in sentinel.cf file. "Acl"'s won't be much helpful in this case.
593 Access control (ACL) can accept one extra parameter in action definition.
594 Typically it could back reference to subexpression in regular expression of
595 event calling this ACL. Like an example below:
596 --
597 [headers]
598 Received: rcvd1:rcvd1:blackRelays:/^from.*\((.+)\s+\[.*\]( \(may be forged\))?\)\s+by\s+mx[1-9]\.mycompany\.com/i
599 ...
600 [actions]
601 blackRelays:acl:${1}:/etc/mail/milter/blackRelays.lst
602 --
603 If you omit first parameter ("${1}" for example above), ACL will apply to entire header.
604 Like below:
605 --
606 [actions]
607 blackRelays:acl:/etc/mail/milter/blackRelays.lst
608 --
609 Please note, it does not work for body rules. Will implement it in next release.
610 However, "url" parameter can be specified in "body" rules and will be ignored in
611 a header context. This parameter tells sentinel to run ACL rules against URL strings
612 only in a message body. All URL strings will be decoded before to run ACL's.
613 For example:
614 --
615 [body]
616 body1:body1:bannedURLS:/.*/
617 ...
618 [actions]
619 bannedURLs:acl:url:/etc/mail/milter/bannedURLS.lst
620 --
621
622Five next actions "program", "rbl", "acl", "resolv", and "quarantine" can be specified with
623arguments that delimited in parenthesis. For "program" action an argument action will be called
624every time when a program return non zero code. For "rbl" in case a name will be found in
625a Remote Blackhole List. ACL's have "null" action by default. It means if you need something else
626for your "acl", you have to specify it ias parameter, like "whitelist(accept)". For "resolv"
627if a name cannot be resolved or results of resolving are different from a second specified argument
628(IP address). For "quarantine" this is just an action that must be called instead of default "discard"
629after a message will be saved in quarantine directory. Only one argument is allowed. But an argument
630action can be called with an argument as well.
631Samples:
632
633 rcvd1:rcvd1,rblpfx:ordb(quarantine(spam)):/^from .*\(.*\[([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\]\).*by mx[1-3]+\.mycompany\.com/i
634 rcvd2:rcvd2:helo(quarantine):/^from\s+([^ \t]+)\s+\((unknown\s+)?\[(\d+\.\d+\.\d+\.\d+)\]\)\s+by\s+mx[1-3]+\.mycompany\.com/i
635 att10:att10,rcvd1:vscan(quarantine(virus)):/\.exe$/i
636
637 where actions:
638
639 ordb(quarantine(spam)),quarantine(spam),helo(quarantine),spam,vscan(quarantine(virus)),quarantine(virus),virus
640
641 are define below as:
642
643 spam:reject:The message was classified as SPAM.
644 virus:reject:The attachment "$file" of the message was classified as unsafe.
645 quarantine(virus):quarantine:/var/spool/quarantine
646 quarantine(spam):quarantine:/var/spool/quarantine
647 ordb(quarantine(spam)):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
648 helo(quarantine):resolv:${1}, ${3}
649 vscan(quarantine(virus)):program:/usr/local/sbin/vscan -b -f $file
650
651Four actions rbl, acl, resolv, and program will trigger events with the same names in case
652of non zero return code for "program", positive results for "rbl" and "acl", and negative
653result for "resolv". For the sample above the event names will be "ordb" and "vscan" - action
654name without arguments. You can use these triggered events in any another event lists.
655Sample:
656
657 subj3:subj3,ordb:rblpfx:/^RBL:/in
658
659 that means if current subject is not prefixed and ordb action has positive
660 result, then add "RBL:" prefix to a subject header by action "rblpfx". For
661 this sample "rblpfx" action might looks as:
662
663 rblpfx:chghdr:RBL: ${0}
664
665Very simple configuration below is a real sample how "negative events"
666could be used to distinguish internal "outbound" and external "inbound"
667smtp connections. It's useless resource consumption to do rbl lookup for
668"private network" hosts.
669##############################################################################
670[global]
671tmp:/var/tmp
672log:/var/log/sentinel.log
673user:smmsp
674group:smmsp
675max_nofiles:512
676max_soconn:30
677max_parse_txt:524288
678
679[hosts]
680haddr1:haddr1:null:/^(192\.168\.|172\.16\.|10\.)/
681# It does not make any sense to do ordb lookup for internal hosts
682haddr2:haddr2,!haddr1:ordb(rejectordb):/^(\d+)\.(\d+)\.(\d+)\.(\d+)/
683
684[actions]
685ordb(rejectordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
686rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}).
687null:null
688
689Below is more complex sample.
690##############################################################################
691[global]
692tmp:/var/tmp
693log:/var/log/sentinel.log
694user:smmsp
695group:smmsp
696max_nofiles:512
697max_soconn:30
698max_parse_txt:524288
699
700[headers]
701X-Mailer: xmlr1:xmlr1,rcvd1:spam:/WorldMerge|Extractor Pro|Floodgate Pro|Emailer Platinum.*Internet Marketing|BritecastMailer/i
702
703#
704# "subj3" event is defined with "negative" option in regex in order to
705# eliminate duplicate prefixing.
706# The rule for "subj3" is about "Do a subject prefixing by rblpfx action in
707# case 'ordb' action returned positive result and a subject wasn't prefixed
708# before".
709#
710Subject: subj1:subj1,rcvd1:spam:/^adv:|save money|lose weight|save up to/i
711 subj2:subj2,rcvd1:spam:/adult|pussy|girl| ass | fuck | sex |fucking/i
712 subj3:subj3,ordb:rblpfx:/^RBL:/in
713
714#
715# The rules in aol.com, msn.com, and juno.com don't allow to use
716# names that have first numeric symbols
717#
718From: from1:from1:spam:/^[0-9]+@(aol|msn|juno)\.com/i
719 from2:from2:spam:/girls\.net|jobseekernews\.com|jobseekernews\.net|jobfly\.com|supportgate\.com/i
720
721To: to1:to1,rcvd1:spam:/undisclosed\.recipients|friend@|@public\.com/i
722
723#
724# Do RBL checking and add an extra "X-RBL" header for all blackholed sources only
725# if a subject header was not prefixed. This case is for Milter that's behind of
726# firewall. Otherwise we could use "hosts" chapter in order to catch an IP.
727#
728Received: rcvd1:rcvd1,subj3:ordb(addhdrordb):/^from .*\(.*\[([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\]\).*by mx[1-3]+\.mycompany\.com/i
729 rcvd2:rcvd2:spam:/\.nas[0-9]+\.dialup\..*\.someISP\.net/i
730
731#
732# Next recipient's addresses are "pass through" addresses, no matter from where
733# they are and which message content
734#
735EnvelopeRcpt: rcpt1:rcpt1:accept:/autoparser@mycompany\.com|postmaster@mycompany\.com/i
736
737[attachments]
738#
739# reject all unsafe attachments from outside, some of them from inside as well.
740# All attachments below are according to the next article for microsoft:
741# http://support.microsoft.com/support/kb/articles/Q262/6/17.ASP
742# "rcvd1" event in this case allow to distinguish inbound external traffic
743# (see "rcvd1" event above)
744#
745att01:att01,rcvd1:virus:/\.ade$/i
746att02:att02,rcvd1:virus:/\.adp$/i
747att03:att03,rcvd1:virus:/\.bas$/i
748att04:att04,rcvd1:virus:/\.bat$/i
749att05:att05,rcvd1:virus:/\.chm$/i
750att06:att06,rcvd1:virus:/\.cmd$/i
751att07:att07,rcvd1:virus:/\.com$/i
752att08:att08,rcvd1:virus:/\.cpl$/i
753att09:att09,rcvd1:virus:/\.crt$/i
754att10:att10,rcvd1:virus:/\.exe$/i
755att11:att11,rcvd1:virus:/\.hlp$/i
756att12:att12,rcvd1:virus:/\.hta$/i
757att13:att13,rcvd1:virus:/\.inf$/i
758att14:att14,rcvd1:virus:/\.ins$/i
759att15:att15,rcvd1:virus:/\.isp$/i
760att16:att16,rcvd1:virus:/\.js$/i
761att17:att17,rcvd1:virus:/\.jse$/i
762att18:att18,rcvd1:virus:/\.lnk$/i
763att19:att19,rcvd1:virus:/\.mdb$/i
764att20:att20,rcvd1:virus:/\.mde$/i
765att21:att21,rcvd1:virus:/\.msc$/i
766att22:att22,rcvd1:virus:/\.msi$/i
767att23:att23,rcvd1:virus:/\.msp$/i
768att24:att24,rcvd1:virus:/\.mst$/i
769att25:att25,rcvd1:virus:/\.pcd$/i
770att26:att26:virus:/\.pif$/i
771att27:att27,rcvd1:virus:/\.reg$/i
772att28:att28:virus:/\.scr$/i
773att29:att29,rcvd1:virus:/\.sct$/i
774att30:att30,rcvd1:virus:/\.shs$/i
775att31:att31,rcvd1:virus:/\.shb$/i
776att32:att32,rcvd1:virus:/\.url$/i
777att33:att33:virus:/\.vb$/i
778att34:att34:virus:/\.vbe$/i
779att35:att35:virus:/\.vbs$/i
780att36:att36,rcvd1:virus:/\.wsc$/i
781att37:att37,rcvd1:virus:/\.wsf$/i
782att38:att38,rcvd1:virus:/\.wsh$/i
783att39:att39:confd:/SunPricing2002\.xls/i
784
785[mime types]
786#
787# Strip all javascript attachments for a message
788#
789mime1:mime1:stripatt:/^application/x-javascript$/i
790
791[actions]
792#
793# All actions are defined here
794#
795spam:reject:The message was classified as SPAM.
796virus:reject:The attachment "$file" of the message was classified as unsafe.
797stripatt:strip:Unsafe attachment was stripped.
798ordb(rejectordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
799ordb(addhdrordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
800rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}). Please contact postmaster@netapp.com in case any business related issues.
801addhdrordb:addhdr:X-RBL: dubious source ${1}.${2}.${3}.${4} according to ORDB Realtime Blackhole List (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4})
802rblpfx:chghdr:RBL: ${0}
803discard:discard
804accept:accept
805null:null
806
807###############################################################################
808
809What's in my TODO:
810
811 1. more flexible event's list with or/and logic like below:
812
813 event1 | (event2 & event3)
814
815 2. ms-tnef support (don't know if I realy need it)
816
817 3. different character set support for headers/body mime decoding / compare
818
819 4. bugs fixing (if somebody will report)
820
821If you have any questions or comments, just send them to smfilter2002@yahoo.com.
822
823----
824Igor
825