DNS协议消息示例

4
我正在尝试弄清如何从应用程序套接字适配器向DNSBL发送DNS消息。我花了最近两天时间了解基础知识,并使用WireShark实验捕获消息交换的示例。现在,我想在不使用dig或host命令(我使用Ubuntu)的情况下查询DNS。我该如何在低级别执行此操作,而无需使用这些工具将请求包装成适当的DNS消息格式?消息应如何发布?十六进制还是字符串?
感谢您提前提供任何帮助。 问候 Alessandro Ilardo
评论添加
我正在调查JDev和Oracle SOA。该平台提供一个Socket Adapter,它简单地应用转换(XSLT)并直接将消息发送到套接字。如何将有效载荷参数(例如我要查找的主机)包含在消息中由开发人员决定。因此,我对整个DNS消息的结构有一些了解,但与其立即将所有内容放在JDev上,我想自己进行一些测试,以确保我得到了有效的消息格式。
所以,我没有使用任何特定语言(我甚至不明白为什么他们把我的问题从serverfault移动)。我不想使用任何会隐藏消息一部分(例如头)的工具。我知道它们很好用。我猜这个东西与数据包注入有关。有人建议我使用telnet,但我只用过SMTP或HTTP,对于DNS请求它是如何工作的我一无所知。现在更有意义了吗?

根据我的回答 - 你在使用什么编程语言? - MikeyB
1
“有人建议我使用telnet。”:太好了,你现在可以停止听这个人的建议了,你知道他是一无所知的(DNS 是二进制协议)。 - bortzmeyer
3个回答

8

哎呀呀... 与其手动构建DNS协议,你真的应该使用编程环境提供的某种库进行查找。

没有非常充分的理由,不要手动构建协议。认真点,别这么干。


@Synetech:不,OP并没有考虑使用库。他只是想不使用命令行工具。至于示例库,你不需要走远。dns库怎么样?这不需要太多的努力。

#!/usr/bin/python3
import dns
import dns.message
import dns.query

from ipaddress import IPv6Address, IPv6Network

query = dns.message.make_query('www.google.ca', dns.rdatatype.ANY)
resp = dns.query.tcp(query, '2001:4860:4860::8888', timeout=5)
aaaa_data = resp.get_rrset(resp.answer, resp.question[0].name,
                           dns.rdataclass.IN, dns.rdatatype.AAAA)

aaaa_addrs = (IPv6Address(x) for x in aaaa_data)
for addr in aaaa_addrs:
    if addr in IPv6Network('2607:F8B0::/32'):
        print("{} is in Google's network".format(addr))
    else:
        print("{} is NOT in Google's network".format(addr))

3
除非只是为了教育目的,否则不会这样做。(我曾经在一个512字节的微控制器上构建了一个TCP协议栈。好吧,它有点有用,但更多是为了挑战自己的教育目的。) - Brady Moritz
好的,虽然我会把它归为非常好的理由之一。 - MikeyB

4
我无法真正理解你要找的东西。如Alnitak和MikeyB所提到的,你使用的编程语言(Jdev,我不知道)可能提供了一个发送DNS请求的库(大多数编程语言都有)。如果你想要发送常规的DNS请求,就用它吧。在这一点上,我完全同意Alnitak和MikeyB的看法。
然而,如果你想构建特殊的DNS数据包,并且担心(当然应该)手工完成一切,也许你可以使用Scapy之类的工具?
这里是使用Scapy创建DNS请求的示例:
# scapy
>>> p = IP(dst="203.0.113.162")/UDP(sport=RandShort(),dport=53)/\
...      DNS(rd=1,qd=DNSQR(qname="www.slashdot.org", qtype="AAAA"))
>>> sr1(p)
Begin emission:
.Finished to send 1 packets.
Received 2 packets, got 1 answers, remaining 0 packets
<IP  version=4L ihl=5L tos=0x0 len=62 id=0 flags=DF frag=0L ttl=63 proto=udp chksum=0xb1bb src=203.0.113.162 dst=203.0.113.69 options='' |<UDP  sport=domain dport=50474 len=42 chksum=0x1c97 |<DNS  id=0 qr=1L opcode=QUERY aa=0L tc=0L rd=1L ra=1L z=0L rcode=ok qdcount=1 ancount=0 nscount=0 arcount=0 qd=<DNSQR  qname='www.slashdot.org.' qtype=AAAA qclass=IN |> an=None ns=None ar=None |>>>

4
该协议在许多RFC中进行了全面描述,从RFC 1035开始,但是,不要重复造轮子。查看其他人的实现“通过网络”是一个确定会出错的方法。
如果使用'C'语言,请查看ldns。对于Perl,默认解决方案是从CPAN提供的Net::DNS。其他语言也有类似的库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接