我正在尝试在包含.zone文件的情况下运行此脚本: https://github.com/howCodeORG/howDNS
我在/中有DNS.py,在/ zones中有.zone。
当我dig howcode.org @127.0.0.1
我得到:
Traceback (most recent call last):
File "/dns.py", line 171, in <module>
r = buildresponse(data)
File "/dns.py", line 145, in buildresponse
ANCOUNT = len(getrecs(data[12:])[0]).to_bytes(2, byteorder='big')
File "/dns.py", line 96, in getrecs
zone = getzone(domain)
File "/dns.py", line 88, in getzone
return zonedata[zone_name]
KeyError: 'howcode.org.'
将文件移动到〜/ desktop / DNS文件夹中以再次运行,并对代码进行一些调整以尝试获得更直接的DNS路由
import socket, glob, json
port = 53
ip = '127.0.0.1'
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((ip, port))
def load_zones():
jsonzone = {}
zonefiles = glob.glob('zones/*.zone')
for zone in zonefiles:
with open(zone) as zonedata:
data = json.load(zonedata)
zonename = data["$origin"]
jsonzone[zonename] = data
return jsonzone
zonedata = load_zones()
def getflags(flags):
byte1 = bytes(flags[:1])
byte2 = bytes(flags[1:2])
rflags = ''
QR = '1'
OPCODE = ''
for bit in range(1,5):
OPCODE += str(ord(byte1)&(1<<bit))
AA = '1'
TC = '0'
RD = '0'
# Byte 2
RA = '0'
Z = '000'
RCODE = '0000'
return int(QR+OPCODE+AA+TC+RD, 2).to_bytes(1, byteorder='big')+int(RA+Z+RCODE, 2).to_bytes(1, byteorder='big')
def getquestiondomain(data):
state = 0
expectedlength = 0
domainstring = ''
domainparts = []
x = 0
y = 0
for byte in data:
if state == 1:
if byte != 0:
domainstring += chr(byte)
x += 1
if x == expectedlength:
domainparts.append(domainstring)
domainstring = ''
state = 0
x = 0
if byte == 0:
domainparts.append(domainstring)
break
else:
state = 1
expectedlength = byte
y += 1
questiontype = data[y:y+2]
return (domainparts, questiontype)
def getzone(domain):
global zonedata
zone_name = '.'.join(domain)
return zonedata[zone_name]
def getrecs(data):
domain, questiontype = getquestiondomain(data)
qt = ''
if questiontype == b'\x00\x01':
qt = 'a'
zone = getzone(domain)
return (zone[qt], qt, domain)
def buildquestion(domainname, rectype):
qbytes = b''
for part in domainname:
length = len(part)
qbytes += bytes([length])
for char in part:
qbytes += ord(char).to_bytes(1, byteorder='big')
if rectype == 'a':
qbytes += (1).to_bytes(2, byteorder='big')
qbytes += (1).to_bytes(2, byteorder='big')
return qbytes
def rectobytes(domainname, rectype, recttl, recval):
rbytes = b'\xc0\x0c'
if rectype == 'a':
rbytes = rbytes + bytes([0]) + bytes([1])
rbytes = rbytes + bytes([0]) + bytes([1])
rbytes += int(recttl).to_bytes(4, byteorder='big')
if rectype == 'a':
rbytes = rbytes + bytes([0]) + bytes([4])
for part in recval.split('.'):
rbytes += bytes([int(part)])
return rbytes
def buildresponse(data):
# Transaction ID
TransactionID = data[:2]
# Get the flags
Flags = getflags(data[2:4])
# Question Count
QDCOUNT = b'\x00\x01'
# Answer Count
ANCOUNT = len(getrecs(data[12:])[0]).to_bytes(2, byteorder='big')
# Nameserver Count
NSCOUNT = (0).to_bytes(2, byteorder='big')
# Additonal Count
ARCOUNT = (0).to_bytes(2, byteorder='big')
dnsheader = TransactionID+Flags+QDCOUNT+ANCOUNT+NSCOUNT+ARCOUNT
# Create DNS body
dnsbody = b''
# Get answer for query
records, rectype, domainname = getrecs(data[12:])
dnsquestion = buildquestion(domainname, rectype)
for record in records:
dnsbody += rectobytes(domainname, rectype, record["ttl"], record["value"])
return dnsheader + dnsquestion + dnsbody
while 1:
data, addr = sock.recvfrom(512)
r = buildresponse(data)
sock.sendto(r, addr)
预期结果:
dig howcode.org @127.0.0.1
; <<>> DiG 9.8.3-P1 <<>> howcode.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45939
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;howcode.org. IN A
;; ANSWER SECTION:
howcode.org. 300 IN A 255.255.255.255
howcode.org. 300 IN A 127.0.0.1
howcode.org. 300 IN A 127.0.0.1
howcode.org. 300 IN A 127.0.0.1
howcode.org. 300 IN A 10.10.10.10
;; Query time: 54 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Wed Aug 21 22:59:04 2019
;; MSG SIZE rcvd: 61