Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

Иванов Илья, 3530901/70203, lab2s #35

Closed

Conversation

BigAwesomeTurtle
Copy link

@BigAwesomeTurtle BigAwesomeTurtle commented Nov 29, 2020

Инструкция по сборке/установке и использованию

Клиент реализован на языке python, сборка не требуется.
Запуск на Linux :
image
Права суперпользователя требуются, так как сервер использует 53-ий порт, входящий в число системных портов.

На Windows необходимо открыть терминал от имени администратора, а затем выполнить python3 DNS_Server.py

Адрес и порт DNS сервера, а также путь до файла, в котором будут храниться соответствия доменных имён и IP адресов, указываются в файле NTP_Servert.py:
image

Описание используемого протокола

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

    +---------------------+
    |        Header       |
    +---------------------+
    |       Question      | the question for the name server
    +---------------------+
    |        Answer       | RRs answering the question
    +---------------------+
    |      Authority      | RRs pointing toward an authority
    +---------------------+
    |      Additional     | RRs holding additional information
    +---------------------+

Header - заголовок пакета
Question - секция запросов
В общем случае, секция Question может содержать более одного запроса, но, зачастую, запрос всё же один, и данная реализация DNS сервера будет обрабатывать только первый запрос в секции Question, игнорируя остальные, если таковые имеются.
Answer - секция ответов
Секции Authority и Additional в данной реализации DNS сервера не используются.

Структура заголовка:
image

ID - уникальный идентификатор транзакции. Он указывает на то, что пакеты принадлежат одной и той же сессии “запросов-ответов”. Сервер копирует ID из запроса клиента.
QR - бит, служащий для идентификации того, является ли пакет запросом (QR = 0) или ответом (QR = 1).
Opcode - Тип запроса (0 - стандартный запрос, 1 - инверсный запрос, 2- запрос статуса сервера, 3-15 - зарезервированы)
Данная реализация сервера поддерживает только стандартные запросы.
AA - Authoritative Answer - бит, свидетельствующий о том, является ли сервер ответственным за запрошенное доменное имя
TC - TrunCation - бит, устанавливаемый, если сервер не смог поместить в пакет всю необходимую информацию из-за каких-либо ограничений
RD - Recursion Desired - бит, устанавливаемый клиентом, и копируемый сервером. Сообщает о том, что клиент просит сервер выполнить запрос рекурсивно
RA - Recursion Available - устанавливается сервером и показывает, поддерживает ли сервер рекурсивное выполнение запроса
Z - зарезервированные биты, равные нулю
Rcode - Response code - код ответа (0 - запрос выполнен без ошибок, 1 - ошибка, связанная с тем, что сервер не смог понять запрос, 2 - внутренняя ошибка на сервере, 3 - запрашиваемое имя не существует в рамках данного домена (существенно только для авторитетных серверов), 4 - сервер не может выполнить запрос данного типа, 5 - сервер не может удовлетворить запроса клиента в силу административных ограничений безопасности, 6-15 - зарезервировано)
QDCOUNT - количество записей в секции запросов
ANCOUNT - количество записей в секции ответов
NSCOUNT - количество записей в секции Authority (в нашем случае всегда 0)
ARCOUNT - количество записей в секции Additional (в нашем случае всегда 0)

Структура секции Question:
image

QNAME - доменное имя, представленное в виде последовательности меток. Возможно два варианта записи этой последовательности:

  1. Если первые два бита метки - 00, то остальные 6 бит определяют длину метки, за которой следует данное количество октетов, затем следует новая длина метки и новое количество октетов, и так пока не будет встречен нулевой байт.
    Полученные октеты содержат коды символов запрашиваемого имени, разделённого на части в соответствии с доменными зонами. Например, имя yandex.ru будет разделено на 2 части yandex и ru, в первой части 6 символов, соответственно, нам понадобится 6 октетов для его хранения и первое число в метке будет 6. За ним будут следовать 6 закодированные символов (y, a, n ,d, e, x). Следом будет идти новая длина метки - 2 (так как "ru" содержит 2 символа) и два октета с закодированными символами. Следом будет идти нулевой байт, говорящий о том, что имя закончено.

  2. Если первые два бита метки - 11, то последующие 14 бит определяют ссылку на начальный адрес последовательности меток первого типа. Ссылка представляет собой сдвиг относительно начала DNS пакета.

QTYPE- тип записи (NS, A, TXT и т.д.)
Данная реализация сервера поддерживает только записи типа A.
QCLASS- класс записи (IN для записей класса Internet, самого широко используемого)

Структура секции Answer:
image

NAME- доменное имя в таком же формате, как и в секции запросов
TYPE- тип ресурсной записи (NS, A, TXT и т.д.)
CLASS- класс ресурсной записи (IN для Internet)
TTL - допустимое время хранения данной ресурсной записи в кэше неответственного DNS-сервера в секундах
RDLENGTH - длина поля RDATA в байтах
RDATA - поле данных. В случае стандартного запроса и типа записи А, содержит 4 октета с IP адресом.

Принцип работы получается следующим:

  1. Сервер запускается на 53-ем порту и ожидает запросов.
  2. Сервер принимает запрос от клиента и проверяет его на корректность (qr=0, qdcount>0). В случае, если запрос некорректен, сервер отправляет ответ, включающий секции Header и Question, с Rcode=1. В случае, если запрос корректен, проверяется, что opcode равен нулю. В случае, если opcode не равен нулю, отправляется ответ с Rcode=4 (операция не поддерживается).
  3. В случае, если запрос корректен и opcode равен нулю, проводится поиск записей с запрошенным доменным именем в файле RR.txt.
  4. Если запись была найдена, формируется ответ, включающий секции Header, Question и Answer. В секции Header в поле ID копируется ID из запроса, в поле QR устанавливается 1 (пакет является ответом), Opcode=0 (стандартный запрос), AA=0 (сервер не является авторитетным для каких-либо доменных имён, поэтому АА всегда 0), TC=0, RD копируется из запроса, RA=1, RCODE=0 (запрос прошёл без ошибок), QDCOUNT =1, ANCOUNT равен количеству найденных IP адресов, NSCOUNT и ARCOUNT равны нулю. В секцию Question копируется секция question из запроса (или первая запись из этой секции, если записей больше, чем одна). В секцию Answers заносятся найденные IP адреса. Для каждого найденного IP в поле Name записывается доменное имя (используется второй тип последовательности меток), в поле Type - 1 (тип А), в поле Class - 1 (класс IN), в поле TTL - 300, в поле Rlength - длина поля Rdata, а в поле Rdata - собственно найденный IP.
  5. Если не было найдено ни одной записи для данного доменного имени, пакет от клиента пересылается на адрес 8.8.8.8, ответ с этого адреса пересылается клиенту, а полученные с помощью этого запроса IP адреса сохраняются в файл RR.txt.

Пример работы

Сервер был запущен с ip 0.0.0.0 на порте 53:
image

Содержание файла RR.txt в начале работы сервера:
image

Запрос на сервер с помощью утилиты dig (имя имеется в RR.txt):
image
Получаем верный ответ с сервера

Запрос на сервер с помощью утилиты dig (имени нет в RR.txt):
image
По TTL видно, что ответ не был сконструирован на сервере (TTL != 300)

Содержание файла RR.txt после этого запроса:
image

Повторим запрос и по увидим, что теперь ответ не перенаправляется откуда-то, а собирается на сервере (TTL = 300):
image

Результат при отправке пакета с opcode !=0:
image
Видно, что пришёл пакет со статусом NOIMPL

@wrbbz wrbbz added the Вторая лабораторная Реальные UDP протоколы label Nov 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Вторая лабораторная Реальные UDP протоколы Зачтено
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants