Получаем DNS записи

altНа работе у меня периодически возникает необходимость в получении различных DNS записей. Например, при поднятии корпоративного почтовика мне пришлось вдоволь пообщаться и познакомиться с нюансами DNS. После редактирования/создания DNS-записей нужно проверять, обновились ли записи на dns-сервере или нет. Это совершенно несложная операция и в составе операционных систем имеются соответствующие консольные тулзы, но поскольку пользоваться ими приходится не часто, я стал забывать параметры, которые нужно им передавать. Я понимаю, что в таких ситуациях недолго и браузер с гуглом дернуть, но мне захотелось написать простенькую тулзу с user friendly интерфейсом. Об этом подвиге и пойдет речь дальше.

Немного предыстории

Я уже сказал, что получить содержание определенных dns-записей вполне реально при помощи имеющихся в операционной системе консольных утилит. Если ты пользуешься Windows, то для получения MX записи (или любой другой) определенного домена достаточно воспользоваться консольной утилитой nslookup:

nslookup –type=mx vr-online.ru



Рисунок 1. Результат выполнения nslookup
Результат выполнения команды я привел на рисунке 1. Как видно из содержания рисунка, почта vr-online доставляется через сервера Google. Для того чтобы получить другой тип записи (например, A) достаточно изменить параметр type:

nslookup –type=A vr-online.ru

Остальные dns-записи получают аналогичным образом.
Если ты предпочитаешь пользоваться unix-like системами, то, конечно же, никакого nslookup’а там нет. Зато в их составе есть утилита host. Пользоваться ей ничуть не сложнее, чем nslookup’ом в Windows:

host –t mx vr-online.ru

Почему эти инструменты мне не нравятся?
Я уже говорил, но повторюсь. В первую очередь меня не устраивает, что при необходимости получения dns-записи требуется запускать терминал/командный интерпретатор и вводить команду. Не знаю почему, но, я постоянно забываю дописывать к nslookup параметр type. Каждый раз приходиться лезть в хелп или в инет. Чтобы избавиться от этих рутинных действий я потратил пять минут времени и написал на Delphi небольшую утилиту. С тех пор, для получения информации о DNS-записях я пользуюсь сугубо ей.

Пять минут – это реально пять минут

Моя фраза, что для создания программы потребуется не больше пяти минут – ничуть не преувеличена. В составе Delphi идет прекрасная библиотека компонентов Indy. Она содержит кучу компонент для работы с различными сетевыми службами: gopher, ftp, irc, dns и т.д. В рамках сегодняшней статьи нам предстоит воспользоваться компонентом для взаимодействия с dns серверами.

Дизайним форму – 2 минуты

Начнем делать наш простенький проект с создания главной формы окна. Я не стал делать чего-то сверх красивого, а обошелся самым простым вариантом (см. рисунок 2).



Рисунок 2. Форма будущей программы
На форму я бросил два компонента TEdit. В первый будем вбивать домен, записи которого требуется получить. Во второй, адрес DNS сервера, к которому должна подключаться наша программа и отправлять запросы на получения определенных записей.

Поскольку DNS-записи бывают разными, нам требуется предоставить пользователю право выбора. Хочет он получить MX запись – пусть себе получает. Так называемое право выбора я реализовал путем добавления компонента TComboBox. В его свойство Items я сразу же занес типы DNS-записей. Для своего примера я указал: MX, A, SOA и NS. Ты можешь расширить этот список (предварительно посмотри типы записей, с которыми умеет работать соответствующий компонент из библиотеки Indy), но мне достаточно и этих.

Результаты выполнения запроса я буду выводить в RichBox. Ты можешь поступить точно также или же воспользоваться тем компонентом, который тебе больше нравится.

Ну и теперь самое главное – компонент, при помощи которого мы и будем получать DNS-записи. В библиотеке Indy за работу с DNS-серверами отвечает компонент TIdDNS Resolver.

Немного про TIdDNSResolver

Перед тем как начать писать код, немного познакомимся с компонентом TIdDNSResolver. Все-таки он будет выполнять главную роль. Итак, для начала рассмотрим свойства компонента, а потом перейдем к методам.

Свойства

AllowRecursiveQueries:boolean; — свойство определяет, должен ли сервер продолжать обрабатывать запросы клиента, которые требуют получения записей с другого dns-сервера. По умолчанию значение установлено в true.

QueryRecords:TqueryType; — в этом свойстве определяется список записей, информацию по которым необходимо получить. В качестве записей могут быть:

