By Furkan
5 minute read

Understanding and Implementing WHOIS Queries with Python

Understanding and Implementing WHOIS Queries with Python

Whois is a protocol that is used to query databases to obtain domain ownership information, such as the owner of a domain name, an IP address block, or an autonomous system number. Understanding WHOIS can be incredibly useful for various purposes, such as cybersecurity, web development, and digital marketing.

WHOIS includes information like:

  • Registrant’s name
  • Registrant’s contact details
  • Registration date
  • Expiry date
  • Name servers
  • Registrar information

These details can be critical for tasks like identifying the ownership of a website, determining the legitimacy of a domain, and for cybersecurity purposes.

Let’s code a Python script to perform WHOIS queries.

We’ll utilize the socket module to dispatch queries to WHOIS servers. This module furnishes Python with the capability to engage with the network via sockets, which serve as endpoints of communication channels.

import socket

To find the correct WHOIS server for the given address, we need to initially query the IANA Whois server (whois.iana.org).

Here’s how to determine the WHOIS server:

determine-whois-server

Query IANA WHOIS server (whois.iana.org):

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('whois.iana.org', 43))
sock.send('furkan.io\r\n'.encode())
response = b''
while True:
    data = sock.recv(4096)
    response += data
    if not data:
        break
sock.close()
print(response.decode())

Response from IANA WHOIS server:

% IANA WHOIS server
% for more information on IANA, visit http://www.iana.org
% This query returned 1 object

refer:        whois.nic.io

domain:       IO

organisation: Internet Computer Bureau Limited
address:      c/o Sure (Diego Garcia) Limited
address:      Diego Garcia
address:      British Indian Ocean Territories, PSC 466 Box 59
address:      FPO-AP 96595-0059
address:      British Indian Ocean Territory (the)

contact:      administrative
name:         Internet Administrator
organisation: Internet Computer Bureau Limited
address:      c/o Sure (Diego Garcia) Limited
address:      Diego Garcia
address:      British Indian Ocean Territories, PSC 466 Box 59
address:      FPO-AP 96595-0059
address:      British Indian Ocean Territory (the)
phone:        +246 9398
fax-no:       +246 9398
e-mail:       administrator@nic.io

contact:      technical
name:         Administrator
organisation: Internet Computer Bureau Ltd
address:      Greytown House, 221-227 High Street
address:      Orpington Kent BR6 0NZ
address:      United Kingdom of Great Britain and Northern Ireland (the)
phone:        +44 (0)1689 827505
fax-no:       +44 (0)1689 831478
e-mail:       admin@icb.co.uk

nserver:      A0.NIC.IO 2a01:8840:9e:0:0:0:0:17 65.22.160.17
nserver:      A2.NIC.IO 2a01:8840:a1:0:0:0:0:17 65.22.163.17
nserver:      B0.NIC.IO 2a01:8840:9f:0:0:0:0:17 65.22.161.17
nserver:      C0.NIC.IO 2a01:8840:a0:0:0:0:0:17 65.22.162.17
ds-rdata:     57355 8 2 95a57c3bab7849dbcddf7c72ada71a88146b141110318ca5be672057e865c3e2

whois:        whois.nic.io

status:       ACTIVE
remarks:      Registration information: http://www.nic.io/

created:      1997-09-16
changed:      2023-01-18
source:       IANA

In this example, we queried the IANA Whois Service (whois.iana.org) to determine which WHOIS server we should use for furkan.io. IANA responded that we should use the address whois.nic.io for the .io TLD.

If we want to examine the packets, we learn that we sent an 11-byte query, which resulted in a 1704-byte reassembled TCP packet.

Now, let’s find out the WHOIS information for furkan.io.

determine-furkan.io-whois

To do this too, we will use the WHOIS protocol, so we will use similar code as in our TLD WHOIS query. We will just change our WHOIS server address.

Query WHOIS server (whois.nic.io):

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(('whois.nic.io', 43))
sock.send('furkan.io\r\n'.encode())
response = b''
while True:
    data = sock.recv(4096)
    response += data
    if not data:
        break
sock.close()
print(response.decode())

Response from WHOIS server (whois.nic.io)

Yes, the WHOIS query has been successfully completed. (My WHOIS information has been hidden by the registrar to prevent spam)

Next, let’s turn this WHOIS script into a class and then use it like a CLI tool.

determine-furkan.io-whois
import socket
class Whois:
    def __init__(self, address):
        self.address = address
        self.query = f'{self.address}\r\n'
        self.determine_whois_server()
        self.response = self.txt = self.query_whois(self.whois_server, self.query)
        self.dict = self.convert_to_dict(self.response)

    def determine_whois_server(self):
        whois_server = f'whois.iana.org'
        response = self.query_whois(whois_server, self.query)
        data = self.convert_to_dict(response)
        if 'whois' in data:
            whois_server = data['whois']
        self.whois_server = whois_server
    
    def query_whois(self, whois_server, query):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((whois_server, 43))
        sock.send(query.encode())
        response = b''
        while True:
            data = sock.recv(4096)
            response += data
            if not data:
                break
        sock.close()
        return response.decode()

    def convert_to_dict(self, response):
        lines = response.split("\n")
        data = {}
        for line in lines:
            if line.startswith(('%', '#', '\n', '\r', '>')):
                continue
            parts = line.split(":")
            if len(parts) == 2:
                key = parts[0].strip()
                value = parts[1].strip()
                data[key] = value
        return data

if __name__ == '__main__':
    import argparse
    parser = argparse.ArgumentParser(description="Perform WHOIS lookup for a domain.")
    parser.add_argument("address", help="The domain to perform the WHOIS lookup on.")
    args = parser.parse_args()
    w = Whois(args.address).txt
    print(w)

To take the domain address as an argument, we include the argparse module in the script.

As seen, we can reach the result with 2 queries and 2 answers for WHOIS.

  • 1. Query 77 byte (localhost -> whois.iana.org)
  • 1. Answer 1704 byte (whois.iana.org -> localhost)
  • 2. Query 77 byte (localhost -> whois.nic.io)
  • 2. Answer 5476 byte (whois.nic.io -> localhost )
classpacketspythonsocketwhois
Leave a Reply