Как перенаправить все субдомены на один хост, используя mDNS?
У меня есть хостинг для разработки веб-сервера под названием "myhost.local", который можно найти с помощью Bonjour/mDNS. На сервере запущен avahi-демон.
Веб-сервер также хочет обрабатывать любые дочерние домены. Например, "cat.myhost.local" и "dog.myhost.local" и "guppy.myhost.local".
Учитывая, что myhost.local находится на динамическом IP-адресе от dhcp, есть ли еще способ направить все запросы для поддоменов в 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 не является уникальным, что было бы в случае псевдонима.
6 ответов
Я отказался от этого как невозможного в то время, и с тех пор я не пересматривал проблему.
Мое текущее решение состоит в том, чтобы кропотливо добавить каждый интересующий поддомен в файл hosts на локальной машине.
Я решил это как можно лучше с небольшим количеством времени, отведенного для этой задачи.
Но, к сожалению, я не думаю, что реализация windows avahi/msdns/bonjour поддерживает псевдонимы (поправьте меня, если я ошибаюсь примерами того, как это поддерживать).
Я начал с примера скрипта Python, представленного на веб-сайте avahi:
Создайте: /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-host было "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 & drupal на моем ноутбуке.
Предостережения
Мое единственное разочарование заключается в том, что реализация Bonjour/Avahi для Windows не поддерживает псевдонимы, которые объявляет эта реализация, она будет видеть только основное объявленное имя хоста avahi (т.е. server.local в нашем примере выше).
Похоже, airtonix реализовал это и сделал его доступным по адресу https://github.com/airtonix/avahi-aliases
Более свежий обновленный форк, который я тестировал на Ubuntu 11.04, находится по адресу https://github.com/hmalphettes/avahi-aliases
Вы можете зарегистрировать дополнительные записи, используя API Avahi. Этот пример на вики Avahi демонстрирует, как публиковать дополнительные записи CNAME (псевдонимы) в Python.
Мне это тоже понадобилось и после долгих поисков я понял, что mDNS — довольно хорошо поддерживаемый протокол и, следовательно, неудивительно, что существуетnpm
пакет для него: multicast-dns. При этом реализовать желаемое поведение тривиально:
const os = require('os');
const mdns = require('multicast-dns')();
const IP = process.argv[2];
if (!IP) {
console.error('You need to provide an IP as argument');
process.exit(1);
}
const hostname = os.hostname();
mdns.on('query', function(query) {
const name = query.questions[0].name;
console.log('got a query, name:', name);
if (name.endsWith(`${hostname}.local`)) {
console.log('responding', name);
mdns.respond({
answers: [{
name,
type: 'A',
ttl: 300,
data: IP
}]
});
}
});
Этот скрипт просто слушает запросы mDNS, проверяет, заканчиваются ли они на наше локальное имя хоста, и если да, то просто отвечает тем же именем, что и в запросе.
Сохранить какmdns.js
и запустите:
npm i multicast-dns
node mdns.js SOME-IP
После этого вы можете использоватьavahi-resolve -n foo-bar-the-great.myhost.local
(еслиmyhost
это ваше имя хоста), и он должен соответствовать вашему IP-адресу по желанию. Конечно, если ваша машина правильно настроена на использование mDNS при разрешении хостов, тоping foo-bar-the-great.myhost.local
будет работать так же, как и любое другое имя субдомена, которое вы придумаете.
Я знаю, что это старый, но лучшее решение было бы dnsmasq.
Это можно сделать так просто... через аргументы /config...
Вернуть ipaddr для всех хостов в указанных доменах.
-A, --address=/<domain>/<ipaddr>
address=/yourdomain.com/10.0.1.100
Вуаля!