🔥 DNS: Или Почему Ваш Сайт Лежит, А Вы Даже Не Подозреваете Отчего
🎯 Спойлер: интернет работает не так, как вы думаете
Слушайте, прошлый раз мы разбирали, как ваш nginx жрёт оперативу и сыпется под нагрузкой. Сегодня поговорим о DNS — той самой магической хуйне, из-за которой половина ваших проблем, но винить вы будете "кривые руки разработчиков".
Формула дня: Незнание DNS × Боевой сервер = Даунтайм в 3 часа ночи
🐕 Собака vs ваша компания: раунд 2
Знаете, что общего у DNS и дрессировки собак? АБСОЛЮТНО НИЧЕГО. Потому что собаку можно научить команде "сидеть" за неделю, а вы за 15 лет не можете понять базовые принципы резолвинга доменов.
Собака: Слышит команду → Выполняет → Получает награду
Ваш DevOps: Видит ошибку → Гуглит → Копирует первое решение со StackOverflow → "У меня работает!"
Разница в том, что собака хотя бы понимает причинно-следственные связи.
💀 Как работает DNS: версия для тех, кто спал на парах
Иерархия, о которой никто не ебёт
ROOT (.)
|
┌──────────────┼──────────────┐
.com .ru .org
| | |
google.com mail.ru wikipedia.org
|
www.google.com
Видите эту ёлочку? Это DNS-иерархия. Каждый уровень — это отдельный сервер. И каждый раз, когда кто-то говорит "просто добавь CNAME", я хочу показать ему эту схему и спросить: "А ты вообще понимаешь, сколько запросов это породит?"
Что происходит, когда вы вводите example.com
Что думает бизнес:
Браузер → Магия → Сайт открылся ✨
Что происходит реально:
// 1. Браузер спрашивает у ОС
resolver.query('example.com', 'A')
// 2. ОС проверяет /etc/hosts
// Кстати, кто прописал тут 127.0.0.1 для прода?
if (hostsFile.contains('example.com')) {
return hostsFile.get('example.com') // Сюрприз, блять!
}
// 3. Идём к кешу DNS resolver'а
if (cache.has('example.com') && !cache.isExpired()) {
return cache.get('example.com') // Единственный нормальный момент
}
// 4. Рекурсивный запрос к корневым серверам
// Тут начинается настоящее веселье
rootServer.query('.')
→ tldServer.query('.com')
→ authoritative.query('example.com')
→ return '93.184.216.34'
// 5. Кешируем на TTL
cache.set('example.com', '93.184.216.34', ttl=3600)
// И вот тут начинаются все проблемы
🔪 Типы DNS-записей: то, что вы постоянно путаете
A-запись (Address)
example.com. 3600 IN A 93.184.216.34
Что это: связывает домен с IPv4-адресом.
Реальный пример из боевого конфига:
# Файл: /etc/bind/zones/prod.zone example.com. IN A 192.168.1.1 # ВНУТРЕННИЙ IP В ПУБЛИЧНОЙ ЗОНЕ, СУКА # Диалог на встрече: # — Почему сайт не открывается у клиентов? # — Потому что 192.168.1.1 — это локальный адрес # — А в чём проблема? # — ...
CNAME (Canonical Name)
www.example.com. IN CNAME example.com. blog.example.com. IN CNAME hosting-provider.com.
Критическое правило: CNAME не может сосуществовать с другими записями на том же уровне.
Как это выглядит в реальности:
# Конфиг от компании на 200+ человек mail.example.com. IN CNAME mailserver.com. mail.example.com. IN MX 10 mx1.mailserver.com. # ← ТАК НЕ РАБОТАЕТ, ЕБАТЬ # Почта не работала 3 дня # — Но мы же всё по инструкции делали! # — По какой инструкции? Статья на Хабре 2008 года? # — ...
MX (Mail Exchange)
example.com. IN MX 10 mail1.example.com. example.com. IN MX 20 mail2.example.com.
Приоритет: чем меньше число, тем выше приоритет.
История про "оптимизацию":
# Было: example.com. IN MX 10 mail.google.com. ✅ # Стало после "улучшения": example.com. IN MX 50 mail.google.com. example.com. IN MX 10 localhost. # 💀💀💀 # Результат: 10,000 писем ушли в /dev/null # — Я хотел добавить резервный сервер! # — Резервный сервер на localhost? # — А что не так? # — Где контракты на $2M, которые пришли письмами? # — ...
TXT-записи: где происходит основная ебля
example.com. IN TXT "v=spf1 include:_spf.google.com ~all" _dmarc.example.com. IN TXT "v=DMARC1; p=reject; rua=mailto:admin@example.com"
SPF, DKIM, DMARC — это не аббревиатуры из корпоративного жаргона, это то, что отделяет вашу почту от папки "Спам".
Классические отмазки:
✅ "Наши письма попадают в спам, Gmail виноват"
❌ SPF не настроен, DKIM отсутствует, DMARC не слышали
✅ "Мы же не спамим!"
❌ У вас нет DMARC-политики, и ботнет радостно использует ваш домен
✅ "Это слишком сложно настроить"
❌ Собака за 3 дня научилась не гадить на диван, а вы за месяц не можете скопировать 3 строчки
⏱️ TTL: время жизни или время страданий
Что такое TTL
example.com. 3600 IN A 93.184.216.34
^^^^
Это TTL в секундах, блять
TTL = Time To Live — сколько секунд DNS-запись живёт в кеше резолвера.
Золотое правило, которое все игнорируют
За 24-48 часов до миграции снижайте TTL до 300 секунд (5 минут).
Реальная история:
# Пятница, 18:00 PM: "Переезжаем на новый сервер в понедельник в 9:00" Я: "Нужно снизить TTL прямо сейчас" PM: "Зачем так рано? Сделаем в понедельник утром" Я: "Потому что текущий TTL 86400 секунд — это 24 часа кеша" PM: "Да ладно, успеем" # Понедельник, 09:05 - Меняем DNS: 93.184.216.34 → 93.184.216.99 # Понедельник, 10:00 PM: "ПОЧЕМУ У ПОЛОВИНЫ КЛИЕНТОВ САЙТ НЕ РАБОТАЕТ?" Я: "Потому что их DNS-резолверы будут обновлять кеш ещё 23 часа" PM: "ТЫ ДОЛЖЕН БЫЛ ПРЕДУПРЕДИТЬ!" Я: *пересылаю письмо от пятницы* PM: *читает, молчит* # Убытки: ~$50,000 за даунтайм # Моя премия: отменена "за недостаточную коммуникацию" # Моё резюме: обновлено
Рекомендации по TTL:
- Стабильная система: 3600-86400 секунд (1-24 часа) — норм, экономим запросы
- Перед миграцией: 300 секунд (5 минут) — СДЕЛАЙТЕ ЭТО ЗАРАНЕЕ, БЛЯТЬ
- Во время миграции: 60-300 секунд — если хотите спать спокойно
- После миграции (48ч): возвращаем обратно к 3600+
- "Мы стартап, быстро меняемся": 300-600 секунд — перестаньте оправдываться, у вас просто всё регулярно падает
🔥 DNS-кеширование: уровни ада
Пользователь вводит example.com
↓
[Браузер кеш] ← Хранит ~1 минуту, точное время — загадка
↓
[ОС кеш] ← Windows: systemd-resolved, Mac: mDNSResponder
↓
[Router/ISP кеш] ← Тут живут настройки вашего провайдера
↓
[Recursive resolver] ← 8.8.8.8, 1.1.1.1 или корпоративный DNS
↓
[Root servers] ← 13 корневых серверов (на самом деле их сотни)
↓
[TLD servers] ← .com, .ru, .org и т.д.
↓
[Authoritative] ← Ваш DNS-сервер с реальными данными
Проблема: вы контролируете только последний уровень. Все остальные — это чёрные ящики со своими правилами кеширования.
Собака vs ваш подход к DNS (раунд 3)
Собака учится команде:
- Слышит команду
- Пробует выполнить
- Получает фидбек
- Запоминает правильный вариант
Ваш подход к DNS:
- Что-то сломалось
- Гуглите "dns not working"
- Применяете первое решение
- "У меня работает!" (работает ли?)
- Через месяц та же проблема, и вы опять не помните, что делали
Итог: собака после 10 повторений понимает систему. Вы после 10 повторений всё ещё не понимаете, что TTL не обновляется мгновенно.
💣 Propagation: почему "подождите 24-48 часов" — это хуйня
Классический диалог:
Техподдержка хостинга: "DNS-изменения распространяются за 24-48 часов" Клиент: "Почему так долго?" Техподдержка: "Так работает интернет"
Реальность:
- DNS-изменения распространяются мгновенно
- Проблема в кешировании на разных уровнях
- Время обновления зависит от TTL, который был установлен ДО изменений
Математика:
// У вас был TTL = 86400 (24 часа)
// Кто-то запросил ваш домен в 08:00
cache.set('example.com', 'old-ip', ttl=86400)
// Вы поменяли IP в 09:00
authoritative.update('example.com', 'new-ip')
// Но кеш того пользователя обновится только в 08:00 следующего дня
// Потому что TTL был установлен на момент первого запроса
// ПОЭТОМУ СНИЖАЮТ TTL ЗАРАНЕЕ, ЁБАНЫЙ В РОТ
🎪 Реальные кейсы: как всё ломается на проде
Кейс 1: "просто поменяй IP"
# Было: example.com. 86400 IN A 93.184.216.34 # PM в пятницу вечером: # "Завтра переезжаем, просто поменяй IP" # Суббота, 10:00 example.com. 86400 IN A 93.184.216.99 # Поменяли # Суббота, 10:05 # 50% пользователей видят новый IP # 50% пользователей видят старый IP (из кеша) # Старый сервер уже выключен # Результат: сайт лежит для половины пользователей на 24 часа # Бизнес: "КАК ТАК ПОЛУЧИЛОСЬ?"
Правильный подход:
# Среда example.com. 86400 IN A 93.184.216.34 # Текущее состояние # Четверг (за 48ч до миграции) example.com. 300 IN A 93.184.216.34 # Снизили TTL # Суббота (миграция) example.com. 300 IN A 93.184.216.99 # Поменяли IP # Максимальное время обновления: 5 минут # Понедельник (через 48ч после миграции) example.com. 86400 IN A 93.184.216.99 # Вернули TTL обратно
Кейс 2: CNAME-апокалисис
# Разработчик решил "оптимизировать" # Было: www.example.com. IN A 93.184.216.34 # Стало: www.example.com. IN CNAME cdn.cloudflare.com. www.example.com. IN A 93.184.216.34 # ← Оставили для "надёжности" # DNS-сервер: *молча игнорирует A-запись* # Браузер: *пытается открыть cdn.cloudflare.com* # Результат: "This domain is not configured" # Разработчик: "Но я же добавил CNAME для ускорения!" # Я: "Ты читал RFC хотя бы одним глазом?" # Разработчик: "А что такое RFC?" # Я: *обновляю резюме*
Кейс 3: круговая зависимость
# "Умный" конфиг: example.com. IN CNAME www.example.com. www.example.com. IN CNAME example.com. # DNS-резолвер: # 1. Запрос example.com → CNAME на www.example.com # 2. Запрос www.example.com → CNAME на example.com # 3. Запрос example.com → CNAME на www.example.com # 4. Запрос www.example.com → ... # 5. *CNAME loop detected* # 6. SERVFAIL # Сайт: не работает вообще никак # Время обнаружения: 6 часов (да, ШЕСТЬ ЧАСОВ) # Причина задержки: "Мы думали, это проблема на стороне клиентов"
🔬 Диагностика: инструменты, которые вы не используете
dig — ваш лучший друг
# Простой запрос dig example.com # Запрос конкретного типа записи dig example.com MX # Запрос к конкретному DNS-серверу dig @8.8.8.8 example.com # Трассировка всей цепочки запросов dig +trace example.com # Короткий вывод (только ответ) dig +short example.com
Реальный пример отладки:
# Жалоба: "Сайт не открывается" $ dig example.com # Результат: ;; ANSWER SECTION: example.com. 3600 IN A 127.0.0.1 # БИНГО! Кто-то оставил тестовую запись в проде # Время на поиск проблемы: 30 секунд # Время, потраченное до этого на "перезагрузи сервер": 2 часа
nslookup — для тех, кто привык к Windows
# Простой запрос nslookup example.com # Запрос к конкретному серверу nslookup example.com 8.8.8.8 # Интерактивный режим nslookup > set type=MX > example.com
host — минималистичный вариант
# Простой запрос host example.com # Все записи host -a example.com # Обратный DNS (PTR) host 93.184.216.34
🏥 DNS-здоровье: чеклист перед катастрофой
Проверка 1: все ли NS-серверы отвечают?
# Получаем список NS-серверов dig example.com NS +short # Проверяем каждый dig @ns1.example.com example.com dig @ns2.example.com example.com # Если хотя бы один не отвечает — у вас проблемы
Реальный случай:
$ dig example.com NS +short ns1.example.com. ns2.example.com. ns3.example.com. $ dig @ns1.example.com example.com # ✅ Работает $ dig @ns2.example.com example.com # ✅ Работает $ dig @ns3.example.com example.com # ❌ Таймаут # Оказалось: ns3 лежит уже 6 месяцев # Но работало, потому что были ns1 и ns2 # Пока ns1 не упал под нагрузкой # И 50% трафика пошло на мёртвый ns3
Проверка 2: SOA и serial
dig example.com SOA
# ANSWER SECTION:
example.com. 3600 IN SOA ns1.example.com. admin.example.com. (
2024100101 ; Serial (должен увеличиваться после каждого изменения)
7200 ; Refresh
3600 ; Retry
1209600 ; Expire
86400 ) ; Minimum TTL
Если serial не увеличился после изменений — изменения не применились.
Проверка 3: DNSSEC (если используете)
dig example.com +dnssec # Должны быть RRSIG-записи # Если их нет, а DNSSEC включен — сайт не работает для части пользователей
🎭 DNS и CDN: где начинается веселье
# Типичная настройка с Cloudflare example.com. IN A 104.21.x.x # IP Cloudflare example.com. IN A 172.67.x.x # Ещё один IP Cloudflare www.example.com. IN CNAME example.com.
Что происходит:
- Браузер резолвит example.com → получает IP Cloudflare
- Браузер подключается к Cloudflare
- Cloudflare проксирует запрос на ваш реальный сервер (origin)
- Если Cloudflare лежит — лежит и ваш сайт
Частая ошибка:
# В конфиге Cloudflare указали origin IP Origin IP: 93.184.216.34 # Но забыли открыть порты на файрволе origin-сервера для Cloudflare IP # Результат: Cloudflare работает, но не может подключиться к origin # Пользователь видит: "Error 522: Connection timed out" # Диагностика заняла 4 часа, потому что: # "Но мы же проверили — Cloudflare работает!"
🚨 Типичные факапы и как их избежать
Факап 1: забыли продлить домен
# Домен истёк # DNS-записи удалены # Сайт не работает # Email не работает # Бизнес: "КАК ТАК ВЫШЛО?" # Я: "Регистратор слал уведомления 3 месяца" # Бизнес: "Они шли на почту прошлого админа" # Я: "..."
Решение: настройте мониторинг срока действия домена хотя бы за 60 дней.
Факап 2: изменили DNS на домене с важной почтой
# Было: example.com. IN MX 10 mail.google.com. # "Переехали на новый хостинг" # Стало: example.com. IN A [новый IP] # MX-запись забыли скопировать # Результат: вся почта потеряна # Время обнаружения: когда клиент спросил "где контракт?"
Решение: перед изменением DNS делайте полный бэкап всех записей.
Факап 3: глобальный поиск-замена
# В зоне было 200 записей # Решили поменять старый IP 93.184.216.34 на новый # Сделали глобальный поиск-замена во всём файле # Заменили даже то, что не нужно было: # Было: mail.example.com. IN A 93.184.216.50 cdn.example.com. IN A 93.184.216.34 # Стало: mail.example.com. IN A [новый IP] # ← ПОЧТА СЛОМАЛАСЬ cdn.example.com. IN A [новый IP] # ← CDN СЛОМАЛСЯ
Решение: меняйте записи точечно, а не глобально.
🎓 Советы для тех, кто ещё не сдох
Для разработчиков
- Изучите RFC 1034 и RFC 1035 — базовые документы по DNS. Да, они скучные. Да, их нужно прочитать.
- Используйте локальный DNS для разработки:
# /etc/hosts 127.0.0.1 local.example.com
- Не прописывайте IP напрямую в коде:
// ❌ Плохо const API_URL = 'http://93.184.216.34/api' // ✅ Хорошо const API_URL = 'http://api.example.com/api'
- Тестируйте с разными DNS-резолверами:
- Google: 8.8.8.8
- Cloudflare: 1.1.1.1
- Quad9: 9.9.9.9
Для DevOps
- Автоматизируйте проверки DNS:
#!/bin/bash
# dns-check.sh
DOMAIN="example.com"
EXPECTED_IP="93.184.216.34"
ACTUAL_IP=$(dig +short $DOMAIN | head -n1)
if [ "$ACTUAL_IP" != "$EXPECTED_IP" ]; then
echo "DNS MISMATCH: Expected $EXPECTED_IP, got $ACTUAL_IP"
exit 1
fi
- Мониторьте все NS-серверы:
for ns in $(dig NS example.com +short); do
dig @$ns example.com || echo "NS $ns is down!"
done
- Держите бэкап DNS-зоны:
dig example.com AXFR > backup-$(date +%Y%m%d).zone
Для менеджеров (да, для вас тоже)
- DNS-изменения требуют времени. Если разработчик просит снизить TTL за 48 часов до миграции — это не блажь, это необходимость.
- "Просто добавь CNAME" — это не всегда "просто". Спросите сначала, что это сломает.
- Домены нужно продлевать. Настройте автоплатёж и уведомления минимум на 3 email.
- DNS — это не то, на чём стоит экономить. Платные DNS-сервисы типа AWS Route53 или Cloudflare Enterprise стоят копейки по сравнению с убытками от даунтайма.
📊 Статистика, которая бьёт по больному
Исследование Verisign (2023):
- 82% компаний испытывали проблемы с DNS за последний год
- Средний даунтайм из-за DNS: 4.7 часа
- Средний ущерб: $140,000 за инцидент
ThousandEyes State of the Internet (2024):
- 41% проблем с доступностью сайтов связаны с DNS
- Среднее время обнаружения DNS-проблем: 47 минут
- Среднее время решения: 3.2 часа
Перевожу на человеческий:
- Половина ваших даунтаймов — из-за DNS
- Вы узнаете об этом через час
- Чините ещё 3 часа
- Теряете кучу денег
- Всё потому что не снизили TTL перед миграцией
🔥 Финальные мысли выгоревшего техлида
Знаете, что меня добивает больше всего? Не то, что DNS сложный — он простой как две копейки. Добивает то, что одни и те же грабли, одни и те же ошибки, одни и те же "но у меня работает!" годами.
Собака после 10 повторений понимает систему команд.
Вы после 10 одинаковых инцидентов всё ещё не понимаете, что TTL нужно снижать заранее.
Может, проблема не в DNS?
📚 Ссылки для тех, кто хочет стать умнее (спойлер: не станете)
- RFC 1034 — Domain Names: Concepts and Facilities
- RFC 1035 — Domain Names: Implementation and Specification
- DNSViz (dnsviz.net) — визуализация вашего DNS
- Verisign Labs — исследования по DNS-безопасности
- OARC (dns-oarc.net) — операторы DNS-инфраструктуры
P.S. Если после прочтения этого поста вы всё ещё не понимаете, зачем снижать TTL перед миграцией, просто увольтесь. Серьёзно. Вам не сюда. Идите разводить собак — там хотя бы результат виден.
P.P.S. Собака поняла бы эту статью с первого раза.