Вопрос или проблема
Я пытаюсь использовать контейнер Docker в качестве локального DNS-сервера для переписывания IP-адреса существующего домена внутри частной сети.
Моя настройка заключается в том, что у меня есть частная сеть с несколькими машинами и маршрутизатором, который имеет общедоступный IP-адрес. Одна из этих машин обслуживает некоторый контент в интернете под доменом (например, example.com), который указывает на публичный IP, при этом порт маршрутизируется от маршрутизатора к этой машине. Дело в том, что другим машинам в частной сети также нужен доступ к этому серверу. Однако маршрутизатор блокирует пакеты, исходящие изнутри, от доступа к публичному IP. Поэтому я подумал, что использую этот контейнер в качестве локального DNS-сервера, чтобы переписать этот публичный IP на локальный.
В общем, вот эта сеть:
- Ubuntu-машина с IP 192.168.1.6 ~> узел Docker
- Ubuntu-машина с IP 192.168.1.4 ~> узел контента для example.com
- другие машины с диапазоном IP 192.168.1.0/8
- DNS-сервер всех машин настроен на 192.168.1.6
Теперь BIND настроен с использованием этого compose-файла:
version: '2'
services:
bind:
image: sameersbn/bind:latest
restart: always
dns: 8.8.8.8
logging:
driver: "json-file"
options:
max-size: "200k"
max-file: "10"
environment:
- ROOT_PASSWORD=somepass
ports:
- 10000:10000
- 53:53/udp
volumes:
- ./data:/data
и имеет такую конфигурацию:
acl localclients {
192.168.0.0/16;
172.17.0.0/16;
172.23.0.0/16;
localhost;
localnets;
};
options {
directory "/var/cache/bind";
dnssec-validation auto;
auth-nxdomain no;
listen-on-v6 { any; };
listen-on {
any;
};
recursion yes;
allow-query { any; };
allow-recursion {
localclients;
};
allow-query-cache { localclients; };
}
В настоящее время запрос имени домена на хост-машине Docker (с IP 192.168.1.6), а также на других машинах в той же сети (IP 192.168.1.x) работает как ожидается:
$ nslookup example.com
Server: 192.168.1.6
Address: 192.168.1.6#53
Name: example.com
Address: 192.168.1.4
но я не могу использовать это в другом контейнере:
$ docker run --rm busybox nslookup example.com
Server: 192.168.1.6
Address 1: 192.168.1.6 servername
Name: example.com
Address 1: 188.15.221.88
когда я принуждаю использовать только локальный DNS-сервер, я получаю следующий вывод:
$ docker run --rm --dns 192.168.1.6 busybox nslookup example.com
nslookup: can't resolve 'example.com'
Server: 192.168.1.6
Address 1: 192.168.1.6
Я не уверен, является ли это проблемой Docker или конфигурацией BIND.
ну это не ответ, а скорее решение, которое я нашел, так что я не буду отмечать его как ответ.
Я не смог найти каких-либо решений для этого, возможно, это ошибка Docker, возможно, (странная) желаемая функциональность. Однако, так как мне действительно нужно было найти решение, я использовал --add-host
для команды run и extra-hosts
в файлах compose, чтобы преодолеть эту проблему.
Решение на основе “–net=host”
Одним из вариантов было бы запустить второй Docker с --net=host
. Тогда --dns 192.168.1.6
должен работать, потому что второй Docker имеет ту же сетевую конфигурацию, что и хост.
Решение на основе “пользовательской мостовой сети”
-
Создайте пользовательскую сеть Docker типа
bridge
с фиксированной подсетью (это делает возможным установку статических IP адресов для контейнеров):docker network create --subnet=172.18.0.0/24 dns-network
-
Запустите “dns docker контейнер”, открывая DNS-порт 53 и подключая его к сети Docker:
docker run --publish 53:53 --net=dns-network --ip 172.18.0.53 sameersbn/bind:latest
-
Запустите другой Docker-контейнер и настройте
172.18.0.53
как DNS-сервер:docker run --dns=172.18.0.53 --net=dns-network busybox nslookup example.com
Ответ или решение
Решение проблемы с разрешением DNS через BIND сервер в Docker
Вы столкнулись с проблемой доступа к домену example.com
в контейнере Docker, где должен использоваться локальный DNS-сервер для перенаправления запросов внутри частной сети. Обратите внимание, что проблема заключается в разрешении имен внутри другого Docker-контейнера и попытке установить связь с частной сетью через локальный DNS.
Анализ проблемы
-
Четыре основных элемента настройки:
- У вас есть частная сеть, где некоторые машины (включая Docker-хост) должны разрешать
example.com
через локальный DNS-сервер (BIND). - DNS-сервер, работающий в контейнере на Docker-хосте с IP
192.168.1.6
. - Сервер контента
example.com
на устройстве с IP192.168.1.4
. - Проблема возникает при попытке разрешения DNS-запросов внутри Docker-контейнеров.
- У вас есть частная сеть, где некоторые машины (включая Docker-хост) должны разрешать
-
Особенности Docker:
- При запуске контейнера Docker, он может использовать отдельную сеть по умолчанию, что не всегда позволяет ему обращаться к вашей сети для разрешения имен или использовать локальный BIND-сервер из контейнера.
Предложенные решения
-
Использование параметра
--net=host
:- Запуск контейнера с помощью
--net=host
позволит контейнеру использовать сетевой стек хоста, тем самым использовав DNS-сервер хоста для разрешения. Однако это влечет за собой потерю изоляции сети, что может быть критично в некоторых сценариях.
- Запуск контейнера с помощью
-
Настройка пользовательской сети bridge:
- Создайте мостовую сеть с фиксированным подсетью:
docker network create --subnet=172.18.0.0/24 dns-network
- Запустите BIND контейнер в этой сети с конкретным IP:
docker run --publish 53:53 --net=dns-network --ip 172.18.0.53 sameersbn/bind:latest
- При запуске других контейнеров, например, с busybox, укажите использование этой сети и DNS-сервера:
docker run --dns=172.18.0.53 --net=dns-network busybox nslookup example.com
- Создайте мостовую сеть с фиксированным подсетью:
Профессиональные рекомендации
-
Проверка конфигураций: Убедитесь, что BIND сервер правильно настроен для прослушивания
53
порта и обработки запросов от всех потенциальных клиентов в вашей сети. -
Настройка доступа: Проверьте ACL (Access Control List) в конфигурации BIND, чтобы разрешить доступ для всех необходимых подсетей, включая подсетку пользовательской мостовой сети.
-
Логирование и диагностика: Используйте логи Docker и BIND для диагностики проблем. Это может помочь выявить отсутствие доступа к DNS-серверу или любые другие потенциальные ошибки в конфигурации.
Работая с Docker и сетевой изоляцией, важно учитывать, как контейнеры взаимодействуют друг с другом и с хостовой системой. Подходы, указанные выше, дают возможность гибко настраивать взаимодействие через DNS внутри Docker-контейнеров с использованием различных методов.