Created
November 4, 2012 09:09
-
-
Save anonymous/4011018 to your computer and use it in GitHub Desktop.
QueryDNS.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
###############file QueryDNS.py################################# | |
#coding: GBK | |
#Get DNS answer | |
#详情见RFC 1035 | |
import os, sys | |
import socket | |
import struct | |
import random | |
from domaintobyte import domaintobyte, bytetodomain | |
#DHOST = '208.67.222.222' #DNS 服务器的地址 | |
DHOST = '8.8.8.8' #DNS 服务器的地址 | |
DPORT = 53 #默认端口是53 | |
LHOST = '' | |
LPORT = 10001 #绑定到的本地端口 | |
TIMEOUT = 3.0 #超时设置为3秒 | |
##数据包整体的格式 | |
## +---------------------+ | |
## | Header | | |
## +---------------------+ | |
## | Question | the question for the name server | |
## +---------------------+ | |
## | Answer | RRs answering the question | |
## +---------------------+ | |
## | Authority | RRs pointing toward an authority | |
## +---------------------+ | |
## | Additional | RRs holding additional information | |
## +---------------------+ | |
def QueryDNS(domain): | |
TID = random.randint(-32768, 32767) | |
Flags = 0x0100 | |
Questions = 0x0001 | |
AnswerRRs = 0x0000 | |
AuthorityRRs = 0x0000 | |
AdditionalRRs = 0x0000 | |
TIDCHARS = struct.pack('!h', TID) | |
domainbyte = domaintobyte(domain) | |
#TYPE value and meaning | |
#A 1 a host address | |
#NS 2 an authoritative name server | |
#MD 3 a mail destination (Obsolete - use MX) | |
#MF 4 a mail forwarder (Obsolete - use MX) | |
#CNAME 5 the canonical name for an alias | |
SEARCHTYPE = 0x0001 | |
#Class 一般为 1 指 Internet | |
SEARCHCLASS = 0x0001 | |
#构造请求报文 | |
Bufhead = struct.pack('!hhhhhh', TID, Flags, Questions, AnswerRRs, AuthorityRRs, AdditionalRRs) | |
Buftail = struct.pack('!hh', SEARCHTYPE, SEARCHCLASS) | |
Buf = Bufhead + domainbyte + Buftail | |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
s.settimeout(TIMEOUT) #设置超时时间 | |
s.bind((LHOST,LPORT)) | |
s.sendto(Buf,(DHOST, DPORT)) | |
print 'Send [OK]' | |
try: | |
data, addr = s.recvfrom(1024) | |
except socket.timeout: | |
s.close() | |
print u'响应超时' | |
return | |
s.close() | |
print 'From', addr | |
print 'Receved', repr(data) | |
if data[0:2] == TIDCHARS: | |
flags = struct.unpack('!h', data[2:4])[0] | |
errormsg = flags & 0x000F | |
if errormsg != 0: | |
return | |
answerRRs = struct.unpack('!h', data[6:8])[0] | |
bitflags = 12; | |
while data[bitflags] != '\x00': | |
bitflags += 1 | |
bitflags += 1 | |
bitflags += 2 | |
bitflags += 2 | |
i = 0 | |
while i < answerRRs: | |
bitflags += 2 | |
if data[bitflags:bitflags+2] == '\x00\x05': | |
bitflags += 8 | |
rdatalength = struct.unpack('!h', data[bitflags:bitflags+2])[0] | |
bitflags += 2 | |
#得到rdata中的全部域名 | |
fullRecord = GetFullName(bitflags, data) | |
bitflags += rdatalength | |
print 'CNAME:', bytetodomain(fullRecord) | |
i += 1 | |
def GetFullName(offset, Buf): | |
fullRecord = '' | |
oneChar = struct.unpack('!B', Buf[offset:offset+1])[0] | |
#print oneChar | |
if oneChar & 0xc0 == 0xc0 : #指针 | |
jump = struct.unpack('!h', Buf[offset:offset+2])[0] | |
jump = jump & 0x3FFF #指针指向的地址 | |
fullRecord += GetFullName(jump, Buf) | |
elif oneChar == 0 : #域名以\0结束 | |
return '\x00' | |
else : #域名部分 | |
fullRecord += Buf[offset:offset+oneChar+1] | |
fullRecord += GetFullName(offset+oneChar+1, Buf) | |
return fullRecord | |
if __name__ == "__main__": | |
print 'main start...' | |
if len(sys.argv) < 2: | |
print "Usage:QueryDNS.py www.google.cn" | |
elif len(sys.argv) == 2: | |
DHOST = '8.8.8.8' #DNS 服务器的地址 | |
else: | |
DHOST = sys.argv[2] | |
try: | |
domain = sys.argv[1] | |
QueryDNS(domain) | |
except Exception, e: | |
logging.error("exit:error:%s" %e) | |
print 'main over' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment