如何实现 avahi 感知的本地子域 dns 服务器?

Posted

技术标签:

【中文标题】如何实现 avahi 感知的本地子域 dns 服务器?【英文标题】:How to implement a local subdomain dns server that is avahi aware? 【发布时间】:2011-09-22 23:45:28 【问题描述】:

我已经构建了一个带有 avahi 感知的 twisted 迷你 dns 服务器。

它的作用是寻找以 .local 结尾的请求;如果它是主机的 URL,例如 hostname.local,则 dns 服务器让操作系统解析地址。如果它类似于subdomain.hostname.local,则服务器将其路由到hostname.local

这个程序的功能还不清楚,它让你可以轻松地使用子域,而不必将你需要的每个子域都添加到 /etc/hosts,而且它还支持本地网络中的机器并且还运行了 avahi dnsconfd 服务器。

代码如下:

编辑:现在服务器返回带有正确 ip 的 A 答案

import socket

from twisted.internet import reactor
from twisted.names import dns
from twisted.names import client, server

hostname = socket.gethostbyaddr(socket.gethostname())[0]
magic_number = + 5 + 1 + len(hostname)


class Resolver(client.Resolver):
    def lookupAddress(self, name, timeout = None):
        if name.endswith('.local'):
            local_name = name[-magic_number:]
            ip = reactor.resolve(local_name)
            if local_name == name:
                ip = reactor.resolve(local_name)
                def answer(adress):
                    a = dns.RRHeader(name=name, ttl=0)
                    payload = dns.Record_A(adress)
                    a.payload = payload
                    return ([a], [], [])
                d = ip.addCallback(answer)
                return d
            else:
                def answer(adress):
                    a = dns.RRHeader(name=name, type=dns.A, ttl=10)
                    payload = dns.Record_A(adress, ttl=10)
                    a.payload = payload

                    return ([a], [], [])
                d = ip.addCallback(answer)
                return d
        else:
            return self._lookup(name, dns.IN, dns.A, timeout)

resolver = Resolver(servers=[('212.27.40.241', 53)])
factory = server.DNSServerFactory(clients=[resolver])
protocol = dns.DNSDatagramProtocol(factory)

reactor.listenUDP(53, protocol)
reactor.listenTCP(53, factory)
reactor.run()

我用 dig 做了一些测试,一切看起来都不错。我的主机名是tachtev

这里是 dig www.tachtev.local 的输出

; <<>> DiG 9.7.3 <<>> www.tachtev.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12794
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;www.tachtev.local.             IN      A

;; ANSWER SECTION:
www.tachtev.local.      500     IN      CNAME   tachtev.local.

;; Query time: 2 msec
;; SERVER: 192.168.0.6#53(192.168.0.6)
;; WHEN: Sun Jun 26 15:51:41 2011
;; MSG SIZE  rcvd: 49

这里是 nslookup 的输出

root@tachtev:~# nslookup -debug www.tachtev.local
Server:         127.0.0.1
Address:        127.0.0.1#53

------------
    QUESTIONS:
        www.tachtev.local, type = A, class = IN
    ANSWERS:
    ->  www.tachtev.local
        internet address = 192.168.0.4
        ttl = 10
    AUTHORITY RECORDS:
    ADDITIONAL RECORDS:
------------
Non-authoritative answer:
Name:   www.tachtev.local
Address: 192.168.0.4

当我挖掘网址时,一切看起来都很好。但是现在当我尝试 curl www.tachtev.local 时,我得到一个找不到主机的错误。

错误从何而来?

编辑:依赖项:avahi + avahi-dnsconfd + twisted + twisted 名称(不能被 pip'ed) 编辑:我没有找到解决方案,但是有一个软件可以实现我想要实现的http://pow.cx/

【问题讨论】:

socket.gethostname 通常不是学习本地主机名的可靠方法。当您运行此程序时,hostname 是否实际上设置为“tachtev”?当我运行它时,我得到的是“localhost.localdomain”。 @Jean-Paul Calderone,是的,它设置为 tachtev,它直接来自 python 文档docs.python.org/library/os.html#os.uname Python 文档并不总是正确的。 :) 这些方法中的每一种都会在某些配置中中断。 你为什么不直接运行 avahi?这听起来给你带来了很多麻烦...... @vidstige,avahi 不会将子域解析为域 ip... 【参考方案1】:

客户端操作系统使用称为存根解析器的东西。存根解析器希望他们的 DNS 服务器是一个成熟的递归解析器,并为它们提供完整的答案。

对存根解析器的 CNAME 回复必须包含 CNAME 的目标;也就是说,您必须在 DNS 有效负载中包含 A 记录以及 CNAME。

【讨论】:

我添加了一条 A 记录,但它不起作用。我修改程序直接回答A记录,而不是CNAME + A,但还是不行。

以上是关于如何实现 avahi 感知的本地子域 dns 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

多个 IP 地址上的 Avahi DNS-SD

本地.local域名访问实现

搭建DNS主从服务器实现反向解析,子域,转发,智能DNS及排错和互联网DNS架构实验

Avahi dnsconfd 是如何工作的?

如何使用 C++ 创建 AVAHI 客户端和服务器?

DNS服务