Получение WHOIS с помощью скрипта на Python

В общем, необходимость получения информации WHOIS может возникнуть при различных обстоятельствах. И вполне себе можно воспользоваться специализированными сервисами для этих целей. Однако, это приемлемо в том случае, если вам не требуется масс-скан неопределенного количества. Тогда использование сервисов становиться не целесообразным, да и слишком уж медленным, хотя, порою не лишенным некоторого преимущества.

Мне понадобился такой инструмент. И я решил поискать, что же есть в библиотеках Python. И да, такой инструмент нашелся — python-whois. Ничего не хочу сказать. Хороший инструмент. Но, имеет несколько ограниченное количество TLD, плюс к тому же иногда выводит не очень красивое сообщение, которое можно убрать. Сначала я думал, что это warning, оказалось — просто print. В общем и целом, пользоваться я им не стал. Еще немного поискав я нашел ipwhois. Однако, тут оказалось все несколько печальнее. И дело даже не в том, что для получения информации нужен ip. Я его все равно в процессе работы своего скрипта получал. А дело в том, какую информацию выдает данная библиотека. Куча информации об ASN, различных адресах и прочей, не особо важной мишуре. Вот только того, что нужно или совсем нет, или… в общем, смотрите сами.

Код:
{'asn': '51659',
 'asn_cidr': '46.17.40.0/23',
 'asn_country_code': 'RU',
 'asn_date': '2010-10-14',
 'asn_description': 'ASBAXET, RU',
 'asn_registry': 'ripencc',
 'nets': [{'address': 'Zelenograd, Sosnovaya alleya, 4, str 2, 33\n'
                      'Moscow, Russia',
           'cidr': '46.17.40.0/23',
           'city': None,
           'country': 'RU',
           'created': '2011-05-20T07:20:59Z',
           'description': 'LLC BAXET',
           'emails': None,
           'handle': 'AP12753-RIPE',
           'name': 'BX-NETWORK',
           'postal_code': None,
           'range': '46.17.40.0 - 46.17.41.255',
           'state': None,
           'updated': '2023-04-06T16:14:15Z'},
          {'address': None,
           'cidr': '46.17.40.0/23',
           'city': None,
           'country': None,
           'created': '2011-05-19T11:23:31Z',
           'description': 'LLC BAXET',
           'emails': None,
           'handle': None,
           'name': None,
           'postal_code': None,
           'range': '46.17.40.0 - 46.17.41.255',
           'state': None,
           'updated': '2011-05-19T11:23:31Z'}],
 'nir': None,
 'query': '46.17.40.108',
 'raw': None,
 'raw_referral': None,
 'referral': None}

Как инструмент неплохой, но не для моих целей. Впрочем, я уже писал статью об этих двух инструментах: Статья - Получение WHOIS-информации о домене по его IP-адресу с помощью Python, однако, я в ней ошибочно предположил способ, каким можно получить информацию WHOIS. Отчасти это правильное предположение. Однако, я даже не подозревал, насколько все будет сложнее, что ли. Или, если точнее, то трудозатратнее.

Получить информацию от WHOIS сервера несложно. Вот собственно код.

Python:
def run_whois(server: str, query: str) -> (tuple, bool):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        s.settimeout(5)
        s.connect((server, 43))

        s.send((bytes(query, 'utf-8')) + b'\r\n')
        msg = ''
        while len(msg) < 10000:
            receive_data = str((s.recv(100)), encoding='utf-8')
            if receive_data == '':
                break
            msg = msg + receive_data
        s.close()
        return msg
    except Exception:
        s.close()
        return False

Сложнее понять, от какого именно сервера нужно получать информацию по той или иной TLD зоне. Именно на это ушла львиная доля времени. Ну и на то, чтобы вручную просмотреть ответ по каждой зоне и сделать парсеры. Их оказалось не так уж и много. Тем более, что я забираю не всю информацию, а только ту, что мне была необходима. Для примера, ответ по домену «codeby.net».

Код:
{'date': {'created': datetime.datetime(2003, 9, 21, 20, 15, 9),
          'expires': datetime.datetime(2024, 9, 21, 20, 15, 9),
          'updated': datetime.datetime(2023, 10, 31, 20, 30, 37)},
 'domain': 'codeby.net',
 'nserver': ['NS1.JUMURO.NET', 'NS2.JUMURO.NET'],
 'registrar': {'registrar': 'REGISTRAR OF DOMAIN NAMES REG.RU LLC',
               'registrar_url': 'http://www.reg.ru',
               'registrar_whois_server': 'whois.reg.com'}}

Вдобавок, есть некоторые доменные зоны, по которым вообще нет информации о WHOIS серверах, то есть, они ее просто не публикуют, даже на сайте IANA. Есть сервера, которые возвращают настолько мало информации, что лучше бы они вообще этого не делали. Поэтому пришлось добавить небольшой параметр, который отвечает за то, чтобы можно было переключить в принудительном режиме скрипт на получение информации с whois.iana.org.

В коде, если вы хотите получить информацию WHOIS, без использования IANA, это будет выглядеть так:

Python:
from pprint import pprint

from whois import whois

pprint(whois("codeby.net"))

Если нужно включить IANA, добавим обработку ответа.

Python:
from pprint import pprint

from whois import whois

if data := whois("codeby.net"):
    pprint(data)
else:
    if data := whois("codeby.net", wh_serv=True):
        pprint(data)
    else:
        print("No data")

Ну и небольшой загвоздкой стал парсинг дат. Каждый WHOIS возвращает дату в своем формате. Ну или не каждый, но есть такие оригиналы… Не стал заморачиваться с ее парсингом, просто использовал стороннюю библиотеку python-dateutil. Она обрабатывает большинство возвращаемых от серверов форматов. А если возникает исключение, то я ее немного корректирую и передаю в эту же библиотеку. Но, как я подозреваю, я обработал еще далеко не все случаи, потому, процесс парсинга даты еще в тестировании. На текущий момент все ровно. Однако, обработку исключений на эту библиотеку вешать не стал, чтобы увидеть, если что-то пойдет не так и поправить.

screenshot1.png

Ну, вот собственно и все. Это в общем не полноценная статья. А только лишь заметка, в которой я хочу поделиться инструментом. Ну и кто знает, может быть вы поможете мне в его тестировании. Если что-то пойдет не так, пишите, буду исправлять.

Ссылка на GitHub: GitHub - evgenycc/whois: A script to get WHOIS information about domains.

Спасибо за внимание. Надеюсь, данная информация будет вам полезна.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!