DNS設定 · 2 min read · Oct 02, 2025

Debian 10でDockerを使用して動的DNSサーバーをデプロイする方法

動的DNSは、ドメイン名を動的(一時的、頻繁に変化する)IPアドレスにマッピングするためのネットワークサービスです。これは、静的IPアドレスを持たないコンピュータ(SOHO(小規模オフィス/ホームオフィス)ネットワーク内のものなど)にアクセスするために使用され、NATファイアウォールの背後にあるシステムにアクセスするためにポートフォワーディングと組み合わせて使用されることがよくあります。この記事では、Debian 10システム上のDockerコンテナ内で動的DNSサーバーを完全にセットアップする方法を説明します。必要なDNSレコードの設定、Nginx HTTPSリバースプロキシの背後に管理APIを配置し、クライアント側のDNSレコードの更新を自動化することを含みます。

要件

  • 単一のDebian 10サーバー、オプションでIPv6接続。 (192.0.2.2および2001:0db8::0db9は、それぞれサーバーのIPv4およびIPv6のプレースホルダーとして使用されます。)
  • rootユーザーへのアクセス、またはsudo権限を持つユーザー。
  • ホスト上でtcp/53およびudp/53ポートが利用可能である必要があります。
  • 登録済みのドメイン名とそのネームサーバー/ゾーンファイルへのアクセス。このドメインのDNSレコードを次のセクションに示すように作成します。
  • $EDITOR環境変数が設定されている必要があります。
  • オプションで、自動DNSレコード更新を設定するためのLinux/Unixクライアントシステム。

DNSレコードの作成

動的DNSサーバーが機能するためには、少なくとも2つのDNSレコードを作成する必要があります。まず、ns1.your_domainのようなサブドメインを選択し、これがサーバーのIPv4アドレスを指すようにします。次に、ddns.your_domainのようなサブドメインを選択し、これがns1.your_domainに委任されます。

動的DNSサーバーは、ddns.your_domainの下のすべてのレコードを処理します。タイプAAAAの3番目のレコードはオプションです。対応するレコードは次のようになります:

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は、DDNSサーバーが実行されるdockerイメージをビルドするために必要です。
  • apt-transport-httpsca-certificatescurlgnupg2および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のインストール

DockerのGPGキーを追加します:

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サーバーは、BindをDNSサーバーとして使用し、Goで書かれた管理APIを使用するdockerコンテナによって動かされます。まず、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レコードがキャッシュされる時間を指定します。頻繁に変化する動的IPには60秒のTTLが推奨されます。

必要に応じて、次のコマンドを使用してシークレットのランダムな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

新しいレコードを作成するためにAPIにGETリクエストを送信します:

注意: 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を使用してそれを保護します。まず、certbotを使用してLet’s EncryptからSSL証明書を取得します:

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:クライアント設定

Pfsenseなどのカスタム動的DNSプロバイダーをサポートするルーターで自動レコード更新を設定できます。また、オフィスや家庭のネットワーク内のほとんどの他のデバイスでも設定できます。レコードを更新または作成するには、次のエンドポイントにGETリクエストを送信する必要があります:

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

1つのリクエストで複数のサブドメインのレコードを更新することもできます。例えば、sub1.ddns.your_domainとsub2.ddns.your_domainのレコードをIPアドレス198.51.100.100で作成/更新するには、次のURLにGETリクエストを送信します:

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

addrパラメータには、AAAA DNSレコードを作成/更新するためにIPv6アドレスを持たせることもできます。例えば:

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}"

このスクリプトは、クライアントのパブリックIPアドレスを取得し、変数に格納するdigコマンドをラップしたwhileループを使用します。ループは、パブリックIPが正しく取得されることを保証します。その後、cURLを使用してこの新しく取得したIPでDNSレコードを更新するAPIリクエストを送信します。your_secretとyour_subdomainの値を置き換えることを忘れないでください。

次に、このスクリプトを実行可能にします:

chmod +x /opt/ddns-update.sh

次に、crontabエディタを起動します:

crontab -e

crontabの最後に次の行を追加します:

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

保存して終了します。これで、スクリプトは2分ごとに実行され、クライアントの最新のパブリックIPアドレスで動的DNSレコードを最新の状態に保ちます。

さらなる読み物

  • 動的DNS Wikipedia記事
  • docker-ddns on Github
Share: X/Twitter LinkedIn

新しい投稿を受信箱で受け取る

スパムはありません。いつでも購読を解除できます。