DNS сервер · 7 min read · Oct 02, 2025

Как развернуть сервер динамического DNS с помощью Docker на Debian 10

Динамический DNS — это сетевой сервис для сопоставления доменных имен с динамическими (временными, часто меняющимися) IP-адресами. Он используется для доступа к компьютерам, которые не имеют статического IP-адреса, таким как те, что находятся в сетях SOHO (малый офис/домашний офис), и часто используется в сочетании с переадресацией портов для доступа к системам, которые находятся за NAT-файрволами. Эта статья проведет вас через полный процесс настройки сервера динамического DNS в контейнере Docker на системе Debian 10, включая настройку необходимых DNS-записей, размещение API управления за обратным прокси Nginx с HTTPS и автоматизацию обновлений DNS-записей на стороне клиента.

Требования

  • Один сервер Debian 10, желательно с поддержкой IPv6. (192.0.2.2 и 2001:0db8::0db9 будут использоваться в качестве заполнителей для IPv4 и IPv6 соответственно.)
  • Доступ к пользователю root или пользователю с правами sudo.
  • Порты tcp/53 и udp/53 должны быть доступны на хосте.
  • Зарегистрированное доменное имя и доступ к его DNS-серверам/зональному файлу. Создайте DNS-записи для этого домена, как показано в следующем разделе.
  • Переменная окружения $EDITOR должна быть установлена.
  • При желании, любая система Linux/Unix для настройки автоматических обновлений DNS-записей.

Создание DNS-записей.

Вам нужно создать как минимум 2 DNS-записи, чтобы ваш сервер динамического DNS работал. Сначала выберите поддомен, такой как ns1.your_domain, который будет указывать на IPv4-адрес вашего сервера. Во-вторых, выберите поддомен, такой как ddns.your_domain, который будет делегирован ns1.your_domain.

Ваш сервер динамического DNS будет обрабатывать все записи под ddns.your_domain. Третья запись типа AAAA является необязательной. Соответствующие записи выглядят следующим образом:

ns1.your_domain A 192.0.2.2
ddns.your_domain NS ns1.your_domain
ns1.your_domain AAAA 2001:0db8::0db9 (необязательно)

Пример DNS-записей

Вы должны создать эти записи в панели управления вашего регистратора доменов. Обратите внимание, что может потребоваться до 24 часов для полной пропаганды этих записей, но обычно это занимает минуты.

Установка

Если вы не используете пользователя root, мы рекомендуем вам начать временную оболочку root, так как большинство команд, показанных в этом руководстве, требуют повышенных привилегий. Чтобы запустить оболочку root, используйте одну из следующих команд:

sudo su - root
sudo -s

Шаг 1: Обновление и установка зависимостей.

Всегда полезно сначала обновить вашу систему:

apt update
apt upgrade -y
reboot

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

  • certbot будет использоваться для получения SSL/TLS сертификатов.
  • make необходим для сборки образа docker, в котором будет работать сервер DDNS.
  • apt-transport-https, ca-certificates, curl, gnupg2 и software-properties-common необходимы для установки репозитория Docker и его соответствующего GPG-ключа.
  • dnsutils предоставляет dig, который будет использоваться для тестирования.
apt install -y certbot make apt-transport-https curl ca-certificates software-properties-common gnupg2 dnsutils

Шаг 2: Установка Docker CE.

Добавьте GPG-ключ Docker:

curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -

Установите репозиторий docker:

add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable"

Обновите кэш репозитория Debian, затем установите docker и его зависимости:

apt update
apt install -y docker-ce docker-ce-cli containerd.io

После завершения установки убедитесь, что служба docker включена и работает следующим образом:

systemctl enable --now docker.service

Шаг 3: Загрузка и сборка docker-ddns

Наш сервер динамического DNS будет работать в контейнере docker, который использует Bind в качестве DNS-сервера и API управления, написанное на Go. Сначала клонируйте репозиторий Github и соберите образ контейнера с помощью следующих команд:

git clone https://github.com/dprandzioch/docker-ddns.git
cd docker-ddns
make image

Подождите, пока процесс завершится, что может занять некоторое время, затем откройте файл envfile с текстовым редактором:

$EDITOR envfile

И введите следующее:

SHARED_SECRET=your_secret   
ZONE=ddns.your_domain   
RECORD_TTL=60

