Порт запроса dns: DNS использует UDP или TCP? Что говорит RFC

Содержание

DNS использует UDP или TCP? Что говорит RFC

Как правило, считается, что DNS использует UDP port 53, но TCP port 53 также зарезервирован под использование для DNS.  

Со временем ответ на довольно примитивный вопрос начинает интересовать каждого специалиста, так или иначе имеющего отношение к информационным технологиям и безопасности: 

В каком случае DNS работает по UDP, а в каком — по TCP?

На этот вопрос отвечает действующий документ RFC5966 , раздел 4. Transport Protocol Selection , в котором фигурируют следующие утверждения:
Most DNS [  RFC1034  ] transactions take place over UDP [  RFC0768  ].  TCP
[ RFC0793 ] is always used for zone transfers and is often used for
messages whose sizes exceed the DNS protocol's original 512-byte
limit.

То есть, большинство DNS-запросов будет обрабатываться с использованием протокола UDP, исключение составляют трансфер зоны (Query type AXFR) и ответы сервера, превышающие 512 байт на одно сообщение. На вопрос «зачем» ответ простой: чтобы не использовались для DDoS.


All general-purpose DNS implementations MUST support both UDP and TCP
transport.

Это означает, что все реализации DNS-серверов в общем случае должны поддерживать использование обоих протоколов транспортного уровня: TCP и UDP.


Теперь более частные случаи:
Authoritative server implementations MUST support TCP so that they
do not limit the size of responses to what fits in a single UDP
packet.

То есть, авторитативный сервер, хранящий зону, должен поддерживать TCP. Как минимум, чтобы передавать зону тому, кто имеет право ее запросить.

Recursive server (or forwarder) implementations MUST support TCP
so that they do not prevent large responses from a TCP-capable
server from reaching its TCP-capable clients.

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

Stub resolver implementations (e.g., an operating system's DNS
resolution library) MUST support TCP since to do otherwise would
limit their interoperability with their own clients and with
upstream servers. 

Stub resolver — это маленький тупой рекурсивный сервер, использующийся для небольшого количества клиентов. Например, домашний маршрутизатор, к которому подключаются клиенты. Он транслирует запросы вышестоящим серверам провайдера.

Stub resolver implementations MAY omit support for TCP when
specifically designed for deployment in restricted environments where
truncation can never occur or where truncated DNS responses are
acceptable.

Как видим, RFC дает поблажку производителям маломощных устройств для того, чтобы снизить нагрузку на сервера в том окружении, где либо большие ответы от DNS маловероятны, либо они предполагается, что не будут вредить. Например, домашний маршрутизатор доступа, к которому подключены пользователи одной квартиры (2-3 устройства). В этом случае попытка выполнить DDoS второго устройства бессмысленна, и, как следствие, маловероятна.


Ну и, конечно, порядок использования протоколов:
A resolver SHOULD send a UDP
query first, but MAY elect to send a TCP query instead if it has good
reason to expect the response would be truncated if it were sent over
UDP (with or without EDNS0) or for other operational reasons, in
particular, if it already has an open TCP connection to the server.

То есть, (маленький тупой) рекурсивный сервер должен сначала пробовать выполнять DNS-запрос с использованием UDP, но при высокой вероятности большого и усеченного ответа, либо при наличии открытой TCP-сессии к запрашиваемому серверу (по которому обрабатывается другой запрос или запрос другого клиента), не возбраняется использование TCP.


DNS сервер BIND (теория) / Хабр

Основная цель DNS — это отображение доменных имен в IP адреса и наоборот — IP в DNS. В статье я рассмотрю работу DNS сервера BIND (Berkeley Internet Name Domain, ранее: Berkeley Internet Name Daemon), как сАмого (не побоюсь этого слова) распространенного. BIND входит в состав любого дистрибутива UNIX. Основу BIND составляет демон named, который для своей работы использует порт UDP/53 и для некоторых запросов TCP/53.
Основные понятия Domain Name System

Исторически, до появления доменной системы имен роль инструмента разрешения символьных имен в IP выполнял файл /etc/hosts, который и в настоящее время играет далеко не последнюю роль в данном деле. Но с ростом количества хостов в глобальной сети, отслеживать и обслуживать базу имен на всех хостах стало нереально затруднительно. В результате придумали DNS, представляющую собой иерархическую, распределенную систему доменных зон. Давайте рассмотрим структуру Системы Доменных Имён на иллюстрации:


Доменная структура DNS представляет собой древовидную иерархию, состоящую из узлов, зон, доменов, поддоменов и др. элементов, о которых ниже пойдет речь. «Вершиной» доменной структуры является корневая зона. Настройки корневой зоны расположены на множестве серверов/зеркал, размещенных по всему миру и содержат информацию о всех серверах корневой зоны, а так же отвечающих за домены первого уровня (ru, net, org и др). Информация о серверах корневой зоны расположена на данном сайте корневых серверов. Настройки корневой зоны всегда доступны тут. Серверы корневой зоны обрабатывают и отвечают на запросы, выдавая информацию только о доменах первого уровня (то есть отвечают на любые запросы, как на нерекурсивные)! Итак, уже много раз повторилось слово зона. Пора этот термин объяснить.

Зона — это любая часть дерева системы доменных имен, размещаемая как единое целое на некотором DNS-сервере. Зону, для бОльшего понимания, можно назвать «зоной ответственности». Целью выделения части дерева в отдельную зону является передача ответственности (Делегирование) за эту ветвь другому лицу или организации. На иллюстрации, примеры зон выделены синим градиентом (зона name., зона k-max.name. со всем подчиненными ресурсами, www.openoffice.org со всем подчиненными поддоменами и ресурсами). На иллюстрации выделены не все зоны, а лишь некоторые для общего понимания и представления. В каждой зоне имеется, по крайней мере, один авторитетный сервер DNS, который хранит ВСЮ информацию о зоне, за которую он отвечает.

Домен — это именованная ветвь или поддерево в дереве имен DNS, то есть это определенный узел, включающий в себя все подчиненные узлы. Следующая цитата из книги Linux Network Administrators Guide хорошо проясняет картину относительно разницы между зоной и доменом:

Таким образом, пространство имен раздроблено на зоны ( zones), каждая из которых управляется своим доменом. Обратите внимание на различие между зоной (zone) и доменом (domain): домен groucho.edu затрагивает все машины в университете Groucho Marx, в то время как зона groucho.edu включает только хосты, которые работают в непосредственно компьютерном центре, например в отделе математики. Хост в отделе физики принадлежат другой зоне, а именно physics.groucho.edu.

Каждый узел в иерархии DNS отделен от своего родителя точкой. Если провести аналогию с файловой системой Linux, система доменных имен имеет похожую структуру, за тем исключением, что разделитель в файловой системе —
слэш
, а в DNS — точка. А так же DNS адрес читается справа налево (от корневого домена к имени хоста) в отличии от пути в файловой системе Linux. Доменное имя начинается с точки (корневого домена) и проходит через домены первого, второго и если нужно третьего и т.д. уровней и завершается именем хоста. Т.о. доменное имя полностью отражает структуру иерархии DNS. Часто (я бы сказал — всегда в повседневной жизни), последняя точка (обозначение корневого домена) в доменном имени опускается (то есть в браузере мы вводим не k-max.name., а k-max.name). Итак, разобрав структуру доменного имени, мы незаметно подошли к понятию FQDN.

FQDN (англ. Fully Qualifed Domain Name, полностью определённое имя домена) — это имя домена, однозначно определяющее доменное имя и включающее в себя имена всех родительских доменов иерархии DNS,

в том числе и корневого. Своеобразный аналог абсолютного пути в файловой системе. Давайте разберем вышесказанное на примере имени домена mail.k-max.name:

mail.k-max.name.
 |     |  |  | |
 |     |  |  | +-корневой домен
 |     |  |  +---домен первого уровня
 |     |  +------точка, разделяющая домены/части FQDN
 |     +---------домен второго уровня
 +---------------поддомен/домен третьего уровня, возможно - имя хоста

Различие между FQDN и обычным доменным (неFQDN) именем появляется при именовании доменов второго, третьего (и т. д.) уровня. Для получения FQDN требуется обязательно указать в доменном имени домены более высокого уровня (например, mail является доменным именем, однако FQDN имя выглядит как mail.k-max.name.). Максимальный размер FQDN — 255 байт, с ограничением в 63 байта на каждое имя домена.

Поддомены, коротко говоря, это — подчиненные домены. По большому счету, все домены в интернете являются подчиненными за исключением корневого. Например домен k-max является поддоменом домена name, а name, в свою очередь — поддоменом корневого домена.

Итак, на схеме выше мы рассмотрели корневой домен, следующим в иерархии идут домены первого/верхнего уровня, они же TLD, они же Top-Level Domain. К данным доменам относятся национальные домены (ru., ua. и др) и общие домены (com., net., и др). Существуют так же специализированные домены, которые не опубликованы в системе DNS, но используются программами (домен .onion используется анонимной сетью Tor для перехвата и последующей маршрутизации обращений к скрытым сервисам этой сети). Еще есть т.н.

зарезервированные доменные имена, определенные в RFC 2606 (Reserved Top Level DNS Names — Зарезервированные имена доменов верхнего уровня) определяет названия доменов, которые следует использовать в качестве примеров (например, в документации), а также для тестирования. К таким именам относятся например example.com, example.org и example.net, а также test, invalid и др. Ниже по иерархии, как видно, идут домены третьего уровня и т.д. Заканчивается доменная иерархия — именами хостов, которые задаются соответствующими ресурсными записями или хостовыми записями.

Ресурсные записи

Ресурсная запись — это то, собственно ради чего в конечном счете и существует DNS. Ресурсная запись — это единица хранения и передачи информации в DNS. Каждая такая запись несет в себе
информацию соответствия
какого-то имени и служебной информации в DNS, например соответствие имени домена — IP адреса.
Запись ресурса состоит из следующих полей:

  • имя (NAME) — доменное имя, к которому привязана или которому «принадлежит» данная ресурсная запись, либо IP адрес. При отсутствии данного поля, запись ресурса наследуется от предыдущей записи.
  • Time To Live (TTL) — дословно «время жизни» записи, время хранения записи в кэше DNS (после указанного времени запись удаляется), данное поле может не указываться в индивидуальных записях ресурсов, но тогда оно должно быть указано в начале файла зоны и будет наследоваться всеми записями.
  • класс (CLASS) — определяет тип сети, (в 99,99% случаях используется IN (что обозначает — Internet). Данное поле было создано из предположения, что DNS может работать и в других типах сетей, кроме TCP/IP)
  • тип (TYPE) — тип записи синтаксис и назначение записи
  • данные (DATA) — различная информация, формат и синтаксис которой определяется типом.

При этом, возможно использовать следующие символы:
  • ;   —  Вводит комментарий
  • #  —  Также вводит комментарии (только в версии BIND 4.9)
  • @  — Имя текущего домена
  • ( )    — Позволяют данным занимать несколько строк
  • *    — Метасимвол (только в поле имя)

