How to Connect and Query DNS Servers via Command Line (TCP/UDP with Netcat/Dig Examples)


3 views

When attempting to interact with DNS servers directly through command line tools, most beginners hit the same wall:

$ telnet 8.8.8.8 53
Trying 8.8.8.8...
Connected to 8.8.8.8.
Escape character is '^]'.
Connection closed by foreign host.

DNS primarily uses UDP port 53 for standard queries, though TCP is used for:

  • Zone transfers (AXFR/IXFR)
  • Responses larger than 512 bytes
  • DNSSEC validation

For UDP communication with a DNS server, use netcat's UDP mode combined with proper DNS message formatting:

echo -n -e "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\x01\x00\x01" | nc -u -w 2 8.8.8.8 53 | hexdump -C

While raw socket communication is educational, these tools provide better visibility:

dig (DNS Lookup Utility)

dig @8.8.8.8 example.com ANY +tcp
dig @8.8.8.8 example.com +short
dig @8.8.8.8 example.com +trace

nslookup (Interactive Query)

nslookup
> server 8.8.8.8
> set type=MX
> example.com

For developers needing to test custom DNS implementations, here's how to craft a Type A query packet:

# Python example using socket
import socket

query = b"\x12\x34\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00" \
        b"\x07example\x03com\x00\x00\x01\x00\x01"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(query, ("8.8.8.8", 53))
response = sock.recv(1024)
print(response.hex())

Capture and inspect actual DNS traffic:

sudo tcpdump -i any -n -v 'port 53' -w dns.pcap
# Analyze with:
tcpdump -r dns.pcap -X

Modern DNS encryption protocols require specialized tools:

# Using cloudflared for DoH
cloudflared proxy-dns --upstream https://1.1.1.1/dns-query

# Using kdig for DoT
kdig @1.1.1.1 +tls example.com

DNS primarily operates on UDP port 53 for standard queries, though TCP is used for responses larger than 512 bytes or zone transfers. This explains why your initial telnet attempt failed - it defaults to TCP without proper DNS protocol handshake.

For interactive DNS queries, we have several options:

# Using netcat for UDP (Linux/Mac)
echo -n -e "\xab\xcd\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\x03com\x00\x00\x01\x00\x01" | nc -u 8.8.8.8 53 | hexdump -C

# Windows equivalent with ncat
ncat -u 8.8.8.8 53 < dns_query.bin

The dig tool provides human-readable DNS queries while showing the raw protocol interaction:

dig +nocmd +nocomments +noquestion +nostats @8.8.8.8 example.com A

Windows users can leverage Resolve-DnsName or raw socket programming:

Resolve-DnsName -Server 8.8.8.8 -Name example.com -Type A
# Raw UDP example
$udp = New-Object System.Net.Sockets.UdpClient(53)
$udp.Connect("8.8.8.8", 53)
$bytes = [System.Text.Encoding]::ASCII.GetBytes("example.com")
$udp.Send($bytes, $bytes.Length)

To observe actual DNS traffic:

tcpdump -i any -n udp port 53 -X
# Filter for specific queries
tcpdump -i eth0 'udp port 53 and host 8.8.8.8' -vv