11 KiB
Руководство по настройке локального DNS-сервера на CoreDNS
Версия: 1.0 Дата: 28.05.2026 Цель: Настройка сервера имен для локальных сервисов (домен .zailon.ru) с возможностью работы при отсутствии интернета.
Введение
CoreDNS — это гибкий DNS-сервер, написанный на Go. В данной инструкции мы настраиваем его как Docker-контейнер. Он будет выполнять две функции:
- Отдавать локальные IP-адреса для сервисов внутри домена
zailon.ru. - Перенаправлять (форвардить) все остальные запросы (например, google.com) на публичные DNS.
Требования
- Сервер Ubuntu 24.04 (или аналогичный Linux).
- Установленный Docker и Docker Compose.
- Статический IP-адрес сервера (в примере: 192.168.1.201).
- Права пользователя
root.
Шаг 1: Подготовка файловой структуры
Создаем рабочие директории на сервере, где будут храниться конфигурация и файлы зон.
mkdir -p /opt/coredns/zones
Шаг 2: Освобождение порта 53 на хосте
По умолчанию в Ubuntu сервис systemd-resolved "слушает" порт 53 на локальном интерфейсе. Это не даст CoreDNS запуститься. Нужно отключить встроенный DNS-слушатель.
- Открываем конфигурационный файл:
sudo nano /etc/systemd/resolved.conf
- Находим строку
#DNSStubListener=yes, раскомментируем её (убираем решетку) и меняем значение наno:
DNSStubListener=no
- Перезапускаем сервис сети для применения изменений:
sudo systemctl restart systemd-resolved
- Проверяем, что порт 53 освободился (вывод должен быть пустым):
sudo ss -tulpn | grep :53
Шаг 3: Создание конфигурации CoreDNS (Corefile)
Создаем файл Corefile, который говорит серверу, как обрабатывать запросы. Важно использовать плагин file для BIND-зоны.
nano /opt/coredns/Corefile
Содержимое файла:
zailon.ru:53 {
file /etc/coredns/zones/zailon.ru.zone zailon.ru
forward . 1.1.1.1 8.8.8.8
cache 30
reload
log
errors
}
.:53 {
forward . 1.1.1.1 8.8.8.8
cache 30
reload
log
errors
}
Разбор плагинов:
file: Читает текстовый файл зоны и отдает локальные IP.forward: Если домен неzailon.ru, шлет запрос в Cloudflare/Google.cache: Запоминает ответы на 30 секунд для скорости.reload: Автоматически перечитывает конфиг при изменениях.
Шаг 4: Создание DNS-зоны
Создаем файл с записями ваших сервисов. Формат: имя IN A ip-адрес.
nano /opt/coredns/zones/zailon.ru.zone
Содержимое файла:
$TTL 3600
@ IN SOA ns1.zailon.ru. admin.zailon.ru. (
2026052801 ; Serial
3600 ; Refresh
600 ; Retry
604800 ; Expire
86400 ; Minimum TTL
)
@ IN NS ns1.zailon.ru.
ab IN A 192.168.1.203
book IN A 192.168.1.203
bw IN A 192.168.1.202
cerberus IN A 192.168.1.208
chat IN A 192.168.1.206
cloud IN A 192.168.1.213
git IN A 192.168.1.209
jellyfin IN A 192.168.1.203
mail IN A 192.168.1.212
music IN A 192.168.1.203
nc IN A 192.168.1.205
olimp IN A 192.168.1.201
wiki IN A 192.168.1.202
Примечание: Список можно дополнять. Обязательно оставьте пустую строку в конце файла.
Шаг 5: Docker Compose
Создаем файл запуска контейнера. Мы явно привязываем порты к интерфейсам 127.0.0.1 (для локальных проверок) и 192.168.1.201 (для сети).
nano /opt/coredns/docker-compose.yml
Содержимое:
services:
coredns:
image: coredns/coredns:latest
container_name: coredns
restart: unless-stopped
ports:
- "127.0.0.1:53:53/tcp"
- "127.0.0.1:53:53/udp"
- "192.168.1.201:53:53/tcp"
- "192.168.1.201:53:53/udp"
volumes:
- /opt/coredns/Corefile:/Corefile:ro
- /opt/coredns/zones:/etc/coredns/zones:ro
dns:
- 1.1.1.1
- 8.8.8.8
cap_add:
- NET_BIND_SERVICE
Шаг 6: Запуск и Проверка
- Запускаем контейнер:
cd /opt/coredns
docker compose up -d
- Проверяем логи (должно быть сообщение о загрузке конфигурации):
docker logs coredns
- Проверяем локальные записи (должен вернуть внутренний IP):
dig @192.168.1.201 book.zailon.ru +short
- Проверяем внешние записи (должен вернуть публичный IP):
dig @192.168.1.201 google.com +short
Полезные команды
- Перезагрузка конфига без рестарта контейнера (сработает плагин reload):
docker restart coredns
- Проверка синтаксиса Corefile перед запуском:
docker run --rm -v /opt/coredns/Corefile:/Corefile coredns/coredns -conf /Corefile
- Трассировка DNS-запроса для отладки:
dig @192.168.1.201 book.zailon.ru +trace
Решение проблем (Troubleshooting)
1. Ошибка: bind: address already in use
Причина: Порт 53 занят systemd-resolved.
Решение: Выполнить Шаг 2 (отключить DNSStubListener).
2. Dig возвращает внешний IP вместо локального
Причина: CoreDNS не нашел запись в локальной зоне. Проверка:
- Убедитесь, что в
Corefileиспользуется плагинfile, а неhosts. - Проверьте права на файл зоны:
chmod 644. - Проверьте пути монтирования в
docker-compose.yml(должны быть абсолютными).
3. Контейнер не видит файлы зоны
Причина: Ошибка монтирования томов (volumes).
Решение: В docker-compose.yml используйте абсолютные пути (/opt/coredns/...), избегайте относительных (./).
4. Ошибка парсинга зоны
Причина: Синтаксическая ошибка в файле zailon.ru.zone.
Решение: Проверьте логи docker logs coredns. Убедитесь, что файл заканчивается пустой строкой.
Безопасность
- Ограничение доступа: В данном конфиге порт 53 открыт только для локальной подсети через привязку к интерфейсу
192.168.1.201. Внешний интерфейс (WAN) не слушает этот порт. - Режим Read-Only: Файлы конфигурации смонтированы с флагом
:ro(Read Only), что предотвращает случайную модификацию конфигов изнутри контейнера. - Обновления: Регулярно выполняйте
docker compose pullиdocker compose up -dдля обновления образа CoreDNS. - Резервное копирование: Сохраняйте копии
Corefileиzailon.ru.zoneв отдельное хранилище. Потеря этих файлов потребует ручного восстановления записей.
🤖 AI Контекст для аварийного восстановления
Скопируйте этот блок и сохраните в отдельный файл ai_emergency_context.txt. При аварии отправьте его нейросети целиком. Она мгновенно восстановит состояние системы.
[AI EMERGENCY CONTEXT - COREDNS SETUP]
DATE: 28.05.2026
HOST_OS: Ubuntu 24.04
SERVER_IP: 192.168.1.201
CONTAINER_NAME: coredns
IMAGE: coredns/coredns:latest
PROJECT_PATH: /opt/coredns/
FILE: /opt/coredns/Corefile
---
zailon.ru:53 {
file /etc/coredns/zones/zailon.ru.zone zailon.ru
forward . 1.1.1.1 8.8.8.8
cache 30
reload
log
errors
}
.:53 {
forward . 1.1.1.1 8.8.8.8
cache 30
reload
log
errors
}
---
FILE: /opt/coredns/zones/zailon.ru.zone
---
$TTL 3600
@ IN SOA ns1.zailon.ru. admin.zailon.ru. (
2026052801 ; Serial
3600 ; Refresh
600 ; Retry
604800 ; Expire
86400 ; Minimum TTL
)
@ IN NS ns1.zailon.ru.
ab IN A 192.168.1.203
book IN A 192.168.1.203
bw IN A 192.168.1.202
cerberus IN A 192.168.1.208
chat IN A 192.168.1.206
cloud IN A 192.168.1.213
git IN A 192.168.1.209
jellyfin IN A 192.168.1.203
mail IN A 192.168.1.212
music IN A 192.168.1.203
nc IN A 192.168.1.205
olimp IN A 192.168.1.201
wiki IN A 192.168.1.202
---
FILE: /opt/coredns/docker-compose.yml
---
services:
coredns:
image: coredns/coredns:latest
container_name: coredns
restart: unless-stopped
ports:
- "127.0.0.1:53:53/tcp"
- "127.0.0.1:53:53/udp"
- "192.168.1.201:53:53/tcp"
- "192.168.1.201:53:53/udp"
volumes:
- /opt/coredns/Corefile:/Corefile:ro
- /opt/coredns/zones:/etc/coredns/zones:ro
dns:
- 1.1.1.1
- 8.8.8.8
cap_add:
- NET_BIND_SERVICE
---
SYSTEM_STATE:
- systemd-resolved DNSStubListener = no
- Port 53 bound to 127.0.0.1 and 192.168.1.201 only
- All paths are ABSOLUTE
- Plugin used: file (NOT hosts)
- Serial: 2026052801
- Fallback DNS: 1.1.1.1, 8.8.8.8
RECOVERY COMMANDS:
1. cd /opt/coredns && docker compose down && docker compose up -d
2. dig @192.168.1.201 book.zailon.ru +short
3. docker logs coredns --tail 20
4. ss -tulpn | grep :53
---