Со всем набором ресурсных записей можно ознакомиться в wikipedia. Наиболее часто применяемые ресурсные записи следующими (далее, мы обязательно рассмотрим их на практике):
  • A — (address record/запись адреса) отображают имя хоста (доменное имя) на адрес IPv4. Для каждого сетевого интерфейса машины должна быть сделана одна A-запись. Например, следующая запись отображает доменное имя k-max.name. в IPv4 адрес хоста 81.177.139.65 (поле NAME k-max.name., поле TTL 86400, поле CLASS IN, поле DATA 81.177.139.65):
    k-max.name.             86400   IN      A       81.177.139.65
  • AAAA (IPv6 address record) аналогична записи A, но для IPv6.
  • CNAME (canonical name record/каноническая запись имени (псевдоним)) — отображает алиас на реальное имя (для перенаправления на другое имя), например, следующая запись задает алиас ftp для хоста www.k-max.name.:
    ftp             86400   IN      CNAME       www.k-max.name.
  • MX (mail exchange) — указывает хосты для доставки почты, адресованной домену. При этом поле NAME указывает домен назначения, поля TTL, CLASS — стандартное значение, поле TYPE принимает значение MX, а поле DATA указывает приоритет и через пробел — доменное имя хоста, ответственного за прием почты. Например, следующая запись показывает, что для домена k-max.name направлять почту сначала на mx.k-max.name, затем на mx2.k-max.name, если с mx.k-max.name возникли какие-то проблемы. При этом, для обоих MX хостов должны быть соответствующие A-записи:
    k-max.name.             17790   IN      MX      10 mx.k-max.name.
    k-max.name.             17790   IN      MX      20 mx2.k-max.name.
  • NS (name server/сервер имён) указывает на DNS-сервер, обслуживающий данный домен. Вернее будет сказать — указывают сервера, на которые делегирован данный домен. Если записи NS относятся к серверам имен для текущей зоны, доменная система имен их практически не использует. Они просто поясняют, как организована зона и какие машины играют ключевую роль в обеспечении сервиса имен. Например, зону name. обслуживают следующие NS:
    name.                   5772    IN      NS      l6.nstld.com.
    name.                   5772    IN      NS      m6.nstld.com.
    name.                   5772    IN      NS      c6.nstld.com.
    name.                   5772    IN      NS      j6.nstld.com.
    ......

    зону k-max.name обслуживают:
    k-max.name.             1577    IN      NS      ns2.jino.ru.
    k-max.name.             1577    IN      NS      ns1.jino.ru.
  • PTR (pointer) — отображает IP-адрес в доменное имя (о данном типе записи поговорим ниже в разделе обратного преобразования имен).
  • SOA (Start of Authority/начальная запись зоны) — описывает основные/начальные настройки зоны, можно сказать, определяет зону ответственности данного сервера. Для каждой зоны должна существовать только одна запись SOA и она должна быть первая. Поле Name содержит имя домена/зоны, поля TTL, CLASS — стандартное значение, поле TYPE принимает значение SOA, а поле DATA состоит из нескольких значений, разделенных пробелами: имя главного DNS (Primary Name Server), адрес администратора зоны, далее в скобках — серийный номер файла зоны (Serial number). При каждом внесении изменений в файл зоны данное значение необходимо увеличивать, это указывает вторичным серверам, что зона изменена, и что им необходимо обновить у себя зону. Далее — значения таймеров (Refresh — указывает, как часто вторичные серверы должны опрашивать первичный, чтобы узнать, не увеличился ли серийный номер зоны, Retry — время ожидания после неудачной попытки опроса, Expire — максимальное время, в течение которого вторичный сервер может использовать информацию о полученной зоне, Minimum TTL — минимальное время, в течение которого данные остаются в кэше вторичного сервера). Ниже в примере приведено 2 одинаковые записи SOA (хотя вторая и записана в несколько строк), но они одинаковы по значению и формат записи второй более понятен в силу его структурированности:
    k-max.name.             86400   IN      SOA     ns1.jino.ru. hostmaster.jino.ru. 2011032003 28800 7200 604800 86400
    k-max.name.             86400   IN      SOA     ns1.jino.ru. hostmaster.jino.ru. (
                                                      2011032003 ; serial (серийный номер)
                                                      28800 ; refresh (обновление)
                                                      7200 ; retry (повторная попытка)
                                                      604800 ; expire (срок годности)
                                                      86400) ; minimum TTL (минимум)
  • SRV (server selection) — указывают на сервера, обеспечивающие работу тех или иных служб в данном домене (например  Jabber и Active Directory).

Давайте рассмотрим, что есть Делегирование. Делегирование (корректнее сказать делегирование ответственности) — это операция передачи ответственности за часть дерева доменных имен (зону) другому лицу или организации. За счет делегирования, в DNS обеспечивается распределенность администрирования и хранения зон. Технически, делегирование заключается в выделении какой-либо части дерева в отдельную зону, и размещении этой зоны на DNS-сервере, принадлежащем другому лицу или организации. При этом, в родительскую зону включаются «склеивающие» ресурсные записи (NS и А), содержащие указатели на авторитативные DNS-сервера дочерней зоны, а вся остальная информация, относящаяся к дочерней зоне, хранится уже на DNS-серверах дочерней зоны. Например, на иллюстрации корневой домен делегирует полномочия серверам отвечающим за TLD, TLD же в свою очередь, делегируют полномочия управления зонами — серверам второго уровня, иногда на этом цепочка заканчивается, но бывает, что делегирование простирается до 4 и даже 5 уровней.

Для бОльшего понимания, приведу пример. Делегирование управления поддоменом k-max.name другому лицу (в моем случае — хостеру) приводит к созданию новой зоны, которая администрируется независимо от остального пространства имен (независимо от вышестоящего name.). Зона k-max.name после делегирования полномочий теперь не зависит от name. и может содержать все (вернее сказать — любые имена, которые я захочу) доменные имена, которые заканчиваются на *.k-max.name. С другой стороны, зона name. содержит только доменные имена, оканчивающиеся на *.name., но не входящие в делегированные этой зоны, такие, например, как k-max.name или a-lab.name или любая другая. k-max.name может быть поделен на поддомены с именами вроде mail.k-max.name, ftp.k-max.name и некоторые из этих поддоменов могут быть выделены в самостоятельные зоны, и ответственность за данные зоны может так же быть делегирована. Если ftp.k-max.name будет являться самостоятельной зоной, то зона k-max.name не будет содержать доменные записи, которые заканчиваются на *.ftp.k-max.name.

Т.о. после делегирования ответственности, информация хранимая делегирующей зоной уже не включает информацию по делегированному поддомену и его ресурсным записям хостов, а хранит информацию о серверах имен, являющихся для делегируемого поддомена авторитативными. Это и есть «склеивающие» записи, о чем я выше уже говорил. В таком случае, если у DNS-сервера родительского домена запрашиваются данные об адресе, принадлежащем делегированному поддомену, в ответ предоставляется список DNS-серверов, которые обладают соответствующей информацией.

Серверы DNS

Выше, при рассмотрении типов ресурсных записей я упоминал о первичном и вторичном сервере. Кроме данных типов, существует еще один тип — кэширующий.

Главный сервер DNS (он же первичный, он же master, он же primary) — это авторитетный сервер (иногда называют — авторитативный, как правильнее называть — не знаю), который хранит главную копию файла данных зоны, сопровождаемую администратором системы.

Вторичный сервер — тоже является авторитетным, но он копирует главный файл зоны с первичного сервера. Отличие главного от вторичного лишь в том, что главный загружает свою информацию из конфигурационных файлов зоны, а вторичный — загружает (получает) настройки зон — с главного сервера. Вторичный DNS может получать свои данные и от другого вторичного сервера. Любой запрос относительно хоста в пределах зоны, за которую отвечает авторитетный сервер, будет в конце концов передан одному из этих серверов (главному или вторичному). Вторичных серверов может быть сколько угодно много. В зависимости от настроек, главный сервер может посылать вторичному сигнал о изменении зоны, при этом вторичный, получив сигнал производит копирование. Данное действие называется трансфер зоны (zone transfer). Существует два механизма копирования зоны: полное копирование (AXFR) и инкрементальное (incremental) копирование зоны (IXFR).

Кэширующие серверы НЕ АВТОРИТЕТНЫ, данные серверы хранят в памяти (кэше), ответы на предыдущие запросы, если данный сервер получил запрос, то он сначала просматривает информацию в кэше, и если в кэше не оказалось необходимого ответа, то отправляет запрос вышестоящему серверу DNS.

Возможно так же настроить DNS в режиме stels (т.н. невидимый), информацию о данном сервере невозможно получить используя прямые запросы. Это может быть полезно для организации primary сервера в защищенной среде и тем самым оградить зону от атак на зону.

Клиенты DNS (resolver)

Как же программы на конечных машинах знают куда и в каком виде посылать запросы DNS? Они этого не знают. Для разрешения имен и IP адресов клиентскими приложениями используется библиотека Resolver. Это не какое-то специальное приложение, это функциональность системы (ядра). Т.о. приложения посылают системные вызовы gethostbyname(2) и gethostbyaddr(2), а ядро уже на основании настроек в файле /etc/nsswitch.conf определяет по какому пути ему далее действовать. Данный файл определяет какие сервисы (будь то файл /etc/hosts или DNS) и в каком порядке использовать. В ранних версиях библиотеки Linux — libc, использовался файл /etc/host.conf. Вот фрагмент файла, который нас интересует:
[email protected]:~# cat /etc/nsswitch.conf
......
hosts:          files dns
networks:       files

Две строки данного фрагмента указывают ядру производить преобразование имен хостов в IP (строка hosts: files dns) сначала из файла hosts, затем силами DNS, а так же преобразование имен сетей в IP (строка networks: files) с помощью файла /etc/network.Возможны так же параметры nis или nisplu, определяющие использовать Network Information System (NIS) чтобы найти адрес. Порядок, в котором перечислены сервисы, определяет последовательность их опроса.
Если согласно /etc/nsswitch.conf запрос отправляется DNS, то используются настройки из файла /etc/resolv.conf, который определяет какие серверы DNS использовать. Вот типичный пример файла /etc/resolv.conf:
[email protected]:~# cat /etc/resolv.conf
nameserver 192.168.1.1
nameserver 192.168.1.2
domain  examle.com

Директива nameserver определяет адрес сервера доменных имен, который будет выполнять рекурсивные запросы resolver. В данном файле указано использовать север имен сначала 192.168.1.1 затем, если первый не смог обработать запрос, 192.168.1.2. Рекомендуется не использовать более 3х параметров nameserver. Если опция nameserver не задана, то резолвер попытается соединиться с сервером на локальном хосте. Параметр domain определяет заданное по умолчанию имя домена, которое будет подставлено, когда DNS не удастся найти имя хоста. Существует так же опция search, которая задает дополнительные домены, в которых необходимо произвести поиск и разрешение имени хоста. Опции search и domain нельзя использовать совместно.

Кроме кэша на ДНС сервере, существуют кэши интернет-браузеров, кэши резолверов. Довольно прозрачную картину предоставляет Wikipedia:

Запросы DNS

В DNS имеются следующие типы запросов: итеративный (он же прямой), обратный и рекурсивный.

Итеративный (он же прямой, он же нерекурсивный) запрос посылает доменное имя DNS серверу и просит вернуть либо IP адрес этого домена, либо имя DNS сервера, авторитативного для этого домена. При этом, сервер DNS не опрашивает другие серверы для получения ответа. Так работают корневые и TLD серверы.

Рекурсивный запрос посылает DNS серверу доменное имя и просит возвратить IP адрес запрошенного домена. При этом сервер может обращаться к другим DNS серверам.

Обратный запрос посылает IP  и просит вернуть доменное имя.