— qtA – адрес хоста;
— qtNS – авторитетный name сервер;
— qtMD – конечные адрес, по которому нужно доставить почту (mail destination). В настоящее время MD записи не применяются. Используй MX;
— qtMF – отправитель почты. В настоящее время опять же не используется. Применяется MX;
— qtName – каноническая запись имени (псевдоним);
— qtSOA – начальная запись зоны. Она указывает сервер, на котором храниться эталонная информация о домене;
— qtMB – почтовый ящик доменного имени;
— qtMG – член почтовой группы;
— qtMR – запись указывает почтовый ящик, соответствующий другому почтовому ящику.
— qtWKS – запись Well-known Service содержит перечень распространенных служб TCP/IP, поддерживаемых определенным протоколом (TCP/UDP) на конкретном IP адресе.
— qtPTR – указатель на доменное имя;
— qtHINFO – информация о хосте;
— qtMINFO – определяет почтовый ящик стороны, ответственный за почтовый ящик или список рассылки;
— qtMX – запись указывает почтовый сервер, принимающий почту для текущей зоны.
— qtTXT – дополнительная информация о зоне;
— qtSTAR – все типы записей;

QueryResult:TQueryResult; — в данном свойстве содержится коллекция с результатами выполнения запроса к dns-серверу.

Host:string; — адрес dns-сервера с которым будет устанавливаться соединение;

Методы

procedure Resolve (ADomain:string); — метод выполняет запрос на получение данных о выбранных dns-записях с dns-сервера для домена, переданного в качестве параметра.

Собственно говоря, это единственный метод, который нас интересует. На этом считаю, что знакомство с компонентом TIdDNSResolve окончено. Переходим к коду.

Пишем код – 2 минуты

С основным компонентом мы познакомились, теперь пришло время для написания кода. Создай обработчик события OnClick для кнопки, по нажатию которой будет выполняться соединение с DNS-сервером и отправка запроса для получения определенных записей и напиши в нем код из листинга 1.

Листинг 1. Основной код

var
i:integer;
begin
DNSResolver.Host := DnsServerEdit.Text;
case RecordTypeComboBox.ItemIndex of
0: DNSResolver.QueryType := [qtMx];
1: DNSResolver.QueryType := [qtA];
2: DNSResolver.QueryType := [qtSOA];
3: DNSResolver.QueryType := [qtNS];
end;
DNSResolver.Resolve(DomainEdit.Text);
with DNSResolver.QueryResult do
for i:=0 to Count-1 do
if (Items is TARecord) then
RichEdit1.Lines.Add((Items[i] as TARecord).IPAddress)
else if (Items[i] is TMXRecord) then
RichEdit1.Lines.Add((Items[i] as TMXRecord).ExchangeServer)
else if (Items[i] is TNSRecord) then
RichEdit1.Lines.Add((Items[i] as TNSRecord).HostName)
else if (Items[i] is TSOARecord) then
RichEdit1.Lines.Add((Items[i] as TSoaRecord).Primary)
end;

В самом начале листинга я присваиваю свойству host компонента DNSResolver адрес DNS сервера, который введен в поле ввода с именем DNSServerEdit. Затем, я определяю, какие dns-записи меня интересуют. Поскольку все возможные DNS-записи у меня определены в ComBox, я просто сравниваю индекс выбранного в настоящее время элемента. Если он равен нулю, то значит, меня интересует тип записи MX. С определением остальных записей ситуация аналогичная.
Определив типы записей, информацию по которым нам требуется получить, я вызываю метод Resolve(). В качестве параметра я передаю текст, введенный в поле DomainEdit. По-хорошему, в нем должно быть введено имя домена, информацию о котором хотим получить.

После вызова метода, я начинаю перебирать коллекцию с результатами и выводить их в RichEdit. На первый взгляд вывод результатов выглядит хитро, но это только на первый. На самом деле все просто. Поскольку результаты попадают в коллекцию, то сразу напрашивается вывод – чтобы перебрать всю коллекцию элементов необходимо воспользоваться циклами. Запускаем цикл и в нем выполняем проверку. Если текущий элемент является классом TMXRecord (как пример), то значит, нам надо считать значение свойства ExchangeServer. Остальные проверки работают по такому же принципу.

Стоп, а как узнать свойство, которое нужно считывать у класса, соответствующего определенной dns-записи? Тут есть несколько выходов:

1. Заглянуть в документацию на официальном сайте;
2. Посмотреть исходники компонента;

Мне проще воспользоваться вторым способом.

alt
Рисунок 3. Программа в действии

Понравилась статья? Поделиться с друзьями: