MilterMonkey
From Syscore
From the Google cache of http://www.membrain.com/miltermonkey/ as retrieved on Jan 23, 2005 06:43:39 GMT.
Contents |
What is MilterMonkey?
MilterMonkey is a system, written in Perl, to make deploying milter-based email systems a breeze. MilterMonkey acts as a framework allowing you to quickly deploy multiple filtering rules (called Monkey Brains) within one Sendmail milter, making your mail system more efficient.
What's a Milter?
It's a mail filter. A milter is a seperate application from the MTA (such as sendmail), which is clued-in to the goinings-on of active SMTP sessions, and can influence the transactions in a multitude of ways. Milters can be connected to an MTA in one of two ways -- through a local UNIX socket, or, through a TCP socket, allowing the "milter" to run on a completely different machine than the MTA itself. Connections are made to the milter for each SMTP connection being processed, so multiple connections can be load balanced over multiple servers. (In one installation MilterMonkey is being used in, roughly 10 machines acting as MTAs utlilized the services of three higher-powered machines for filtering, through a load-balancing switch.)
What else does MilterMonkey do?
Multi-Threading
As the Milter API, and hense the Sendmail::Milter module (which MilterMonkey relies upon) is multi-threaded, MilterMonkey does its best to be aware of this enviornment, taking appropriate steps to avoid potential threading disasters that makes even the simplest milters written with Sendmail::Milter unstable. (It's not Sendmail::Milter's fault, in this case, as folks aren't generally used to writing multi-threaded code in Perl).
Avoiding Over Processing
In common environments, messages may be put through the same milter logic multiple times. In the case of more CPU-intensive milters, such as those that may be doing virus scanning, or submitting a message for processing through SpamAssassin, this multiple-processing can end up eating up quite a few resources. For example, you would 'scan' your messages before they got to your list-server for viruses, but you shouldn't have to scan them on delivery to local folks' mailboxen.
To accomplish this, MilterMonkey places a crytographically signed key in the headers of the message, giving the message a "free pass" when it is encountered by MilterMonkey again. (A "site key", chosen for your administrative domain is used).
Requirements
- Perl >= 5.8.0, compiled with "interpreter threads" enabled
- (other versions may work, but it was tested with 5.8.0 under Solaris)
- Sendmail::Milter >= 0.18
- A Sendmail distribution with a 'libmilter' compiled
Monkey Brains
A "monkey brain" is a perl module which constitutes an actual mail filter. Two samples are included -- one provides an interface to SpamAssassin, the second implements an email virus scanner utilizing the McAffee (Network Associates) virus scanner for Unix. A base class Sendmail::Milter::Monkey::Brains provides a basic functionality needed by the most trivial brain module.
A monkey brain should implement a function called eom_process, which is called at a stage where the message has been read in by the milter process. eom_process is passed the contents of the message, a handle to the a Sendmail::Milter context, so it can do exciting things like muck with message bodies and headers, and finally a handle to Sendmail::Milter::Monkey utility functions, so that your monkey brain can control it's monkey.
Running MilterMonkey
MilterMonkey should be executed by a simple perl script, such as the following, which creates a milter that doesn't acutally do very much, as it only uses the "trivial" monkey brain which is included in the distribution.
#!/usr/av/bin/perl5.8.0 -w use threads; use Sendmail::Milter::Monkey ( 'connection' => 'inet:6609' ); # Use your monkey brains in the order you wish them to be executed. use Sendmail::Milter::Monkey::Brains; # Spank your monkey Sendmail::Milter::Monkey::spank();
Sendmail::Milter::Monkey, at the minimum, must be passed connection information -- a local, or inet socket to listen from. ( see the documentation for Sendmail::Milter for what is acceptable here.
Here is an startup script that is much more useful:
#!/usr/av/bin/perl5.8.0 -w use threads; use Sendmail::Milter::Monkey ( 'connection' => 'inet:6609' ); # Use your monkey brains in the order you wish them to be executed. use Sendmail::Milter::Monkey::AntiVirus ( 'relay_mode' => 0 ); use Sendmail::Milter::Monkey::Spam; # Spank your monkey Sendmail::Milter::Monkey::spank();
Sendmail::Milter::Monkey parameters
- cid_timeout
- This is the length of time a message can sit idle in the milter's memory before the monkey cleans it up, in seconds. (default: 60 * 10, 10 minutes)
- debug_level
- The minimum debug level, 0-99, for logging information. This should be set to something around 50 to get useful logging. Less is more.
- debug_mode
- If you thought the syslog was verbose, turn this on and you'll see more on STDERR
- defaultexpiration
- Default expiration time for a milter key
- milter_key
- Use the milterkey feature. 1 or 0. (default: 1)
- milterkeyheader
- The name of the header the milter key is stored in. (default: X-Milter-Key)
- miltersecretfile
- Path to a file where the secret is held for the 'milter-key' function. (default: /etc/mail/miltersecret)
- pidfile
- Path to a .pid file for the monkey. (default: /tmp/monkey.pid)
- miltername
- The name of the milter. (default: MilterMonkey)
- threads
- Number of threads allowed to be running simultaneously. (default: 20)
- jobsperthread
- Number of messages a thread can process before it is "sent home". (default: 200)
Included Modules
Sendmail::Milter::Monkey::AntiVirus
This is a simple module for virus checking. It has two modes of operation -- the first responds to infected mail via SMTP response codes, good for using on your outgoing mail relays and not generating annoying bounce messages. In the second mode of operation, virus-laden messages are replaced with messages to the sender and the recipient, apprising them of the potential infection. As some viruses are getting craftier, making notification emails simply more confusing, it is also possible to define a regular expression to match certain viruses marking them to simply be discarded.
Here are the parameters that the AntiVirus monkey brain accepts.
- tempfile_template
- Template string for temporary files that may need to be created. AntiVirus needs to write the email to a file to scan it. (default: /var/tmp/av_%s)
- uvscanpath
- Path to the McAfee command line scanner. (default:/usr/av/bin/uvscan
- minscansize
- The minimum size, in bytes, a message must be for it to be virus-scanned. (default: 50000)
- domainname
- Domain name used in bounce messages. (default: membrain.com)
- helpaddr
- An email address sent in the bounce messages to direct the user to appropriate help. (default: postmaster@membrain.com)
- sendmailpath
- The path to sendmail. (default: /usr/lib/sendmail)
- who
- A pretty text string to be used in the bounce messages. (default: Membrain Technologies)
- discard_pattern
- A regex matching viruses that are to be silently discarded. (default: (Klez|SirCam|Exploit-MIME))
- alternate_key_header
- A header name which may contain a key of the same format used in MilterMonkey's key
- Why is this here? Locally we scan messages on our outgoing mail relays (smtp servers) just for viruses, but if the mail is to be locally delivered, it gets passed back to our incoming mail servers which want to check for viruses and scan for spam. Since the virus check has already been done, they know they can skip that, and only do the spam check. (The outgoing mail servers have their MilterMonkey key header set to this value, and they share the same "secret".)
Sendmail::Milter::Monkey::Spam
The SpamAssassin module for MilterMonkey acts as a 'spamc' client, contacting a 'spamd' running on the same server. SpamAssassin, itself, would be very problematic to run as part of the milter itself, as it is soooo beyond not being thread-happy. This module currently doesn't take any parameters. It simply sets the X-Spam-Flag & X-Spam-Status headers on your mail messages. It adds a "rating=" field to X-Spam-Status (beyond what SpamAssasin) does, with a certain number of "S"'s (determined by the function generate_rating), which make filtering via procmail for a spam's minimum certainty level a breeze. (and, as SpamAssassin gets better, the administrator can tweak these rating/score levels, without mucking with users' specific filtering rules.
