Python/Scapy中Bytes转String失败问题求助
解决Scapy解析DNS NAPTR记录rdata的字节转字符串问题
在使用Scapy发送DNS NAPTR(类型35)查询并捕获响应后,提取到的rdata是二进制Bytes类型,直接使用.decode()或str()转换会得到包含大量转义字符的字符串,无法得到可读的NAPTR记录内容。
问题原因
DNS NAPTR记录的rdata并非纯文本字符串,而是符合RFC 3403定义的结构化二进制数据,包含多个字段(Order、Preference、Flags、Service、Regexp、Replacement),其中穿插空字节(\x00)、长度前缀等控制字符,直接整体转码无法解析出有效内容。
解决方案
方法1:利用Scapy自带的NAPTR解析类
Scapy内置了DNSNAPTRRR类专门用于解析NAPTR记录,无需手动处理原始二进制数据:
from scapy.all import * # 构造并发送NAPTR查询 dns = IP()/UDP()/DNS() dns[IP].dst = "194.25.0.70" dns["DNS Question Record"].qname = "12354987.xxxx.xxxx.de" dns["DNS Question Record"].qtype = 35 ans, unans = sr(dns) # 获取解析后的NAPTR记录(自动映射为DNSNAPTRRR对象) naptr_record = ans[0][1][DNS].an # 提取并打印各个可读字段 print(f"Order: {naptr_record.order}") print(f"Preference: {naptr_record.preference}") print(f"Flags: {naptr_record.flags.decode('ascii')}") print(f"Service: {naptr_record.service.decode('ascii')}") print(f"Regexp: {naptr_record.regexp.decode('ascii')}") print(f"Replacement: {naptr_record.replacement.decode('ascii')}")
方法2:手动解析原始rdata(如果需要处理二进制数据)
如果必须手动拆分原始rdata,可按照RFC 3403的格式逐个字段解析:
naptr = ans[0][1][UDP][DNS][DNSRR].rdata # 解析Order(2字节,大端) order = int.from_bytes(naptr[:2], byteorder='big') # 解析Preference(2字节,大端) preference = int.from_bytes(naptr[2:4], byteorder='big') # 解析Flags(从第4字节到第一个\x00) flags_end = naptr.index(b'\x00', 4) flags = naptr[4:flags_end].decode('ascii') # 解析Service(从flags结束的下一个字节到下一个\x00) service_start = flags_end + 1 service_end = naptr.index(b'\x00', service_start) service = naptr[service_start:service_end].decode('ascii') # 解析Regexp(从service结束的下一个字节到下一个\x00) regexp_start = service_end + 1 regexp_end = naptr.index(b'\x00', regexp_start) regexp = naptr[regexp_start:regexp_end].decode('ascii') # 解析Replacement(DNS域名格式,长度前缀+标签,以\x00结尾) replacement_start = regexp_end + 1 replacement_parts = [] pos = replacement_start while naptr[pos] != 0: label_len = naptr[pos] pos += 1 replacement_parts.append(naptr[pos:pos+label_len].decode('ascii')) pos += label_len replacement = '.'.join(replacement_parts) # 打印结果 print(f"Order: {order}") print(f"Preference: {preference}") print(f"Flags: {flags}") print(f"Service: {service}") print(f"Regexp: {regexp}") print(f"Replacement: {replacement}")
关键说明
- 不要尝试直接对整个
rdata进行转码,因为其中包含不可见控制字符,转码后必然出现\x00、\x0c等转义序列。 - Scapy会自动根据DNS记录类型选择对应的解析类,直接访问
ans[0][1][DNS].an即可得到结构化的NAPTR记录对象,这是最简便的方式。
内容的提问来源于stack exchange,提问作者dennis_10-33
相关产品推荐
相关产品推荐

