LINUX-BG   Адрес : http://www.linux-bg.org
DNSmasq - 2 в 1 (DNS + DHCP)
От: Иво Гелов
Публикувана на: 26-01-2008
Адрес на статията: http://www.linux-bg.org/cgi-bin/y/index.pl?page=article&id=programs&key=400454408
Сървърът, който администрирам предоставя DNS и DHCP услуги на потребителите. Разбира се, това става с помощта на
BIND (NAMED) и DHCPD - както при почти всички Linux дистрибуции, те се класика. BIND играе ролята на кеширащ DNS
сървър, за да намаля натоварването към доставчика си - а също и обработва локалните заявки от NetBIOS (WINS).
DHCPD от една страна предоставя удобство на потребителите, които са с лаптоп и често се местят от мрежа в мрежа,
а от друга осигурява постоянно съответствие между раздаваните IP адреси и познатите му MAC-адреси (като позволява
работата и на потребители с непознат MAC-адрес). Така за нуждите на различни статистики се осигурява постоянство на
IP-адресите на потребителите.
Така описаната конфигурация работи безпроблемно, но поради текучество и други причини се налага все по-често да
правя промени по настройките както на DHCPD, така и на BIND - а пък така и не успях да подкарам DDNS (Dynamis DNS,
при който DHCPD информира BIND по RNDC протокол за новопоявили се потребители, така че да бъдат добавени в DNS
листата). Поразрових се из GOOGLE и попаднах на 2 интересни неща:

