Как отправить DNS-ответ a через сокет

#python

#python

Вопрос:

Мне нужно отправить ответ (www.google.com. 58 В 172.217.6.68) через сокет в другой тестируемый код.

Я попробовал sock.sendto (message.answer.to_wire(),addr), но я получаю сообщение от сервера с сообщением AttributeError: объект ‘list’ не имеет атрибута ‘to_wire’

 def process_message(sock):
    global cache, pending_requests

    # Listen for an incoming UDP message through the socket
    data, addr = sock.recvfrom(BUFFERSIZE)
    message = dns.message.from_wire(data)



    sock.sendto(message.to_wire(),(GOOGLE_DNS, DNS_PORT))
    sock.sendto(message.answer.to_wire(),addr)


# Open a UDP socket
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
    # Listen on the PORT for traffic destined to any IP address
    s.setblocking(0)
    s.bind(('', PORT))

    # Read from the socket without blocking, to allow CTRL C to exit our program
    inputs = [s]
    outputs = []
    while inputs:
        # Waiting for a UDP message
        readable, writable, exceptional = select.select(inputs, outputs, inputs)

        for sock in readable:
            # Socket has data, read from it
            process_message(sock)
  

тестовый код

 # Listen for a response from the nameserver
    data, addr = s.recvfrom(BUFFERSIZE)
    message = dns.message.from_wire(data)
    if len(message.answer) == 0:
        print("No ANSWER records in response.")
    else:
        # Print the DNS answer records
        for answer in message.answer:
            print(answer.to_text())
  

Я ожидаю получить ответ от dns на тестовый код (www.google.com. 58 В aA 172.217.6.68), но я получаю ошибку в коде сервера и никакого ответа в тестере.

Ответ №1:

Итак, строка вашего кода, вызывающая ошибку, является:

 sock.sendto(message.answer.to_wire(),addr)
  

Согласно документации класса Message, его атрибут answer возвращает список dns.rrset.Объекты RRset.

Итак, message.answer — это список. Но вы пытаетесь вызвать для него метод to_wire(). Поскольку объект list в Python не имеет метода to_wire(), вы получаете ошибку AttributeError: объект ‘list’ не имеет атрибута ‘to_wire’.

Возможно ли, что вы хотите выполнить итерацию по списку message.answer и вызвать to_wire() для каждого из объектов, содержащихся в этом списке? Согласно документации, у RRset действительно есть метод to_wire(), поэтому я предполагаю, что это то, что вы хотите делать.

… и, возможно, в вашем случае в message.answer всегда есть только один элемент.answer в. Если вы можете сделать это предположение, то вы могли бы просто изменить эту строку на:

 sock.sendto(message.answer[0].to_wire(),addr)
  

или, если у вас может быть несколько ответов, возможно, вы хотите это:

 for answer in message.answer:
    sock.sendto(answer.to_wire(),addr)
  

Комментарии:

1. Это правильно, для каждого ответа я хочу передать этот ответ через сокет тестировщику.

2. Итак, вы говорите, что имеет смысл перебирать список и отправлять каждый ответ через сокет тестировщику? Если да, то просто сделайте это!

3. Проблема, которую я видел, заключалась в том, что pending_requests не используется, и что прокси должен делать, когда он получает ответ на запрос, так это пересылать его. так sock.sendto(message.answer.to_wire(),addr) должно быть sock.sendto(message.to_wire(),addr) , но отсутствует часть, которая заставляет его функционировать по-разному для запросов от тестировщика и ответов с сервера.