请求协助修改Fake-DNS服务器代码以返回2条及以上DNS响应
解决Fake-DNS返回多条DNS响应的问题
我看了你的Fake-DNS代码,帮你调整了一下,实现返回多条DNS响应的功能。原代码主要有两个小问题:一是存在笔误data1应该是data,二是只生成了单条A记录的响应。下面是修改后的完整代码,支持返回多条IP记录:
import socket class DNSQuery: def __init__(self, data): self.data = data self.dominio = '' tipo = (ord(data[2]) >> 3) & 15 # Opcode bits if tipo == 0: # Standard query ini = 12 lon = ord(data[ini]) while lon != 0: self.dominio += data[ini+1:ini+lon+1] + '.' ini += lon + 1 lon = ord(data[ini]) def respuesta(self, ips): packet = '' if self.dominio: # 响应头:保留请求ID + 设置响应标志位 packet += self.data[:2] + "\x81\x80" # 问题数与请求一致 + 回答数匹配IP列表长度 qdcount = self.data[4:6] ancount = chr(len(ips)) + '\x00' # 测试场景下数量不会超过255,足够使用 packet += qdcount + ancount + '\x00\x00\x00\x00' # NS记录和额外记录数设为0 # 保留原请求中的域名问题部分 packet += self.data[12:] # 为每个IP生成一条A记录 for ip in ips: packet += '\xc0\x0c' # 指针指向请求中的域名 # A记录的类型、类别、TTL(60秒)、数据长度(4字节) packet += '\x00\x01\x00\x01\x00\x00\x00\x3c\x00\x04' # 将IP转换为4字节二进制格式 packet += ''.join(map(lambda x: chr(int(x)), ip.split('.'))) return packet if __name__ == '__main__': # 这里可以设置任意数量的IP,比如两条或更多 ips = ['192.168.1.1', '10.0.0.1'] print(f'pyminifakeDNS:: dom.query. 60 IN A {" ".join(ips)}') udps = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udps.bind(('', 53)) try: while True: data, addr = udps.recvfrom(1024) p = DNSQuery(data) response = p.respuesta(ips) udps.sendto(response, addr) print(f'Respuesta: {p.dominio} -> {", ".join(ips)}') except KeyboardInterrupt: print('Finalizando') udps.close()
关键改动说明:
- 多记录响应实现:修改
respuesta方法,让它接收一个IP列表,为每个IP生成一条独立的A记录,打包在同一个DNS响应包中(这是符合DNS协议规范的方式,客户端会一次性收到所有IP记录) - 响应头计数调整:动态设置响应头中的
ancount(回答数)字段,匹配实际返回的IP数量,确保客户端能正确解析所有记录 - 笔误修复:把原代码中的
p=DNSQuery(data1)改成了p=DNSQuery(data),避免运行时报错
如果你想要的是发送多个独立的DNS响应包(而非一个包包含多条记录),可以在主循环里多次调用sendto,比如:
# 替换主循环内的发送逻辑 for ip in ips: single_response = p.respuesta([ip]) udps.sendto(single_response, addr) print(f'Respuesta: {p.dominio} -> {", ".join(ips)}')
不过这种方式不符合DNS协议的常规用法,通常客户端期望一个请求对应一个响应包,因此更推荐第一种实现方式。
内容的提问来源于stack exchange,提问作者erma
相关产品推荐
相关产品推荐