1. MyDNS (http://mydns.bboy.net/) - малък DNS сървър, написан от нулата, който вместо от текстов файл взима DNS
записите си от SQL база данни (MySQL или PostgreSQL). Не е рекурсивен - това означава, че ако търсеният запис го
няма в базата данни, няма да бъде направено запитване до DNS сървъра на доставчика, или пък към ROOT сървърите,
а ще се върне съобщение, че няма такъв адрес. Така че явно приложението му е само за големи организации с голям
брой локални адреси, които често се променят. Всъщност, може да се използва в комбинация с DNScache
(http://cr.yp.to/djbdns/dnscache.html) - това е рекурсивен кеширащ DNS клиент, част от пакета "djbdns" (по-известен
като TinyDNS) на професор D. J. Bernstein (автор на Qmail) - на адрес http://cr.yp.to/djbdns.html
Струва си да бъде разгледан, и вероятно дори инсталиран. Лично на мен точно в този момент ми липсва достатъчно време,
но определено бих посъветвал всички, които имат сериозни интереси в мрежовото администриране да погледнат този
проект.

2. DNSmasq (http://www.thekelleys.org.uk/dnsmasq/do...) - много апетитна комбинация от типа 2-в-1 (DNS + DHCP).
Използва се в някои фирмуери (firmware) за специализирани (dedicated или embedded) рутери - например в OpenWRT
(http://openwrt.org/). Това е кеширащ рекурсивен (по-скоро термина е forwarder, защото препраща заявките към
DNS сървъра на доставчика, а не директно към ROOT DNS сървърите) DNS сървър с модул за DHCP/BOOTP - тясно интегрирани
един с друг.

Реших да си направя "upgrade" - да премина от BIND + DHCPD към DNSmasq. Хем по-малък и по-бърз сървър, хем DDNS ще
си се прави автоматично :-) Речено-сторено - свалих си последната версия 2.40 и започнах да разучавам параметрите
в конфигурацията. Написах си елементарен скрипт на PHP, с който през WEB-интерфейс да обновявам списъка с IP адреси
и тяхното съответствие с MAC-адреси и имена на хостове. Първо ще покажа моят конфигурационен файл, а след това ще
го обясня заедно с 1-2 подводни камъка, на които се натъкнах.

addn-hosts = /etc/dnsmasq/dns_host
expand-hosts
log-facility = /var/log/dnsmasq.log
group = nobody
listen-address = 127.0.0.1
listen-address = 192.168.0.1
listen-address = 192.168.2.1
bind-interfaces
localise-queries
bogus-priv
filterwin2k
no-resolv
no-poll
domain-needed
server = xx.xx.xx.xx
cache-size = 9000
dhcp-range=net0,192.168.0.2,192.168.0.100,10h
dhcp-range=net2,192.168.2.150,192.168.2.220,10h
#dhcp-hostsfile = /etc/dnsmasq/dhcp_host
read-ethers
domain = my-domain.com
dhcp-ignore-names
dhcp-authoritative
#log-dhcp

# This tells M$ to release their lease when they shutdown
dhcp-option=vendor:MSFT,2,1i
# Router
dhcp-option=net0,3,192.168.0.1
dhcp-option=net2,3,192.168.2.1
# DNS
dhcp-option=net0,6,192.168.0.1
dhcp-option=net2,6,192.168.2.1
# WINS server
dhcp-option=net0,44,192.168.0.1
dhcp-option=net2,44,192.168.2.1
# NetBIOS over TCP/IP Datagram Distribution Server Option
dhcp-option=net0,45,192.168.0.1
dhcp-option=net2,45,192.168.2.1
# Node type - P (Point-to-Point UDP, not generate and not accept broadcasts)
dhcp-option=net0,46,2
dhcp-option=net2,46,2
# NetBIOS over TCP/IP Scope Option (probably domain - they usually leave empty)
dhcp-option=net0,47
dhcp-option=net2,47

ОПИСАНИЕ

addn-hosts = /etc/dnsmasq/dns_host - добавя съдържанието на този файл към информацията, прочетена от "/etc/hosts".
Този файл (/etc/dnsmasq/dns_host) се генерира чрез моя PHP скрипт и съдържа DNS информация за локалните потребители.
Форматът му е същия както на "/etc/hosts"

expand-hosts - автоматично добавя домейн-име към имената от "/etc/hosts" и файла от "addn-hosts", ако липсва

group = nobody - групата, с чиито права да се стартира DNSmasq. По дефолт е "dip", което мен не ме устройва

listen-address - изброяват се адресите на сървъра, през които ще получава заявки. По дефолт слухти на всички
достъпни интерфейси (0.0.0.0)

bind-interfaces - по дефолт, дори ако се укаже "listen-address", DNSmasq пак слухти на 0.0.0.0, и игнорира
заявките, които не са от изброените интерфейси. Това е "удобство", така че ако интерфейсите динамично си сменят
адресите, това не пречи на работата на DNSmasq (при мен няма такава опасност, затова и bind-interfaces)

localise-queries - ако едно и също DNS име е обявено за няколко IP адреса в "/etc/hosts" (или "addn-hosts"),
DNSmasq се опитва да върне само адреса, който отговаря на същата подмрежа, от която идва запитването

bogus-priv - всички обратни запитвания (тоест от IP към домейн име) за частни адреси (10, 172.16-31, 192.168) се
обработват само локално без да се препращат към DNS сървъра на доставчика (ако ги няма описани в "/etc/hosts" се
връща съобщение, че няма такъв адрес)

filterwin2k - елиминира LDAP заявките (тъй като потребителите ми не са в Windows-domain, а в Workgroup-и)

no-resolv - не взима автоматично адресите за DNS сървърите на Интернет доставчика от "/etc/resolv.conf", а
само изрично указаните в конфигурационния файл

no-poll - не проверява периодично "/etc/resolv.conf" за промени (приложимо само при PPP и PPPoE)

domain-needed - забранява да се препращат към DNS сървъра на доставчика заявки за имена, които не съдържат точка "."
Това са локални имена - ако ги няма описани в "/etc/hosts" или настройките на DHCP модула, се връща грешка "Not found"

server = xx.xx.xx.xx - това е адресът на DNS сървъра на Интернет доставчика

cache-size = 9000 - колко DNS отговора от сървъра на доставчика да се кешират (максимума е установен на 10000
в изходния код на DNSmasq)

dhcp-range=net0,192.168.0.2,192.168.0.100,10h - тази команда разрешава обработването на DHCP заявки за съответната
подмрежа, дава й име (net0) което може да се използва след това в "dhcp-option" и установява времетраенето по подразбиране
на раздаваните IP адреси да бъде 10 часа

#dhcp-hostsfile = /etc/dnsmasq/dhcp_host - това беше основния препъни-камък. Този файл се генерираше от моя PHP
скрипт, в него се описваше съответсвието между IP и MAC адреси и се задаваха имена на хостовете. DNSmasq упорито отказва
да признае това, и при получаване на заявка DHCPREQUEST с IP, което е описано в този файл - връща отговор DHCPNAK със
съобщение "address reserved", след което клиента изпраща отново DHCPREQUEST (този път без IP) и получава IP-адрес - само
че НЕ ТОЗИ, който съм описал във файла, а някой свободен от обхвата на "dhcp-range". Борих се няколко дни, рових се
в изходния код - и не можах да схвана защо е направено така. В документацията на DNSmasq е указано, че ако в "dhcp-range"
вместо краен адрес се напише ключовата дума "static", той престава да раздава динамично адреси - тоест IP адрес ще получат
само клиентите, чиито MAC адреси са описани в "dhcp-hostsfile" или "dhcp-host" директиви. Когато обаче го изпробвах,
получих грешка за DHCPDISCOVER "no address available in the range". Накрая, абсолютно случайно, реших да изпробвам какво
ще стане с директивата "read-ethers". Тя е подобна на "dhcp-hostsfile" - прочита от "/etc/ethers" съответствието между
MAC и IP адресите, но не позволява никакви други опции (например времетраене на IP адреса, идентификатор на мрежата, на
хоста и т.н.). Форматът на файла е MAC-адрес, 1 или повече шпации (или табулации) и след това или IP-адрес, или име на хоста
(но не и двете). И о, чудо ! Всичко се получи - DNSmasq започна да раздава точно посочените IP адреси за всеки MAC адрес.
Не успях да открия никаква информация в GOOGLE за тази или подобна ситуация, скоро ще пиша до автора на DNSmasq, и при
нужда ще напиша коментар към статията.

read-ethers - както написах по-горе, това решава проблема за статичното привързване на MAC към IP адрес. В моя случай
"/etc/ethers" е символична връзка към "/etc/dnsmasq/ethers", който се генерира от моя PHP скрипт

domain = my-domain.com - фиктивен локален домейн, може да си измислите собствен

dhcp-ignore-names - винаги игнорира името на хоста, което той сам предлага в DHCP заявката, и го регистрира в DNS
списъка с името, което е зададено в конфигурационните файлове ("/etc/hosts", "/etc/ethers" или "dhcp-hostsfile")

dhcp-authoritative - използва се, когато DNSmasq със сигурност е единствения DHCP сървър в мрежата. Тогава той вече
не игнорира заявки, които не е раздал той самия. По този начин ако се развали файла с описание на раздадените адреси
(/var/lib/misc/dnsmasq.leases) - той се създава динамично по информацията от клиентските заявки. Аз лично го използвам, за
да намаля времето за time-out при преход от DHCPD към DNSmasq (или пък ако в мрежата се включи лаптоп, който има lease от
друга DHCP сървър в друга мрежа)

#log-dhcp - указва на DNSmasq да записва информация за DHCP заявките и отговорите в лог-файла (log-queries се използва
да записва информация за DNS заявките и отговорите)

