Перейти к содержимому
RootPoligon

Имя и адрес

Чтение и практика ~60 мин

вы проверяете, куда на самом деле идёт запрос с нужным именем, и не принимаете «по IP отвечает» и «пинг есть» за доказательство, что служба работает для пользователей.

Лаборатория и подготовка — архив один для всех пяти глав. Перед новым сценарием остановите прежний через Ctrl+C.

Что нового

На одном адресе и порту веб-сервер может обслуживать несколько сайтов. Какой из них ответит, сервер решает по заголовку Host, который клиент берёт из адреса: http://notes.lab.test:18080/… → Host: notes.lab.test:18080. Если обратиться по адресу http://127.0.0.1:18080/…, заголовок будет Host: 127.0.0.1:18080 — и ответит другой сайт, если он настроен.

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

curl -i -H 'Host: notes.lab.test' http://127.0.0.1:18080/путь
curl -i --resolve notes.lab.test:18080:127.0.0.1 http://notes.lab.test:18080/путь

Для HTTP они равноценны. Чем они различаются для HTTPS, разберём в главе 5.

Подготовка

Из папки курса, в первом окне: python3 lab/netlab.py start ch2.

Ситуация

Суббота, 17 октября, 09:15. Ночью «Заметки 3.0» переехали на новый сервер. Старый (версия 2.9) пока не выключен — «на всякий случай». Мобильное приложение 3.0 ходит на http://notes.lab.test:18080/api/v2/notes, и с утра пользователи видят «Ошибка 404».

Администратор Пётр пишет:

Новый сервер работает, проверил:

$ curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:18080/health
200
$ ping -c 1 notes.lab.test          # (вывод — учебная модель)
PING notes.lab.test (127.0.0.2) 56(84) bytes of data.
64 bytes from notes.lab.test (127.0.0.2): icmp_seq=1 ttl=64 time=0.041 ms

С нашей стороны всё в порядке, это приложение.

Мини-задача

До разбора запишите:

  1. Что именно доказывает каждая из двух проверок Петра и чего она не доказывает? По одной строке на проверку.

  2. Повторите запрос пользователя и запишите участок (1–4 из главы 1) и одну строку вывода, которая на него указывает:

    python3 lab/netlab.py fetch http://notes.lab.test:18080/api/v2/notes
    
Наблюдения, которые можно сделать (открывайте по одному)
Н1. Проверка Петра целиком, с телом ответа
python3 lab/netlab.py fetch http://127.0.0.1:18080/health
Н2. Что отвечает DNS
python3 lab/netlab.py dig notes.lab.test
Н3. Запрос с нужным именем на новый сервер
curl -sS -i --noproxy '*' -H 'Host: notes.lab.test' http://127.0.0.1:18080/api/v2/notes
Н4. Куда соединяется клиент пользователя
python3 lab/netlab.py fetch --verbose http://notes.lab.test:18080/api/v2/notes 2>&1 | grep -E 'Trying|Connected|X-App'

Разбор мини-задачи

Откройте, когда записали свои ответы

Проверка по IP. Тело ответа (Н1) — «Добро пожаловать… сайт по умолчанию». Запрос без имени попал в сайт по умолчанию, который отвечает 200 на любой путь. Доказано: на 127.0.0.1:18080 принимают соединения и отвечает HTTP-сервер. Не доказано: что сайт notes.lab.test там работает и что пользователи вообще приходят на этот адрес. -o /dev/null спрятал тело — единственное, что отличало «наш сайт» от «чей-то».

Пинг. В строке ответа — адрес 127.0.0.2. Это старый сервер: имя у Петра разрешилось в старый адрес. Пинг доказывает только, что этот адрес отвечает на служебные сообщения ICMP; он не проверяет ни порт, ни HTTP, ни сайт. Петра пинг успокоил, хотя показал адрес, по которому видна причина.

Запрос пользователя. HTTP/1.1 404, X-App-Version: 2.9; в --verbose — Trying 127.0.0.2:18080 (Н4). Участки 1–3 работают, ответ приходит — но от старого сервера, где пути /api/v2/… нет. Причина на участке 1: DNS отдаёт старый адрес (Н2: 127.0.0.2, TTL 3600). Новый сервер исправен: с правильным именем (Н3) — 200, X-App-Version: 3.0.

Развилка: 09:30, что делать

Запись DNS ведёт Ирина (инфраструктура), она в сети. Решения (порядок случайный):

  • А. Перезапустить новый сервер: вдруг сайт notes.lab.test не загрузился.
  • Б. Попросить Ирину поменять запись notes.lab.test на 127.0.0.1, проверить dig; предупредить поддержку, что у части пользователей ошибка может держаться до часа; старый сервер пока не выключать.
  • В. Как Б, и на время до истечения старых ответов настроить старый сервер передавать запросы на новый; записать, что эту настройку нужно снять.
  • Г. Выключить старый сервер: тогда клиенты увидят, что он не работает, и пойдут на новый.
  • Д. Передать разработчикам, что маршрут /api/v2/notes отвечает 404.

Для выбранного: что увидит пользователь в 09:45 и в 10:45.