Любой DNS-server должен отвечать на итеративные запросы. Возможно настроить DNS отвечать и на рекурсивные запросы. Если DNS не настроен отвечать на рекурсивные запросы, он обрабатывает их как итеративные.

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

Давайте разберем, что тут нарисовано по шагам:

  1. Клиент (браузер, почтовая программа, либо любое другое приложение) отправляет запрос резолверу, резолвер на основании указанных конфигов определяет адрес настроенного сервера имен.
  2. Резолвер посылает запрос указанному серверу имен.
  3. Сервер имен принимает данный рекурсивный запрос и, т.к. не имеет информации ни о домене, ни, возможно, даже о зоне name., отправляет рекурсивный (или нерекурсивный в зависимости от настроек) запрос серверу, отвечающему за корневую зону.
  4. Сервер корневой зоны не обрабатывает рекурсивные запросы, в результате обрабатывает данный запрос как итеративный и возвращает имя и адрес сервера, авторитетного за зону name.
  5. Сервер последовательно продолжает опрашивать авторитативные сервера для последующих зон, в порядке убывания уровня зон в имени
  6. пока не получает удовлетворительный ответ, данных шагов может быть больше, в зависимости от длины доменного имени
  7. и «вложенности» доменных имен.
  8. В итоге, сервер получает необходимый ответ от сервера имен, хранящего необходимую ресурсную запись о хосте.
  9. Сервер провайдера локальной сети возвращает резолверу клиента запрошенные данные.

Обычно, количество шагов сокращено до минимума, т.к. на пути прохождения запросов встречается кэширующий сервер, который хранит необходимую информацию в кэше. В данной схеме может возникнуть вопрос: каким образом локальный DNS сервер, получивший рекурсивный запрос от резолвера, выбирает DNS-сервер из списка авторитативных? Существует множество корневых DNS-серверов в сети Интернет, какому из корневых серверов наш DNS-сервер отправит запрос?

Для решения данного вопроса DNS-серверы BIND используют метрику, называемую временем отклика (roundtrip time, или RTT), для выбора среди авторитативных DNS-серверов одной зоны. RTT определяет задержку, с которой приходит ответ на запросы от удаленного сервера. Каждый раз, при передаче запроса удаленному серверу, DNS-сервер BIND запускает внутренний таймер. Таймер останавливается при получении ответа, и метрика фиксируется локальным сервером. Если приходится выбирать один из нескольких авторитативных серверов, выбор падает на сервер с наименьшим показателем RTT.

До того как BIND впервые послал запрос какому-либо серверу и получил от него ответ, удаленному серверу присваивается случайное значение RTT, которое меньше, чем все прочие, полученные на основании замеров. Таким образом, DNS BIND гарантированно опросит все авторитативные серверы для определенной зоны случайным образом, прежде чем начнет выбирать предпочтительный на основании метрики.

Ответы DNS сервера

Ответы DNS бывают следующего типа:
  • Авторитативный ответ (authoritative response) приходит от серверов, являющихся ответственными за зону.
  • Неавторитативный ответ (non authoritative response) приходит от серверов, которые не отвечают за зону (от кэширующих).

Ответ DNS обычно содержит следующую информацию:
  • Запись заголовка — служебную информацию о запросе.
  • Запись запроса — повторяет отправленный запрос.
  • Запись ответа — собственно, сам ответ.
  • Записи авторитетных серверов — информацию об авторитетных серверах, хранящих информацию по текущему запросу.
  • Дополнительную информацию — дополнительные записи, например адреса NS-серверов.

Вышенаписанное наглядно подтверждается утилитой dig:
[email protected]S:~# dig ya.ru
; <<>> DiG 9.7.3 <<>> ya.ru (раздел заголовка)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53499
;; flags: qr rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 2, ADDITIONAL: 3

;; QUESTION SECTION: (раздел запроса)
;ya.ru.                         IN      A

;; ANSWER SECTION: (раздел ответа)
ya.ru.                  4813    IN      A       87.250.250.203
ya.ru.                  4813    IN      A       87.250.251.3
ya.ru.                  4813    IN      A       93.158.134.3
ya.ru.                  4813    IN      A       93.158.134.203
ya.ru.                  4813    IN      A       213.180.204.3
ya.ru.                  4813    IN      A       77.88.21.3
ya.ru.                  4813    IN      A       87.250.250.3

;; AUTHORITY SECTION: (авторитативные сервера)
ya.ru.                  4813    IN      NS      ns1.yandex.ru.
ya.ru.                  4813    IN      NS      ns5.yandex.ru.

;; ADDITIONAL SECTION: (дополнительная информация - адреса авторитативных name servers)
ns5.yandex.ru.          345565  IN      A       213.180.204.1
ns1.yandex.ru.          345565  IN      A       213.180.193.1
ns1.yandex.ru.          3565    IN      AAAA    2a02:6b8::1

;; Query time: 7 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Sat Jul  2 23:02:45 2011
;; MSG SIZE  rcvd: 238

Обратное преобразование имен

DNS используется в первую очередь для преобразования доменных имён в IP-адреса, но он также может выполнять обратный процесс, называемый Обратное преобразование имен или обратным отображением. Т.к. записи в прямой базе DNS структурированы иерархически по доменным именам, DNS не может эффективно выполнять поиск по IP адресу в такой базе. Для обратного преобразования в DNS используется специальный домен in-addr.arpa. Ресурсные записи в данном домене в поле Name содержат IP-адреса, в поле TypePTR, а в поле DataFQDN-имя соответствующее данному IP.

На схеме представлена структура домена arpa. Думаю, что тут все довольно наглядно. Домен arpa. имеет 2 поддомена in-addr и ip6, отвечающие за IPv4 и IPv6 адреса соответственно. Домен in-addr.arpa. имеет от *.0.in-addr.arpa. до *.255.in-addr.arpa. поддоменов, каждый из которых так же имеет по 256 поддоменов.

В целях уменьшения объёма нежелательной корреспонденции (спама) многие почтовые серверы могут проверять наличие PTR записи для хоста, с которого происходит отправка. В этом случае PTR запись для IP адреса должна соответствовать имени отправляющего почтового сервера, которым он представляется в процессе SMTP сессии.

Наглядно приведенную схему можно представить командами:

[[email protected]~]# dig www.ru
...
;; QUESTION SECTION:
;www.ru                                IN      A

;; ANSWER SECTION:
www.ru                 52119   IN      A       194.87.0.50
...
[[email protected]~]# dig -x 194.87.0.50
...
;; QUESTION SECTION:
;50.0.87.194.in-addr.arpa.      IN      PTR

;; ANSWER SECTION:
50.0.87.194.in-addr.arpa. 30385 IN      PTR     www.ru
....

При этом, команду dig -x 194.87.0.50 правильнее будет представить как dig 50.0.87.194.in-addr.arpa., то есть записи в поддоменах *.in-addr.arpa. представлены в так называемой обратной нотации (или reverse форме), то есть хосту с IP 194.87.0.50 будет соответствовать PTR-запись, имеющая FQDN 50.0.87.194.in-addr.arpa., которая в свою очередь указывает на домен www.ru  Хочется отметить, что чаще всего за обратную зону и ее редактирование отвечает поставщик интернета.

Как и обещал, описываю ресурсную запись PTR в домене IN-ADDR.ARPA, соответствующая приведенной выше записи А для машины www.ru. будет иметь такой вид:

50.0.87.194 IN PTR www.ru

Имя 50.0.87.194 не заканчивается точкой и поэтому является относительным. Вопрос: относительным относительно чего? Ни в коем случае не относительно «www.ru». Для того чтобы эта запись была FQDN, домен по умолчанию должен называться «IN-ADDR.ARPA.». Этого можно добиться либо поместив записи PTR в отдельный файл, в котором доменное имя зоны по умолчанию — IN-ADDR.ARPA. (заданный в файле начальной загрузки демона named), либо изменив этот домен с помощью директивы $ORIGIN. Если домен по умолчанию определен как 0.87.194.IN-ADDR.ARPA., то запись можно представить так:

80 IN PTR www.ru
Регистрация доменных имен

В двух словах хотел бы затронуть вопрос регистрации доменных имен.

Регистрация доменов — это действие, посредством которого клиент сообщает регистратору, каким DNS-серверам следует делегировать поддомен, и также снабжает регистратора контактной и платежной информацией. Регистратор передает информацию в соответствующий реестр. Чаще всего, это процесс внесения в реестр зоны первого уровня (то есть в TLD зоны ru, com или др.), записи о новом доменном подимени.

Регистратор доменных имён — это организация, имеющая полномочия создавать (регистрировать) новые доменные имена и продлевать срок действия уже существующих доменных имён в домене, для которого установлена обязательная регистрация.

Уровни доменов, для которых необходима обязательная регистрация лица, ответственного за домен, следующие:

  • корневой домен
  • все домены первого уровня (TLD)
  • некоторые домены второго уровня (например, com.ru или co.uk)

Регистратором для корневого домена является организация ICANN. Чтобы стать регистратором доменов в зонах второго уровня (.com .net .org .biz .info .name .mobi .asia .aero .tel .travel .jobs …), необходимо получить аккредитацию ICANN.

Правила регистрации в международных (gTLD — com., org, и др.) доменах устанавливаются ICANN. Правила регистрации в национальных (ccTLD — ru, us и др.) доменах устанавливаются их регистраторами и/или органами власти соответствующих стран, например единые правила для всех регистраторов в доменах .ru, и.рф задаются Координационным центром национального домена сети Интернет. Для многих доменов (в том числе и для ru) регистратор не единственный. При наличии нескольких регистраторов все они должны использовать единую (централизованную или распределённую) базу данных для исключения конфликтов и обеспечения уникальности доменного имени.

Услуга регистрации домена в большинстве случаев платная, цену и условия регистрации определяет регистратор. Для регистрации домена, необходимо выбрать свободное имя и отправить заявку на регистрацию у одного из регистраторов (например nic.ru), оплатить предоставление услуги. После подтверждения регистрации, необходимо в интерфейсе регистратора определить (делегировать) dns сервера, скорее всего это будут DNS вашего хостера.

В завершение статьи хочу отметить так же о таком маркетинговом нюансе, что иногда домены второго уровня называют именами доменов ПЕРВОГО уровня, тем самым «опуская» значение корневого домена и принимая за корневой домен — домены TLD.

Так же хочу отметить, что доменный адрес и IP-адрес не тождественны — один IP-адрес может иметь множество имён, что позволяет поддерживать на одном компьютере множество веб-сайтов (это называется виртуальный хостинг). Обратное тоже справедливо — одному имени может быть сопоставлено множество IP-адресов: это позволяет создавать балансировку нагрузки.

Резюме

Итак, в сегодняшней статье я постарался как можно понятней описать работы доменной системы имен. Надеюсь, это у меня получилось. Мы рассмотрели иерархическую структуру базы данных DNS, а так же рассмотрели процессы взаимодействия клиентов и серверов DNS, а так же разновидности серверов DNS. В следующей статье я рассмотрю практические вопросы установки и настройки DNS сервера BIND на Linux. Буду рад Вашим комментариям.
Что еще почитать:

man (5) resolver: http://www.opennet.ru/man.shtml?topic=resolver&category=5&russian=0
man (3) gethostbyname:  http://www.opennet.ru/cgi-bin/opennet/man.cgi?topic=gethostbyname&category=3
Linux Network Administrators Guide v2 Russian: скачать.
RFC882, 1035, 1183

