от Hapkoc(5-05-2006)

рейтинг (11)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване

Работа с изгледи в BIND9

Copyright (c) 2006 Александър Илиев

Лиценз: CC Attribution-ShareAlike


Мотивация и аудитория
Проблемът
Решението
По-простото и елегантно решение
Реалното приложение на изгледите
Обработка на заявки от локалната машина


Мотивация и аудитория

Мотивацията за статията е, че напоследък няколко човека задават един и същи въпрос във форума на linux-bg.org, а отговора един от възможните отговори на този въпрос е именно в разглежданата тема.

Статията е предназначена за хора, които са наясно с основните термини в областта на DNS и са се занимавали с конфигуриране на BIND.

Проблемът

На все повече места в последно време имаме следната ситуация - малка (фирмена или домашна) мрежа, обикновено използваща IP адреси от RFC1918 имаща входно/изходна точка към интернет в лицето на машина, която играе ролята на маршрутизатор, DNS сървър, огнена стена и т.н.

DNS сървърът може да обслужва заявки само от вътрешната мрежа, при условие, че на него не се съхранява зона, за която същия този сървър е отговорен (authoritative [1]). Ако сървъра обслужва заявки по зона, за която е отговорен, тогава има проблем, т.к. обикновено не е желателно сървъра да обслужва рекурсивно заявки от хостове извън локалната мрежа.

Решението

Или по-точно едно от възможните решения на този проблем са т.нар. изгледи (views) в BIND9. Изгледите определят различни начини на обслужване на заявките в зависимост от източника на заявката и адреса, към който е насочена.

За нагледност ще използваме следната схема:

DNS сървър, обслужващ рекурсивно мрежата 192.168.1.0/24 с адрес от тази мрежа 192.168.1.1 и адрес към интернет доставчик 10.0.0.1 (адресът е с цел илюстриране на примера и фактът, че е от адресното пространство, дефинирано в RFC1918 няма отношение).

Имаме домейн "some.domain", за който въпросия сървър е първичен отговорен сървър (т.е. зоната на домейна се съхранява на този сървър и се редактира върху него). Искаме сървъра да обработва в рекурсивен режим заявки от мрежата 192.168.1.0/24, а за всички останали да отказва извършването на рекурсия.

Ще дефинираме два изгледа - един за заявки от 192.168.1.0/24 и един за всички останали. Това става чрез директивата view в named.conf. За всеки изглед се задава име и клас, който може да се пропусне, като в такъв случай се приема класа IN по подразбиране. Ключовите директиви при използване на изгледи са match-clients и match-destinations. Чрез тях дефинираме какви комбинации от адрес на източника и адрес на получателя в DNS заявките от кой изглед ще се обслужват. И двете директиви приемат за параметри списък от address_match_element. В примера по-долу ще използваме за удобство acl, който сме дефинирали за вътрешната мрежа.

Извадката от named.conf илюстрира дефинирането на двата изгледа - local и public. Изгледът local ще обслужва заявки за локалната мрежа в рекурсивен режим, а изгледът public ще обслужва нерекурсивно заявките към домейна some.domain.

------ named.conf ------

 acl local { 192.168.1.0/24; };
 
 options {
     listen-on port 53 { 127.0.0.1; 192.168.1.1; 10.0.0.1; }; 
 };
 
 view "local" {
     match-clients { local; };
     match-destinations { 192.168.1.1; };
 
     recursion yes;
 
     allow-query { local; };
 
     zone "." {
         type hint;
         file "standard/root.hint";
     };
 
     zone "com" { type delegation-only; };
     zone "net" { type delegation-only; };
 
     zone "localhost" {
         type master;
         file "standard/localhost";
         allow-transfer { localhost; };
     };
 
     zone "127.in-addr.arpa" {
         type master;
         file "standard/loopback";
         allow-transfer { localhost; };
     }; 
 };
 
 view "public" {
     match-clients { any; };
     match-destinations { 10.0.0.1; };
 
     recursion no;
 
     allow-query { any; };
 
     zone "some.domain" {
         type master;
         file "public/master/some.domain";
         ...
     };
 };
 


(забележка: пропуснати са някой директиви от named.conf като controls и logging)

При такава конфигурация named слуша на двата адреса - 192.168.1.1 и 10.0.0.1. Какво се случва при заявка към сървъра? Първо се проверява адреса на изпращача на заявката (ip source address) и адреса, до който е изпратена (ip destination address) и тези адреси се сравняват съответно с адресите, описани в match-clients и match-destinations директивите на всеки изглед. Използва се първия изглед, за който адресите на изпращача и получателя в заявката са в рамките на списъка от address_match_elements в match-clients и match-destinations директивите, което значи, че е от съществено значение в какъв ред ще бъдат описани изгледите в named.conf.

