I use scapy and python to build my DNS request. No problem for UDP request but when I want to use TCP (with exactly the same request that I use with UDP), Wireshark say that my DNS request are malformed.
Here my python code:
from scapy.all import *
ip=IP(dst="130.104.254.1")
dns = DNS(rd=1, qd=DNSQR(qname = "google.be", qtype="A"))
SYN=ip/TCP(sport=RandNum(1024,65535), dport=53, flags="S", seq=42)
SYNACK=sr1(SYN)
ACK=ip/TCP(sport=SYNACK.dport, dport=53, flags="A", seq=SYNACK.ack, ack=SYNACK.seq + 1)
send(ACK)
DNSRequest = ip/TCP(sport=SYNACK.dport, dport=53, flags="PA", seq=SYNACK.ack, ack=SYNACK.seq + 1) / dns
DNSReply = sr1(DNSRequest, timeout = 1)
The Three Way Handshake are fully completed before I send my request.

Thank you very much !
After more research I found in the RFC 1035 :
4.2.2. TCP usage
Messages sent over TCP connections use server port 53 (decimal). The message is prefixed with a two byte length field which gives the message length, excluding the two byte length field. This length field allows the low-level processing to assemble a complete message before beginning to parse it.
So the solution is in the code below :
from scapy.all import *
ip=IP(dst="216.239.32.10")
request = DNS(rd=1, qd=DNSQR(qname = "google.be", qtype="A")) #size = 27(dec) = 1b (hex)
twoBytesRequestSize = "\x00\x1b" #BIG ENDIAN
completeRequest = str(request) + twoBytesRequestSize
SYN=ip/TCP(sport=RandNum(1024,65535), dport=53, flags="S", seq=42)
SYNACK=sr1(SYN)
ACK=ip/TCP(sport=SYNACK.dport, dport=53, flags="A", seq=SYNACK.ack, ack=SYNACK.seq + 1)
send(ACK)
DNSRequest = ip/TCP(sport=SYNACK.dport, dport=53, flags="PA", seq=SYNACK.ack, ack=SYNACK.seq + 1) / completeRequest
DNSReply = sr1(DNSRequest, timeout = 1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With