Разместил с разрешения mcsim85, у которого еще нет полноценного аккаунта на хабре, но который за такие качественный статьи безусловно его заслуживает! На всякий случай ссылка на оригинал.

DNS Протокол — Описание и Принцип Работы Протокола для Чайников

В прошлой статье мы рассмотрели систему доменных имен DNS, которая позволяет по доменному имени определить ip-адрес компьютера.

Рассмотрим протокол, который используется для сетевого взаимодействия в службе DNS. Напомню, что в системе доменных имен есть дерево серверов DNS, каждый из которых отвечает за некоторую часть пространства доменных имен, которое называется зоной. Клиент хочет узнать ip-адрес сервера для которого ему известно доменное имя. Например maps.yandex.ru.

Поиск начинается с корневого домена, отправляется запрос на доменное имя maps.yandex.ru.

Но корневой сервер отвечает, что он не знает  ip-адрес этого компьютера, зато он знает ip-адрес DNS-сервера, которому делегировано управление зоной ru.

Клиент DNS отправляет запрос к серверу, который отвечает за зону ru.

Но тот  в свою очередь, снова присылает ответ, что адрес этого компьютера ему неизвестен, но он знает адрес сервера, которому делегировано управление зоной yandex.ru.

Отправляется третий запрос к DNS серверу, который отвечает за зону yandex.ru.

У этого сервера есть необходимая нам информация и он присылает необходимый нам ip-адрес.

Режим работы DNS

Серверы DNS могут работать в двух режимах:

  1. Итеративный, если сервер отвечает за ту зону для который пришел запрос он присылает ответ, а если нет то он присылает адрес другого сервера, к которому нужно обратиться с запросом.
  2. Рекурсивный, в этом режиме DNS-сервер сам отправляет необходимые запросы всем DNS серверам пока не найдет необходимый сервер, получит от него ответ и этот ответ возвращается к клиенту.

Инфраструктура DNS

Два режима работы необходимы, потому что в системе DNS используются два типа серверов. DNS серверы, которые хранят информацию об отображении доменных имен в ip-адресах, работают в интеративном режиме, так как к этим серверам, особенно к корневым серверам или серверам первого уровня, приходит большое количество запросов, и у них не хватит производительности для работы в рекурсивном режиме.

И есть серверы, которые занимаются разрешением имен для клиентов Эти серверы работают в рекурсивном режиме, получают запрос от клиента, выполняют поиск в дереве серверов DNS, получают ответ и возвращают его клиенту.

Сервер разрешения имен DNS

Сервер разрешения имен находится в локальной сети, он предоставляется либо вашим провайдером, либо вашей организации. Часто адреса таких серверов компьютеры получают автоматически, вместе с ip- адресом по протоколу DHCP.

Другой вариант это использовать открытый сервер разрешения имен, которые предоставляют некоторые компании. Например, широко известен общедоступный DNS сервер компании Google с адресом 8.8.8.8, который может использовать кто угодно. Зачем может понадобиться использовать открытый сервер, вместо серверов вашей локальной сети? Некоторые такие серверы, например, сервер компании Яндекс с таким адресом 77.88.8.7 блокирует контент для взрослых.

Кэширование

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

Иногда, это время может составлять несколько дней или даже недель в зависимости от настроек DNS resolver. Поэтому не удивляйтесь, если вы внесли изменения в DNS записи, но они пока не видны.

Типы ответов DNS

В DNS есть два типа ответов:

  • Авторитетный или как пишется в утилите nslookup windows —  authoritative «заслуживающий доверие», это ответ, который получен от DNS сервера, который ответственный за данную зону. Ответ получен из конфигурационных файлов на диске сервера, и точно является актуальным.
  • Неавторитетный (non-authoritative) или «не заслуживающий доверия ответ», это ответ который получен от сервера, который не является ответственным за эту зону. Как правило, это DNS resolver, который закэшировал полученный ранее ответ. С момента создания записи в кэше данные могли измениться, поэтому ответ называется не заслуживающим доверия, но как правило в кэше находятся верные данные.

Протокол DNS

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

Формат пакета DNS

Пакет DNS состоит из двух частей заголовок и данные. Заголовок свою очередь состоит из шести полей.

  • Первое поле это идентификатор запроса, любое целое число должно быть одинаково в запросе и ответе.
  • Поле флаги мы его рассмотрим подробнее.
  • И четыре поля, которые указывают сколько у нас данных в пакете. Количество DNS запросов, количество DNS ответов, количество ответов об авторитетных серверах и количество дополнительных ответов.
  • В поле данных у нас содержится информация о запросах DNS, где мы указываем доменное имя компьютера для которого хотим узнать ip-адрес.
  • Ответов DNS в которых содержится ip-адрес необходимого нам компьютера.
  • Поле авторитетные серверы используется ветеративном режиме работы, здесь указываются ip-адреса серверов, которые отвечают за интересующую нас DNS зону.
  • И в поле дополнительной информации указываются некоторые дополнительные записи, которые могут быть нам полезны.

В одном и том же DNS пакете может быть несколько запросов DNS и несколько ответов, в том числе несколько ответов на один запрос, если одному доменному имени соответствует несколько ip-адресов.

Флаги

Поле флаги состоит из нескольких полей:

  1. Поле QR — тип операции запрос (0) или ответ (1).
  2. Поле OPCODE (4 бита) — тип запроса, но на практике используются только 0-стандартный запрос.
  3. Флаг AA указывает, является полученный ответ авторитетным (1) или нет (0).
  4. Флаг TC говорит о том был пакет обрезан (1) или не был (0).
  5. Флаг RD указывается только в запросах, если этот флаг установлен, клиент просит сервер работать в рекурсивном режиме.
  6. Флаг RA используется только в ответах, с помощью этого флага сервер сообщает, что он может работать в рекурсивном режиме.
  7. Флаг Z зарезервирован для будущего использования.
  8. RCODE (4 бита) последние четыре бита это статус выполнение операции, статус 0 говорит о том что операция прошла успешно, любые другие коды говорят о том что произошла какая-то ошибка.

Формат запроса DNS

Формат DNS запроса очень простой, содержит имя, тип и класс записи.

Например, имя www.yandex.ru, тип записи 1, (запись типа A) отображение доменного имени в ip- адрес. В системе DNS также используются другие типы записей. Класс записи 1 (IN, Интернет) код единица, других классов записей в системе DNS сейчас не используется.

Формат ответа DNS

Формат DNS ответа более сложный, первые три поля точно такие же имя, тип записи и класс записи. Затем указывается время жизни, это время на которые запись может сохранить в кэше DNS resolver, затем указывается длина данных и собственно данные ответа.

Пример, ответа DNS имя www.yandex.ru, запись типа A, класс записи интернет, время жизни 90 секунд, однако администратор DNS resolver  может принудительно установить другое время жизни. Длина данных измеряется в байтах, 4 байта и ip-адрес сервера www.yandex.ru.

Типы записей DNS

До сих пор мы рассматривали единственное применение системы dns это определение IP-адреса по доменному имени компьютера, но кроме этого DNS выполняет много других функций, которые необходимы для работы сети интернет. Для их реализации используются разные типы записей DNS.

Каждая запись dns по-английский (Resource Record, RR) имеет тип записи и класс записи. Тип записей говорит о том для чего эта запись предназначена, а класс указывает в каких сетях эта запись может использоваться. Сейчас DNS применяется только в сетях интернет, поэтому в классе записи вы почти всегда увидите IN, сокращение от интернета.

Записи, которые используются для определения ip адреса компьютера (IPv4) по доменному имени имеют тип A, для адресов IPv6 используется тип запись 4 раза (AAAA ).

Запрос записей разных типов

В утилите nslookup можно указать тип записи, который вы запрашиваете с помощью ключа минус type, например если вы укажете -type=A, нужно узнать Ipv4 адрес для доменного имени www.yandex.ru, то получите адреса ip версии 4.

А если указать тип записей четыре раза A, то получим адрес IPv6 для того же самого доменного имени.

DNS псевдонимы

Для одного и того же IP-адреса можно задавать несколько доменных имен. Есть два варианта, как это можно сделать.

  • Первый вариант использовать DNS запись типов CNAME (Canonical Name каноническое имя) эта запись определяет псевдоним для доменного имени. Например, доменное имя ftp.zvondozvon.ru является псевдонимом www.zvondozvon.ru, то есть два этих имени указывают на один и тот же IP-адрес. Канонических имен для одного и того же доменного имени можно создавать очень много. Для того чтобы такие имена работали необходимо, чтобы для доменного имени на которые они указывают существовала запись, которая определяет IP-адрес для этого доменного имени.
  • Альтернативный способ, создать большое количество A записей, которые указывают на один и тот же ip адрес. Но это не всегда удобно, например если вы хотите поменять IP адрес, то вам придется менять его в разных местах. С другой стороны на применение записей типа CNAME есть ряд технических ограничений со стороны системы DNS например, нельзя определять цепочки из канонических имен, которые ссылаются друг на друга, о других ограничениях можно подробно посмотреть в документах RFC, которые описывают работу DNS.

Адрес почтового сервера

Система DNS активно используются при работе электронной почты предположим, что мы хотим отправить электронное письмо на некоторый адрес в домене gmail.com, но как мы узнаем адрес почтового сервера, который принимает почту для этого домена?

Это можно сделать с помощью DNS. Для этого в DNS есть запись специального типа MX (Mail eXechange), например для домена gmail.com есть целых пять записей типа MX, которые задают пять серверов, принимающие почту в домене Google.

Запись MX содержит два поля. Первое поле это приоритет, а второе это адрес сервера принимающего почту для данного домена. Чем ниже значение, тем более высокий приоритет. Самый высокий приоритет у сервера, у которого значение приоритета пять и самый низкий приоритет у сервера со значением 40. Таким образом, при отправке электронной почты сначала будет выбираться сервер с наименьшим приоритетом, если по каким-либо причинам он будет недоступен, следующий сервер и так далее.

Адреса сетевых сервисов

Для некоторых типов сервисов интернет, можно указывать не только IP адрес, но и порт на котором этот сервис работает. Для этого используются DNS записи типа SRV (Service record). Структуры этой записи достаточно сложны, вместо доменного имени указывается строка с описанием сервисов в специальном формате (_сервис._протокол.имя.-˃ приоритет вес порт имя).

Например, если мы хотим узнать на каком компьютере и на каком порту работает jabber сервер работающий по протоколу tcp в домене example.com мы получим вот такую запись (0 5 5269 xmpp.example.com). Проще всего разбирать её с конца. Сервис работает на компьютере с доменным именем xmpp.example.com порт 5269, приоритет 0, вес 5. Так же как и с почтовыми серверами, чем меньше значение приоритета, тем более высокий приоритет у сервера.

Резервный jabber сервер для этого домена работает на компьютере backup_xmpp.xample.com порт 5269 приоритет 20, вес 0. Вес используются для распределения нагрузки между разными серверами, которые имеют один и тот же приоритет.

Делегирование ответственности

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

Записи серверов имен

Для этого используются dns-записи типа NS (Name Server). Например, за доменную зону yandex.ru отвечают серверы ns1.yandex.ru и ns2.yandex.ru, а за доменную зону urfu.ru отвечает целых 3 сервера. Записи типа ns задаются на домене более высокого уровня в нашем случае на сервере, который отвечает за зону ru. Именно этот сервер содержит записи ns для домена yandex.ru и для домена urfu.ru.

