Python: effettuare una richiesta WHOIS

Python: effettuare una richiesta WHOIS

In questo articolo vedremo come effettuare una richiesta WHOIS con Python.

Una richiesta WHOIS si effettua interrogando un server remoto collegandosi sulla porta 43 tramite socket e inviando il nome del dominio come flusso di byte seguito da un ritorno a capo.

Abbiamo bisogno di una lista di server WHOIS in formato JSON o CSV che contenga il nome dell'host del server e l'estensione del dominio che gestisce.

Per estrarre l'estensione del dominio dal nome a dominio completo possiamo installare il modulo tldextract che gestisce anche le doppie estensioni (come .co.uk). Il nostro file JSON contenente la lista dei server WHOIS avrà la seguente struttura per ciascuna voce:

{
    "extension": ".it",
    "server": "whois.nic.it",
    "response": "AVAILABLE"
}

Definiamo una prima funzione per leggere il contenuto di questo file come una lista di dizionari.

import socket
import json
import tldextract


def get_whois_server_list(list_path='./servers.json'):
    with open(list_path, 'r') as f:
        return json.load(f)

Ora dobbiamo trovare in questa lista di dizionari l'elemento la cui chiave extension corrisponde all'estensione che dovremo estrarre dal nome a dominio. Per effettuare la ricerca in modo efficiente, useremo la funzione filter() sulla lista.

def find_whois_server_for_domain(domain_name=None):
    if domain_name is None:
        return None
    full_domain_url = f'https://{domain_name}'
    domain_extension = tldextract.extract(full_domain_url)
    full_extension = f'.{domain_extension.suffix}'
    whois_server_list = get_whois_server_list()
    whois_server_found = list(
        filter(lambda server: server['extension'] == full_extension, whois_server_list))
    whois_server = whois_server_found[0] if len(
        whois_server_found) > 0 else None
    return whois_server

Infine, dobbiamo effettuare la connessione tramite socket verso il server che gestisce l'estensione del dominio selezionato e restituire in output la risposta. Tale risposta dovrà essere costruita leggendo dal flusso di dati restituito man mano che il server remoto lo invia.

def whois_lookup(domain_name=None):
    if domain_name is None:
        return None
    whois_server = find_whois_server_for_domain(domain_name)
    if whois_server is None:
        return None
    query = f'{domain_name}\r\n'
    server = whois_server['server']
    connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connection.connect((server, 43))
    connection.send(query.encode())
    response = ''

    while len(response) < 10000:
        chunk = connection.recv(100).decode()
        if (chunk == ''):
            break
        response = response + chunk
    return response

La risposta giunge come stream di byte, quindi dobbiamo convertirla in stringa se vogliamo rappresentarla in modo leggibile sulla shell. Esempio d'uso:

def main():
    domain = input('Enter domain name:')
    print(whois_lookup(domain))


if __name__ == '__main__':
    main()
Torna su