kbandla / dpkt

fast, simple packet creation / parsing, with definitions for the basic TCP/IP protocols
Other
1.09k stars 270 forks source link

Parsing DNS Query Type 65 #537

Closed brightpinefield closed 3 years ago

brightpinefield commented 3 years ago

Hi guys,

I was trying to parse some DNS data out of some JMirror packets and ran into a potential issue with parsing DNS Query Type 65 (HTTPS). This is what I see in Wireshark (note Packet #1):

Screen Shot 2021-01-25 at 6 03 02 PM

$ python3 dump_dns.py jmirror_test.pcap ErrorParsingDNS: Warning: Not all DNS fields might have been populated CNAME: init.itunes.apple.com - init-cdn.itunes-apple.com.akadns.net CNAME: init-cdn.itunes-apple.com.akadns.net - itunes.apple.com.edgekey.net

Is there a way to get around the error on the unpack of the DNS item for this? I'd like to print the query name found if possible..

I was using a script modified by Kiran with help from Oscar for the JMirror encapsulation. attached it here.. dump_dns.py.zip

Thanks!

obormot commented 3 years ago

Hi @brightpinefield . I'm happy to look at it. Script looks good. Would you be able to attach the pcap? 1 or 2 packets is probably all we need (use "Export specified packets" in Wireshark).

brightpinefield commented 3 years ago

Thanks Oscar! I forgot to attach the pcap earlier.. I've attached one now .. It contains the same 3 packets as in the screenshot. Packet 1 is the culprit.. Oh, also, the script I haven't updated to print the Query name along with the query answer names found.. I want to do that eventually to catch query names that don't resolve..

jmirror_test.pcap.zip

obormot commented 3 years ago

The culprit appears to be packet 3, it's truncated (Wireshark reports it as well), so dpkt is doing the right thing.. You can workaround it though by overriding the DNS parser in your script, e.g.

class ResilientDNS(dpkt.dns.DNS):
    def unpack(self, buf):
        try:
            return super().unpack(buf)
        except dpkt.NeedData:
            self.data = b''

then replace the parser call

        dns = ResilientDNS()        # <---- THIS
        dns.unpack(udp.data)        # <---- HERE

the resulting dns has the 2 answers decoded (3rd was truncated)

ipdb> p dns
ResilientDNS(id=50103, op=33152, 
  qd=[Q(name='init.itunes.apple.com', type=65)], 
  an=[
     RR(name='init.itunes.apple.com', type=5, ttl=2181, rlen=38, 
        rdata=b'\x08init-cdn\x0citunes-apple\x03com\x06akadns\x03net\x00', 
        cname='init-cdn.itunes-apple.com.akadns.net'), 
     RR(name='init-cdn.itunes-apple.com.akadns.net', type=5, ttl=1362, rlen=27,
        rdata=b'\x06itunes\x05apple\x03com\x07edgekey\xc0T', 
        cname='itunes.apple.com.edgekey.net')], ns=1, ar=0)
brightpinefield commented 3 years ago

Oh I see what you're saying. Thanks Oscar! I'll give that a shot. Appreciate the help!

obormot commented 3 years ago

No problem!

brifordwylie commented 3 years ago

@obormot @brightpinefield I added an example for truncated DNS packet just a while back: https://github.com/kbandla/dpkt/blob/master/examples/print_dns_truncated.py

We should make sure that example is 'good' (shows best practices)...

$ cd examples
$ python print_dns_truncated.py
Timestamp:  2020-11-25 10:12:43.787495
Ethernet Frame:  88:1d:fc:ba:ed:80 20:47:47:8d:8d:5e 2048
IP: 192.168.1.100 -> 24.157.241.171   (len=224 ttl=59 DF=1 MF=0 offset=0)
UDP: sport=53 dport=18741 sum=23042 ulen=204

Error Parsing DNS, Might be a truncated packet...
Exception: error('unpack requires a buffer of 10 bytes')
Queries: 1
     api.spd.samsungdm.com Type:1
Answers: 6
     api.spd.samsungdm.com: type: CNAME Answer: api.samsungspd.com
     api.samsungspd.com: type: A Answer: 54.75.141.161
     api.samsungspd.com: type: A Answer: 99.81.251.12
     api.samsungspd.com: type: A Answer: 52.50.121.244
     api.samsungspd.com: type: A Answer: 52.210.193.207
     api.samsungspd.com: type: A Answer: 52.50.159.204