Но нам недостаточно знать только доменные имена dns-серверов, необходимо знать их IP адреса. Для этого используются «приклеенные» записи А, которые указывают IP-адреса. Вся остальная информация о делегированных доменных зонах хранится на этих dns серверах.

Определение имени по IP-адресу

Кроме определения ip адреса по компьютеру, по доменному имени, система dns может использоваться для обратной задачи определения доменного имени компьютера по его IP адресу. Для этого используются специальные зоны, называются обратные (reverse) или реверсивные.

Реверсивная зона содержит записи типа PTR (Pointer), которые ставят в соответствии IP-адрес компьютера доменному имени. Однако из-за технических ограничений DNS не может работать напрямую с IP адресами, поэтому для обратных зон был придуман обходной путь, представлять IP адрес в виде доменного имени. Для этих целей создан специальный домен in-addr.arpa и в этом домене IP адреса записываются в обратном порядке, например адрес 77.88.55.66 в обратной зоне будет записан следующим образом 66.55.88.77.in-addr.arpa.

Видео про типы записей DNS

Список портов для работы сервисов

Столкнулся на работе с заказом изминений на открытие портов в корпоративной сети…
И вот подготовил такой список

Список необходимых портов для работы AD

Имя системной службы: LSASS


Прикладной протокол

Протокол

Порты

Сервер глобального каталога

TCP

3269

Сервер глобального каталога

TCP

3268

Сервер LDAP

TCP

389

Сервер LDAP

UDP

389

LDAP SSL

TCP

636

LDAP SSL

UDP

636

IPsec ISAKMP

UDP

500

NAT-T

UDP

4500

RPC

TCP

135

Порты ТСР с большими номерами, произвольно назначенные службой RPC

TCP

1024 – 65536*

Список необходимых портов для работы DHCP

Имя системной службы: DHCPServer

Прикладной протокол

Протокол

Порты

Сервер DHCP

UDP

67

MADCAP

UDP

2535

Список необходимых портов для работы почтового клиента

Имя системной службы: outlook

Прикладной протокол

Протокол

Порты

IMAP (SLL)

TCP

993

SMTP (SLL)

TCP

587

Список необходимых портов для работы DNS

Имя системной службы: DNS

Прикладной протокол

Протокол

Порты

DNS

UDP

53

DNS

TCP

53

Составляем DNS-запрос вручную / Хабр

Об авторе. Джеймс Рутли — бэкенд-разработчик в компании Monzo.

В этой статье мы изучим двочиный формат сообщений Domain Name Service (DNS) и напишем вручную одно сообщение. Это больше, чем вам нужно для использования DNS, но я подумал, что для развлечения и в образовательных целях интересно посмотреть, что находится под капотом.

Мы узнаем, как:

  • Написать запросы DNS в двоичном формате
  • Отправить сообщение в теле датаграммы UDP с помощью Python
  • Прочитать ответ от DNS-сервера

Писать в двоичном формате кажется сложным, но в реальности я обнаружил, что это вполне доступно. Документация DNS хорошо написана и понятна, а писать мы будем маленькое сообщение — всего 29 байт.


DNS используется для перевода человекочитаемых доменных имён (таких как example.com) в машиночитаемые IP-адреса (такие как 93.184.216.34). Для использования DNS нужно отправить запрос на DNS-сервер. Этот запрос содержит доменное имя, которое мы ищем. DNS-сервер пытается найти IP-адрес этого домена в своём внутреннем хранилище данных. Если находит, то возвращает его. Если не может найти, то перенаправляет запрос на другой DNS-сервер, и процесс повторяется до тех пор, пока IP-адрес не будет найден. Сообщения DNS обычно отправляются по протоколу UDP.

Стандарт DNS описан в RFC 1035. Все диаграммы и бóльшая часть информации для этой статьи взята в данном RFC. Я бы рекомендовал обратиться к нему, если что-то непонятно.

В этой статье мы используем шестнадцатеричный формат для упрощения работы с бинарником. Ниже я добавил краткое пояснение, как они переводятся друг в друга [1].


У всех сообщений DNS одинаковый формат:
+---------------------+
|       Заголовок     |
+---------------------+
|        Вопрос       | Вопрос для сервера имён
+---------------------+
|         Ответ       | Ресурсные записи (RR) с ответом на вопрос
+---------------------+
|       Authority     | Записи RR с указанием на уполномоченный сервер
+---------------------+
|     Дополнительно   | Записи RR с дополнительной информацией
+---------------------+

Вопрос и ответ находятся в разных частях сообщения. В нашем запросе будут секции «Заголовок» и «Вопрос».

Заголовок


У заголовка следующий формат:
0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

На этой диаграмме каждая ячейка представляет единственный бит. В каждой строчке 16 колонок, что составляет два байта данных. Диаграмма поделена на строки для простоты восприятия, но реальное сообщение представляет собой непрерывный ряд байтов.

Поскольку у запросов и ответов одинаковый формат заголовка, некоторые поля не имеют отношения к запросу и будут установлены в значение 0. Полное описание каждого из полей см. в RFC1035, раздел 4.1.1.

Для нас имеют значение следующие поля:

  • ID: Произвольный 16-битный идентификатор запроса. Такой же ID используется в ответе на запрос, так что мы можем установить соответствие между ними. Возьмём AA AA.
  • QR: Однобитный флаг для указания, является сообщение запросом (0) или ответом (1). Поскольку мы отправляем запрос, то установим 0.
  • Opcode: Четырёхбитное поле, которое определяет тип запроса. Мы отправляем стандартный запрос, так что указываем 0. Другие варианты:
    • 0: Стандартный запрос
    • 1: Инверсный запрос
    • 2: Запрос статуса сервера
    • 3-15: Зарезервированы для будущего использования
  • TC: Однобитный флаг, указывающий на обрезанное сообщение. У нас короткое сообщение, его не нужно обрезать, так что указываем 0.
  • RD: Однобитный флаг, указывающий на желательную рекурсию. Если DNS-сервер, которому мы отправляем вопрос, не знает ответа на него, он может рекурсивно опросить другие DNS-серверы. Мы хотим активировать рекурсию, так что укажем 1.
  • QDCOUNT: 16-битное беззнаковое целое, определяющее число записей в секции вопроса. Мы отправляем 1 вопрос.

Полный заголовок


Совместив все поля, можно записать наш заголовок в шестнадцатеричном формате:
AA AA - ID
01 00 – Параметры запроса
00 01 – Количество вопросов
00 00 – Количество ответов
00 00 – Количество записей об уполномоченных серверах
00 00 – Количество дополнительных записей

Для получения параметров запроса мы объединяем значения полей от QR до RCODE, помня о том, что не упомянутые выше поля установлены в 0. Это даёт последовательность 0000 0001 0000 0000, которая в шестнадцатеричном формате соответствует 01 00. Так выглядит стандартный DNS-запрос.

Вопрос


Секция вопроса имеет следующий формат:
0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                     QNAME                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QTYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QCLASS                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

  • QNAME: Эта секция содержит URL, для которого мы хотим найти IP-адрес. Она закодирована как серия надписей (labels). Каждая надпись соответствует секции URL. Так, в адресе example.com две секции: example и com.

    Для составления надписи нужно закодировать каждую секцию URL, получив ряд байтов. Надпись — это ряд байтов, перед которыми стоит байт беззнакового целого, обозначающий количество байт в секции. Для кодирования нашего URL можно просто указать ASCII-код каждого символа.

    Секция QNAME завершается нулевым байтом (00).

  • QTYPE: Тип записи DNS, которую мы ищем. Мы будем искать записи A, чьё значение 1.
  • QCLASS: Класс, который мы ищем. Мы используем интернет, IN, у которого значение класса 1.

Теперь можно записать всю секцию вопроса:
07 65 – у 'example' длина 7, e
78 61 – x, a
6D 70 – m, p
6C 65 – l, e
03 63 – у 'com' длина 3, c
6F 6D – o, m
00    - нулевой байт для окончания поля QNAME 
00 01 – QTYPE
00 01 – QCLASS

В секции QNAME разрешено нечётное число байтов, так что набивка байтами не требуется перед началом секции QTYPE.
Мы отправляем наше DNS-сообщение в теле UDP-запроса. Следующий код Python возьмёт наш шестнадцатеричный DNS-запрос, преобразует его в двоичный формат и отправит на сервер Google DNS по адресу 8.8.8.8:53.
import binascii
import socket


def send_udp_message(message, address, port):
    """send_udp_message sends a message to UDP server

    message should be a hexadecimal encoded string
    """
    message = message.replace(" ", "").replace("\n", "")
    server_address = (address, port)

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        sock.sendto(binascii.unhexlify(message), server_address)
        data, _ = sock.recvfrom(4096)
    finally:
        sock.close()
    return binascii.hexlify(data).decode("utf-8")


def format_hex(hex):
    """format_hex returns a pretty version of a hex string"""
    octets = [hex[i:i+2] for i in range(0, len(hex), 2)]
    pairs = [" ".join(octets[i:i+2]) for i in range(0, len(octets), 2)]
    return "\n".join(pairs)


message = "AA AA 01 00 00 01 00 00 00 00 00 00 " \
"07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01"

response = send_udp_message(message, "8.8.8.8", 53)
print(format_hex(response)) 

Можете запустить этот скрипт, скопировав код в файл query.py и запустив в консоли команду $ python query.py. У него нет никаких внешних зависимостей, и он должен работать на Python 2 или 3.
После выполнения скрипт выводит ответ от DNS-сервера. Разобьём его на части и посмотрим, что можно выяснить.

Заголовок


Сообщение начинается с заголовка, как и наше сообщение с запросом:
AA AA – Тот же ID, как и раньше
81 80 – Другие флаги, разберём их ниже
00 01 – 1 вопрос
00 01 – 1 ответ
00 00 – Нет записей об уполномоченных серверах
00 00 – Нет дополнительных записей

Преобразуем 81 80 в двоичный формат:
8    1    8    0
1000 0001 1000 0000

Преобразуя эти биты по вышеуказанной схеме, можно увидеть:
  • QR = 1: Это сообщение является ответом
  • AA = 0: Этот сервер не является уполномоченным для доменного имени example.com
  • RD = 1: Для этого запроса желательна рекурсия
  • RA = 1: На этом DNS-сервере поддерживается рекурсия
  • RCODE = 0: Ошибки не обнаружены

Секция вопроса


Секция вопроса идентична такой же секции в запросе:
07 65 – у 'example' длина 7, e
78 61 – x, a
6D 70 – m, p
6C 65 – l, e
03 63 – у 'com' длина 3, c
6F 6D – o, m
00    - нулевой байт для окончания поля QNAME 
00 01 – QTYPE
00 01 – QCLASS

Секция ответа


