Reverse DNS LookUp mit Net::DNS

Aus Performance-Gründen sind die meißten Webserver so konfiguriert, daß IP Adressen nicht aufgelöst werden. Wenn man nun aber doch den Hostnamen des Rechners der auf die eigene Homepage zugegriffen hat erfahren will, kann man diese hinterher auflösen, dazu dient dieses Script.

Features:

Dieses Script implementiert eine Timeout Funktion die man unter Win32 sonst nicht erreichen kann (mangels Unterstützung von alarm).

Konfiguration:

Man muß nur ggf. $timeout und $nameserver den eigenen Wünschen anpassen. $logfile muß auf eine Datei verweisen die nach dem Schema

62.158.89.239 beliebiger text, also z.B.:
62.157.13.236 - - [07/Nov/1999:05:27:29 -0800] "GET / HTTP/1.0" 200 2804

aufgebaut ist, also allen gängigen Lofgile Formaten. Aufgerufen wird das Script dann mit

perl reverse-dns-lookup.pl access_log >access_log.resolved

wobei 'access_log' das Ausgangslogfile ist und 'access_log.resolved' die Datei in der das Logfile mit aufgelösten Hostnames gespeichert werden soll.

Außerdem braucht man das Net::DNS Modul aus dem CPAN:

Script:

#!/usr/bin/perl
#
# reverse-dns-lookup.pl

use strict;
use Net::DNS;
use IO::Select;

my $timeout = 5;
my $nameserver = "ns.maz.net";
my $logfile = shift;
my %host;

sub lookup {
    my $ip_address = shift;
    my $result;
    my $res = new Net::DNS::Resolver;
    $res->nameservers( $nameserver );
    my $bgsock = $res->bgsend( $ip_address );
    my $sel = new IO::Select($bgsock);
    my @ready = $sel->can_read($timeout);
    if (@ready) {
        foreach my $sock (@ready) {
            if ($sock == $bgsock) {
                my $packet = $res->bgread($bgsock);
                if ($packet) {
                    foreach my $rr ($packet->answer) {
                        my $hostname = $rr->rdatastr;
                        $hostname =~ s/\.$//g;
                        $result = $hostname;
                    }
                }
                else { 
                    $result = $ip_address;
                }
                $bgsock = undef;
            }
            $sel->remove($sock);
            $sock = undef;
        }
    }
    else {
        $result = $ip_address;
    }
    if ( $result eq "" ) { $result = $ip_address; }
    return $result;
}

open LOGFILE, "<$logfile" || die $!;
while(<LOGFILE>) {
    my $eintrag = $_;
    my ( $ip, $rest ) = $eintrag =~ /^(\S+)+(.*)/;

    if ( !( defined $host{$ip} ) ) {
        if ( $ip =~ /^\d+(?:\.\d+){0,3}$/ ) {
            $host{$ip} = &lookup($ip);
        }
        else { $host{$ip} = $ip; }
    }
    print $host{$ip}, $rest, "\n";
}

close LOGFILE || die $!;