DNS服务器没有响应



如果我这样做,dns就不工作了,它会出现这个错误,idk怎么了,它只会给我这个错误:

Traceback (most recent call last):
File "c:UsersenginDownloadsAll filesdns.py", line 160, in <module>
r = buildresponse(data)
File "c:UsersenginDownloadsAll filesdns.py", line 155, in buildresponse
dnsbody += rectobytes(domainname, rectype, record["ttl"], record["value"])
TypeError: string indices must be integers

我确实为我的DNS服务器写了这个代码:

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((ip, port))
def load_zone():
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_zone()
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'
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
expectedlenght = 0
domainsting = ''
domainparts = []
x = 0
y = 0
for byte in data:
if state == 1:
if byte != 0:
domainsting += chr(byte)
x += 1
if x == expectedlenght:
domainparts.append(domainsting)
domainsting = ''
state = 0
x = 0
if byte == 0:
domainparts.append(domainsting)
break
else:
state = 1
expectedlenght = byte
# x += 1
y += 1
questiontype = data[y + 1 : y + 3]

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'x00x01':
qt = 'a'

zone = getzone(domain)
return (zone, qt, domain)
def rectobytes(domainname, rectype, recttl, recval):
rbytes = b'xc0x0c'
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 buildquestion(domainname, rectype):
qbytes = b''
for part in domainname:
lenght = len (part)
qbytes += bytes([lenght])
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 buildresponse(data):
TransactionID = data[:2]

# TID = ''
# for byte in TransactionID:
# TID += hex(byte)

Flags = getFlags(data[2:4])
QDCOUNT = b'x00x01'
# getquestiondomain(data[12:])
ANCOUNT = len(getrecs(data[12:])[0]).to_bytes(2, byteorder='big')
NSCOUNT = (0).to_bytes(2, byteorder='big')
ARCOUNT = (0).to_bytes(2, byteorder='big')
dnsheader = TransactionID + Flags + QDCOUNT + ANCOUNT + NSCOUNT + ARCOUNT

dnsbody = b''
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)

在buildresponse的最底部的for中,它只打印出@origin我知道有什么问题,然后我创建了这个帖子,请帮忙。

请帮忙!

好的,现在您已经显示了您的records值是以下字典:

records =  {'$origin': 'status.minecraft.de.', '$ttl': 3600, 'soa': {'mname': 'ns1.status.minecraft.de.', 'rname': 'admin.status.minecraft.de.', 'serial': '{time}', 'refresh': 3600, 'retry': 600, 'expire': 604800, 'minimum': 86400}, 'ns': [{'host': 'ns1.status.minecraft.de.'}, {'host': 'ns2.status.minecraft.de.'}], 'a': [{'name': '@', 'ttl': 400, 'value': '255.255.255.255'}, {'name': '@', 'ttl': 400, 'value': '127.0.0.1'}, {'name': '@', 'ttl': 400, 'value': '127.0.0.1'}]}

这意味着,如果你按照目前的方式循环使用它——for record in records——我们知道,由于它是一个字典,每个record都将是该字典的一个键(根据这个(。因此,以下代码:

for record in records:
print(record)
print(type(record))

给出以下输出-这只是字典中的所有键:

$origin
<class 'str'>
$ttl
<class 'str'>
soa
<class 'str'>
ns
<class 'str'>
a
<class 'str'>

因此,这意味着,如果您尝试访问record["ttl"]record["value"],由于record是一个字符串,这将类似于尝试执行类似"$ttl"["ttl"]的操作,这将给出错误string indices must be integers

然而,仅仅用records替换record并不能解决这个问题,因为records对象没有"value""ttl"密钥。看起来您实际上是在尝试循环遍历records字典中"a"关键字中的每个值,因为它的值是一个同时具有"ttl""value"关键字的字典数组:

[{'name': '@', 'ttl': 400, 'value': '255.255.255.255'}, {'name': '@', 'ttl': 400, 'value': '127.0.0.1'}, {'name': '@', 'ttl': 400, 'value': '127.0.0.1'}]

因此,您的解决方案很简单:

for record in records["a"]:
dnsbody += rectobytes(domainname, rectype, record["ttl"], record["value"])

最新更新