У секции ответа формат ресурсной записи:
0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                                               /
/                      NAME                     /
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      TYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     CLASS                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      TTL                      |
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                   RDLENGTH                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/                     RDATA                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
C0 0C - NAME
00 01 - TYPE
00 01 - CLASS
00 00 
18 4C - TTL
00 04 - RDLENGTH = 4 байта
5D B8 
D8 22 - RDDATA

  • NAME: Этой URL, чей IP-адрес содержится в данном ответе. Он указан в сжатом формате:
    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F 
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | 1  1|                OFFSET                   |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

    Первые два бита установлены в значение 1, а следующие 14 содержат беззнаковое целое, которое соответствует смещению байт от начала сообщения до первого упоминания этого имени.

    В данном случае смещение составляет c0 0c или двоичном формате:

    1100 0000 0000 1100

    То есть смещение байт составляет 12. Если мы отсчитаем байты в сообщении, то можем найти, что оно указывает на значение 07 в начале имени example.com.
  • TYPE и CLASS: Здесь используется та же схема имён, что и в секциях QTYPE и QCLASS выше, и такие же значения.
  • TTL: 32-битное беззнаковое целое, которое определяет время жизни этого пакета с ответом, в секундах. До истечения этого интервала результат можно закешировать. После истечения его следует забраковать.
  • RDLENGTH: Длина в байтах последующей секции RDDATA. В данном случае её длина 4.
  • RDDATA: Те данные, которые мы искали! Эти четыре байта содержат четыре сегмента нашего IP-адреса: 93.184.216.34.


Мы увидели, как составить DNS-запрос. Теперь можно попробовать следующее:
  • Составить запрос для произвольного доменного имени
  • Запрос на другой тип записи
  • Отправить запрос с отключенной рекурсией
  • Отправить запрос с доменным именем, которое не зарегистрировано



1. Шестнадцатеричные числа (base 16) часто используются как удобная краткая запись для 4 битов двоичных данных. Вы можете конвертировать данные между этими форматами по следующей таблице:
Десятичный Hex Двоичный Десятичный Hex Двоичный
0 0 0000 8 8 1000
1 1 0001 9 9 1001
2 2 0010 10 A 1010
3 3 0011 11 B 1011
4 4 0100 12 C 1100
5 5 0101 13 D 1101
6 6 0110 14 E 1110
7 7 0111 15 F 1111

Как видите, можно представить любой байт (8 бит) двумя шестнадцатеричными символами. ↑

Битва за данные пользователей: зачем нужно шифровать DNS-запросы


Специалисты по обеспечению конфиденциальности и безопасности находятся в центре публичной борьбы за будущее шифрования трафика в интернете. В сентябре кабельные компании и другие представители телекоммуникационной отрасли в США направили в Конгресс письмо с протестом против планов Google по шифрованию трафика системы доменных имен (DNS) в браузере. В этом месяце Mozilla отправила в Конгресс собственное письмо, в котором просила законодателей не рассматривать этот протест, поскольку он основан на «фактических неточностях».

Речь идет о том, как следует шифровать DNS-трафик — сетевые запросы, которые преобразуют понятные людям доменные имена (адреса сайтов) в IP-адреса серверов. Когда пользователь вводит доменное имя в браузере, тот запрашивает у ближайшего указанного в настройках DNS-сервера IP-адрес, связанный с этим доменным именем.

По умолчанию эти запросы и ответы сервера отправляются по сети в виде обычного текста, что означает, что кто-то может перехватить их и перенаправить пользователя в другое место назначения. Простые текстовые DNS-запросы также позволяют администраторам сети видеть, на какие сайты заходят пользователи: фактические действия могут быть зашифрованы, но и такие знания могут предоставить ценную информацию, например, для рекламодателей.

Шифрование DNS гарантирует, что «браузер общается с тем, с чем вы хотите взаимодействовать, а не с тем, куда вас зовут вредоносные программы», — говорит Тим Эйприл, главный архитектор сетевой компании Akamai.

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

Существует два варианта: так называемые DNS поверх TLS и DNS поверх HTTPS. Первый подчеркивает безопасность и дает администраторам сетей больше контроля, а второй подчеркивает конфиденциальность пользователей. С точки зрения удобства использования пользователи не заметят различий с любым из этих подходов, чего нельзя сказать о системных администраторах.

Два способа шифрования

Современные сети полагаются на протокол защиты транспортного уровня (TLS) для безопасного обмена данными, например, для просмотра веб-страниц, передачи файлов, VPN-подключений, сеансов удаленного рабочего стола и передачи голоса по IP-телефонии. Одна сторона соединения, обычно сервер, имеет сертификат с цифровой подписью, выданный доверенным центром сертификации. Другая сторона соединения, обычно клиент, использует сертификаты для проверки того, с кем он обменивается данными.

Поскольку протокол TLS уже широко используется для обеспечения конфиденциальности, аутентификации и целостности данных, расширение протокола для работы с DNS является вполне логичным. DNS поверх TLS (IETF RFC 7858) определяет, как DNS-пакеты будут шифроваться с помощью TLS и передаваться по широко используемому протоколу управления передачей (TCP).

По умолчанию DNS проходит через порт 53 по протоколу TCP или UDP. При использовании DNS поверх TLS все зашифрованные пакеты отправляются через порт 853. Большинство общедоступных DNS-серверов, включая Cloudflare, Quad9 и Google, уже поддерживают DNS поверх TLS, и компании, использующие собственную DNS-инфраструктуру, также могут использовать такое шифрование. 

Google включил поддержку DNS поверх TLS в Android Pie (Android 9), чтобы пользователи могли настраивать шифрование DNS как для Wi-Fi, так и для мобильной сети, и многие приложения и устройства уже умеют работать с этой опцией.

«Мы решили проблему, добавив DNS к TLS», — сказал Пол Викси, изобретатель DNS и генеральный директор Farsight Security. Он также признает, что такое решение не является «веб-дружественным» в том смысле, что нет простого пользовательского интерфейса для включения этой функции.

DNS поверх HTTPS (IETF RFC8484) в значительной степени разработан с оглядкой на принципы работы современного интернета, поскольку он вбрасывает все пакеты данных в поток HTTPS вместе с другим зашифрованным веб-трафиком. В отличие от своего конкурента, DNS поверх HTTPS не шифрует отдельные запросы, а вместо этого пропускает их через зашифрованный туннель между клиентом и сервером. 

Поскольку соединение использует HTTPS и HTTP/2, все пакеты выглядят одинаково. Любой, кто отслеживает порт 443 — стандартный порт HTTPS — не сможет идентифицировать DNS-запросы из всего остального веб-трафика.

Плюсы и минусы каждого подхода

Для сторонников конфиденциальности DNS через TLS недостаточно хорош, потому что любой, кто контролирует сеть, будет знать, что любая активность на 853-ем порту связана с этим DNS. Хотя наблюдатель не будет знать фактическое содержание запроса, поскольку и ответ, и запрос зашифрованы, тот факт, что сетевой администратор или провайдер будут знать, что есть такая активность, уже может привести к последствиям для пользователя (в худшем случае этот порт может быть вообще закрыт). Хотя DNS поверх TLS безопасен, он не так удобен с точки зрения конфиденциальности, как DNS поверх HTTPS.

Еще один недостаток DNS поверх TLS заключается в том, что разработчикам программного обеспечения и производителям устройств необходимо внести изменения, чтобы их приложения и оборудование поддерживали этот протокол. И если такой поддержки нет, даже если указанный DNS-сервер может работать с таким шифрованием, оно не будет защищать данные пользователя.

DNS поверх HTTPS более демократичен, поскольку любой пользователь, использующий поддерживаемый веб-браузер, автоматически получает шифрование DNS. DNS поверх HTTPS лишает любые третьи стороны — в том числе поставщиков интернет-услуг и правительственные учреждения — возможности просматривать информацию о том, какие сайты посещает пользователь. Это именно то, что хотят защитники конфиденциальности, но это противоположно тому, что нужно сетевым администраторам.

Конфиденциальность против безопасности

DNS поверх HTTPS возводит конфиденциальность в абсолют, но создатели приложений родительского контроля, антивирусных программ, корпоративных брандмауэров и других сетевых инструментов не разделяют эту идеологию. Включение DNS поверх HTTPS по умолчанию в веб-браузере означает, что все DNS-запросы передаются на указанный DNS-сервер, который может не являться собственным DNS-сервером организации или провайдера.

Mozilla объявила, что DNS поверх HTTPS будет использоваться по умолчанию для пользователей Firefox в Соединенных Штатах, и это изменение в настоящее время активно внедряется. Firefox автоматически передает весь DNS-трафик популярному серверу Cloudflare 1.1.1.1 и игнорирует существующие настройки DNS пользователя. Это обходит все связанные с DNS сетевые правила фильтрации, в том числе позволяет попасть на сайты, доступ к которым блокируется по DNS.

Google также включил DNS поверх HTTPS для пользователей Chrome, но тут его принцип работы немного отличается, поскольку браузер по умолчанию использует DNS поверх HTTPS только в том случае, если у пользователя есть служба, совместимая с DNS поверх HTTPS.

Microsoft, как обычно, хочет усидеть на двух стульях одновременно: с одной стороны, компания планирует поддерживать DNS поверх HTTPS в Windows, с другой — хочет дать системным администраторам некоторый контроль.

Эйприл считает, что шифрование DNS — это «разумное ограничения доступа» к плохим ресурсам, но с ним нужно быть осторожнее. Провайдеры частенько блокируют имена хостов, используемые Wannacry и другими вредоносными программами, и временами перенаправляют пользователей, пытающихся получить доступ к вредоносным или заблокированным сайтам. Администраторы общедоступных сетей Wi-Fi модифицируют DNS-запросы, чтобы сначала загружалась страница авторизации для новых пользователей. DNS поверх HTTPS ломает все эти настройки.

Отчасти поэтому Mozilla не включает DNS поверх HTTPS для пользователей Firefox в Соединенном Королевстве, так как там закон требует от интернет-провайдеров блокировать доступ к нелегальным веб-сайтам, таким как те, которые связаны с детской порнографией.

DNS поверх HTTPS против DNS поверх TLS — это еще одна разновидность борьбы за данные о просмотре веб-страниц пользователем и за то, кто получит доступ к ним. DNS-запросы от Firefox будут отправляться в Cloudflare, что означает, что Cloudflare будет иметь доступ к огромному количеству данных DNS. По словам Викси, технологические компании, которые управляют централизованными DNS-серверами, такие как Cloudflare и Google, в конечном итоге получат выгоду от DNS поверх HTTPS, поскольку именно они будут получать информацию о том, что люди просматривают в интернете.

Сторонники конфиденциальности считают, что не провайдеры, а сами пользователи должны отвечать за то, как они попадают на сайты в интернете. Но решение Mozilla заставляет пользователей Firefox использовать Cloudflare независимо от их собственных предпочтений.

Большинство пользователей не заметят никакой разницы, когда шифрованный DNS станет стандартным, что уже произошло для пользователей Chrome. Для компаний и интернет-провайдеров социально-сознательный, ориентированный на пользователя подход вынуждает идти на компромисс: ценой повышения конфиденциальности является снижение безопасности.

Реальность современного интернета заключается в том, что интернет-провайдеры и компании играют определенную роль в предотвращении угроз для пользователей. В идеале веб-браузеры должны позволять пользователям выбирать, следует ли использовать DNS поверх TLS или DNS поверх HTTPS, а также предоставлять пользователям возможность контролировать, какого поставщика DNS использовать.


iGuides в Telegram — t.me/igmedia
iGuides в Яндекс.Дзен — zen.yandex.ru/iguides.ru

DNS over TLS — Шифруем наши DNS запросы с помощью Stunnel и Lua / Хабр


источник изображения


DNS (англ. Domain Name System — система доменных имён) — компьютерная распределённая система для получения информации о доменах.

TLS (англ. transport layer security — Протокол защиты транспортного уровня) — обеспечивает защищённую передачу данных между Интернет узлами.

