我正在编写一个程序来接收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当量吗?
我的回答是否也应该有这种格式?
答案 0 :(得分:6)
它以十六进制形式出现,因为它是原始二进制请求,但您可能会尝试将其作为字符串打印出来。这显然是如何通过你用来打印出来的不可打印字符来显示的;它以十六进制序列的形式逃脱它们。
您根本不将其解释为“hex”或UTF-8;您需要解释RFC描述的二进制格式。如果您提到您正在使用的语言,我(或其他人)可能会向您描述如何以二进制格式处理数据。
Untile那么,让我们看一下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表示它是一个查询,opcode = 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地址。