在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.com
。0xC012
表示指向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']
但是,我很难构建一个正则表达式或一个高效的函数来搜索已经为x04blogx07examplex03comx00
、x07examplex03comx00
或x03com00
编写的消息部分。我想找到最长的匹配。我尝试构建这样的正则表达式:
(((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']