После новости «Google Public DNS тихо включили поддержку DNS over TLS» я решил попробовать его. У меня есть Stunnel который создаст шифрованный TCP туннель. Но программы обычно общаются с DNS по UDP протоколу. Поэтому нам нужен прокси который будет пересылать UDP пакеты в TCP поток и обратно. Мы напишем его на Lua.

Вся разница между TCP и UDP DNS пакетами:


4.2.2. TCP usage
Messages sent over TCP connections use server port 53 (decimal). The message is prefixed with a two byte length field which gives the message length, excluding the two byte length field. This length field allows the low-level processing to assemble a complete message before beginning to parse it.

RFC1035: DOMAIN NAMES — IMPLEMENTATION AND SPECIFICATION

То есть делаем туда:


  1. берём пакет из UDP
  2. добавляем к нему в начале пару байт в которых указан размер этого пакета
  3. отправляем в TCP канал

И в обратную сторону:


  1. читаем из TCP пару байт тем самым получаем размер пакета
  2. читаем пакет из TCP
  3. отправляем его получателю по UDP

Настраиваем Stunnel


  1. Скачиваем корневой сертификат Root-R2.crt в директорию с конфигом Stunnel
  2. Конвертируем сертификат в PEM
    openssl x509 -inform DER -in Root-R2.crt -out Root-R2.pem -text
  3. Пишем в stunnel.conf:

    [dns]
    client = yes
    accept  = 127.0.0.1:53
    connect = 8.8.8.8:853
    CAfile = Root-R2.pem
    verifyChain = yes
    checkIP = 8.8.8.8

То есть Stunnel:


  1. примет не шифрованное TCP по адресу 127.0.0.1:53
  2. откроет шифрованный TLS туннель до адреса 8.8.8.8:853 (Google DNS)
  3. будет передавать данные туда и обратно

Запускаем Stunnel

Работу тунеля можно проверить командой:

nslookup -vc ya.ru 127.0.0.1

Опция ‘-vc’ заставляет nslookup использовать TCP соединение к DNS серверу вместо UDP.

Результат:

*** Can't find server name for address 127.0.0.1: Non-existent domain
Server:  UnKnown
Address:  127.0.0.1

Non-authoritative answer:
Name:    ya.ru
Address:  (здесь IP яндекса)

Пишем скрипт

Я пишу на Lua 5.3. В нём уже доступны бинарные операции с числами. Ну и нам понадобится модуль Lua Socket.

Имя файла: simple-udp-to-tcp-dns-proxy.lua

local socket = require "socket" -- подключаем lua socket

--[[--

Напишем простенькую функцию которая позволит отправить дамп пакета в консоль. Хочется видеть что делает прокси.

--]]--

function serialize(data)
    -- Преобразуем символы не входящие в диапазоны a-z и 0-9 и тире в HEX представление '\xFF'
    return "'"..data:gsub("[^a-z0-9-]", function(chr) return ("\\x%02X"):format(chr:byte()) end).."'"
end

--[[--


UDP в TCP и обратно

Пишем две функции которые будут оперировать двумя каналами передачи данных.

--]]--

