This is Bavaria, Germany!
mail2:/# apt-get install -t testing mimedefang mail2:/# /etc/init.d/mimedefang startMimedefang runs now, there should be a file /var/spool/MIMEDefang/mimedefang.sock which is the pipe to put all mails in for sendmail.
Don't care for /var/spool/MIMEDefang/mimedefang-multiplexor.sock, this simply means that some mimedefang.pl programms are started in and endless loop. So the load of the system is much lower because there will not be a new programm started for every mail you get through your system.
Put this line into /etc/mail/sendmail.mc and run a make after that. This is not done by the installation of mimedefang. I found this hint in /usr/share/doc/mimedefang/README.Debian
# vim /etc/mail/sendmail.mc
...
LOCAL_CONFIG
...
INPUT_MAIL_FILTER(`mimedefang', `S=unix:/var/spool/MIMEDefang/mimedefang.sock, F=T, T=S:1m;R:1m')dnl
...
LOCAL_CONFIG
...
Localize mimedefang-message in mail-header:
# vim /etc/mail/mimedefang.conf
...
# The contents of the "X-Scanned-By" header added to each mail. Do
# not use the quote mark (') in this setting. Setting it to "-"
# prevents the header from getting added at all.
# X_SCANNED_BY="MIMEDefang N.NN (www . roaringpenguin . com / mimedefang)"
# This seems not to work when there are spaces in the string!
X_SCANNED_BY="MIMEDefang_at_mail2.zdf__Stadt_Zirndorf"
...
# Bad extensions
$bad_exts = '(ade|adp|app|......|exe|....|pif|....|scr|....|\{[^\}]+\})';
Bad mails will be moved to directory /var/spool/MIMEdefang. Take a look:
mail2:/etc/mail# ls -l /var/spool/MIMEDefang/ drwx------ 2 defang defang 4096 Mär 23 13:18 qdir-2004-03-23-13.18.05-001 drwx------ 2 defang defang 4096 Mär 23 13:24 qdir-2004-03-23-13.24.05-001 drwx------ 2 defang defang 4096 Mär 23 13:30 qdir-2004-03-23-13.30.16-001 drwx------ 2 defang defang 4096 Mär 23 13:58 qdir-2004-03-23-13.58.05-001 drwx------ 2 defang defang 4096 Mär 23 13:58 qdir-2004-03-23-13.58.07-001 drwx------ 2 defang defang 4096 Mär 23 14:00 qdir-2004-03-23-14.00.16-001 drwx------ 2 defang defang 4096 Mär 23 14:04 qdir-2004-03-23-14.04.05-001 drwx------ 2 defang defang 4096 Mär 23 14:30 qdir-2004-03-23-14.30.07-001 drwx------ 2 defang defang 4096 Mär 23 14:32 qdir-2004-03-23-14.32.06-001 drwx------ 2 defang defang 4096 Mär 23 14:34 qdir-2004-03-23-14.34.05-001Create a cronjob which removes old defanged files from /var/spool/MIMEdefang
# crontab -e
# delete old mimedefang-dirs, older that 7 days 00 18 * * * (find /var/spool/MIMEDefang -type d -mtime +7 -maxdepth 1 -print | xargs rm -rf) >/dev/null 2>&1
/etc/init.d/sendmail stop /etc/init.d/mimedefang stop sleep 2 /etc/init.d/mimedefang start sleep 2 /etc/init.d/sendmail start
Send a testmail like this which must be intercepted by mimedefang, because standard in /etc/mail/mimedefang-filter is to filter *.exe-files. Look in /var/spool/mail.log for mimedefangs behaviour:
mail2:~/bin/testmail# apt-get install sharutils ### install uuencode mail2:~/bin/testmail# echo dontcare-dontcare >bad.exe mail2:~/bin/testmail# uuencode bad.exe bad.exe | mail -s "test for bad attach" lippmann@zirndorf.deRemember that mimedefang checks attachment simply by their filenames! You should see something like this in /var/spool/mail.log:
|
Mar 19 07:31:21 mail2 mimedefang.pl[22067]: MDLOG,i2J7VKjB022691, bad_filename, bad.exe, application/octet-stream, <root@mail2.zdf>, <lippmann@zirndorf.de>, test for bad attach Mar 19 07:31:21 mail2 mimedefang.pl[22067]: filter: i2J7VKjB022691: quarantine=1 Mar 19 07:31:21 mail2 sm-mta[22691]: i2J7VKjB022691: Milter message: body replaced Mar 19 07:31:21 mail2 sm-mta[22691]: i2J7VKjB022691: Milter add: header: X-Scanned-By: 'MIMEDefang |
My users like to have a german warning-message, not like this:
|
[Variable $GeneralWarning] WARNING: This e-mail has been altered by MIMEDefang. Following this paragraph are indications of the actual changes made. For more information about your site's MIMEDefang policy, contact <you-know-who@hogwarts.co.uk>. For more information about MIMEDefang, see: http://www.roaringpenguin.com/mimedefang/enduser.php3 [Defined in sub filter of /etc/mail/mimedefang-filter] An attachment named bad.exe was removed from this document as it constituted a security hazard. If you require this document, please contact the sender and arrange an alternate means of receiving it. |
This is defined in /usr/bin/mimedefang.pl, look for if (!defined($GeneralWarning)) {
But it's a better idea to include a line like this in /etc/mail/mimedefang-filter:
# Put this new line at the very beginning |
What has happened to the files? The user gets informed
Restart everything and test:
/etc/init.d/sendmail stop /etc/init.d/mimedefang stop sleep 2 /etc/init.d/mimedefang start sleep 5 # wait until all processes start /etc/init.d/sendmail start echo dontcare >/tmp/bad.exe uuencode /tmp/bad.exe bad.exe | mail -s "umbridge sends bad mail" lippmann@zirndorf.de
mail2:/etc/mail# apt-get install -t testing spamassassin mail2:/etc/mail# /etc/init.d/sendmail stop mail2:/etc/mail# /etc/init.d/mimedefang stop
Create a little special rule for testing to see spamassassin work.
mail:/# vim /etc/mail/spamassassin/local.cf
# Only to test
header BAD_TEST Subject =~ /i am evil/i
score BAD_TEST 5.00
mail2# /etc/init.d/mimedefang start mail2# /etc/init.d/sendmail start mail2# mail -s "i am evil" lippmann@zirndorf.de </dev/nullYou should see something like this in /var/spool/mail.log:
|
Mar 19 10:48:38 mail2 sendmail[27376]: i2JAmcjn027376: from=root, size=45, class=0, nrcpts=1, msgid=<200403191048.i2JAmcjn027376@mail2.zdf>, relay=root@localhost Mar 19 10:48:38 mail2 sm-mta[27378]: i2JAmcVx027378: from=<root@mail2.zdf>, size=309, class=0, nrcpts=1, msgid=<200403191048.i2JAmcjn027376@mail2.zdf>, proto=ESMTP, daemon=MSA, relay=mail2 [10.95.81.71] Mar 19 10:48:38 mail2 mimedefang.pl[27174]: MDLOG, i2JAmcVx027378, spam,15,10.95.81.71, <root@mail2.zdf>, <lippmann@zirndorf.de>, i am evil Mar 19 10:48:38 mail2 sm-mta[27378]: i2JAmcVx027378: Milter message: body replaced |
/etc/mail/spamassassin/local.cf is the point to create all your local rules. If you are good-skilled in database-programming you can do this with a script from a database (best practise, sorry no link here for that!). This is a small part of my ruleset:
################################################################### # ruleset whitelist ################################################################### whitelist_from me@home.de whitelist_from mywife@home.de ################################################################### # ruleset blacklist ################################################################### blacklist_from *@*.cnetchannel.com blacklist_from *@jeepmania.it ################################################################### # ruleset rescore ################################################################### score CHINA_HEADER 3 score FORGED_YAHOO_RCVD 5 score HTML_IMAGE_ONLY_02 5 score SUB_FREE_OFFER 4 ################################################################### # content-check, ruleset bad ################################################################### header ZDF_BOESE_1 Subject =~ /your account/i describe ZDF_BOESE_1 your account score ZDF_BOESE_1 5.00 header ZDF_BOESE_2 From =~ /^admin\@/i describe ZDF_BOESE_2 Mail from admin score ZDF_BOESE_2 5.00 body ZDF_BOESE_4 /sent as a binary/i describe ZDF_BOESE_4 Sent as a binary score ZDF_BOESE_4 5.00 ################################################################### # these rules are _always_ valid ################################################################### header ZDF_ZZ_1 From =~ /./i describe ZDF_ZZ_1 local.cf lives score ZDF_ZZ_1 0.01 body ZDF_ZZ_2 /./i describe ZDF_ZZ_2 local.cf body lives score ZDF_ZZ_2 0.01 |
/etc/mail/mimedefang-filter is the perl-script to make your things happen: log mails into a database, log attachments, log spam... I changed it like this.
sub get_dbh {
use DBI;
my ($dbname,$dbuser,$dbpass,$dbhost)=
qw(watchtower wwwrun XXXX mysql.internal.org);
my $dbh = DBI->connect("dbi:mysql:$dbname:$dbhost",$dbuser,$dbpass);
return $dbh;
}
|
sub log2db {
# You must have this table in your MySQL-database:
# CREATE TABLE `mailtrouble` (
# `lfdnr` int(11) NOT NULL auto_increment,
# `intime` datetime NOT NULL default '0000-00-00 00:00:00',
# `sender` varchar(50) default NULL,
# `recipient` varchar(50) default NULL,
# `subject` varchar(50) default NULL,
# `reason` varchar(20) NOT NULL default '',
# `shortreason` varchar(80) NOT NULL default '',
# PRIMARY KEY (`lfdnr`)
# ) TYPE=MyISAM;
my (%args)=@_;
my $shortreason = $args{shortreason} || "";
my $reason = $args{reason} || "";
# Kann man als Argumente angeben, muss man aber nicht
my $subject = exists $args{subject} ? $args{subject} : $Subject;
my $dbh = &get_dbh;
return unless $dbh;
my $sql = sprintf "insert into mailtrouble (intime, sender, recipient, subject, reason, shortreason) values (now(),%s,%s,%s,%s,%s)",
$dbh->quote($Sender),
$dbh->quote(join(",",@Recipients)),
$dbh->quote($Subject),
$dbh->quote($reason),
$dbh->quote($shortreason);
$dbh->do($sql);
$dbh->disconnect();
}
|
File: /etc/mail/mimedefang-filter
sub filter_end ($) {
...
# Spam checks if SpamAssassin is installed
if ($Features{"SpamAssassin"}) {
# we have to scan larger mails!
# if (-s "./INPUTMSG" < 100*1024) {
if (-s "./INPUTMSG" < 3000*1024) {
# Only scan messages smaller than 100kB. Larger messages
# are extremely unlikely to be spam, and SpamAssassin is
# dreadfully slow on very large messages.
...
|
Usually you would deny accepting virus-mails, but I accept them. Because I get mails from fetchmail or from other own systems from the borderline. So virus-mails
sub filter ($$$$) {
...
# Virus scan
if ($FoundVirus) {
...
# Log and throw away, you need a "sub log2db"!
&log2db( shortreason=>"virus", reason=> $VirusName);
action_discard();
# I cannot bounce in my environment
# action_bounce("Virus $VirusName found in mail - rejected");
...
|
I want to have an overview about attachments
sub filter ($$$$) {
...
# Log every attachment to a database
&log_attachments(attach_fn=>$fname)
if $fname;
if (filter_bad_filename($entity)) {
...
...
|
You need a subroutine to log into the database, first the single point to open the database:
sub get_dbh {
use DBI;
my ($dbname,$dbuser,$dbpass,$dbhost)=
qw(watchtower wwwrun XXXX mysql.internal.org);
my $dbh = DBI->connect("dbi:mysql:$dbname:$dbhost",$dbuser,$dbpass);
return $dbh;
}
|
Then the log-routine:
sub log_attachments {
# You must have this table in your MySQL-database:
# CREATE TABLE `mailattachments` (
# `lfdnr` int(11) NOT NULL auto_increment,
# `intime` datetime NOT NULL default '0000-00-00 00:00:00',
# `sender` varchar(50) default NULL,
# `recipient` varchar(50) default NULL,
# `subject` varchar(50) default NULL,
# `attachment_fn` varchar(80) NOT NULL default '',
# PRIMARY KEY (`lfdnr`)
# ) TYPE=MyISAM;
my (%args)=@_;
my $attach_fn = $args{attach_fn} || "";
my $dbh = &get_dbh;
return unless $dbh;
# <h@lisa.de> --> h@lisa.de
my $lsender = $Sender;
$lsender =~ s/^<(.+)>$/$1/;
my $sql = sprintf "insert into mailattachments (intime, sender, recipient, subject, attachment_fn) values (now(),%s,%s,%s,%s)",
$dbh->quote($lsender),
$dbh->quote(join(", ",@Recipients)),
$dbh->quote($Subject),
$dbh->quote($attach_fn);
$dbh->do($sql);
$dbh->disconnect();
}
|
In a company you get a lot of mails for a lot of users. If they shall not get all the spam and viruses, you have to redirect these mails to a special user (bad@we_are_good.org) which can take a view over this stuff to find false positives.
Create a new subroutine like this:
sub redirect_mail_to_mr_spam {
# Delete all Recipients from Spammail and send these mails
# to a special user in our domain
my $towhom_msg;
foreach my $rec (@Recipients) {
$towhom_msg .= "This mail should have been sent to: $rec\n";
delete_recipient($rec);
}
add_recipient("edv\@exchange.zdf");
# Add a file which shows to whom this mail should have been gone
action_add_part($entity, "text/plain", "-suggest",
"$towhom_msg\n",
"to_whom_this_mail_was_addressed.txt", "inline");
}
|
Now you can redirect bad mails to this user if catched exe, dll, bat, pif-files:
sub filter ($$$$) {
...
if (filter_bad_filename($entity)) {
# Send mails to a special spam/virus-recipient
&redirect_mail_to_mr_spam;
|
and it it's spam:
sub filter_end ($) {
...
if ($hits >= $req) {
# Send mails to a special spam/virus-recipient
&redirect_mail_to_mr_spam;
# Put a record into a database, if you have a "sub log2db"
&log2db(shortreason=>"spam", reason=>"X-Spam-Score was $hits");
|
# we don't use FPROT as filescanner
$Features{'Virus:FPROT'} = ('/bin/false' ne '/bin/false' ? '/bin/false' : 0);
# we would use FPROT as filescanner, but every file would
# be a new process
# $Features{'Virus:FPROT'} = ('/usr/local/bin/f-prot' ne '/bin/false' ? '/usr/local/bin/f-prot' : 0);
...
$Features{'Virus:FPROTD'} = 1;
...
# If running on a vserver or you have to customize an IP-address:
# $FprotdHost = "127.0.0.1:10200";
$FprotdHost = "10.95.81.71:10200";
|
Send an EICAR-test-virus as mail like this:
# echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' >/tmp/eicar.txt # uuencode /tmp/eicar.txt eicar.txt | mail -s "Test eicar" lippmann@zirndorf.deYou will see this in your /var/log/mail.log:
Mar 24 16:53:14 mail2 sendmail[6234]: i2OFrDZd006234: from=root, size=169, |