Lösen Sie alle IP-Adressen in der Befehlsausgabe mit Standard-Befehlszeilentools auf

8

Ich habe mehrere Protokolldateien, die eine Reihe von IP-Adressen enthalten. Ich würde gerne in der Lage sein, die Daten durch ein Programm zu leiten, das mit IP-Adressen übereinstimmt und diese auflöst.

IE cat / var / log / somelogfile | Wirt

das würde eine Linie wie drehen

10:45 Zugriff bis 10.13.13.10

in

10:45 Zugriff über myhostname.intranet

Meiner Meinung nach gibt es eine Möglichkeit, dies mit einer Kombination aus Sed und Host zu tun, aber ich habe keine Ahnung, wie ich das tun soll. Ich weiß, dass ich ein einfaches Skript schreiben könnte, das dies tun würde, aber ich würde lieber eingebaute Tools verwenden können, wenn dies möglich ist. Irgendwelche Vorschläge?

Daniel
quelle
2
Der Grund, warum dies normalerweise nicht gemacht wird, ist, dass es ziemlich langsam sein kann, all diese PTR-Abfragen zu machen. Ein Multithread-Skript (z. B. Python), das die Ergebnisse (möglicherweise dauerhaft) zwischenspeichert, funktioniert am besten.
Alexios

Antworten:

8

Hier ist eine schnelle und schmutzige Lösung für dieses Problem in Python. Es macht Caching (einschließlich negatives Caching), aber kein Threading und ist nicht das schnellste, was Sie gesehen haben. Wenn Sie es als so etwas speichern rdns, können Sie es so nennen:

zcat /var/log/some-file.gz | rdns
# ... or ...
rdns /var/log/some-file /var/log/some-other-file # ...

Wenn Sie es ausführen, werden die IP-Adressen mit ihren PTR-Einträgen versehen:

$ echo "74.125.132.147, 64.34.119.12." | rdns
74.125.132.147 (rdns: wb-in-f147.1e100.net), 64.34.119.12 (rdns: stackoverflow.com).

Und hier ist die Quelle:

#!/usr/bin/env python

import sys, re, socket

cache = dict()

def resolve(x):
    key = x.group(0)
    try:
        return "%s (rdns: %s)" % (key, cache[key])
    except KeyError:
        try:
            cache[key] = socket.gethostbyaddr(key)[0]
        except socket.herror:
            cache[key] = '?'
        return "%s (rdns: %s)" % (key, cache[key])

for f in [open(x) for x in sys.argv[1:]] or [sys.stdin]:
    for line in f:
        sys.stdout.write(re.sub("\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", resolve, line))

# End of file.

Bitte beachten Sie: Dies ist nicht ganz das, wonach Sie suchen (mit 'Standardwerkzeugen'). Aber es hilft Ihnen wahrscheinlich mehr als ein Hack, der jede IP-Adresse jedes Mal auflöst, wenn sie auftritt. Mit ein paar Zeilen mehr können Sie sogar festlegen, dass die Ergebnisse dauerhaft zwischengespeichert werden, was bei wiederholten Aufrufen hilfreich wäre.

Alexios
quelle
Danke für das Skript. Es macht genau das, wonach ich gesucht habe. Ich hatte gehofft, eine Lösung zu finden, für die kein Skript geschrieben werden musste, aber dies ist wahrscheinlich das nächstbeste.
Daniel
3

Ich würde verwenden jdresolve -n -a

Verpackt für Debian usw. auch erhältlich bei:

https://github.com/jdrowell/jdresolve

    jdresolve löst IP-Adressen in Hostnamen auf. Jedes Dateiformat ist
    unterstützt, einschließlich solcher, bei denen die Leitung nicht mit der IP beginnt
    Adresse.

Ich benutze es seit über einem Jahrzehnt, um Apache-Protokolle, Tintenfisch-Protokolle und alles andere mit vielen IP-Adressen aufzulösen, die aufgelöst werden müssen. Es funktioniert gut, zuverlässig und schnell und kann Suchvorgänge aus früheren Läufen zwischenspeichern.

cas
quelle
2

Ein Bash-Skript, in das Sie Ihre Protokolldatei und Pipe einfügen können.

#!/bin/bash

while read input; do

    for arg in $( echo $input ); do
            match=$(echo "$arg" | grep -P '([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])\.([01]?\d\d?|2[0-4]\d|25[0-5])' )
            if [ "x${match}" = "x" ]; then
                    printf "%-s" "$arg "
            else
                    dns=$( host $arg | tail -1 | awk '{print $NF}' 2>/dev/null )
                    if [ "${dns}" == "3(NXDOMAIN)" ]; then
                            printf "%-s" "$arg "
                    else
                            if [ "x${dns}" == "x" ]; then
                                    printf "%-s" "$arg "
                            else
                                    printf "%-s" "$dns "
                            fi
                    fi
            fi
    done
done
printf "\n"

Ausgabe sieht aus wie:

tk-air:~ tim$ echo "10:45 accessed by 8.8.8.8" | ./get-dns 
10:45 accessed by FWDR-8.FWDR-8.FWDR-8.FWDR-8. 

tk-air:~ tim$ echo "10:45 accessed by 8.8.8.8 26 times" | ./get-dns 
10:45 accessed by FWDR-8.FWDR-8.FWDR-8.FWDR-8. 26 times 
Tim Kennedy
quelle
2

Ein kurzer Perl:

perl -MSocket -pe 's/(\d+\.){3}\d+/"$&\[".gethostbyaddr(inet_aton($&), AF_INET)."]"/ge'
Stéphane Chazelas
quelle
1

Wenn das Protokollformat konsistent dasselbe anzeigt, wie Sie es oben gezeigt haben, können Sie dies wirklich schmutzig machen echo 10:45 accessed by 10.13.13.10|awk '{print $4}'|nslookup

Tim
quelle