Created
December 12, 2012 12:20
-
-
Save bitfolk/4267353 to your computer and use it in GitHub Desktop.
Check that reverse DNS exists for every one of a big list of IPv4 and IPv6 addresses.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use strict; | |
use warnings; | |
use Net::IP qw(:PROC); | |
use Net::DNS; | |
use Getopt::Long; | |
use Pod::Usage; | |
my ($allow_invalid, $help, $man) = (0, 0, 0); | |
GetOptions( | |
'allowinvalid|a|daviey' => \$allow_invalid, | |
'help|?' => \$help, | |
'man' => \$man, | |
) or pod2usage(2); | |
pod2usage(1) if ($help); | |
pod2usage(-exitstatus => 0, -verbose => 2) if ($man); | |
my $res = Net::DNS::Resolver->new; | |
my @invalid_v6; | |
my @invalid_v4; | |
# IP ranges that aren't valid on the Internet (localhost, RFC1918, etc.) in | |
# CIDR format. | |
foreach ( | |
'0000::0/127', # Loopback | |
'fc00::/8', # Unique local | |
'fd00::/8', # Unique local | |
'fe80:0000::/10', # Link-local | |
'0000::/3', # Non-interface | |
'0000::/8', # Reserved | |
'fec0:0000::/10', # Site-local (obsolete) | |
) { | |
push(@invalid_v6, Net::IP->new($_)); | |
} | |
foreach ( | |
'127.0.0.0/8', # Loopback | |
'10.0.0.0/8', # RFC1918 | |
'172.16.0.0/12', # RFC1918 | |
'192.168.0.0/16', # RFC1918 | |
'224.0.0.0/4', # Class D multicast | |
'240.0.0.0/5', # Class E reserved | |
'248.0.0.0/5', # Reserved | |
'192.0.2.0/24', # Reserved for test | |
'0.0.0.0/8', # Reserved broadcast | |
'169.254.0.0/16', # Link-local | |
) { | |
push(@invalid_v4, Net::IP->new($_)); | |
} | |
my %ips; | |
my $dsh; | |
open $dsh, '-|', 'sudo', 'dsh', '-Mca', '-r', 'ssh', '-o-q', 'ip -4 addr' | |
or die "Can't pipe from dsh: $!"; | |
while (<$dsh>) { | |
# admin.bitfolk.com: 1: lo: <LOOPBACK,UP,10000> mtu 16436 qdisc noqueue | |
# admin.bitfolk.com: inet 127.0.0.1/8 scope host lo | |
# . | |
# . | |
# | |
# Only interested in lines that match inet and then an IPv4 address. | |
next unless (/^(\S+):\s+inet\s+(\d+\.\d+\.\d+\.\d+)\/\d+/i); | |
# Put them in a hash, which makes them unique as a side benefit. | |
$ips{$2} = $1; | |
} | |
close($dsh) or warn "Something weird when closing pipe: $!"; | |
open $dsh, '-|', 'sudo', 'dsh', '-Mca', '-r', 'ssh', '-o-q', | |
'ip -o -6 addr show scope global' or die "Can't pipe from dsh: $!"; | |
while (<$dsh>) { | |
# admin.bitfolk.com: 2: eth0 inet6 2001:ba8:1f1:f040::3/128 scope global \ valid_lft forever preferred_lft forever | |
# admin.bitfolk.com: 2: eth0 inet6 2001:ba8:1f1:f040::123/128 scope global \ valid_lft forever preferred_lft forever | |
# admin.bitfolk.com: 2: eth0 inet6 2001:ba8:1f1:f040:a800:ff:fe13:5ca4/64 scope global \ valid_lft forever preferred_lft forever | |
# backup0.bitfolk.com: 2: eth0 inet6 2001:ba8:1f1:f1e0::2/64 scope global \ valid_lft forever preferred_lft forever | |
# . | |
# . | |
# | |
# Only interested in lines that match a device called /eth|bond/, inet6 and | |
# then an IPv6 address. | |
next unless (/^(\S+):\s+\d+:\s+(?:eth|bond)\d+\s+inet6\s+([0-9a-f:]+)\/\d+/i); | |
$ips{$2} = $1; | |
} | |
foreach my $i (keys %ips) { | |
my $is_invalid = 0; | |
my $net_ip = Net::IP->new($i); | |
my $invalid_ref; | |
if (not $allow_invalid) { | |
if (ip_is_ipv6($i)) { | |
$invalid_ref = \@invalid_v6; | |
} else { | |
$invalid_ref = \@invalid_v4; | |
} | |
foreach (@{ $invalid_ref }) { | |
if ($_->overlaps($net_ip) == $IP_B_IN_A_OVERLAP) { | |
$is_invalid = 1; | |
last; | |
} | |
} | |
if ($is_invalid) { | |
print "Not bothering to query $i because it isn't valid on the Internet.\n"; | |
next; | |
} | |
} | |
my $query = $res->query($net_ip->reverse_ip, 'PTR'); | |
if ($query) { | |
foreach my $rr ($query->answer) { | |
next unless $rr->type eq 'PTR'; | |
# print $rr->rdatastr, "\n"; | |
} | |
} else { | |
warn "query failed: ", $res->errorstring, " for $i on ", | |
$ips{$i}, "\n"; | |
} | |
} | |
__END__ | |
=pod | |
=head1 NAME | |
check_rev_dns_exists.pl -- Check that reverse DNS exists for every IP address on every host | |
=head1 SYNOPSIS | |
check_rev_dns_exists.pl [options] | |
Options: | |
-a, --allowinvalid, --daviey Check reverse DNS even for invalid IPs | |
=head1 OPTIONS | |
=over 4 | |
=item B<-a>, B<--allowinvalid>, B<--daviey> | |
By default, IP addresses that belong to ranges that aren't expected to be valid | |
on the Internet do not have their reverse DNS checked. Supplying one of these | |
flags will force these to be checked too. | |
=back | |
=head1 DESCRIPTION | |
Connects to every host (using dsh) and lists configured IPv4 and v6 addresses. | |
Then checks that reverse DNS configuration exists for every one of them. | |
Ignores addresses that are not valid on the Internet, such as RFC1918 and | |
reserved ranges. | |
=head AUTHOR | |
Andy Smith <andy@bitfolk.com> | |
=head1 COPYRIGHT AND LICENSE | |
Copyright 2012 Andy Smith <andy@bitfolk.com>. | |
This program is free software; you can redistribute it and/or modify it under | |
the terms of the Perl Artistic License. | |
=cut | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment