How it works
This plugin checks if a mail has been delivered directly from a dialup-IP. It simply uses the last trusted received-line for the IP and the DNS-Names and tries to find out if the IP-Number is somehow coded into the DNS.
Requirements
none.
Installation
Save the two files below in your local configuration directory.
Remarks
Note that this is my first SA plugin, so any feedback is welcome
This Plugin can only be a hint about spam, so don't set the score to high.
-- Author: Lars Uffmann, lu -at- cachescrubber -dot- org, converted to a module by Cord Beermann,
cord@Wunder-Nett.org
Code
relayed_by_dialup.cf
loadplugin RelayedByDialup /etc/spamassassin/relayed_by_dialup.pm header RELAYED_BY_DIALUP eval:relayed_by_dialup() describe RELAYED_BY_DIALUP Sent directly from dynamic IP address score RELAYED_BY_DIALUP 1
relayed_by_dialup.pm
# written by Lars Uffmann <lu -at- cachescrubber -dot- org>
# converted to a SA-module by Cord Beermann <cord@Wunder-Nett.org>
# Licence: same as Spamassassin
package RelayedByDialup;
use Mail::SpamAssassin;
use Mail::SpamAssassin::Plugin;
our @ISA = qw(Mail::SpamAssassin::Plugin);
$dbg_text = 'dynamic_relay: ';
sub new {
my ($class, $mailsa) = @_;
$class = ref($class) || $class;
my $self = $class->SUPER::new($mailsa);
bless ($self, $class);
$self->register_eval_rule ("relayed_by_dialup");
return $self;
}
sub relayed_by_dialup {
my ($self, $permsgstatus) = @_;
my $match = 0;
# we need the reveived header from _our_ first MX.
# we can only match this if we have at least 1 untrusted header
Mail::SpamAssassin::Plugin::dbg("dynamic_relay: starting");
unless ($permsgstatus->{num_relays_untrusted} > 0) {
Mail::SpamAssassin::Plugin::dbg("dynamic_relay: num_relays_untrusted undefined");
return 0;
} else {
my $relay = $permsgstatus->{relays_untrusted}->[0];
Mail::SpamAssassin::Plugin::dbg ("dynamic_relay: mx=" . $relay->{by});
if ($relay->{no_reverse_dns} || $relay->{rdns} eq '' ) {
Mail::SpamAssassin::Plugin::dbg($dbg_text . "cannot perform, no rDNS");
return 0;
}
if (_is_dynamic_ip($relay->{ip}, $relay->{rdns})) {
Mail::SpamAssassin::Plugin::dbg($dbg_text . "match: " . $relay->{ip} . "=" . $relay->{rdns});
return 1;
}
Mail::SpamAssassin::Plugin::dbg($dbg_text . "tried: " . $relay->{ip} . "=" . $relay->{rdns});
return 0;
}
}
sub _is_dynamic_ip {
my @ip = split(/\./, $_[0]);
my $name = $_[1];
return 0 unless ($name);
# convert addresses in hex to dotted decimal notation.
$name =~ s/\b([a-f0-9]{8})\b/join(".", unpack("C*", pack("H8", $1)))/eg;
# try shorter suffixes of $IP
return 1 if (_is_rr_dynamic_ip(join(".",@ip), $name));
shift(@ip);
return 1 if (_is_rr_dynamic_ip(join(".",@ip), $name));
return 0;
# will lead to false positives ...
shift(@ip);
return 1 if (_is_rr_dynamic_ip(join(".",@ip), $name));
return 0;
}
sub _is_rr_dynamic_ip {
my $ip = $_[0];
my $is_ip = $_[1];
my $is_ip_sum = 0;
my $ip_test_sum = 0;
# remove anything but digits > 0
$is_ip =~ s/[^1-9]//g;
# normalize the ip
my $ip_test = $ip;
# remove anything but digits > 0
$ip_test =~ s/[0.]//g;
my $diff = length($is_ip) - length($ip_test);
return 0 if ($diff < 0);
my $offset = 0;
map { $ip_test_sum += $_ } split("", $ip_test);
do {
$is_ip_sum = 0;
my $test = substr($is_ip, $offset++, length($ip_test));
map { $is_ip_sum += $_ } split("", $test);
return 1 if (($is_ip_sum == $ip_test_sum));
} while ($diff--);
return 0;
}
1;