И така - ако се получи заявка от хост в мрежата 192.168.1.0/24 адресирана до 192.168.1.1, то тя ще бъде обслужена от изгледа local, в който е разрешено изпълнението на рекурсивни заявки. Ако заявката е от източник с адрес, извън локалната мрежа и е адресирана до 10.0.0.1, то тя ще се обслужи от изгледа public.

Има още една директива, свързана с изгледите - match-recursive-only. Чрез нея може да се дефинира изглед, който да обслужва само рекурсивни заявки.


По-простото е елегантно решение

Както подсказа Георги Александров, обаче, изгледите далеч не са най-доброто решение в случая. Много по-удачно е за такава конфигурация да се приложи следното - в опциите на BIND (options в named.conf) се добавя ограничение за изпълнение на рекурсивни заявки само от локалната мрежа. Добре е също да се разрешат заявките към сървъра само от локалната мрежа в options, и за всяка зона, за която сървъра е отговорен да се разрешат заявките отвсякъде:

 ------ named.conf ------
 options {
     ...
 
     allow-recursion { local; };
     allow-query { local; };
 };
 
 ...
 
 zone "some.domain" {
     type master;
     allow-query { any; };
     ...
 };
 

В противен случай хостове извън локалната мрежа ще могат да получават отговори на заявки, за които не се изисква рекурсия, като например кеширани записи, които обаче са извън зоните, за които отговаря BIND.

Реалното приложение на изгледите

Изгледите, разбира се, могат да се използват по посочения по-горе начин, но това не е основната им функция.

Да кажем, че в домейна "some.domain" от горния пример има описани три хоста - www, mail и pop. Приемаме, че в примера единствения публичен адрес на разположение е 10.0.0.1 (и пак се абстрахираме от факта, че той съвсем не е публичен :) ). Тези имена от зоната "some.domain" в изгледа "public" ще изглеждат горе-долу така:

 ------ public/some.domain ------
 $ORIGIN some.domain.
 
 www     IN      A   10.0.0.1
 mail    IN      A   10.0.0.1
 pop     IN      A   10.0.0.1
 

За нашия пример ще приемем, че на машината, която се явява DNS сървър и маршрутизатор, са пренасочени tcp/udp портовете на съответните услуги към машини от вътрешната мрежа, например:

  10.0.0.1:80  -> 192.168.1.5:80
  10.0.0.1:25  -> 192.168.1.6:25
  10.0.0.1:101 -> 192.168.1.8:101
 

Ако искаме от вътрешната мрежа да ползваме тези услуги със същите имена то изгледите са (пак не единственото) решение. Дефинираме отново изгледите "local" и "public", като този път и двата включват домейна "some.domain".

В "local" ще е нещо от рода на:

 ------ local/some.domain ------
 $ORIGIN some.domain.
 
 www     IN      A   192.168.1.5
 mail    IN      A   192.168.1.6
 pop     IN      A   192.168.1.8
 ------ local/some.domain ------
 

В named.conf просто добавяме зоната "some.domain" в изгледа "local" като master и посочваме, че файлът с описанието на зоната е local/some.domain. По този начин клиентите от локалната мрежа ще получават www.some.domain отговор 192.168.1.5, докато клиентите извън локалната мрежа ще получават 10.0.0.1.


Обработка на заявки от локалната машина

Вероятно е коректно конфигурацията на изгледите да се промени малко, така че да позволява обработка на заявки от локалната машина (тази, на която работи named). Това става по следния начин:

 ------ named.conf ------
 ...
 
 view "local" {
     match-clients { local; 127.0.0.1; };
     match-destinations { 192.168.1.1; 127.0.0.1; };
     
     ...
 };
 
 ...
 


Друг вариант е, вместо да се добавя в match-clients директивата, 127.0.0.1 да се добави в acl local списъка. Доколкото целта на статията е да покаже как може да се реализира такава схема в малка мрежа, то и двата варианта са еднакво удачни според мен. При по-сложни конфигурации може би първия е за предпочитане, при условие че трябва да се прави някакво разграничение между локалната машина и клиентите от локалната мрежа, въпреки че точно в момента не ми хрумва такъв сценарий.

Независимо кой от двата варианта се приложи, заявките от localhost към localhost ще се обработват по същия начин като заявките от локалната мрежа (в случая - рекурсивно).

Тази промяна може да не се прилага, при условие, че в конфигурацията на локалния resolver фигурира IP адреса от локалната мрежа, а не 127.0.0.1:
 $ cat /etc/resolv.conf
 nameserver 192.168.1.1
 

Все пак е за предпочитане заявките от 127.0.0.1 да се разрешат по посочения начин, дори и при така конфигуриран resolver.


[1] Ако някой има по-добра идея за превод да казва


<< Модулна поддръжка на XFS за RHEL и дериватите му | BIND9 в многонодов режим на работа >>