在Python中实现DNS消息NAME压缩算法



在DNS消息中,域名的表示方式如下:

Address    Value
----------------------------------------------------------------
0x00C      0x5 s t o r e 0x7 e x a m p l e 0x3 c o m 0x0
0x023      0x4 b l o g  0xC012

在地址0x00C我们有store.example.com,在地址0x023我们有blog.example.com0xC012表示指向0x012的指针,其中example.com从第一个域名开始,所以我们不必重复

我使用以下代码成功地将域名变成了一组标签:

labels = []
for part in self.domain.split('.'):
label = part.encode('ascii')
length = len(label).to_bytes(1, 'big')
labels.append(length + label)

这给了我以下数组:

[b'x04blog', b'x07example', b'x03com']

但是,我很难构建一个正则表达式或一个高效的函数来搜索已经为x04blogx07examplex03comx00x07examplex03comx00x03com00编写的消息部分。我想找到最长的匹配。我尝试构建这样的正则表达式:

(((x04blog)?x07example)?x03com)?x00

但在这种情况下,regex引擎似乎更喜欢只匹配x00。我该怎么解决?

还有另一个问题:从技术上讲,我们可以添加my.blog.example.com,它需要包含0x2 m y 0xC023,而0xC023指向blog.example.com

首先很抱歉我给你的错误提示,有更简单的事情要做。事实上,有比在这里使用正则表达式更简单的事要做。regex太强大了,无法做到这一点,您可以在没有regex的情况下获得相同的结果。

DNS消息格式在RFC 1035中定义:;域名-实现和规范";

第4.1.4节对名称压缩进行了说明。还要注意,您必须考虑不区分大小写的方面,如第2.3.3节所述

以下代码中的情况肯定可以优化,示例名称取自RFC:

#!/usr/bin/python3
names=['F.ISI.ARPA', 'FOO.F.ISI.ARPA', 'ARPA']
cache={}
pos=0
results=[]
for name in names:
labels = name.split('.')
while len(labels):
key = '.'.join(labels)
if key.lower() in cache:
results.append((cache[key.lower()] + 2**15 + 2**14).to_bytes(2, 'big'))
pos += 2
break
else:
label = labels.pop(0).encode('ascii')
length = len(label).to_bytes(1, 'big')
results.append(length + label)
cache[key.lower()] = pos
pos += len(label) + 1
else:
results.append(b'0')
pos += 1

print(results)

其产生:

[b'x01F', b'x03ISI', b'x04ARPA', b'0', b'x03FOO', b'xc0x00', b'xc0x06']

如果使用您的示例:

names=['store.example.com', 'blog.example.com', 'my.blog.example.com']

它产生:

[b'x05store', b'x07example', b'x03com', b'0', b'x04blog', b'xc0x06', b'x02my', b'xc0x13']

相关内容

最新更新