достижимость имени сервера в dnspython - PullRequest
0 голосов
/ 20 апреля 2020

В настоящее время я пытаюсь найти способ проверить, могут ли серверы имен отвечать на пакеты TCP или UDP.

Моя идея заключалась в том, чтобы получить все серверы имен с веб-сайта ( например, google.com), сохраните их в списке, а затем попытайтесь отправить всем им сообщения TCP и UDP.

Несмотря на то, что я получаю серверы имен, мой интерпретатор выявляет проблему при попытке сделать запрос на udp (отметьте udpPacket в коде), сказав:

"TypeError: coercing to Unicode: need string or buffer, NS found"

Я новичок в Python (из C и C ++), и я предполагаю, что это просто несовместимо типов.

Я проверил документацию dnspython и не смог найти, что это за тип NS (вероятно, это сам по себе тип) и почему его нельзя передать в качестве аргумента.

Как вы думаете, в чем проблема? Может быть, есть лучший способ решить такую ​​проблему?

def getNSResults(url):

    #create an empty list where we can store all the nameservers we found
    nameServers = []

    nameServers = dns.resolver.query(url,dns.rdatatype.NS, raise_on_no_answer=False)

    #create a dictionary where based on all the nameservers.
    #1st label refers to the ns name of our url that we inserted.
    #2nd label shows wether or not we received a UDP response or not.
    #3rd label shows wether or not we received a TCP response or not.
    results = {}

    for nameServer in nameServers:

        #make a dns ns query, acts as a dumb message since whatever we send we just care of what we get back
        query = dns.message.make_query(dns.name.from_text(url), dns.rdatatype.ANY)

        query.flags |= dns.flags.AD

        query.find_rrset(query.additional, dns.name.root, 65535, dns.rdatatype.OPT, create=True, force_unique=True)

        #try sending a udp packet to see if it's listening on UDP
        udpPacket = dns.query.udp(query,nameServer)

        #try sending a tcp packet to see if it's listening on TCP
        tcpPacket = dns.query.tcp(None,nameServer)

        #add the results in a dictionary and return it, to be checked later by the user.
        results.update({"nsName" == nameServer, "receivedUDPPacket" == isNotNone(udpPacket),"receivedTCPPacket" == isNotNone(tcpPacket)})

Заранее спасибо!

1 Ответ

0 голосов
/ 23 апреля 2020

Глядя на ваш код, я вижу некоторые проблемы с DNS, некоторые проблемы Python и некоторые проблемы с DNS python. Давайте посмотрим, не сможем ли мы чему-то научиться вместе.

DNS

