Раздел 11 · Network

Под капотом HTTP: DNS, TCP, TLS, keep-alive, CORS

middle-senior~35 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

Под капотом HTTP: DNS, TCP, TLS, keep-alive, CORS

До этого HTTP был для нас текстом, который как-то долетает до сервера. Пора открыть это “как-то”. Между fetch('https://api.example.com') и первым байтом ответа происходит четыре отдельных события: имя превращается в адрес, открывается TCP-соединение, поверх него договаривается шифрование, и только потом едет HTTP. А браузер вдобавок проверяет, имеешь ли ты право вообще стучаться на этот адрес. Разберём всё по слоям.

Слои: где что живёт

Модель OSI полезна как карта. На практике достаточно держать в голове стек TCP/IP:

  • Прикладной: HTTP, DNS, WebSocket. То, с чем работает твой код.
  • Транспортный: TCP и UDP.
  • Сетевой: IP, маршрутизация пакетов между сетями.
  • Канальный: Ethernet, Wi-Fi, физическая передача.

Каждый уровень заворачивает данные верхнего в свой конверт. HTTP-запрос едет внутри TCP-сегмента, тот внутри IP-пакета, тот внутри Ethernet-кадра.

Шаг 1: DNS превращает имя в адрес

Браузер не умеет соединяться с api.example.com, ему нужен IP. Этим занят DNS.

Путь одного запроса полезно знать целиком:

  1. Приложение спрашивает stub-резолвер в ОС.
  2. Тот идёт к рекурсивному резолверу (провайдер или публичный 8.8.8.8, 1.1.1.1).
  3. Резолвер идёт по иерархии: корневые серверы, серверы зоны .com, и наконец авторитетный сервер домена с настоящими записями.

Каждый шаг кешируется по TTL, включая негативные ответы (NXDOMAIN кешируется тоже, отсюда задержка у только что заведённого домена).

Типы записей: A (IPv4), AAAA (IPv6), CNAME (алиас на другое имя), MX (почта), TXT (верификация, SPF, DKIM), NS (кто отвечает за зону), SOA (параметры зоны), CAA (какому CA разрешено выписывать сертификат, про него в блоке TLS). Проверить руками:

dig api.example.com A +short
dig example.com MX
dig +trace example.com        # показать весь путь от root до авторитетного

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

  • DNSSEC подписывает записи, защита от подмены.
  • DoH и DoT шифруют сам запрос, защита приватности.

Резолверы и авторитетные серверы часто стоят на anycast (один IP из многих точек мира), поэтому DNS-ответ прилетает из ближайшей. На этом же механизме CDN раздаёт пользователям разные адреса по геолокации.

Частая боль на проде: поменяли запись, а старый адрес ещё живёт в кешах из-за TTL. Поэтому перед переездом TTL заранее опускают (например, до 60 секунд).

Шаг 2: TCP-рукопожатие

TCP даёт надёжный упорядоченный поток байтов, но за это платит круговой задержкой при установлении соединения, тем самым тройным рукопожатием:

клиент --- SYN --->        сервер
клиент <-- SYN-ACK ---     сервер
клиент --- ACK --->        сервер
(дальше можно слать данные)

Дальше начинается то, ради чего TCP и нужен, надёжность поверх ненадёжного IP. Разберём механику чуть глубже, потому что именно она объясняет задержки.

  • Sequence и ack номера: TCP нумерует байты, получатель подтверждает полученное, неподтверждённое переотправляется. Так чинятся потери и порядок.
  • Скользящее окно: сколько байт можно держать в полёте без подтверждения. Flow control ограничивает окно буфером получателя.
  • Congestion control ограничивает окно состоянием сети. Стартует со slow start, поэтому новое соединение разгоняется не сразу. Алгоритмы: CUBIC (по умолчанию в Linux), BBR (о нём в уроке 4).
  • MSS и MTU: данные режутся на сегменты под размер кадра сети.
  • Алгоритм Нейгла склеивает мелкие записи в один сегмент. Для интерактивных протоколов его гасят флагом TCP_NODELAY, иначе ловишь лишнюю задержку.

Закрытие соединения тоже не бесплатно: обмен FIN/ACK с каждой стороны, и инициатор потом висит в состоянии TIME_WAIT около двух минут. На сервере с тысячами коротких соединений это копится. RST рвёт соединение жёстко, без прощания.

Вот зачем нужен keep-alive (ниже) и почему UDP быстрее в начале обмена: у него ни рукопожатия, ни slow start, ни TIME_WAIT, поэтому на нём строят DNS, видеозвонки и QUIC. Посмотреть всё это вживую помогает Wireshark или tcpdump.

дальше после входа

Урок целиком открыт всем, кто вошёл. Войди по своему email, чтобы читать дальше.

Вход пока по приглашению. Если хочешь учиться, напиши Vassiliy.