Общий секрет — это пароль, который будет использоваться для аутентификации с API управления. ZONE указывает, за какую DNS-зону будет отвечать ваш сервер, а TTL записи указывает, как долго DNS-записи могут кэшироваться. Рекомендуется использовать TTL в 60 секунд для часто меняющихся динамических IP.

При необходимости вы можете сгенерировать случайную строку из 40 символов для секрета, используя следующую команду:

cat /dev/urandom | tr -dc "a-zA-Z0-9" | fold -w 40 | head -1

Теперь мы можем создать контейнер:

docker create -it -p 127.0.0.1:8080:8080 -p 53:53 -p 53:53/udp --env-file envfile -v /mnt/ddns-data:/var/cache/bind --name ddns-server davd/docker-ddns

Эта команда создаст контейнер с именем ddns-server из образа, который мы собрали ранее, и сопоставит порты 8080/tcp, 53/tcp и 53/udp с хоста на контейнер. Она также смонтирует директорию /mnt/ddns-data с хоста на /var/cache/bind в файловой системе контейнера. Это используется для сохранения данных DNS между пересозданиями контейнера.

Проверьте, что контейнер был создан с помощью команды:

docker container ls -a

Должен быть выведен единственный элемент с именем ddns-server.

Шаг 4: Служба systemd (необязательно)

Этот шаг предназначен для упрощения управления, но не является строго обязательным. Если вы решите не использовать службу systemd, вам придется управлять контейнером вручную или использовать другое решение для управления. Обратите внимание, что для более крупных и сложных развертываний контейнеров рекомендуется использовать решение для оркестрации, такое как Kubernetes или Docker Swarm. В этом случае служба systemd идеально подходит, так как мы запускаем только один контейнер.

Чтобы иметь возможность управлять этим контейнером как системной службой, мы обернем его в единицу systemd. Создайте файл /etc/systemd/system/ddns-server-ct.service с вашим текстовым редактором:

$EDITOR /etc/systemd/system/ddns-server-ct.service

И добавьте следующее:

[Unit]  
Description=DDNS Server Docker Container  
After=docker.service  
Requires=docker.service  
Requires=network.target  
[Service]  
Type=oneshot  
TimeoutStartSec=240  
Restart=no  
RemainAfterExit=yes  
ExecStart=/usr/bin/docker start ddns-server  
ExecStop=/usr/bin/docker stop ddns-server  
[Install]  
WantedBy=multi-user.target

Сохраните и выйдите, затем установите правильные разрешения на этот файл единицы:

chmod 664 /etc/systemd/system/ddns-server-ct.service

Загрузите новый файл службы с помощью следующей команды:

systemctl daemon-reload

Теперь вы должны иметь возможность запускать и останавливать этот контейнер, используя systemctl, как любую другую системную службу.

Если вы хотите, чтобы сервер DDNS запускался автоматически при загрузке системы, выполните следующее:

systemctl enable ddns-server-ct.service

Шаг 5: Тестирование вашего сервера

Перед тем как продолжить настройку, мы протестируем API управления локально. Запустите контейнер:

systemctl start ddns-server-ct.service

Отправьте GET-запрос к API для создания новой записи:

ПРИМЕЧАНИЕ: API в настоящее время доступен только локально (т.е. с localhost).

curl "http://127.0.0.1:8080/update?secret=your_secret&domain=test1&addr=1.1.1.1"

Curl должен вернуть следующий ответ:

{"Success":true,"Message":"Updated A record for test1 to IP address 1.1.1.1","Domain":"test1","Domains":["test1"],"Address":"1.1.1.1","AddrType":"A"}

ПРИМЕЧАНИЕ: Домен test1 относится к test1.ddns.your_domain, так как сервер обрабатывает зону ddns.your_domain.

Выполните DNS-запрос, чтобы проверить, что запись действительно была создана и протестировать разрешение DNS:

dig +short -t A test1.ddns.your_domain @127.0.0.1

Вывод должен быть 1.1.1.1.

Шаг 6: Обратный прокси

Поскольку API работает по HTTP, ваш секрет аутентификации может быть потенциально перехвачен всякий раз, когда вы отправляете запрос по сети. Злоумышленник может затем манипулировать вашими DNS-записями, используя ваш секрет. Мы настроим обратный прокси с помощью Nginx и защитим его с помощью HTTPS. Сначала получите SSL-сертификат от Let’s Encrypt с помощью certbot:

certbot certonly --standalone --agree-tos -m [email protected] -d ns1.your_domain

Право собственности на ваш домен будет проверено, и сертификат будет выдан. Затем установите Nginx и убедитесь, что он включен и работает:

