Как работает метод HTTP GET по отношению к протоколу DNS?

17

Я пытаюсь понять протоколы прикладного уровня в стеке TCP / IP. Я знаю, что протокол HTTP и DNS остаются на верхнем уровне (прикладной уровень). Поэтому, когда браузер хочет получить доступ к ресурсу, он должен отправить запрос на HTTP-сервер, например:

GET www.pippo.it/hello.htm HTTP/1.1

Делая этот запрос, следуя правилам протокола HTTP, он использует URL-адрес страницы, а не IP-адрес.

Я знаю, что DNS-запрос необходим для преобразования URL в IP. Итак, мой вопрос: HTTP вызывает протокол DNS? Это кажется мне невозможным, поскольку оба являются протоколами верхнего уровня (поэтому DNS не может предоставить службу HTTP). Точно так же даже TCP (который находится на более низком уровне) не может запрашивать услугу на протоколе более высокого уровня, таком как DNS.

Итак, когда происходит запрос DNS? А кто выполняет такой запрос?

Джанкарло Перло
источник
1
Не могли бы вы принять один из ответов, чтобы уточнить, какой из этих ответов отвечает на вопрос?
030

Ответы:

38

Данный HTTP-запрос на самом деле недействителен, если браузер не общается с посредником (прокси).

Ваш пример был бы похож на следующий, если бы браузер напрямую общался с веб-сервером:

GET /hello.htm HTTP/1.1
Host: www.pippo.it

Теперь, чтобы рассмотреть это в перспективе, рассмотрим модель OSI:

Модель OSI

У нас есть 3 системы в действии:

  • Клиент работает браузер
  • Веб - сервер , обслуживающий сайт
  • DNS сервер зная IP - адрес сайта

Используемые протоколы, снизу вверх (минимальное значение для OP):

  • IP
  • TCP, UDP
  • HTTP, DNS

HTTP-связь осуществляется по протоколу TCP (TCP находится поверх IP-протокола), в то время как DNS-связь, в данном случае, осуществляется по протоколу UDP (UDP также находится поверх IP-протокола).

Вот последовательность общения вкратце:

  1. Клиент , работающий браузер, запрашивает сервер DNS для Aзаписи на www.pippo.it, используя протокол UDP.

    1.1. На клиенте именно операционная система выполняет решающую часть и обращается к браузеру - браузер никогда не обращается к DNS-серверу напрямую, а через ОС, вызывая gethostbyname () или более новый getaddrinfo () . В Windows порядок, в котором ОС разрешает адреса, вероятно, определяется чем-то вроде этого , в то время как в Linux приоритет разрешения определяется/etc/nsswitch.conf

  2. DNS сервер , используя протокол UDP, реагирует на клиента с записью / IP - адрес, если он существует

  3. Клиент открывает соединение TCP на порт 80 веб - сервера и записывает следующий текст:

    HTTP-запрос:

    GET /hello.htm HTTP/1.1
    Host: www.pippo.it
    

    Вы можете повторить то же самое, выполнив что-то подобное в консоли или командной строке:

    > telnet www.pippo.it 80
    Trying 195.128.235.49...
    Connected to www.pippo.it.
    Escape character is '^]'.
    GET /hello.htm HTTP/1.1
    Host: www.pippo.it
    

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

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

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

Хрвое Шполяр
источник
4
@trikly: для этого и нужен заголовок «Host». Без него вы можете иметь только один веб - сайт за IP - адрес. Это ключевое различие между HTTP / 1.0 и HTTP / 1.1. К счастью, теперь браузеры HTTP / 1.0 встречаются редко, но если вы хотите обслуживать их, вам нужен отдельный IP-адрес для каждого сайта (они все еще могут быть размещены на одном сервере).
AE
1
@ AE Спасибо. Я думаю, что я был неясен в своем вопросе, и именно поэтому Хрвое не понял, о чем я говорю. (Я должен был указать домен, а не URL). Я рад, что вы все еще поняли.
trlkly
1
Вы говорите « Это неверный HTTP-запрос », и это в основном верно, но это ближе, чем вы предполагаете: « Чтобы разрешить переход к absoluteURIs во всех запросах в будущих версиях HTTP, все серверы HTTP / 1.1 ДОЛЖНЫ принимать форму absoluteURI в запросы ". (RFC 2616 §5.1.2) Таким образом, GET http://www.pippo.it/hello.htm HTTP/1.1будет действительный, если необычный, запрос. Это также будет действительный и обычный запрос к HTTP-прокси.
wfaulk
1
gethostbyname()несколько устарел. Можно было бы лучше использовать getaddrinfo()...
glglgl
1
@ Utku, к сожалению, нет, потому что SSH предполагает, что другой конец говорит по протоколу SSH, в то время как telnet - это простой текстовый протокол, и его можно использовать для связи с любым другим простым протоколом, таким как, например, POP3, IMAP, если они не используют SSL / TLS, в этом случае вы нужно будет обернуть сеанс telnet с помощником, как sslwrap или что-то подобное.
Хрвое Шполяр
12

