2017-09-27 2 views
1

Ich versuche, NFQUEUE und Scapy zu verwenden, um jede UDP DNS Anfrage zu TCP DNS Anfragen umzuwandeln und dann die UDP DNS Anfrage mit einem in Handarbeit gemachten UDP Paket zu beantworten, das auf TCP DNS resonse basiert. Dies ist das Skript, das ich bisher geschrieben:Python UDP DNS zu TCP DNS Konverter

#! /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 

Das Problem mit dem Skript ist, dass es funktioniert nicht!

Eigentlich kann ich die Korrespondenz-DNS-Pakete in der wireshark sehen und sie scheint in Ordnung: enter image description here

Aber ich kann eine Website nicht öffnen! Tatsächlich ist die UDP-DNS-Anforderung abgelaufen:

[email protected]:~$ dig www.xyw.com 

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

Was ist los?


Update:

Nach @ Pierre Antwort, ich habe die IPTable Regel geändert, um die empfangenen UDP-DNS-Antworten auf die NFQUEUE (statt gesendet DNS-Anfragen) und dann zu senden, wie unten I modifizierte resolv_dns Funktion (zu IP-Adresse in der UDP-DNS-Antwort mit der neuen IP-Adresse ersetzen, die ich unter Verwendung von TCP DNS-Abfrage erhalten):

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() 

Aber noch ist es nicht funktioniert!

Antwort

1

Ihr Skript würde wahrscheinlich funktionieren, wenn Ihre Box ein Router ist, der weitergeleitete Pakete abfängt. Aber da Sie die Kette OUTPUT verwenden, nehme ich an, dass die abgefangenen Pakete vom lokalen Host stammen. In diesem Fall denke ich, dass der ursprüngliche Client niemals Ihre gefälschte Antwort erhalten wird.

Meiner Meinung nach ist die beste Option ist zu

  • einen UDP-Server schreiben, die auf 127.0.0.1:5300 zum Beispiel hören würde, die die DNS-Abfrage lesen würde (man kann immer noch das tun, mit scapy, mit DNS(data_from_client)) , lösen Sie es (indem Sie TCP wie Ihr Skript verwenden), und senden Sie die Antwort (Sie können die mit dem Aufruf DNS() erstellten Daten erneut aus Ihrem Skript senden).
  • Verwenden Sie iptables, aber anstatt ausgehende Pakete mit dem Ziel NFQUEUE abzufangen, einfach DNAT sie an Ihren Server (so etwas wie iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to 127.0.0.1:5300).

aktualisieren: Ich habe keine Ahnung, warum Sie darauf bestehen, NFQUEUE anstelle einer einfachen UDP-Server mit DNAT verwenden (Ihre IP-Stack & netfilter die Arbeit machen zu lassen), wie das ist wahrscheinlich der beste Weg, was zu tun ist Sie Willst du, aber du hast wahrscheinlich einen guten Grund. Bitte beachten Sie, dass Sie mit Ihrer vorgeschlagenen zweiten Lösung eine Antwort vom DNS-Server erhalten müssen, damit Ihr Skript funktioniert (Sie müssen also einen funktionierenden und erreichbaren UDP-DNS-Resolver haben).

In Ihrem zweiten Versuch, ändern Sie die UDP-Daten, so müssen Sie erneut die IP & UDP-Prüfsumme und Länge Felder berechnen (mit dem Server + DNAT Lösung, würde Ihr Kernel diesen Job tun). Sie können das mit del pkt[IP].chksum, pkt[IP].len, pkt[UDP].chksum, pkt[UDP].len tun (Scapy wird die richtigen Werte für Sie berechnen).