dhcp-option - използват се за указване на опции към цяла група от клиенти. Форматът е
"dhcp-option=net-id,option-id,option-value". NET-ID трябва да съвпада с този, зададен в "dhcp-range" или "dhcp-host", това е
наименованието на групата клиенти. Опциите са описани в RFC2132 (http://www.faqs.org/rfcs/rfc2132.html), точка 3. Най-често
използваните са като тези в моя конфигурационен файл (от коментарите се вижда предназначението им)

Макар и описано най-накрая, всъщност това е нещото, което трябва да проверите най-напред - става дума за настройките на
защитната стена (IPtables). DHCPD е така написан, че в повечето случаи успява да заобиколи IPtables вътре в самото ядро.
Така че, дори DHCPD да е работил във вашата мрежа - това не значи, че и DNSmasq ще заработи. По-конкретно, трява да сте
уверени, че за всички интерфейси, на които слухти DNSmasq е разрешено получаването на пакети с източник 0.0.0.0 и
получател 255.255.255.255. Иначе ще се чудите защо DHCPD си раздава адреси с кеф, а пък DNSmasq сякаш изобщо не усеща
заявките :-)

Документацията на DNSmasq е доста пестелива, а и в мейлинг-листите не забелязах достатъчно специалисти - така че пускането
му в действие е едно малко предизвикателство. Но пък според мен за не особено натоварени мрежи успешно може да замени
BIND и DHCPD.

Искаше ми се да публикувам и PHP скрипта за елементарния WEB интерфейс, но може би е по-добре направо да дам линк. Сложил
съм го на безплатен сървър - така че след 30-ина дни линка ще бъде неактивен. Но всеки желаещ може да ми прати PM с емайла
си, и ще му го изпратя. А линкът е
http://rapidshare.com/files/86787611/dn...
http://www.zshare.net/download/68957842...
http://www.uploading.com/files/G92VLP4M...


Таблиците в базата данни имат следния формат:

DROP TABLE IF EXISTS `host`;

CREATE TABLE `host` (
 `NET` tinyint(3) unsigned NOT NULL default '0',
 `IP` tinyint(3) unsigned NOT NULL default '0',
 `MAC` varchar(12) NOT NULL,
 `PERSON` varchar(24) NOT NULL,
 PRIMARY KEY  (`NET`,`IP`),
 UNIQUE KEY `MAC` (`MAC`),
 UNIQUE KEY `PERSON` (`PERSON`)
) ENGINE=MyISAM /*!40100 DEFAULT CHARSET=cp1251*/;

DROP TABLE IF EXISTS `mreza`;

CREATE TABLE `mreza` (
 `ID` tinyint(3) unsigned NOT NULL default '0',
 `MREZA` varchar(20) NOT NULL,
 PRIMARY KEY  (`MREZA`,`ID`)
) ENGINE=MyISAM /*!40100 DEFAULT CHARSET=cp1251*/;

<< | >>

Авторите на сайта, както и техните сътрудници запазват авторските права върху собствените си материали публикувани тук, но те са copyleft т.е. могат свободно да бъдат копирани и разпространявани с изискването изрично да се упоменава името на автора, както и да се публикува на видно място, че те са взети от оригиналния им URL-адрес на този сървър (http://www.linux-bg.org). Авторските права на преводните материали принадлежат на техните автори. Ако с публикуването тук на някакъв материал неволно са нарушени нечии права - след констатирането на този факт материалът ще бъде свален.

All trademarks, logos and copyrights mentioned on this site are the property of their respective owners.
Linux is copyright by Linus Torvalds.
© Линукс за българи ЕООД 2007
© Slavei Karadjov 1999 - 2006

All rights reserved.

Изпълнението отне: 0 wallclock secs ( 0.15 usr + 0.02 sys = 0.17 CPU)