# Руководство по настройке локального DNS-сервера на CoreDNS **Версия:** 1.0 **Дата:** 28.05.2026 **Цель:** Настройка сервера имен для локальных сервисов (домен .zailon.ru) с возможностью работы при отсутствии интернета. ## Введение CoreDNS — это гибкий DNS-сервер, написанный на Go. В данной инструкции мы настраиваем его как Docker-контейнер. Он будет выполнять две функции: 1. Отдавать локальные IP-адреса для сервисов внутри домена `zailon.ru`. 2. Перенаправлять (форвардить) все остальные запросы (например, google.com) на публичные DNS. ## Требования * Сервер Ubuntu 24.04 (или аналогичный Linux). * Установленный Docker и Docker Compose. * Статический IP-адрес сервера (в примере: 192.168.1.201). * Права пользователя `root`. --- ## Шаг 1: Подготовка файловой структуры Создаем рабочие директории на сервере, где будут храниться конфигурация и файлы зон. ```bash mkdir -p /opt/coredns/zones ``` --- ## Шаг 2: Освобождение порта 53 на хосте По умолчанию в Ubuntu сервис `systemd-resolved` "слушает" порт 53 на локальном интерфейсе. Это не даст CoreDNS запуститься. Нужно отключить встроенный DNS-слушатель. 1. Открываем конфигурационный файл: ```bash sudo nano /etc/systemd/resolved.conf ``` 2. Находим строку `#DNSStubListener=yes`, раскомментируем её (убираем решетку) и меняем значение на `no`: ```text DNSStubListener=no ``` 3. Перезапускаем сервис сети для применения изменений: ```bash sudo systemctl restart systemd-resolved ``` 4. Проверяем, что порт 53 освободился (вывод должен быть пустым): ```bash sudo ss -tulpn | grep :53 ``` --- ## Шаг 3: Создание конфигурации CoreDNS (Corefile) Создаем файл `Corefile`, который говорит серверу, как обрабатывать запросы. Важно использовать плагин `file` для BIND-зоны. ```bash nano /opt/coredns/Corefile ``` Содержимое файла: ```text 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-адрес`. ```bash nano /opt/coredns/zones/zailon.ru.zone ``` Содержимое файла: ```text $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` (для сети). ```bash nano /opt/coredns/docker-compose.yml ``` Содержимое: ```yaml 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: Запуск и Проверка 1. Запускаем контейнер: ```bash cd /opt/coredns docker compose up -d ``` 2. Проверяем логи (должно быть сообщение о загрузке конфигурации): ```bash docker logs coredns ``` 3. Проверяем локальные записи (должен вернуть внутренний IP): ```bash dig @192.168.1.201 book.zailon.ru +short ``` 4. Проверяем внешние записи (должен вернуть публичный IP): ```bash dig @192.168.1.201 google.com +short ``` --- ## Полезные команды * **Перезагрузка конфига без рестарта контейнера** (сработает плагин reload): ```bash docker restart coredns ``` * **Проверка синтаксиса Corefile перед запуском:** ```bash docker run --rm -v /opt/coredns/Corefile:/Corefile coredns/coredns -conf /Corefile ``` * **Трассировка DNS-запроса для отладки:** ```bash 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`. Убедитесь, что файл заканчивается пустой строкой. --- ## Безопасность 1. **Ограничение доступа:** В данном конфиге порт 53 открыт только для локальной подсети через привязку к интерфейсу `192.168.1.201`. Внешний интерфейс (WAN) не слушает этот порт. 2. **Режим Read-Only:** Файлы конфигурации смонтированы с флагом `:ro` (Read Only), что предотвращает случайную модификацию конфигов изнутри контейнера. 3. **Обновления:** Регулярно выполняйте `docker compose pull` и `docker compose up -d` для обновления образа CoreDNS. 4. **Резервное копирование:** Сохраняйте копии `Corefile` и `zailon.ru.zone` в отдельное хранилище. Потеря этих файлов потребует ручного восстановления записей. --- ## 🤖 AI Контекст для аварийного восстановления Скопируйте этот блок и сохраните в отдельный файл `ai_emergency_context.txt`. При аварии отправьте его нейросети целиком. Она мгновенно восстановит состояние системы. ```text [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 --- ```