DNS и TLS: как браузер находит и проверяет сервер
Оглавление · HTTP · Reverse proxy
Задача: проследить путь от URL до защищённого соединения и локализовать сбой. Нужны основы HTTP и процессов. Рассматриваем обычный HTTPS по TCP; HTTP/3 использует QUIC и разобран в следующей главе.
URL задаёт несколько независимых вещей
Для https://media.example.invalid/photos/sky.webp?size=small схема задаёт HTTPS,
имя — media.example.invalid, стандартный порт — 443, путь — /photos/sky.webp,
query — size=small. Fragment после # обычно остаётся в браузере и не входит
в HTTP-запрос. Домен example.invalid вымышленный; это не рабочий сайт.
Исходник схемы
flowchart TD URL["URL: схема, имя, порт, путь"] --> DNS["Получить адрес для имени"] DNS --> TCP["Соединиться с адресом и портом"] TCP --> TLS["TLS: проверить сервер и согласовать ключи"] TLS --> HTTP["HTTP: имя сайта, метод, путь, заголовки"] HTTP --> Response["Ответ: статус, заголовки, тело"]
Браузер может использовать кеши и существующее соединение; схема показывает ответственность этапов, а не обязательный новый обмен для каждого изображения. DNS-ответ не подтверждает, что порт открыт. TCP-соединение не подтверждает сертификат. Успешный TLS не проверяет содержание страницы.
DNS — распределённое пространство имён
DNS хранит записи разных типов. A задаёт IPv4-адрес, AAAA — IPv6, CNAME — другое имя, NS — серверы зоны; TXT используется, например, при подтверждении управления доменом. DNS не задаёт HTTP-путь и обычно не выбирает сервис по порту URL. Авторитетный сервер отвечает за зону, recursive resolver ищет ответ для клиента и кеширует его. Root и TLD помогают найти сервер зоны, а не обслуживают сайт. Модель DNS, RFC 1034.
Исходник схемы
sequenceDiagram participant Client as Клиент participant Resolver as Recursive resolver participant Authority as Авторитетный сервер зоны Client->>Resolver: Запись A для site.example.invalid? Note over Resolver: При cache miss найти сервер зоны через делегации Resolver->>Authority: Запись A для имени? Authority-->>Resolver: Адрес и TTL Resolver-->>Client: Ответ из найденной записи Note over Resolver: Следующий запрос может обслужить кеш
TTL ограничивает время обычного кеширования записи; это не единый таймер «распространения DNS» во всём интернете. При смене адреса часть клиентов ещё использует старый ответ. Снижение TTL после изменения не сокращает уже выданный старый TTL. NXDOMAIN обозначает отсутствие имени, а пустой ответ конкретного типа не обязательно означает отсутствие самого имени. Отрицательные ответы тоже могут кешироваться. Отрицательное кеширование, RFC 2308.
Для чтения записей своего учебного домена:
dig site.example.invalid A
dig site.example.invalid AAAA
Смотрите status, ANSWER и сервер, который ответил. +short удобен для адресов,
но скрывает часть диагностического контекста. Успех A при неверном AAAA может
давать разные результаты у IPv4- и IPv6-клиентов. Это не повод удалять IPv6
наугад: сначала проверьте, куда он ведёт и доступен ли сервис этим путём.
Внутренняя Docker-сеть разрешает имена сервисов отдельно от публичного DNS. Имя web:3000 удобно Caddy внутри Compose, но браузер пользователя его не знает. Запись внешнего домена в DNS не создаёт контейнер или маршрут Caddy.
TLS устанавливает защищённый канал
TLS согласует параметры и ключи, обеспечивает конфиденциальность и целостность обмена и обычно аутентифицирует сервер сертификатом. Клиент проверяет цепочку доверия, срок и соответствие имени сертификату. Сервер доказывает владение приватным ключом; сертификат содержит публичный ключ. Сам сертификат не является общим секретом. TLS 1.3, RFC 8446.
Исходник схемы
sequenceDiagram participant Browser as Клиент participant Caddy as TLS-сервер Caddy Browser->>Caddy: ClientHello: параметры, SNI, ALPN Caddy-->>Browser: Параметры, сертификат и доказательство владения ключом Note over Browser: Проверить имя, доверие и обмен Browser->>Caddy: Завершить handshake Browser->>Caddy: HTTP внутри защищённого канала
Схема опускает детали криптографии. SNI сообщает желаемое серверное имя при handshake, до обычного HTTP-запроса; оно помогает выбирать сертификат на общем IP. HTTP Host или :authority затем задаёт адресата HTTP-запроса. Изменение Host после подключения к IP не подменяет имя для проверки сертификата. SNI, RFC 6066. ALPN согласует прикладной протокол, например h2 или http/1.1. ALPN, RFC 7301.
HTTPS подтверждает защищённое соединение с проверенным именем. Оно не гарантирует, что владелец сайта добросовестен, данные верны или пользователь имеет право читать CMS. Аутентификация пользователя и авторизация операций остаются задачей приложения. При TLS termination в Caddy канал до браузера защищён; отдельное соединение Caddy → web в нашем Compose использует HTTP внутри сети. Это разные участки.
Сертификат тоже имеет жизненный цикл
Для публичных имён Caddy автоматически получает и обновляет сертификаты через ACME и добавляет перенаправление HTTP → HTTPS. Требуются подходящие DNS-записи, доступность портов для выбранной проверки и постоянное writable-хранилище Caddy. Явный адрес http:// в локальной конфигурации отключает automatic HTTPS для него. Caddy Automatic HTTPS.
HTTP-01 доказывает управление через специальный HTTP-путь на порту 80; TLS-ALPN-01 — через специальный TLS-обмен на 443; DNS-01 — через TXT-запись. Возможность обычного GET страницы не равна прохождению каждой ACME-проверки. DNS-01 требует отдельной интеграции; в проект её не добавляем. ACME-проверки Let's Encrypt.
В Atmanki compose сохраняет /data Caddy в named volume caddy_data. Удаление контейнера и удаление этого тома имеют разные последствия. Ошибка выпуска или обновления сертификата диагностируется по DNS, доступности и логам Caddy; отключение проверки TLS у клиента не исправляет сервер.
Проверяйте по слоям
| Симптом | Следующий вопрос | Чего вывод пока не доказывает |
|---|---|---|
| Имя не найдено | Какой resolver и какой тип записи? | Состояние приложения |
| Адрес получен, connect timeout | Доступны ли маршрут, порт, firewall? | Неверный сертификат |
| Ошибка сертификата | Какое имя, срок, цепочка и время клиента? | Ошибка React |
| TLS успешен, HTTP 502 | Какой upstream выбран и доступен? | Отказ DNS клиента |
| HTML 200, изображение 404 | Каков URL, rewrite, bucket и key? | Отказ всего TLS-входа |
Timeout может иметь несколько причин; таблица задаёт направление проверки, а не однозначный диагноз по одному сообщению.
Для своего домена используйте ограниченное ожидание и обычный GET:
curl --connect-timeout 5 --max-time 15 --fail --silent --show-error \
--output /dev/null --write-out 'status=%{http_code} version=%{http_version}\n' \
https://site.example.invalid/api/health
Команда с вымышленным именем ожидаемо не проверяет реальный VPS. curl -I делает HEAD, а не GET; используйте тот метод, который входит в контракт проверки. Не добавляйте -k: он отключает проверку сертификата и ослабляет вывод опыта. Опции curl.
Упражнение
Для двух клиентов один домен даёт разные адреса. Нарисуйте источники ответов и кеши, затем предложите проверку. Во втором случае подключение к IP успешно, но сертификат не подходит URL: какие имена участвуют в DNS, SNI и HTTP? Не меняйте записи production ради опыта. Дальше — прокси и транспорт HTTP.