python如何导入数据包_在Python中读取DNS数据包

I'm playing around with Python sockets, and decided to see if I could implement a very basic name server (i.e. a lookup table for a domain name to an IP address). So I've set up my server so far to just dump the received data.

#!/usr/bin/python

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

host = ''

port = 53

size = 512

s.bind((host, port))

while True:

data, addr = s.recvfrom(size)

print repr(data)

When I run the above code and point my DNS to 127.0.0.1 I get something akin to the following:

'Y\x04\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01'

'J\xaa\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x1c\x00\x01'

'Y\x04\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x03www\x06google\x03com\x00\x00\x01\x00\x01'

I'm assuming that it is something to do with the DNS question packet structure, but I'm not to sure.

A) Are the above escape characters? A specific text encoding? Or simply just bytes?

B) How can I interpret the data and work with it?

EDIT: Changing the socket to take raw instead of datagrams results in the following:

'E\x00$\x00\xe4\x96\x00\x00@\x01\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\x03\x03X\xb6\x00\x00\x00\x00E\x00V\x00m\x82\x00\x00\xff\x11\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\xf3\xe1\x005\x00B\x00\x00'

解决方案

You could start with something like this:

#!/usr/bin/env python

import pprint

import socket

import struct

def decode_labels(message, offset):

labels = []

while True:

length, = struct.unpack_from("!B", message, offset)

if (length & 0xC0) == 0xC0:

pointer, = struct.unpack_from("!H", message, offset)

offset += 2

return labels + decode_labels(message, pointer & 0x3FFF), offset

if (length & 0xC0) != 0x00:

raise StandardError("unknown label encoding")

offset += 1

if length == 0:

return labels, offset

labels.append(*struct.unpack_from("!%ds" % length, message, offset))

offset += length

DNS_QUERY_SECTION_FORMAT = struct.Struct("!2H")

def decode_question_section(message, offset, qdcount):

questions = []

for _ in range(qdcount):

qname, offset = decode_labels(message, offset)

qtype, qclass = DNS_QUERY_SECTION_FORMAT.unpack_from(message, offset)

offset += DNS_QUERY_SECTION_FORMAT.size

question = {"domain_name": qname,

"query_type": qtype,

"query_class": qclass}

questions.append(question)

return questions, offset

DNS_QUERY_MESSAGE_HEADER = struct.Struct("!6H")

def decode_dns_message(message):

id, misc, qdcount, ancount, nscount, arcount = DNS_QUERY_MESSAGE_HEADER.unpack_from(message)

qr = (misc & 0x8000) != 0

opcode = (misc & 0x7800) >> 11

aa = (misc & 0x0400) != 0

tc = (misc & 0x200) != 0

rd = (misc & 0x100) != 0

ra = (misc & 0x80) != 0

z = (misc & 0x70) >> 4

rcode = misc & 0xF

offset = DNS_QUERY_MESSAGE_HEADER.size

questions, offset = decode_question_section(message, offset, qdcount)

result = {"id": id,

"is_response": qr,

"opcode": opcode,

"is_authoritative": aa,

"is_truncated": tc,

"recursion_desired": rd,

"recursion_available": ra,

"reserved": z,

"response_code": rcode,

"question_count": qdcount,

"answer_count": ancount,

"authority_count": nscount,

"additional_count": arcount,

"questions": questions}

return result

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

host = ''

port = 53

size = 512

s.bind((host, port))

while True:

data, addr = s.recvfrom(size)

pprint.pprint(decode_dns_message(data))

And then fill in the decoding functions for the remaining records.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值