Server IP : 85.214.239.14 / Your IP : 13.58.61.176 Web Server : Apache/2.4.62 (Debian) System : Linux h2886529.stratoserver.net 4.9.0 #1 SMP Tue Jan 9 19:45:01 MSK 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.18 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, MySQL : OFF | cURL : OFF | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : OFF Directory : /bin/ |
Upload File : |
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Getopt::Long; use Pod::Usage; $|++; my %command_line_options = ( 'author:s' => \my $author, 'from_dom:s' => \my $from, 'begin:s' => \my $begin, 'end:s' => \my $end, 'disposition:s' => \my $disposition, 'dkim:s' => \my $dkim, 'spf:s' => \my $spf, 'dns' => \my $dns_opt, 'geoip:s' => \my $geoip_opt, 'help' => \my $help, 'verbose' => \my $verbose, ); GetOptions (%command_line_options); use lib 'lib'; use Mail::DMARC::Report; my $report = Mail::DMARC::Report->new; my $gip; pod2usage if $help; my $reports = $report->store->retrieve( (defined $from ? (from_domain => $from ) : () ), (defined $author ? (author => $author ) : () ), (defined $begin ? (begin => $begin ) : () ), (defined $end ? (end => $end ) : () ), ); print_header(); foreach my $report_ref ( reverse @$reports ) { my $rows = $report->store->backend->get_rr( rid => $report_ref->{rid} )->{rows}; next if $disposition && ! grep { $_->{disposition} eq $disposition } @$rows; next if $dkim && ! grep { $_->{dkim} eq $dkim } @$rows; next if $spf && ! grep { $_->{spf } eq $spf } @$rows; print_record($report_ref); print_rows( $rows ); print "\n"; } sub print_record { my $rec = shift; printf "%3s %26s %15s\n", @$rec{qw/ rid author begin /}; return; }; sub print_rows { my $rows = shift; foreach my $row ( @$rows ) { no warnings; ## no critic (NoWarn) next if $disposition && $disposition ne $row->{disposition}; next if $dkim && $dkim ne $row->{dkim}; next if $spf && $spf ne $row->{spf}; printf " | -- %3s %20s %39s %13s %7s %7s", @$row{qw/ count header_from source_ip disposition dkim spf /}; foreach my $r ( @{ $row->{reasons} } ) { print ' ' . $r->{type}; print "( $r->{comment} )" if $r->{comment}; }; my $geoip_details = get_geoip_details( $row->{source_ip} ); print " $geoip_details"; my $dns_hostname = get_dns_hostname( $row->{source_ip} ); print " $dns_hostname\n"; } return; }; sub print_header { printf "%3s %26s %15s\n", qw[ ID Author Report-Start ]; printf " | -- %3s %20s %39s %13s %7s %7s\n", 'Qty','From','IP','Disposition','DKIM','SPF'; return; }; sub get_geoip_details { my $ip = shift; return if ! defined $geoip_opt; $geoip_opt ||= 'city,country_code,continent_code'; $gip ||= get_geoip_db(); return if ! $gip; if ($ip =~ /^\d+\.\d+\.\d+\.\d+$/) { $ip = '::ffff:'.$ip; } my $r = $gip->record_by_addr_v6($ip) or return ''; my @result; my @fields = split(',', $geoip_opt); my @allowed = qw( country_code country_code3 country_name region region_name city postal_code latitude longitude time_zone area_code continent_code metro_code ); foreach my $f (@fields) { next if ! grep {$_ eq $f} @allowed; next if ! $r->${f}(); push @result, $r->${f}(); } return join(', ', @result); } sub get_geoip_db { return $gip if $gip; eval "require Geo::IP"; ## no critic (Eval) if ($@) { warn "unable to load Geo::IP\n"; return; }; foreach my $local ( '/usr/local', '/opt/local', '/usr' ) { my $db_dir = "$local/share/GeoIP"; foreach my $db (qw/ GeoIPCityv6 GeoLiteCityv6 /) { if (-f "$db_dir/$db.dat") { print "using db $db" if $verbose; $gip = Geo::IP->open("$db_dir/$db.dat"); } last if $gip; } last if $gip; }; return $gip; } sub get_dns_hostname { my $ip = shift; return if ! $dns_opt; my @answers = $report->has_dns_rr('PTR', $ip); return '' if 0 == scalar @answers; return $answers[0] if scalar @answers >= 1; print Dumper(\@answers); return; }; exit; __END__ =head1 NAME dmarc_view_reports - view the contents of the DMARC data store =head1 SYNOPSIS dmarc_view_reports [ --option=value ] Dumps the contents of the DMARC data store to your terminal. The most recent records are show first. =head2 Search Options author - report author (Yahoo! Inc, google.com, etc..) from_dom - message sender domain begin - epoch start time to display messages after end - epoch end time to display messages before disposition - DMARC disposition (none,quarantine,reject) dkim - DKIM alignment result (pass/fail) spf - SPF alignment result (pass/fail) =head2 Other Options dmarc_view_reports [ --geoip --dns --help --verbose ] geoip - do GeoIP lookups (requires the free Maxmind GeoCityLitev6 database). dns - do reverse DNS lookups and display hostnames help - print this syntax guide verbose - print additional debug info =head1 EXAMPLES To search for all reports from google.com that failed DMARC alignment: dmarc_view_reports --author=google.com --dkim=fail --spf=fail Note that we don't use --disposition. That would only tell us the result of applying DMARC policy, not necessarily if the messages failed DMARC alignment. To display GeoIP lookup data for the source ip: dmarc_view_reports --geoip By default; city, country_code & continent_code are shown. You can optionally pass a comma delimited string to --geoip= with any of the following fields: country_code country_code3 country_name region region_name city postal_code latitude longitude time_zone area_code continent_code metro_code dmarc_view_reports --geoip=country_name,continent_code dmarc_view_reports --geoip=continent_code,country_name # keep order dmarc_view_reports --geoip=city,city,city # repeat =head1 SAMPLE OUTPUT ID Recipient From/Sender Report-Start | -- Qty Source IP Disposition DKIM SPF 570 theartfarm.com simerson.net 2013-05-20 09:40:50 | -- 1 75.126.200.152 quarantine fail fail 568 yeah.net tnpi.net 2013-05-21 09:00:00 | -- 1 111.176.77.138 reject fail fail 567 126.com tnpi.net 2013-05-21 09:00:00 | -- 1 49.73.135.125 reject fail fail 565 google.com mesick.us 2013-05-20 17:00:00 | -- 88 208.75.177.101 none pass pass 564 google.com theartfarm.com 2013-05-20 17:00:00 | -- 3 208.75.177.101 none pass pass 563 google.com lynboyer.com 2013-05-20 17:00:00 | -- 1 2a00:1450:4010:c03::235 none pass fail forwarded | -- 12 208.75.177.101 none pass pass | -- 1 209.85.217.174 none pass fail forwarded 561 google.com simerson.net 2013-05-20 17:00:00 | -- 1 208.75.177.101 none pass pass 560 google.com tnpi.net 2013-05-20 17:00:00 | -- 1 208.75.177.101 none pass pass | -- 1 27.20.110.240 reject fail fail 559 hotmail.com lynboyer.com 2013-05-20 20:00:00 | -- 6 208.75.177.101 none pass pass =head1 AUTHORS =over 4 =item * Matt Simerson <msimerson@cpan.org> =item * Davide Migliavacca <shari@cpan.org> =item * Marc Bradshaw <marc@marcbradshaw.net> =back =cut