代码之家  ›  专栏  ›  技术社区  ›  Ebrahim Ghasemi

Python UDP DNS到TCP DNS转换器

  •  1
  • Ebrahim Ghasemi  · 技术社区  · 8 年前

    #! /usr/bin/env python2.7
    from scapy.all import *
    from netfilterqueue import NetfilterQueue
    import os
    import dns.resolver
    
    myResolver = dns.resolver.Resolver()
    
    def resolv_dns(payload):
        udp_query_pkt = IP(payload.get_payload())
        domain =  udp_query_pkt[DNS].qd.qname
        ip_addrs = myResolver.query(domain, "A", tcp=True) 
    
        if not udp_query_pkt.haslayer(DNSQR):
            payload.set_verdict(nfqueue.NF_ACCEPT)
        else:
            if domain in udp_query_pkt[DNS].qd.qname:
                print str(ip_addrs[0])
                udp_resp_pkt = IP(dst=udp_query_pkt[IP].src, src=udp_query_pkt[IP].dst)/\
                              UDP(dport=udp_query_pkt[UDP].sport, sport=udp_query_pkt[UDP].dport)/\
                              DNS(id=udp_query_pkt[DNS].id, qr=1, aa=1, qd=udp_query_pkt[DNS].qd,\
                              an=DNSRR(rrname=udp_query_pkt[DNS].qd.qname, ttl=10, rdata=str(ip_addrs[0])))
                send(udp_resp_pkt)
                payload.drop()
    
    nfqueue = NetfilterQueue()
    nfqueue.bind(1, resolv_dns) 
    
    try:
        os.system("iptables -A OUTPUT -p udp --dport 53 -j NFQUEUE --queue-num 1")
        print "[*] waiting for data"
        nfqueue.run()
    except KeyboardInterrupt:
        os.system("iptables -D OUTPUT -p udp --dport 53 -j NFQUEUE --queue-num 1")
        pass
    

    脚本的问题是它不工作!

    enter image description here

    但是我不能打开任何网站!实际上,UDP DNS请求超时:

    ebrahim@ebrahim:~$ dig www.xyw.com
    
    ; <<>> DiG 9.10.3-P4-Ubuntu <<>> www.xyw.com
    ;; global options: +cmd
    ;; connection timed out; no servers could be reached
    

    发生了什么?


    更新:

    resolv_dns

    def resolv_dns(packet):
        pkt = IP(packet.get_payload())
        domain =  pkt[DNS].qd.qname
        ip_addrs = myResolver.query(domain, "A", tcp=True)
        pkt[DNS].an.rdata = str(ip_addrs[0])
        packet.set_payload(str(pkt))
        packet.accept()
    

    但还是不行!

    1 回复  |  直到 8 年前
        1
  •  1
  •   Pierre    8 年前

    如果你的盒子是一个拦截转发数据包的路由器,那么你的脚本可能会工作。但既然你用的是 OUTPUT

    在我看来,你最好的选择是

    • 127.0.0.1:5300 例如,哪个将读取DNS查询(您仍然可以使用Scapy,使用 DNS(data_from_client) DNS() 从脚本调用)。
    • 使用 iptables ,而不是使用 NFQUEUE DNAT 将它们发送到服务器(类似 iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to 127.0.0.1:5300 ).

    使现代化 NF队列 而不是一个简单的UDP服务器 (让你的IP堆栈和网络过滤器完成这项工作),因为这可能是做你想做的事情的最好方式,但你可能有一个很好的理由。请注意,对于您提出的第二个解决方案,您必须从DNS服务器获得响应才能使脚本工作(因此您必须有一个工作且可访问的UDP DNS解析器)。

    在第二次尝试中,您修改了UDP数据,因此必须再次计算IP&UDP校验和和长度字段(使用服务器+ DNAT del pkt[IP].chksum, pkt[IP].len, pkt[UDP].chksum, pkt[UDP].len (Scapy将为您计算正确的值)。