Skip to content

Instantly share code, notes, and snippets.

@starzia
Last active November 2, 2018 20:41
Show Gist options
  • Save starzia/938e8a98f1e0f2b62da9da88a417b015 to your computer and use it in GitHub Desktop.
Save starzia/938e8a98f1e0f2b62da9da88a417b015 to your computer and use it in GitHub Desktop.
TCP DNS server test case
# Sends a TCP DNS request in two packets.
# First sends the message size, then sends the message.
# This behavior is similar to that of the Windows nslookup command.
import socket, binascii, sys, struct
def main(dns_server):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# disable Nagle's algorithm, to allow request to be sent in two pieces.
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True)
s.connect((dns_server, 53))
# an A record lookup of eecs340.com, captured with wireshark:
dns_request_hex = "4ba901000001000000000000076565637333343003636f6d0000010001"
size_bytes = struct.pack(">H", len(dns_request_hex)//2)
s.send(size_bytes)
s.send(binascii.unhexlify(dns_request_hex))
# get response
response = b'';
while 1:
rcv_data = s.recv(2048)
if not rcv_data: break
#print("received data of size ", len(rcv_data))
#print("got bytes:", binascii.hexlify(rcv_data))
response += rcv_data
# check size header
if len(response) > 2:
size, = struct.unpack(">H", response[0:2])
# check that full response was received
if len(response) >= size + 2: # plus two is for the length header
break
print("binary response is: ", binascii.hexlify(response))
print("ASCII response is: ", response)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("please pass the dns server hostname/IP as a parameter")
sys.exit(-1)
dns_server = sys.argv[1]
main(dns_server)
@starzia
Copy link
Author

starzia commented Nov 2, 2018

Fixed to work on Python 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment