代码之家  ›  专栏  ›  技术社区  ›  John Mee

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

  •  22
  • John Mee  · 技术社区  · 15 年前

    我有一个名为“myhost.local”的开发Web服务器,可以使用Bonjour/MDN找到它。服务器正在运行avahi守护进程。

    Web服务器还希望处理其自身的任何子域。例如“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发布主机名。

    不,他不能。因为他想定义一个别名,而不是一个新的 主机名。也就是说,他只想注册A RR,不想注册反向PTR RR。但是 如果你在/etc/avahi/hosts中插入一些东西,那么它会同时注册两个, 如果ptr rr是非唯一的,则检测到冲突,这将是 别名的大小写。

    5 回复  |  直到 10 年前
        1
  •  12
  •   Nurpax    14 年前

    我已经用分配给这个任务的少量时间尽可能地解决了这个问题。

    但不幸的是,我不认为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主机名是“server.local”,那么我们可以填充 /etc/avahi/别名 带有额外主机名的文本文件,如下所示:

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

    (但事实上,我很确定如果网络上没有主机名,您可以在其中使用任何主机名,这就是为什么我只创建普通Avahi主机名的“子域”)。

    然后我们运行:

    sudo avahi-publish-aliases

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

    告诫

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

        2
  •  5
  •   Robert J Berger    13 年前

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

    我在Ubuntu 11.04上测试过的更新版fork位于 https://github.com/hmalphettes/avahi-aliases

        3
  •  4
  •   andrewtj    15 年前

    您可以使用avahi API注册其他记录。 This example 在avahi上,wiki演示了如何在python中发布额外的cname(别名)记录。

        4
  •  4
  •   John Mee    15 年前

    当时我尽可能地放弃了,从此以后我再也没有重新考虑过这个问题。

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

        5
  •  0
  •   Alex Gray    10 年前

    我知道这很古老,但更好的解决办法是 dnsmasq .

    这可以很简单地完成…通过参数/配置…

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

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

    γ射线

    address=/yourdomain.com/10.0.1.100

    哇!