You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求协助修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:45:08