1

我正在编写一个程序来接收 dns 消息并响应适当的答案(一个仅回复 A 记录的简单 dns 服务器)。
但是当我收到消息时,它不像 1035 RFC 中描述的格式。
例如,这是一个由 nslookup 生成的 dns 查询:

'\xe1\x0c\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x06google\x03com\x00\x00\x01\x00\x01'

我知道 1035 RFC 中定义的 dns 标头和位,但为什么它应该是十六进制的?
我应该将它们视为十六进制数字还是它们的 utf-8 等价物?
我的回复也应该采用这种格式吗?

4

1 回答 1

7

它以十六进制形式出现,因为它是一个原始二进制请求,但您可能正试图将其打印为字符串。显然,这就是您用来打印不可打印字符的方式;它将它们作为十六进制序列转义。

您根本不会将其解释为“十六进制”或 UTF-8;您需要解释 RFC 描述的二进制格式。如果您提及您使用的是什么语言,我(或其他人)也许能够向您描述如何处理像这样的二进制格式的数据。

在那之前,让我们看一下RFC 1035,看看如何手动解释您的查询:

The header contains the following fields:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                      ID                       |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    QDCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ANCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    NSCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                    ARCOUNT                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

每行有 16 位,所以是 12 个字节。让我们将前 12 个字节填充到那里:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   ID = e10c                   |  \xe1 \x0c
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 0|  Opcode=0 | 0| 0| 1| 0| Z=0    |  RCODE=0  |  \x01 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  QDCOUNT = 1                  |  \x00 \x01
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  ANCOUNT = 0                  |  \x00 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  NSCOUNT = 0                  |  \x00 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  ARCOUNT = 0                  |  \x00 \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

所以。我们有一个 ID = 的查询e10c(只是一个任意数字,因此客户端可以将查询与响应匹配),QR = 0 表示它是一个查询,操作码 = 0 表示它是一个标准查询,AA 和 TC 用于响应,RD = 1 表示需要递归(我们正在对本地名称服务器进行递归查询)。Z 保留供将来使用,RCODE 是响应的响应代码。QDCOUNT = 1 表示我们有 1 个问题,其余都是响应中不同类型记录的数量。

现在我们来回答问题。每个都有以下格式:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                                               |
    /                     QNAME                     /
    /                                               /
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QTYPE                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                     QCLASS                    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

QNAME 是查询的名称。格式是一个八位字节,指示标签的长度,后跟标签,以长度为 0 的标签终止。

所以我们有:

                                    1  1  1  1  1  1
      0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |       LEN = 6         |           g           |  \x06 g
    |           o           |           o           |  o    o
    |           g           |           l           |  g    l
    |           e           |       LEN = 3         |  e    \x03
    |           c           |           o           |  c    o
    |           m           |       LEN = 0         |  m    \x00
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   QTYPE = 1                   |  \x00 \x01
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                  QCLASS = 1                   |  \x00 \x01
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

这表明我们正在查找的名称是google.com(有时写为google.com.,末尾的空标签是明确的)。QTYPE = 1 是 A(IPv4 地址)记录。QCLASS = 1 是一个 IN(互联网)查询。所以这是要求 google.com 的 IPv4 地址。

于 2012-11-14T04:38:00.043 回答