Во-первых, параметр вашей функции getNSResults называется url. Когда вы отправляете DNS-запросы, вы запрашиваете имя домена . URL - это нечто совершенно другое (например, https://example.com/index.html). Я бы переименовал url во что-то вроде domain_name, domain или name. Подробнее о разнице между URL-адресами и именами доменов см. https://www.copahost.com/blog/domain-vs-url/.

Во-вторых, давайте поговорим о том, что вы пытаетесь сделать.

В настоящее время я пытаюсь найти способ проверить, могут ли серверы имен отвечать на пакеты tcp или udp.

Моя идея заключалась в том, чтобы получить все серверы имен с веб-сайта (например, Google .com), сохраните их в списке, а затем попробуйте отправить всем tcp и udp сообщения.

Звучит как отличный подход. Я думаю, вы можете упустить некоторые детали здесь. поэтому позвольте мне объяснить шаги, которые вы можете предпринять, чтобы сделать это:

  1. Выполните запрос NS для доменного имени. У вас уже есть этот шаг в вашем коде. Что вы на самом деле получите из этого запроса, так это просто другое доменное имя (или несколько доменных имен). Например, если вы запустите dig +short NS google.com, вы получите такой вывод:
ns3.google.com.
ns1.google.com.
ns4.google.com.
ns2.google.com.
На этом шаге у нас есть список из одного или нескольких имен авторитетных серверов. Теперь нам нужен IP-адрес для отправки запросов. Поэтому мы сделаем запрос типа A для каждого из имен, которые мы получили на шаге 1. Теперь у нас есть список IP-адресов. Мы можем отправить DNS-запрос по UDP и один по TCP, чтобы убедиться, что они поддерживаются.

Python

По большей части ваш синтаксис Python в порядке , Самым большим красным флажком, который я вижу, является следующий код:

results.update({"nsName" == nameServer, 
    "receivedUDPPacket" == isNotNone(udpPacket),
    "receivedTCPPacket" == isNotNone(tcpPacket)})

Давайте разберем это немного. Во-первых, у вас есть results, то есть dict. Тогда у вас есть это:

{"nsName" == nameServer, 
"receivedUDPPacket" == isNotNone(udpPacket),
"receivedTCPPacket" == isNotNone(tcpPacket)}

, что составляет set из bool с. Я думаю, что вы хотели сделать что-то вроде этого:

results.update({
    "nsName": nameServer,
    "receivedUDPPacket": true,
    "receivedTCPPacket": true
})

Имена функций и переменных в Python обычно пишутся строчными буквами, а слова разделяются подчеркиванием (например, my_variable, def my_function()) , Имена классов обычно в верхнем верблюжьем регистре (например, class MyClass). Ничего из этого не требуется, вы можете называть свой материал по своему усмотрению, множество супер-популярных библиотек и встроенных программ нарушают это соглашение, просто подумав, что я его выброшу, потому что это может быть полезно при чтении Python кода.

днс python

Когда вы не уверены в типах вещей или в каких атрибутах вещей, запомните этих четырех друзей, встроенных в Python: 1. pdb 2. dir 3. type 4. print

pdb - отладчик Python. Просто import pdb и поставьте pdb.set_trace() там, где вы хотите сломаться. Ваш код остановится на этом, и тогда вы сможете проверить значения всех переменных.

dir вернет атрибуты и методы того, что вы передадите ему. Пример: print(dir(udpPacket)).

type вернет тип объекта.

print, как вы, вероятно, уже знаете, распечатает материал, чтобы вы могли его видеть.

Я собираюсь оставить эту часть для вас, чтобы проверить. Запустите dir() на всем, если вы не знаете, что это такое. Я также, вероятно, должен упомянуть help(), который очень полезен для встроенных вещей.

Резюме этого раздела таково, что иногда документации не все, или ее трудно найти, особенно когда вы новый язык / библиотека / что угодно. Таким образом, вы должны разобраться с этим самостоятельно, а это означает, что вы используете все инструменты, которые я только что упомянул, просматривая исходный код и тому подобное.

Резюме

Я надеюсь, что это было полезно. Я знаю, что это много, возможно, это слишком много, но просто наберитесь терпения и знайте, что DNS и Python очень полезны и интересны для изучения.

Я продолжил и написал кое-что, что начать с того, что я думаю, вы надеетесь достичь. Я рекомендую пройти через все это и убедиться, что вы понимаете, что происходит. Если вы чего-то не понимаете, запомните pdb и dir (и всегда есть Google, SO, et c).

import dns.resolver
import dns.message
import dns.rdatatype

import json
import sys

def check_tcp_and_udp_support(name):
    # this will give me the first default system resolver from /etc/resolv.conf
    # (or Windows registry)
    where = dns.resolver.Resolver().nameservers[0]

    q = dns.message.make_query(name, dns.rdatatype.NS)
    ns_response = dns.query.udp(q, where)

    ns_names = [t.target.to_text() for ans in ns_response.answer for t in ans]

    # this code is the same as the one-liner above
    # ns_names = []
    # for ans in ns_response.answer:
    #     for t in ans:
    #         ns_names.append(t.target.to_text())

    results = {}

    for ns_name in ns_names:

        # do type A lookup for nameserver
        q = dns.message.make_query(ns_name, dns.rdatatype.A)
        response = dns.query.udp(q, where)

        nameserver_ips = [item.address for ans in response.answer for item in ans.items if ans.rdtype == dns.rdatatype.A]

        # now send queries to the nameserver IPs
        for nameserver_ip in nameserver_ips:
            q = dns.message.make_query('example.com.', dns.rdatatype.A)
            try:
                udp_response = dns.query.udp(q, nameserver_ip)
                supports_udp = True
            except dns.exception.Timeout:
                supports_udp = False
            try:
                tcp_response = dns.query.tcp(q, nameserver_ip)
                supports_tcp = True
            except dns.exception.Timeout:
                supports_tcp = True

            results[nameserver_ip] = {
                'supports_udp': supports_udp,
                'supports_tcp': supports_tcp
            }

    return results

def main():
    results = check_tcp_and_udp_support('google.com')

    # this is just fancy JSON printing
    # you could do print(results) instead
    json.dump(results, sys.stdout, indent=4)

if __name__ == '__main__':
    main()

Опять же, я надеюсь, что это полезно. Тяжело, когда я не знаю точно, что происходит в твоей голове, но это то, что у меня есть для тебя.

...