HTTP передается через TCP, который является протоколом IP. Чтобы сделать HTTP-запрос, браузер должен открыть TCP-соединение, и для этого ему нужен IP-адрес назначения (то есть IP-адрес сервера). Чтобы разрешить имя хоста сервера, он, таким образом, должен выдать DNS-запрос (обычно сам DNS-запрос отправляется операционной системой, когда программа вызывает свои функции разрешения имен; однако ничто не мешает программе самостоятельно отправлять DNS-запросы в DNS. сервер). Как только соединение установлено, оно может отправить свой HTTP-запрос, который содержит путь к запрашиваемому ресурсу и поле Host с именем хоста сервера (например, Host: www.pippo.it). Имя хоста не идет в строке запроса (это было бы на самом делеGET /hello.htm HTTP/1.1), за исключением случаев, когда запрос отправляется на HTTP-прокси (и в этом случае присутствует полный URL-адрес, включая, например GET http://www.pippo.it/hello.htm HTTP/1.1, часть протокола ),

эль
источник
Спасибо, теперь стало понятнее, но не полностью. Вы пишете, что браузер должен выдать DNS-запрос. Хорошо, но после получения IP-адреса от DNS-сервера, как он его использует? Я имею в виду, что такой IP не появляется в HTTP-запросе. Поэтому я предполагаю, что есть еще один шаг перед отправкой HTTP-запроса, и я думаю, что это открытие соединения. Этот момент мне не очень понятен ... Еще раз спасибо!
Джанкарло Перло
5
Действительно, IP необходим для открытия TCP-соединения, внутри которого передается HTTP-запрос. На самом деле, IP-адрес как клиента, так и сервера отправляется вместе со ВСЕМИ пакетами соединения. Лучший способ узнать, как это работает, - это, вероятно, установить инструмент захвата пакетов (Wireshark - отличный мультиплатформенный и с открытым исходным кодом), захватить простой HTTP-запрос, отфильтровать его от остальной сетевой активности и посмотреть, как все пакеты были отправлены по проводам. На самом деле вы также должны видеть DNS-запрос перед TCP-соединением.
Ale
1
Прокси-запросы должны использовать заголовок Host, а не указывать полный URL-адрес в строке GET.
OrangeDog
1
@OrangeDog: Нет, наоборот. RFC 7230 (раздел 5.3.2) прямо говорит, что клиент, делающий запрос к прокси, ДОЛЖЕН использовать абсолютный URI в строке запроса. (Все еще должен быть заголовок хоста, дублирующий информацию из строки запроса; раздел 5.4).
Хмакхольм покинул Монику
7

Процедура идет так:

  1. Пользователь (вы) дает браузеру URL-адрес, например http://www.pippo.it/hello.htm
  2. Браузер разделяет это на три части:

    • протокол http
    • Hostname www.pippo.it
    • URL-путь /hello.htm

    (более сложный URL-адрес может содержать и другие части, пока я буду игнорировать эту возможность)

  3. Браузер знает, что для создания IP-соединения ему необходим IP-адрес. Чтобы получить IP-адрес, он должен использовать DNS (если только он не кэширован).

    1. Браузер запрашивает у операционной системы IP-адрес DNS-сервера; Предположим, это получится 8.8.8.8.
    2. Браузер создает следующее многослойное соединение:

      • Уровень IP: подключиться к 8.8.8.8
      • Уровень UDP: установить пакет для порта назначения 53
      • Уровень DNS: создайте запрос DNS для Aзаписи для имени хостаwww.pippo.it

      Конечно, я опускаю много деталей, например, о точном формате пакетов.

    3. Браузер получает ответ DNS (многоуровневый поверх UDP, многоуровневый поверх IP и т. Д.), Который дает IP-адрес для www.pippo.it, скажем,10.11.12.13
  4. Браузер знает, что для создания TCP-соединения ему нужен номер порта. Чтобы получить номер порта, он ищет протокол httpво внутренней таблице и узнает, что ему следует использовать порт 80.
  5. Браузер создает следующее многослойное соединение:

    • Уровень IP: подключиться к 10.11.12.13
    • Уровень TCP: установить пакеты на порт назначения 80
    • Уровень HTTP: создайте запрос HTTP для URL /hello.htmна хосте www.pippo.it(поскольку на компьютере 10.11.12.13может быть размещено несколько доменов, поэтому ему необходимо знать, какой из них нужен)

      GET /hello.htm HTTP/1.1
      Host: www.pippo.it
      ...
      

    Конечно, я опускаю все детали TCP-рукопожатия и тому подобное.

  6. Браузер получает HTTP-ответ (многоуровневый поверх TCP, многоуровневый поверх IP и т. Д.), Содержащий содержимое hello.htm

И в качестве меры предосторожности я упомяну, что браузер теперь анализирует содержимое этого ответа и определяет любые дополнительные ресурсы, необходимые: изображения, CSS, Javascript и т. Д. Затем он повторяет весь этот процесс для каждого такого ресурса.

Дэвид З
источник
4
Шаг 3 действительно не то, что делает само приложение. Приложение просто использует что-то вроде getaddrinfoили gethostbynameпросит ОС разрешить адрес для него. Кроме того, ОС обычно использует несколько механизмов для поиска имен, а не только DNS. (Как правило, по крайней мере, файл hosts в дополнение к DNS.)
Håkan Lindqvist
Благодарность! Это действительно впечатляющий и подробный ответ, а также очень полезный!
Джанкарло Перло