-- здесь пакеты из UDP пересылаются в TCP поток
function udp_to_tcp_coroutine_function(udp_in, tcp_out, clients)
    repeat
        coroutine.yield() -- возвращаем управление главному циклу
        packet, err_ip, port = udp_in:receivefrom() -- принимаем UDP пакет
        if packet then
            -- > - big endian
            -- I - unsigned integer
            -- 2 - 2 bytes size
            tcp_out:send(((">I2"):pack(#packet))..packet) -- добавляем размер пакета и отправляем в TCP
            local id = (">I2"):unpack(packet:sub(1,2))    -- читаем ID пакета
            if not clients[id] then
                clients[id] = {}
            end
            table.insert(clients[id] ,{ip=err_ip, port=port, packet=packet}) -- записываем адрес отправителя
            print(os.date("%c", os.time()) ,err_ip, port, ">", serialize(packet)) -- отображаем пакет в консоль
        end
    until false
end

-- здесь пакеты из TCP потока пересылаются к адресату по UDP
function tcp_to_udp_coroutine_function(tcp_in, udp_out, clients)
    repeat
        coroutine.yield() -- возврашяем управление главному циклу
        -- > - big endian
        -- I - unsigned integer
        -- 2 - 2 bytes size
        local packet = tcp_in:receive((">I2"):unpack(tcp_in:receive(2)), nil) -- принимаем TCP пакет
        local id = (">I2"):unpack(packet:sub(1,2))                            -- читаем ID пакета

        if clients[id] then
            for key, client in pairs(clients[id]) do
                -- сравниваем query в запросе и ответе
                if packet:find(client.packet:sub(13, -1), 13, true) == 13 then -- находим получателя
                    udp_out:sendto(packet, client.ip, client.port) -- отправляем пакет получателю по UDP
                    clients[id][key] = nil                         -- очищаем ячейку
                    -- отображаем пакет в консоль
                    print(os.date("%c", os.time()) ,client.ip, client.port, "<", serialize(packet))
                    break
                end
            end
            if not next(clients[id]) then
                clients[id] = nil
            end
        end
    until false
end

--[[--

Обе функции сразу после запуска выполняют coroutine.yield(). Это позволяет первым вызовом передать параметры функции а дальше делать coroutine.resume(co) без дополнительных параметров.


main

А теперь main функция которая выполнит подготовку и запустит главный цикл.

--]]--

function main()
    local tcp_dns_socket = socket.tcp() -- подготавливаем TCP сокет
    local udp_dns_socket = socket.udp() -- подготавливаем UDP сокет

    local tcp_connected, err = tcp_dns_socket:connect("127.0.0.1", 53) -- соединяемся с TCP тунелем
    assert(tcp_connected, err) -- проверяем что соединились
    print("tcp dns connected") -- сообщаем что соединились в консоль

    local udp_open, err = udp_dns_socket:setsockname("127.0.0.1", 53) -- открываем UDP порт
    assert(udp_open, err)      -- проверяем что открыли
    print("udp dns port open") -- сообщаем что UDP порт открыт

    -- пользуемся тем что таблицы Lua позволяют использовать как ключ что угодно кроме nil
    -- используем как ключ сокет чтобы при наличии данных на нём вызывать его сопрограмму
    local coroutines = {
        [tcp_dns_socket] = coroutine.create(tcp_to_udp_coroutine_function), -- создаём сопрограмму TCP to UDP
        [udp_dns_socket] = coroutine.create(udp_to_tcp_coroutine_function)  -- создаём сопрограмму UDP to TCP
    }

    local clients = {} -- здесь будут записываться получатели пакетов

    -- передаём каждой сопрограмме сокеты и таблицу получателей
    coroutine.resume(coroutines[tcp_dns_socket], tcp_dns_socket, udp_dns_socket, clients) 
    coroutine.resume(coroutines[udp_dns_socket], udp_dns_socket, tcp_dns_socket, clients)

    -- таблица из которой socket.select будет выбирать сокет готовый к получению данных
    local socket_list = {tcp_dns_socket, udp_dns_socket} 

    repeat -- запускаем главный цикл
        -- socket.select выбирает из socket_list сокеты у которых есть данные на получение в буфере
        -- и возвращает новую таблицу с ними. Цикл for последовательно возвращает значения из новой таблицы  
        for _, in_socket in ipairs(socket.select(socket_list)) do
            -- запускаем ассоциированную с полученным сокетом сопрограмму
            local ok, err = coroutine.resume(coroutines[in_socket])
            if not ok then
                -- если сопрограмма завершилась с ошибкой то
                udp_dns_socket:close() -- закрываем UDP порт
                tcp_dns_socket:close() -- закрываем TCP соединение
                print(err) -- выводим ошибку
                return     -- завершаем главный цикл
            end
        end
    until false
end

--[[--

Запускаем главную функцию. Если вдруг будет закрыто соединение мы через секунду установим его заново вызвав main.

--]]--

repeat
    local ok, err = coroutine.resume(coroutine.create(main)) -- запускаем main
    if not ok then
        print(err)
    end
    socket.sleep(1) -- перед рестартом ждём одну секунду
until false

проверяем


  1. Запускаем stunnel


  2. Запускаем наш скрипт

    lua5.3 simple-udp-to-tcp-dns-proxy.lua

  3. Проверяем работу скрипта командой

    nslookup ya.ru 127.0.0.1

    На этот раз без ‘-vc’ так так мы уже написали и запустили прокси который заворачивает UDP DNS запросы в TCP тунель.


Результат:

*** Can't find server name for address 127.0.0.1: Non-existent domain
Server:  UnKnown
Address:  127.0.0.1

Non-authoritative answer:
Name:    ya.ru
Address:  (здесь IP яндекса)

Если всё нормально можно указать в настройках соедидения как DNS сервер «127.0.0.1»


заключение

Теперь наши DNS запросы под защитой TLS.


P.S. Не даём гуглу лишней информации о нас

Сразу после соединения Windows пытается зарегистрировать нас на DNS серверах гугла через наш туннель. Это отключается в продвинутых настройках DNS снятием галочки.

Есть ещё запрос на time.windows.com. Он уже не такой личный но как его отключить я так и не нашёл. Автоматическая синхронизация времени отключена.


ссылки


  1. RFC1035: DOMAIN NAMES — IMPLEMENTATION AND SPECIFICATION
  2. DNS поверх TLS
  3. simple-udp-to-tcp-dns-proxy.lua
  4. Составляем DNS-запрос вручную

DNS-



Прозрачный

: 28.01.2004
#: 13,812
: 20



: 29, 2004 13:53: DNS-

!
MR

: 04.11.2003
#: 11,293
: 427



: 29, 2004 14:00:

Винни Пух

: 12.09.2003
#: 9,715
: 1296
: Санкт-Петербург


: 29, 2004 14:13:

Рустам

: 13.09.2002
#: 2,280
: 1006
:


: 29, 2004 14:35:


_________________
Нет рута — без комментариев!
Прозрачный

: 28.01.2004
#: 13,812
: 20



: 29, 2004 17:31:

skyx

: 04.07.2003
#: 7,471
: 1508



: 29, 2004 17:40:


_________________
«
Прозрачный

: 28.01.2004
#: 13,812
: 20



: 29, 2004 17:52:

skyx

: 04.07.2003
#: 7,471
: 1508



: 29, 2004 18:26:


_________________
«
Прозрачный

: 28.01.2004
#: 13,812
: 20



: 29, 2004 18:56:

dexen

: 25.05.2001
#: 13
: 768


: 4


: 30, 2004 8:38:

!
.
optimism.ru
.

DNS для служб и модулей

На этой странице представлен обзор поддержки DNS в Kubernetes.

Введение

Kubernetes DNS планирует DNS Pod и службу в кластере и настраивает кублеты, чтобы указать отдельным контейнерам использовать IP-адрес службы DNS для разрешить DNS-имена.

Что получают DNS-имена?

Каждая служба, определенная в кластере (включая сам DNS-сервер), назначил DNS-имя. По умолчанию список поиска DNS клиентского модуля будет включить собственное пространство имен Pod и домен кластера по умолчанию.Это лучше всего проиллюстрировано примером:

Предположим, что служба с именем foo находится в пространстве имен Kubernetes bar . Стручок работает в пространстве имен панель может найти эту службу, просто выполнив DNS-запрос для foo . Pod, работающий в пространстве имен quux , может найти эту службу, выполнив DNS-запрос для foo.bar .

В следующих разделах подробно описаны поддерживаемые типы записей и макет, который поддерживается. Любой другой макет, имена или запросы, которые могут работать, рассмотрены детали реализации и могут быть изменены без предупреждения.Для получения более свежих технических характеристик см. Обнаружение службы Kubernetes на основе DNS.

Службы

Записи A / AAAA

«Нормальным» (не безголовым) службам назначается запись DNS A или AAAA, в зависимости от семейства IP-адресов службы, для имени в форме мой-svc.my-namespace.svc.cluster-domain.example . Это разрешает IP-адрес кластера Службы.

«Безголовые» (без IP-адреса кластера) Службам также назначается запись DNS A или AAAA, в зависимости от семейства IP-адресов службы, для имени в форме мой-svc.мой-namespace.svc.cluster-domain.example . В отличие от обычного Службы, это разрешается набором IP-адресов модулей, выбранных Службой. Ожидается, что клиенты будут использовать набор или использовать стандартный циклический перебор. выбор из набора.

записей SRV

Записи SRV создаются для именованных портов, которые являются частью обычного или безголового Сервисы. Для каждого именованного порта запись SRV будет иметь вид _my-port-name._my-port-protocol.my-svc.my-namespace.svc.cluster-domain.example .Для обычной службы это разрешается в номер порта и имя домена: мой-svc.my-namespace.svc.cluster-domain.example . Для безголовой службы это разрешает несколько ответов, по одному для каждого модуля. который поддерживает службу и содержит номер порта и доменное имя модуля формы автоматически сгенерированное-имя.my-svc.my-namespace.svc.cluster-domain.example .

Pods

A / AAAA записей

Как правило, pod имеет следующее разрешение DNS:

pod-ip-address.мой-namespace.pod.cluster-domain.example .

Например, если модуль в пространстве имен по умолчанию имеет IP-адрес 172.17.0.3, и имя домена для вашего кластера — cluster.local , тогда у Pod есть DNS-имя:

172-17-0-3.default.pod.cluster.local .

Любые модули, созданные с помощью развертывания или DaemonSet, предоставляемого службой, имеют доступно следующее разрешение DNS:

pod-ip-address.deployment-name.my-namespace.svc.cluster-domain.example .

Поля имени хоста и поддомена пода

В настоящее время, когда под создается, его имя хоста — это значение metadata.name пода.

В спецификации Pod есть необязательное поле hostname , которое можно использовать для указания Имя хоста пода. Если указано, оно имеет приоритет перед именем пода. имя хоста модуля. Например, для Pod с именем хоста установлено значение « my-host », имя хоста Pod будет установлено на « my-host ».

В спецификации Pod также есть необязательное поле поддомена , которое можно использовать для указания его поддомен. Например, Pod с именем хоста , установленным на « foo », и поддоменом установлен на « bar », в пространстве имен « my-namespace », будет иметь полное доменное имя (FQDN) « foo.bar.my-namespace.svc.cluster-domain.example ».

Пример:

  apiVersion: v1
вид: Сервис
метаданные:
  имя: субдомен по умолчанию
спецификации:
  селектор:
    имя: busybox
  clusterIP: Нет
  порты:
  - name: foo # На самом деле порт не нужен.порт: 1234
    targetPort: 1234
---
apiVersion: v1
вид: Стручок
метаданные:
  имя: busybox1
  ярлыки:
    имя: busybox
спецификации:
  имя хоста: busybox-1
  субдомен: субдомен по умолчанию
  контейнеры:
  - изображение: busybox: 1.28
    команда:
      - спать
      - «3600»
    имя: busybox
---
apiVersion: v1
вид: Стручок
метаданные:
  имя: busybox2
  ярлыки:
    имя: busybox
спецификации:
  имя хоста: busybox-2
  субдомен: субдомен по умолчанию
  контейнеры:
  - изображение: busybox: 1.28
    команда:
      - спать
      - «3600»
    имя: busybox
  

Если существует автономная служба в том же пространстве имен, что и модуль, и с то же имя, что и поддомен, DNS-сервер кластера также возвращает A или AAAA запись для полного имени хоста Pod.Например, для модуля Pod с именем хоста, установленным на « busybox-1 «, и поддоменом, установленным на « default-subdomain » и автономная служба с именем « default-subdomain » в то же пространство имен, модуль будет видеть свое полное доменное имя как « busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example ». DNS обслуживает Запись A или AAAA с этим именем, указывающая на IP-адрес модуля. Оба модуля « busybox1 » и « busybox2 » может иметь свои отдельные записи A или AAAA.

Объект Endpoints может указать имя хоста для любых адресов конечных точек, вместе со своим IP.

Примечание: Поскольку записи A или AAAA не создаются для имен Pod, имя хоста требуется для Pod A или AAAA запись, которую нужно создать. Pod без имени хоста , но с поддоменом создаст только Запись A или AAAA для автономной службы ( default-subdomain.my-namespace.svc.cluster-domain.example ), указывая на IP-адрес пода.Кроме того, Pod должен быть готов, чтобы иметь запись, если для Службы не установлено значение publishNotReadyAddresses = True .

Поле setHostnameAsFQDN Pod

СОСТОЯНИЕ ФУНКЦИИ: Kubernetes v1.19 [alpha]

Предварительные требования : Шлюз функций SetHostnameAsFQDN должен быть включен для Компонент плоскости API ServerControl, обслуживающий Kubernetes API.

Когда модуль настроен на использование полного доменного имени (FQDN), его имя хоста является коротким именем хоста.Например, если у вас есть Pod с полным доменным именем busybox-1.default-subdomain.my-namespace.svc.cluster-domain.example , то по умолчанию команда hostname внутри этого Pod возвращает busybox -1 , а команда hostname --fqdn возвращает полное доменное имя.

Когда вы устанавливаете setHostnameAsFQDN: true в спецификации Pod, kubelet записывает полное доменное имя Pod в имя хоста для этого пространства имен Pod. В этом случае и hostname , и hostname --fqdn возвращают полное доменное имя Pod.

Примечание:

В Linux поле имени хоста ядра (поле nodename структуры struct utsname ) ограничено 64 символами.

Если модуль включает эту функцию и его полное доменное имя превышает 64 символа, он не запустится. Pod останется в состоянии Pending ( ContainerCreating , как видно из kubectl ), генерируя события ошибок, такие как Failed to build FQDN from pod hostname and cluster domain, FQDN long-FDQN is too long (64 символа — не более 70 требуемых символов).Один из способов улучшить взаимодействие с пользователем для этого сценария — создать контроллер доступа к веб-перехватчику для управления размером FQDN, когда пользователи создают объекты верхнего уровня, например Deployment.

Политика DNS модуля

Политики DNS можно настроить для каждого модуля. В настоящее время Kubernetes поддерживает следуя политикам DNS для конкретного модуля. Эти политики указаны в dnsPolicy поле спецификации пода.

  • « Default »: Pod наследует конфигурацию разрешения имен от узла. что стручки работают.См. Обсуждение по теме Больше подробностей.
  • « ClusterFirst »: любой DNS-запрос, не соответствующий настроенному кластеру. суффикс домена, например « www.kubernetes.io », перенаправляется в вышестоящую сервер имен, унаследованный от узла. Администраторы кластера могут иметь дополнительные тупиковый домен и вышестоящие DNS-серверы настроены. См. Обсуждение по теме для получения подробной информации о том, как обрабатываются DNS-запросы в таких случаях.
  • « ClusterFirstWithHostNet «: для модулей, работающих с hostNetwork, следует явно установите свою политику DNS « ClusterFirstWithHostNet ».
  • « Нет »: позволяет поду игнорировать настройки DNS из Kubernetes. среда. Все настройки DNS должны быть предоставлены с помощью dnsConfig поле в Pod Spec. См. Подраздел конфигурации DNS Pod ниже.

Примечание. «По умолчанию» не является политикой DNS по умолчанию. Если dnsPolicy не является явно указано, то используется «ClusterFirst».

В примере ниже показан модуль с политикой DNS, установленной на « ClusterFirstWithHostNet », потому что для него hostNetwork установлено значение true .

  apiВерсия: v1
вид: Стручок
метаданные:
  имя: busybox
  пространство имен: по умолчанию
спецификации:
  контейнеры:
  - изображение: busybox: 1.28
    команда:
      - спать
      - «3600»
    imagePullPolicy: IfNotPresent
    имя: busybox
  restartPolicy: Всегда
  hostNetwork: true
  dnsPolicy: ClusterFirstWithHostNet
  

Конфигурация DNS Pod

Конфигурация DNS Pod позволяет пользователям больше контролировать настройки DNS для Pod.

Поле dnsConfig является необязательным и может работать с любыми настройками dnsPolicy .Однако, когда для параметра dnsPolicy Pod установлено значение « None », в поле dnsConfig будет уточнено.

Ниже приведены свойства, которые пользователь может указать в поле dnsConfig :

  • nameservers : список IP-адресов, которые будут использоваться в качестве DNS-серверов для Под. Можно указать не более 3 IP-адресов. Когда на поде dnsPolicy установлен на « Нет », список должен содержать хотя бы один IP-адрес, в противном случае это свойство не является обязательным.Перечисленные серверы будут объединены с базовыми серверами имен, созданными из указанная политика DNS с удалением повторяющихся адресов.
  • поиски : список доменов поиска DNS для поиска имени хоста в Pod. Это свойство не является обязательным. Если указано, предоставленный список будет объединен в базовые поисковые доменные имена, созданные на основе выбранной политики DNS. Удаляются повторяющиеся доменные имена. Kubernetes позволяет использовать не более 6 поисковых доменов.
  • параметры : дополнительный список объектов, где каждый объект может иметь имя свойство (обязательно) и значение свойство (необязательно).Содержание в этом будет объединено с параметрами, созданными на основе указанной политики DNS. Повторяющиеся записи удаляются.

Ниже приведен пример модуля с пользовательскими настройками DNS:

.

DNS ip



sinthetic89

: 01.11.2019
#: 172,524
: 2



: 01, 2019 19:12: DNS ip

: sinthetic89 (01, 2019 20:08), 2 ()

!
игорглав

: 22.12.2011
#: 136,164
: 1186


: 7


: 01, 2019 19:41:

karavan750
Системные администраторы

: 22.01.2016
#: 160,064
: 8597


: 94


: 01, 2019 20:00:


_________________

NixOS -.
karavan750
Системные администраторы

: 22.01.2016
#: 160,064
: 8597


: 94


: 01, 2019 20:01:


_________________

NixOS -.
sinthetic89

: 01.11.2019
#: 172,524
: 2



: 01, 2019 20:07:

VanDyke
, склиф

: 09.10.2007
#: 62,098
: 75145
: сеть назначения недоступна

: 619


: 01, 2019 20:12:


_________________
Не такой идеальный, как 42, но довольно близко …
,,,.
СтасСтрюков

: 16.05.2012
#: 139 671
: 460
:

: 3


: 01, 2019 20:18:


_________________
CCNA R&S, CCNA Security, CCDA, CCS Enterprise Core, ENARSI в процессе
MTCNA, MTCTCE
питон
rex_3
Windows guru

: 23.02.2005
#: 24,533
: 13230
:

: 132


: 01, 2019 22:47: Re: DNS ip


_________________
,.
.
игорглав

: 22.12.2011
#: 136,164
: 1186


: 7


: 01, 2019 22:52:

КривоСофт

: 29.08.2005
#: 28,524
: 171
: i

: 1


: 02, 2019 19:39: Re: DNS ip

!
.
optimism.ru
.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *