一、目标简述
我们要用 Scapy 实现: 构造一个 DNS 查询包(UDP 协议,目标 DNS 服务器是 114.114.114.114,端口 53) 查询域名:www.baidu.com 的 A 记录(IPv4 地址) 发送这个 DNS 查询包 接收 DNS 服务器的响应,并从中提取 http://www.baidu.com 的 IP 地址
二、关键知识点
DNS 协议 : 用于域名解析(如将 www.baidu.com 转为 39.156.66.14)
默认端口: DNS over UDP 使用 端口 53
DNS 服务器: 你使用的是国内公共 DNS:114.114.114.114(端口 53)
传输协议: 通常是 UDP(有时 DNS over TCP,但查询一般用 UDP)
查询类型: 我们要查 A 记录(IPv4 地址)
Scapy 模块: 使用 scapy.layers.dns 和 scapy.layers.inet 相关功能
三、完整代码示例:
用 Scapy 构造并发送 DNS 查询请求 注意:运行此代码需要管理员权限(root / sudo),因为要发送和接收原始数据包。
from scapy.all import *
import random
1.目标 DNS 服务器
dns_server = "114.114.114.114"
dns_port = 53 # DNS 服务默认端口
2.要查询的域名
domain = "www.baidu.com"
3.随机源端口(DNS 客户端端口通常是随机的)
src_port = random.randint(1024, 65535)
4.构造 DNS 查询包
dns_query = IP(dst=dns_server) /UDP(sport=src_port, dport=dns_port) / DNS(rd=1,qd=DNSQR(qname=domain, qtype="A"))
//rd=1 表示希望 DNS 服务器进行递归查询(Recursive)
//qtype="A" 表示查询 A 记录(IPv4 地址)
//qname="www.baidu.com" 是要解析的域名
5.发送 DNS 查询并等待响应(超时设为 5 秒)
print(f"[*] 正在向 DNS 服务器 {dns_server} 查询域名:{domain} …")
response = sr1(dns_query, timeout=5, verbose=0)
6. 处理响应
if response:
if response.haslayer(DNS):
dns_layer = response.getlayer(DNS)
if dns_layer and dns_layer.an: # dns_layer.an 是 Answer Section
for answer in dns_layer.an:
if answer.type == 1: # type=1 表示 A 记录(IPv4)
ip = answer.rdata
print(f"[+] 域名 {domain} 的 IP 地址是:{ip}")
else:
print("[-] 响应中未找到有效的 DNS Answer 记录")
else:
print("[-] 收到响应,但不是 DNS 响应")
else:
print("[-] 未收到 DNS 服务器的响应(可能超时、被阻、或 DNS 服务器无响应)")
1.A解析请求
dns_a_query = ( IP(dst="114.114.114.114") / UDP(sport=12345, dport=53) / DNS(rd=1, qd=DNSQR(qname="www.baidu.com", qtype="A")) )
dns_a_query .show()
A解析请求的回应
a_response = sr1(dns_a_query, timeout=3, verbose=0)
a_response.show()
2.PTR解析请求,注意反向解析IP要反写+.in-addr.arpa
dns_ptr_query = ( IP(dst="114.114.114.114") / UDP(sport=RandShort(), dport=53) / DNS(rd=1, qd=DNSQR(qname="73.51.101.180.in-addr.arpa", qtype="PTR")) )
dns_ptr_query.show()
PTR请求的回应
ptr_response = sr1(dns_ptr_query, timeout=3, verbose=0)
ptr_response.show()
浙公网安备 33010602011771号