在单个DNS查询中请求A和AAAA记录

41

我正在使用C语言实现DNS查询,希望在一个单独的查询数据包中请求A记录和AAAA记录(IPv4和IPv6),但是当我将这两个查询放在一个数据包中时,未能从名称服务器获得任何响应。我已尝试将查询发送到几个不同的名称服务器(本地和8.8.8.8),但没有成功。这是否意味着它不起作用,还是我的查询数据包可能存在问题?

我追加AAAA查询的基本算法(到现有的A请求数据包)是增加数据包头中的QDCOUNT字段,然后添加一个RR查询,其中TYPE设置为AAAA,NAME指向现有A查询中主机名的指针(从数据包开头偏移12字节,即0xC0 0x0C)。这听起来正确吗?

也就是说,在只有A查询的数据包中一切正常。

编辑: 显然,我的所有查询都略微格式错误(我不知道与回答不同,查询没有TTL和RDLENGTH / RDATA字段)。修复后,我收到了RCODE = 1的格式错误回复,该回复确认了2个查询的存在。这是否意味着不支持每个数据包多个查询?

编辑2: 这是查找www.google.com的hexdump:

d8 32 01 00 00 02 00 00 00 00 00 00 03 77 77 77 06 67 6f 6f 67 6c 65 03 63 6f 6d 00 00 01 00 01 c0 0c 00 1c 00 01

我没有发现任何问题。


Wireshark也没有发现问题,这通常是你正确阅读规范的好迹象。 - SimonJ
4个回答

49
我不知道有哪些名称服务器支持在单个查询中处理多个问题。
这样的查询存在歧义的可能性,因为每个数据包都有一些标志(例如AA),这些标志可能仅适用于其中一个问题。如果您提出了两个问题并且服务器只对其中一个域具有权威性,那么服务器是否应该设置标志呢?我怀疑此类问题已经阻止了实现者。
已经有许多解决您所说问题的提案(例如this 提议引入将A和AAAA结合起来的QTYPE,以及Paul Vixie的repeated attempts 引入EDNS形式的多个问题),但目前支持IPv4和6的程序通常执行两个单独的查询,要么是AAAA后跟A(在超时后),要么同时查询两个。
我想还有“all” QTYPE,但它可以返回比您需要的更多的数据。 编辑:来自BIND源代码中的query.c:
   dns_message_currentname(message, DNS_SECTION_QUESTION,
         &client->query.qname);
   client->query.origqname = client->query.qname;
   result = dns_message_nextname(message, DNS_SECTION_QUESTION);
   if (result != ISC_R_NOMORE) {
     if (result == ISC_R_SUCCESS) {
       /*
        * There's more than one QNAME in the question
        * section.
        */
       query_error(client, DNS_R_FORMERR, __LINE__);
     } else
       query_error(client, result, __LINE__);
     return;
   }

编辑:此外,来自BIND源代码中的resolver.c:

    /*
     * XXXRTH  Currently we support only one question.
     */
    if (message->counts[DNS_SECTION_QUESTION] != 1) {
            log_formerr(fctx, "too many questions");
            return (DNS_R_FORMERR);
    }

我认为“all” QTYPE并不实用,因为它无法像A或AAAA查询那样解析CNAME。 - R.. GitHub STOP HELPING ICE
也没错——更多地是为了完整性而提及,而不是建议你实际上“使用”它 :) - SimonJ
已更新您的FORMERR源代码。 - SimonJ
他所说的“all”可能意味着“any”。然而,许多服务器,尤其是Cloudflare都拒绝这个。 - Nick
5
使用 ANY 查询时的另一个问题是,当存根解析器向递归服务器发送 ANY 查询时,服务器仅需响应当前缓存中的内容(如果缓存中没有,则会将查询发送到上游)。如果 A 在缓存中但 AAAA 不在,则只能获得 A。请注意,不要改变原文的意思。 - Alnitak

22

虽然数据包格式在技术上支持在问题部分中有多个记录(参见RFC 1035 §4.1.2),但实际上不起作用,正如您所发现的那样。

特别是没有人能够为两个问题产生两个不同的RCODE时该怎么做定义正确的语义。

我曾经在IETF上尝试定义这些语义,但目前进展缓慢。

在我的DNS数据包解析代码中,我总是拒绝任何这样的数据包。


0
我尝试了同样的方法,但结果略有不同。 当在一个电报中发送两个查询(A和AAAA)时,我没有从我的本地DNS(dnsmasq)获得任何响应,但是当使用Google的8.8.8.8服务器进行相同的测试时,我会收到响应。 Google NS仅返回一个查询和一个响应的响应,它简单地忽略第二个条目。

请求:

Frame 5: 78 bytes on wire (624 bits), 78 bytes captured (624 bits) on interface any, id 0
Linux cooked capture v1
Internet Protocol Version 4, Src: 192.168.0.94, Dst: 8.8.8.8
User Datagram Protocol, Src Port: 48440, Dst Port: 53
Domain Name System (query)
    Transaction ID: 0x6f23
    Flags: 0x0100 Standard query
    Questions: 2
    Answer RRs: 0
    Authority RRs: 0
    Additional RRs: 0
    Queries
        google.com: type A, class IN
            Name: google.com
            [Name Length: 10]
            [Label Count: 2]
            Type: A (Host Address) (1)
            Class: IN (0x0001)
        google.com: type AAAA, class IN
            Name: google.com
            [Name Length: 10]
            [Label Count: 2]
            Type: AAAA (IPv6 Address) (28)
            Class: IN (0x0001)
    [Response In: 11]

响应:

Frame 11: 88 bytes on wire (704 bits), 88 bytes captured (704 bits) on interface any, id 0
Linux cooked capture v1
Internet Protocol Version 4, Src: 8.8.8.8, Dst: 192.168.0.94
User Datagram Protocol, Src Port: 53, Dst Port: 48440
Domain Name System (response)
    Transaction ID: 0x6f23
    Flags: 0x8180 Standard query response, No error
    Questions: 1
    Answer RRs: 1
    Authority RRs: 0
    Additional RRs: 0
    Queries
        google.com: type A, class IN
            Name: google.com
            [Name Length: 10]
            [Label Count: 2]
            Type: A (Host Address) (1)
            Class: IN (0x0001)
    Answers
        google.com: type A, class IN, addr 142.250.186.142
            Name: google.com
            Type: A (Host Address) (1)
            Class: IN (0x0001)
            Time to live: 300 (5 minutes)
            Data length: 4
            Address: 142.250.186.142
    [Request In: 5]
    [Time: 0.023670110 seconds]

-4

AAAAA查询可以在单个数据包中组合,因此我猜测您的数据包仍然存在某种方式的格式错误,特别是考虑到查询不使用彼此数据的偏移量。如果您能展示实际代码或至少发送的原始字节,那将非常有帮助。


同一个查询数据包中的两个问题(QDCOUNT=2)应该能够共享数据,对吗?当然,两个答案可以。我将发布我发送的字节转储。 - R.. GitHub STOP HELPING ICE
我之前不知道这个功能,但是在RFC 1035第4.1.4节中,指针和偏移量的使用被通用地定义为所有消息类型。 - Remy Lebeau
1
实际上,答案通常可以使用问题内的偏移量。 - caf
@R.. 问题不在于问题本身,而在于如何在结果代码不同的情况下放置多个结果的语义未被定义。请参见http://tools.ietf.org/html/draft-bellis-dnsext-multi-qtypes-01。 - Alnitak

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