apt install -y nginx systemctl enable --now nginx.service

Затем отключите файл блока сервера по умолчанию, так как он не нужен:

unlink /etc/nginx/sites-enabled/default

Теперь мы создадим новый конфигурационный файл для обратного прокси, например:

$EDITOR /etc/nginx/sites-available/ddns-api-proxy.conf

И вставьте следующее, убедившись, что вы заменили IP-адреса и доменные имена на свои:

server {  
listen 192.0.2.2:8080;  
server_name ns1.your_domain;  
ssl on;  
ssl_certificate /etc/letsencrypt/live/ns1.your_domain/fullchain.pem;  
ssl_certificate_key /etc/letsencrypt/live/ns1.your_domain/privkey.pem;  
  
location /update {  
proxy_pass http://127.0.0.1:8080;  
}  
location / {  
return 404;  
}  
access_log /var/log/nginx/ddns-api-access.log;  
error_log /var/log/nginx/ddns-api-error.log;  
}

Необязательно: Если вы хотите, чтобы API был доступен по IPv6, добавьте следующую строку после существующей директивы listen:

listen [2001:0db8::0db9]:8080;

Включите эту конфигурацию и примените изменения, перезагрузив Nginx:

ln -s /etc/nginx/sites-available/ddns-api-proxy.conf /etc/nginx/sites-enabled/
systemctl reload nginx.service

API теперь должен быть доступен через интернет и будет принимать только HTTPS-соединения. Чтобы протестировать это, выполните команду:

curl "https://ns1.your_domain:8080/update?secret=your_secret&domain=test2&addr=1.1.1.2"

Он должен вернуть следующее:

{"Success":true,"Message":"Updated A record for test2 to IP address 1.1.1.2","Domain":"test2","Domains":["test2"],"Address":"1.1.1.2","AddrType":"A"}

Шаг 7: Конфигурация клиента

Вы можете настроить автоматические обновления записей на любом маршрутизаторе, который поддерживает пользовательские провайдеры динамического DNS, таких как Pfsense. Вы также можете настроить их на большинстве других устройств в вашей офисной или домашней сети. Чтобы обновить или создать запись, должен быть отправлен GET-запрос к следующему конечному пункту:

https://ns1.your_domain:8080/update?secret=your_secret&domain=your_subdomain&addr=your_ip_address

Вы также можете обновить записи нескольких поддоменов с помощью одного запроса. Например, чтобы создать/обновить записи для sub1.ddns.your_domain и sub2.ddns.your_domain с IP-адресом 198.51.100.100, вы должны отправить GET-запрос по этому URL:

https://ns1.your_domain:8080/update?secret=your_secret&domain=sub1,sub2&addr=198.51.100.100

Параметр addr также может содержать IPv6-адрес для создания/обновления AAAA DNS-записей, например:

https://ns1.your_domain:8080/update?secret=your_secret&domain=cheese&addr=2001:0db8:aaaa::

Чтобы автоматизировать эти обновления на клиенте Linux, сохраните следующий bash-скрипт как /opt/ddns-update.sh:

#!/bin/bash  
  
while [ -z $CURRENTIP ]
do  
CURRENTIP=`dig -r +short myip.opendns.com @resolver1.opendns.com 2>/dev/null`  
sleep 1  
done  
curl -s "https://ns1.your_domain:8080/update?secret=your_secret&domain=your_subdomain&addr=${CURRENTIP}"

Этот скрипт использует цикл while, обернутый вокруг команды dig, которая получает публичный IP-адрес клиента и сохраняет его в переменной. Цикл гарантирует, что публичный IP будет правильно получен. Затем cURL используется для отправки API-запроса на обновление DNS-записи с этим только что полученным IP. Убедитесь, что вы заменили значения для your_secret и your_subdomain.

Затем сделайте этот скрипт исполняемым:

chmod +x /opt/ddns-update.sh

Затем запустите редактор crontab:

crontab -e

Добавьте следующую строку в конец вашего crontab:

*/2 * * * * /opt/ddns-update.sh

Сохраните и выйдите. Скрипт теперь будет выполняться каждые две минуты, поддерживая вашу запись динамического DNS в актуальном состоянии с последним публичным IP-адресом клиента.

Дополнительные материалы

  • Статья о динамическом DNS в Википедии
  • docker-ddns на Github
Share: X/Twitter LinkedIn

Get new posts in your inbox

No spam. Unsubscribe anytime.