How to route all subdomains to a single host using mDNS?

后端 未结 5 1017
清歌不尽
清歌不尽 2021-01-31 04:27

I have a development webserver hosting as \"myhost.local\" which is found using Bonjour/mDNS. The server is running avahi-daemon.

The webserver also wants to handle any

5条回答
  •  深忆病人
    2021-01-31 04:54

    I've solved this as best as I can with the small amount of time I assigned to this task.

    But unfortunately I do not think the windows implementation of avahi/msdns/bonjour supports aliases (correct me if I am wrong with examples of how to support this).

    What i did was start with the example python script provided on the avahi website :

    Create : /usr/bin/avahi-announce-alias

    Make it executable & Fill it with

    #! /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"
    

    This script handles the announcement of each individual alias, and will remain running until you kill it. (because of this, we need to create another script which I've shown below)

    Create text file /etc/avahi/aliases

    This we use to store aliases to this machine one per line

    Create directory /etc/avahi/aliases.d/

    I haven't actually made use of this in any of the scripts i show here yet, but for those enterprising individuals out there, you can see what needs to be done.

    The idea is that you can group aliases into separate text files (which will make more sense when you deal with virtual hosts in apache), this is something many daemon applications on *nix already provide (apache and apt are just two examples).

    Create /usr/bin/avahi-announce-aliases

    Make it executable and fill it with

    #!/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")
    

    It is by no means meant to be the pinnacle of python programming, so feel free to make improvements where you see fit.

    Usage

    If our hostname was "server" and the avahi-hostname was "server.local", then we could fill up the /etc/avahi/aliases text file with your extra hostnames like so :

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

    (but really, I'm pretty sure you could have any hostname in there providing you made sure it did not already exist on the network, which is why i just create 'subdomains' of the normal avahi hostname)

    Then we run :

    sudo avahi-publish-aliases

    My main reason for setting this up was to facilitate easier simulation of django & drupal website development on my laptop.

    Caveats

    My only disappointment is that the windows implementation of Bonjour/Avahi does not support the aliases that this implementation announces, it will only see the main avahi hostname normally announced (ie server.local in our example above).

提交回复
热议问题