résoudre toutes les adresses IP dans la sortie de commande à l'aide des outils de ligne de commande standard

8

J'ai plusieurs fichiers journaux qui contiennent un tas d'adresses IP. Je serais ravi de pouvoir diriger les données via un programme qui correspondrait et résoudrait les adresses IP.

IE cat / var / log / somelogfile | hôte

qui tournerait une ligne comme

10:45 consulté par 10.13.13.10

dans

10:45 accessible par myhostname.intranet

Je pense qu'il pourrait y avoir un moyen de le faire avec une combinaison de sed et host, mais je ne sais pas comment le faire. Je sais que je pourrais écrire un script simple qui le ferait, mais je préférerais pouvoir utiliser des outils intégrés si possible. Aucune suggestion?

Daniel
la source
2
La raison pour laquelle cela n'est pas normalement fait est qu'il peut être assez lent de faire toutes ces requêtes PTR. Un script multi-thread (dans, par exemple Python) qui met en cache les résultats (éventuellement de manière persistante) fonctionnerait mieux.
Alexios

Réponses:

8

Voici une solution rapide et sale à cela en Python. Il fait de la mise en cache (y compris la mise en cache négative), mais pas de thread et ce n'est pas la chose la plus rapide que vous ayez vue. Si vous l'enregistrez comme quelque chose comme rdns, vous pouvez l'appeler comme ceci:

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

L'exécuter annotera les adresses IP avec leurs enregistrements PTR en place:

$ 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).

Et voici la source:

#!/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.

Veuillez noter: ce n'est pas tout à fait ce que vous recherchez à la lettre (en utilisant des «outils standard»). Mais cela vous aide probablement plus qu'un hack qui résout chaque adresse IP à chaque fois qu'elle est rencontrée. Avec quelques lignes supplémentaires, vous pouvez même lui faire mettre en cache ses résultats de manière persistante, ce qui aiderait à répéter les appels.

Alexios
la source
Merci pour le script. Il fait exactement ce que je cherchais. J'espérais trouver une solution qui ne nécessitait pas d'écrire un script, mais c'est probablement la meilleure chose suivante.
Daniel
3

J'utiliserais jdresolve -n -a

Emballé pour debian, etc. également disponible sur:

https://github.com/jdrowell/jdresolve

    jdresolve résout les adresses IP en noms d'hôtes. Tout format de fichier est
    pris en charge, y compris ceux où la ligne ne commence pas par l'IP
    adresse.

Je l'utilise depuis plus d'une décennie pour résoudre les journaux Apache, les journaux Squid et toute autre chose avec beaucoup d'adresses IP qui doivent être résolues. Il fonctionne bien, de manière fiable et rapide, et il peut mettre en cache les recherches des exécutions précédentes.

cas
la source
2

un script bash dans lequel vous pouvez ajouter votre fichier journal et votre pipe.

#!/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"

la sortie ressemble à:

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
la source
2

Un rapide perl:

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

Si le format du journal affiche toujours la même chose que vous le montrez ci-dessus, vous pouvez le faire vraiment sale avec echo 10:45 accessed by 10.13.13.10|awk '{print $4}'|nslookup

Tim
la source