Current Path :
/
etc
/
mail
/
spamassassin
/
Or
Select Your Path :
Upload File :
New :
File
Dir
//etc/mail/spamassassin/check_domain_spoofing.pm
package Mail::SpamAssassin::Plugin::CheckDomainSpoofing; use strict; use warnings; use Mail::SpamAssassin::Plugin; use vars qw(@ISA); @ISA = qw(Mail::SpamAssassin::Plugin); # Configuration: List of whitelisted domains and email addresses (space-separated) # These will be considered trusted senders and bypass all checks # Examples: # Domains: 'trusteddomain.com company.org' # Full addresses: 'ceo@company.com admin@system.org' # Mixed: 'trusteddomain.com admin@company.com support@help.com' my $WHITELISTED_ENTRIES = ''; # Constructor for the SpamAssassin plugin sub new { my ($class, $mailsa) = @_; $class = ref($class) || $class; my $self = $class->SUPER::new($mailsa); bless ($self, $class); # Register our evaluation function with SpamAssassin $self->register_eval_rule('check_domain_spoofing'); return $self; } # Main evaluation function that performs domain spoofing detection # Returns: # 1 if potential spoofing is detected # 0 if the email appears legitimate sub check_domain_spoofing { my ($self, $pms) = @_; # Step 1: Extract and validate the From address my $from_addr = lc($pms->get('From:addr')); return 0 unless $from_addr; # No From address, skip checks # Step 2: Check whitelist # First check full email address match foreach my $whitelisted (split(/\s+/, lc($WHITELISTED_ENTRIES))) { # If the whitelisted entry contains @, treat it as a full email address if ($whitelisted =~ /\@/) { if (lc($from_addr) eq $whitelisted) { # Exact email address match found return 0; } } # Otherwise treat it as a domain name elsif ($from_addr =~ /\@(?:.*?\.)?([^.]+\.[^.]+)$/i) { my $sender_domain = lc($1); if ($sender_domain eq $whitelisted) { # Domain match found return 0; } } } # Step 3: Extract sender's domain for self-CC check return 0 unless $from_addr =~ /\@(?:.*?\.)?([^.]+\.[^.]+)$/; my $sender_domain = $1; # Step 4: Process CC addresses first to check for self-CC behavior # Spammers typically don't CC themselves, so if we find a self-CC, # we can consider the email legitimate my @cc_addresses = $pms->get('Cc:addr'); my @recipient_addresses; # Will hold all recipient addresses for later checks foreach my $cc_addr (@cc_addresses) { next unless $cc_addr; $cc_addr = lc($cc_addr); # Check if any CC address is from the same domain as sender if ($cc_addr =~ /\@(?:.*?\.)?([^.]+\.[^.]+)$/) { my $cc_domain = $1; if ($cc_domain eq $sender_domain) { # Found a self-CC, indicating legitimate sender behavior return 0; } } push @recipient_addresses, $cc_addr; } # Step 5: Add To: addresses to the recipient list my @to_addresses = $pms->get('To:addr'); foreach my $addr (@to_addresses) { next unless $addr; push @recipient_addresses, lc($addr); } return 0 unless @recipient_addresses; # No valid recipients found # Step 6: Get From display name for additional checking my $from_name = lc($pms->get('From:name')); # Step 7: Main spoofing detection logic foreach my $recipient_addr (@recipient_addresses) { # Extract domain and TLD from recipient address # Example: for "user@sub.example.com", extracts "example" and "com" next unless $recipient_addr =~ /\@(?:.*?\.)?([^.]+)\.([^.]+)$/; my ($recipient_domain, $recipient_tld) = ($1, $2); # Check for spoofing indicators: # 1. Recipient's domain appears in FROM local-part or display name # 2. BUT the actual FROM domain is different # First check: Does recipient domain appear in From address or name? next unless ( # Check if domain appears in local-part of From address # Example: example.support@malicious.com ($from_addr && $from_addr =~ /^[^@]*\Q$recipient_domain\E[^@]*@/i) || # Check if domain appears in From display name # Example: "Example Support" <support@malicious.com> ($from_name && $from_name =~ /\Q$recipient_domain\E/i) ); # Second check: Is this actually legitimate same-domain communication? # If FROM address domain matches recipient domain, it's legitimate next if $from_addr =~ /\@(?:.*?\.)?$recipient_domain\.$recipient_tld$/i; # If we get here, we found a potential spoofing attempt: # - Recipient's domain appears in FROM local-part or display name # - BUT the actual FROM address is from a different domain return 1; } # No spoofing detected return 0; } 1;