如何使用mDNS将所有子域路由到单个主机?

时间:2009-04-22 00:20:02

标签: bonjour zeroconf mdns

我有一个开发网络服务器托管为“myhost.local”,可以使用Bonjour / mDNS找到。服务器正在运行avahi-daemon。

网络服务器也想处理自己的任何子域。例如“cat.myhost.local”和“dog.myhost.local”和“guppy.myhost.local”。

鉴于myhost.local位于dhcp的动态IP地址上,是否还有办法将子域的所有请求路由到myhost.local?

我开始认为目前不可能......

http://marc.info/?l=freedesktop-avahi&m=119561596630960&w=2

  
    

您可以使用/ etc / avahi / hosts文件执行此操作。或者你可以     使用avahi-publish-host-name。

  
     不,他不能。因为他想定义别名,而不是新的   主机名。即他只想注册A RR,没有反向PTR RR。但   如果你把东西放到/ etc / avahi / hosts中那么它会注册两者,   如果PTR RR是非唯一的,则检测到碰撞,这将是   别名的情况。

5 个答案:

答案 0 :(得分:12)

我已经尽可能地解决了这个问题,只花了很少的时间来完成这项任务。

但不幸的是,我不认为avahi / msdns / bonjour的windows实现支持别名(如果我错误的解决了如何支持这个问题,请纠正我。)

我所做的是从avahi网站上提供的示例python脚本开始:

创建:/usr/bin/avahi-announce-alias

让它可执行&填写

#! /usr/bin/env python
# avahi-alias.py

import avahi, dbus
from encodings.idna import ToASCII

# Got these from /usr/include/avahi-common/defs.h
CLASS_IN = 0x01
TYPE_CNAME = 0x05

TTL = 60

def publish_cname(cname):
    bus = dbus.SystemBus()
    server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER),
            avahi.DBUS_INTERFACE_SERVER)
    group = dbus.Interface(bus.get_object(avahi.DBUS_NAME, server.EntryGroupNew()),
            avahi.DBUS_INTERFACE_ENTRY_GROUP)

    rdata = createRR(server.GetHostNameFqdn())
    cname = encode_dns(cname)

    group.AddRecord(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, dbus.UInt32(0),
        cname, CLASS_IN, TYPE_CNAME, TTL, rdata)
    group.Commit()


def encode_dns(name):
    out = []
    for part in name.split('.'):
        if len(part) == 0: continue
        out.append(ToASCII(part))
    return '.'.join(out)

def createRR(name):
    out = []
    for part in name.split('.'):
        if len(part) == 0: continue
        out.append(chr(len(part)))
        out.append(ToASCII(part))
    out.append('\0')
    return ''.join(out)

if __name__ == '__main__':
    import time, sys, locale
    for each in sys.argv[1:]:
        name = unicode(each, locale.getpreferredencoding())
        publish_cname(name)
    try:
        # Just loop forever
        while 1: time.sleep(60)
    except KeyboardInterrupt:
        print "Exiting"

此脚本处理每个别名的公告,并将一直运行直到您将其删除。 (因此,我们需要创建另一个我在下面显示的脚本)

创建文本文件/etc/avahi/aliases

我们使用这种方法将别名存储到本机器

创建目录/etc/avahi/aliases.d/

我还没有在我在这里展示的任何剧本中使用过这个,但对那些有进取心的人来说,你可以看到需要做什么。

这个想法是你可以将别名分组到单独的文本文件中(当你在apache中处理虚拟主机时更有意义),这是* nix上已经提供的许多守护程序应用程序(apache和apt只是两个例子) )。

创建/usr/bin/avahi-announce-aliases

使其可执行并用

填写
#!/usr/bin/env python

import os, sys
from subprocess import Popen


def ensure_file (path):
    """
        Looks for  file at provided path, creates it if it does not exist.
        Returns the file.
    """
    rfile = None    
    if not os.path.exists(path) and os.path.isfile(path) :
        rfile = open(path,"w+");
        print("ensuring file : %s " % path)

    print("file ensured : %s " % path)
    return rfile


command = '/usr/bin/avahi-announce-alias'
alias_pid_path = "/tmp/avahi-aliases.pid"
alias_file_path = "/etc/avahi/aliases"

alias_file = open(alias_file_path)
if not os.path.exists(alias_pid_path) :
    open(alias_pid_path,"w").close()

alias_pid = open(alias_pid_path,"r")


for line in alias_pid :
    txt = line.strip('\n')
    if len(txt) > 0 :
        print("kill %s" % txt )
        os.system("kill %s" % txt)          
alias_pid.close()
alias_pid = open(alias_pid_path,"w+")

for line in alias_file :
    txt = line.strip('\n')
    if len(txt) > 0 :
        print("publishing : << %s >>" % txt)
        process = Popen([command, txt])
        alias_pid.write("%s\n" % str(process.pid))    
alias_pid.close()

print("done")

它绝不是python编程的巅峰之作,所以请随意在你认为合适的地方进行改进。

用法

如果我们的主机名是“server”且avahi-hostname是“server.local”,那么我们可以用你的额外主机名填写/etc/avahi/aliases文本文件,如下所示:

deluge.server.local
username.server.local
accounts.server.local
something-else.server.local
another.hostname.home

(但实际上,我很确定你可以在那里拥有任何主机名,只要你确定它不存在于网络上,这就是为什么我只是创建普通avahi主机名的“子域名”)

然后我们运行:

sudo avahi-publish-aliases

我设置这个的主要原因是为了更容易模拟django&amp; amp;我的笔记本电脑上的drupal网站开发。

注意事项

我唯一的失望是,Bonjour / Avahi的Windows实现不支持此实现宣布的别名,它只会看到通常宣布的主要avahi主机名(即上面示例中的server.local)。

答案 1 :(得分:5)

看起来airtonix实现了这一点,并在https://github.com/airtonix/avahi-aliases

上提供了它

我在Ubuntu 11.04上测试过的最近更新的fork是https://github.com/hmalphettes/avahi-aliases

答案 2 :(得分:4)

您可以使用Avahi API注册其他记录。 Avahi wiki上的This example演示了如何在Python中发布其他CNAME(别名)记录。

答案 3 :(得分:4)

我放弃了当时不可能的事情,因为我没有重新审视这个问题。

我目前的解决方案是费力地将每个感兴趣的子域添加到本地计算机上的hosts文件中。

答案 4 :(得分:0)

我知道这是旧的,但更好的解决方案是dnsmasq

这可以简单地完成......通过arguments / config ...

  

为指定域中的所有主机返回ipaddr。

     

-A, --address=/<domain>/<ipaddr>

  

address=/yourdomain.com/10.0.1.100

瞧!