Последствия
  • А. Новый сервер и так отвечает правильно (Н3); перезапуск ничего не меняет, пользователи по-прежнему ходят на старый.
  • Б. После смены записи dig отдаёт 127.0.0.1. Клиенты и промежуточные резолверы, которые уже получили старый ответ, могут хранить его до конца TTL — до часа; у них 404 продолжится. После истечения старых ответов клиенты с обычным TTL-кэшированием получат новый адрес. Это не обещание для любого клиента: постоянная запись в hosts или дополнительный кэш требуют отдельной проверки. Допустимо, если час ошибок у части пользователей приемлем и об этом знает поддержка.
  • В. То же, но пользователи со старым ответом тоже получают ответ нового сервера сразу. Цена — изменение на старом сервере, которое нужно не забыть убрать. Допустимо, если час ошибок неприемлем.
  • Г. Без смены записи пользователи будут ходить на выключенный адрес — вместо 404 получат отказ в соединении (код 7 из главы 1) до тех пор, пока запись не исправят. Причина не устранена, ошибка стала хуже.
  • Д. На новом сервере маршрут работает (Н3); разработчики ничего не найдут.

Приёмка

  • Для каждой проверки Петра записано, что она доказывает и чего нет, — со ссылкой на строку вывода (тело «сайт по умолчанию», адрес 127.0.0.2 в пинге).
  • Есть команда, которая отправляет запрос с именем notes.lab.test на 127.0.0.1, и её ответ — 200 с X-App-Version: 3.0.
  • Есть вывод dig с адресом и TTL, и вы объясняете, как TTL влияет на то, когда пользователи перестанут видеть ошибку.
  • Выбранное решение называет условие: сколько ошибок допустимо и кто об этом предупреждён.

Подсказки

Подсказка 1 — направление

Проверки Петра касаются адреса и пинга. А что делает клиент пользователя: с каким именем и на какой адрес он идёт?

Подсказка 2 — нужное наблюдение

Посмотрите тело ответа Петра (Н1), адрес в строке пинга и что отвечает DNS (Н2). Затем отправьте запрос с нужным именем на новый адрес (Н3) и сравните X-App-Version.

Подсказка 3 — разбор

Ответ по IP пришёл от сайта по умолчанию — это не notes.lab.test. Пинг показал старый адрес 127.0.0.2 и проверил только ICMP. Пользователь получает 404 от старого сервера (2.9), потому что DNS отдаёт старый адрес с TTL 3600; новый сервер с правильным именем отвечает 200 (3.0). Чинить — запись DNS (её владелец — Ирина). Допустимы Б (если час ошибок у части пользователей приемлем и предупреждён) и В (если нет: старый сервер временно передаёт запросы на новый). А и Д чинят то, что исправно; Г превращает 404 в отказ соединения. Альтернативный путь наблюдения: вместо -H 'Host: …' — --resolve notes.lab.test:18080:127.0.0.1; для HTTP результат тот же.

Второй вариант

Та же суббота, 12:30. Опоры меньше. Перезапустите лабу со сценарием ch2b. Ирина поменяла запись в 10:00; у всех пользователей ошибка прошла. Но скрипт выгрузки Бориса, который работает на отдельном сервере, всё ещё получает 404. Вы подключились к серверу Бориса. В лабе его особенности воспроизводит учебная копия файла hosts: lab/hosts.boris.

Н1. DNS с сервера Бориса
python3 lab/netlab.py dig notes.lab.test
Н2. Запрос скрипта Бориса
python3 lab/netlab.py fetch --hosts lab/hosts.boris http://notes.lab.test:18080/api/v2/notes
Н3. Что отвечает резолвер сервера Бориса
python3 lab/netlab.py resolve --hosts lab/hosts.boris notes.lab.test

На настоящем сервере это getent hosts notes.lab.test: так имя разрешает сама система — по порядку из строки hosts: в /etc/nsswitch.conf (обычно files dns: сначала /etc/hosts, потом DNS). dig спрашивает сервер имён напрямую и /etc/hosts не читает.

Решения (порядок случайный):

  • А. Попросить Ирину проверить запись ещё раз и уменьшить TTL.
  • Б. Подождать ещё час: у сервера Бориса, наверное, свой кэш.
  • В. Попросить владельца сервера Бориса убрать строку notes.lab.test из /etc/hosts, затем проверить getent hosts и запрос скрипта.
  • Г. Выключить старый сервер, чтобы скрипт Бориса перешёл на новый.
  • Д. Сбросить кэш DNS на сервере Бориса.
  • Е. Пока владелец сервера Бориса недоступен — оставить старый сервер и настроить его передавать запросы на новый; записать, что снять после правки /etc/hosts.
Подсказка 1

dig и запрос скрипта говорят разное. Кто из них спрашивает то же, что скрипт?

Подсказка 2

Посмотрите Н3: откуда взят адрес? Прочитайте lab/hosts.boris.

Подсказка 3 — разбор

DNS уже правильный (Н1: 127.0.0.1), но система на сервере Бориса сначала читает /etc/hosts, а там с 16 октября осталась строка 127.0.0.2 notes.lab.test от проверки перед переездом (Н3: «источник: файл»). Буквальный повтор прошлого решения — чинить DNS (А) — бесполезен: запись верна. Б и Д тоже: это не кэш, строка в файле не истечёт. Г — скрипт получит отказ соединения вместо 404. Допустимы В (убрать строку — устранить причину) и Е (временная мера, пока владелец недоступен, с записью, что снять). Факт, который меняет решение: dig и резолвер системы отвечают по-разному — значит, причина не в DNS, а в том, что читается до него.

Источники

Тексты сообщений могут отличаться между сборками curl. Поведение учебного DNS и службы задаёт лаборатория; в главе 2 вывод ping обозначен как модель. TTL в опыте — поле ответа, кэширование всех реальных клиентов лаборатория не воспроизводит.

Прочитали и разобрались? Отметьте урок — прогресс сохранится в этом браузере.