#!/usr/bin/perl #-------------------------------------------------# #Copyright(C)2007 Y.Ohkouchi. All rights reserved.# #procdnsbl ver070508.8 # #Url :http://cmf.ohtanz.com/ # #Mail :cmf@ohtanz.com # #-------------------------------------------------# use strict; use MIME::Base64; use MIME::QuotedPrint; #ここにDNSBLを列挙して下さい my @DNS_BL = ( 'all.rbl.jp', 'bl.spamcop.net', ); #ここにURLBLを列挙して下さい my @URL_BL = ( 'url.rbl.jp', 'multi.surbl.org', 'multi.uribl.com', ); my @MAIL_HEADER; my @MAIL_BODY; my $SPLIT_SWITCH; my $SPAM_FLAG; while () { if (!$SPLIT_SWITCH) { if ($_ =~ /^\n$/) { $SPLIT_SWITCH = 1; } else { push(@MAIL_HEADER,$_); } } else { push(@MAIL_BODY,$_); } } if (($SPAM_FLAG = &CheckDnsBL(@MAIL_HEADER))) { push(@MAIL_HEADER,$SPAM_FLAG); } elsif (($SPAM_FLAG = &CheckUrlBL(@MAIL_BODY))) { push(@MAIL_HEADER,$SPAM_FLAG); } print @MAIL_HEADER; print "\n"; print @MAIL_BODY; exit(0); sub CheckDnsBL { my @C_HEADER = @_; my $RECEIVE; my $LINE; my %CACHE; my $HOST; my $ADDR; my $SEARCH; my $PLUS_HEADER; foreach $LINE (@C_HEADER) { if (!$RECEIVE && $LINE =~ /^Received: from .+? \(.+? \[127\.0\.0\.1\]\)/i) { $RECEIVE = 1; next; } if ($RECEIVE && $LINE =~ /^Received: from .+/i) { while ($LINE =~ /.*?[\x20\[\(]([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[0-9a-z\-\.]+\.[a-z]+)[\x20\]\)].*/i) { $CACHE{$1} = 1; $LINE =~ s/(.*?)[\x20\[\(]([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}|[0-9a-z\-\.]+\.[a-z]+)[\x20\]\)](.*)/$1$3/i; } } } foreach (keys(%CACHE)) { if ($_ !~ /^127\.0\.0\.1|192\.168\./) { if ($_ =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) { $HOST = ""; $ADDR = $_; } else { $HOST = $_; $ADDR = ""; } if (!($SEARCH = &SearchFqdn($HOST))) { $SEARCH = join('.', reverse(split(/\./,$ADDR))); } if ($SEARCH) { foreach my $r (@DNS_BL) { my $DNSBL = $SEARCH . '.' . $r; if (join('.', unpack("C4", gethostbyname($DNSBL)))) { $PLUS_HEADER = "X-DnsBL: " . $DNSBL . "\n"; last; } } } last if $PLUS_HEADER; } } return($PLUS_HEADER); } sub CheckUrlBL { my @C_BOBY = &B64QDecode(@_); my $LINE; my %CACHE; my $SEARCH; my $PLUS_HEADER; foreach $LINE (@C_BOBY) { while ($LINE =~ /.*?http:\/\/([\w\.\~\-\/\?\&\+\=\:\@\%\;\#]+).*/i) { my $RIP = $1; $RIP =~ s/^(.+?)\/.*/$1/; if ($RIP =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) { $SEARCH = join('.', reverse(split(/\./,$RIP))); } else { $SEARCH = &SearchFqdn($RIP); } if ($SEARCH && !$CACHE{$SEARCH}) { my $r; foreach $r (@URL_BL) { my $DNSBL = $SEARCH . '.' . $r; if (join('.', unpack("C4", gethostbyname($DNSBL)))) { $PLUS_HEADER = "X-UrlBL: " . $DNSBL . "\n"; last; } } $CACHE{$SEARCH} = 1; } last if $PLUS_HEADER; $LINE =~ s/(.*?)http:\/\/[\w\.\~\-\/\?\&\+\=\:\@\%\;\#]+(.*)/$1$2/i; } last if $PLUS_HEADER; } return($PLUS_HEADER); } sub SearchFqdn { my $C_HOST = shift; my $SEARCH; if ($C_HOST =~ /[\w\-]+\.[\w\-]+$/) { my @NAMES = reverse(split(/\./,$C_HOST)); my $FQDN = shift(@NAMES); my $n; foreach $n (@NAMES) { $FQDN = $n . '.' . $FQDN; if (join('.', unpack("C4", gethostbyname($FQDN)))) { $SEARCH = $FQDN; last; } } } return($SEARCH); } sub B64QDecode { my @C_BODY = @_; my $B64QD_FLAG; my $ENC_TYPE; my $DEC_LINE; my @D_BODY; foreach (@C_BODY) { if (!$B64QD_FLAG && $_ =~ /^Content-Type: text\/.+/i) { $B64QD_FLAG = 1; next; } elsif ($B64QD_FLAG == 1 && $_ =~ /^Content-Transfer-Encoding: (base64|quoted-printable)/i) { $ENC_TYPE = $1; $B64QD_FLAG = 2; next; } elsif ($B64QD_FLAG == 2 && $_ =~ /^\n/) { $B64QD_FLAG = 3; next; } elsif ($B64QD_FLAG == 3) { if ($_ =~ /^--/) { if ($ENC_TYPE =~ /^base64$/i) { $DEC_LINE = decode_base64($DEC_LINE); } elsif ($ENC_TYPE =~ /^quoted-printable$/i) { $DEC_LINE = decode_qp($DEC_LINE); } push(@D_BODY,$DEC_LINE); $ENC_TYPE = ""; $DEC_LINE = ""; $B64QD_FLAG = 0; } else { $DEC_LINE .= $_; } } else { push(@D_BODY,$_); } } return(@D_BODY); }