簡単なDynamicDNSサービスを作ってみる

NetBSD/i386 6.1はDynamic DNSに対応したBIND 9.9.2-P1が含まれているので、パッケージでApacheをインストールして、CGIが動作する設定にしたところで、Dynamic DNSの更新を行うシェルスクリプトBASIC認証かけて動かすといった安直な方法でDynamicDNSサービスを作ってみた。
まずはBASIC認証のために.htaccessを作成する。
AuthUserFileにパスワードファイルのパス名を、SPECIAL_NAMEにDynamic DNSサービスで使うドメイン名を、SPECIAL_PATHにDynamic DNSの更新に使うキーファイルのパス名を指定する。
GnuDIPで使っているキーファイルがあるなら、それを共用できる。

<Files update.cgi>
        AuthName update
        AuthType Basic
        AuthUserFile /usr/pkg/share/httpd/www/.htpasswd
        Require valid-user
        SetEnv SPECIAL_NAME example.jp
        SetEnv SPECIAL_PATH /usr/pkg/share/httpd/www/Kwww-key.+157+xxxxx.key
</Files>

Dynamic DNS更新のためのシェルスクリプト(update.cgi)を作成する。
ユーザー名をホスト名として現在割り当てられているIPアドレスを調べ、アクセス元のIPアドレスと違う場合にDynamic DNSの更新を行っている。

#!/bin/sh
set -f
echo "Content-type: text/plain; charset=iso-8859-1"
echo
HOST_ADDR=`host $REMOTE_USER.$SPECIAL_NAME | sed -e 's/.* //'`
if [ "$REMOTE_ADDR" = "$HOST_ADDR" ]; then
        echo "$REMOTE_USER.$SPECIAL_NAME has address $HOST_ADDR"
        exit 0
fi
nsupdate -k $SPECIAL_PATH << EOT
update delete $REMOTE_USER.$SPECIAL_NAME.
update add $REMOTE_USER.$SPECIAL_NAME. 60 IN A $REMOTE_ADDR
send
quit
EOT
if [ $? -eq 0 ]; then
        echo "$REMOTE_USER.$SPECIAL_NAME was updated address to $REMOTE_ADDR from $HOST_ADDR"
        exit 0
fi
exit 1

あとはこのCGIに定期的にクライアントからwgetコマンドやWebブラウザ等でアクセスするだけでDynamic DNSの更新が行える。

wget http://www.example.jp/cgi-bin/update.cgi --http-user hogehoge --http-password hoge001 -O -

パスワードファイルはhtpasswdコマンドで作成する。この例ではユーザー名にhogehoge、パスワードにhoge001を指定してる。さらにユーザーを追加する時には下記コマンドの「-bc」を「-b」に変えて繰り返し行う。

htpasswd -bc .htpasswd hogehoge hoge001

キーファイルはdnssec-keygenコマンドで作成する。この例ではキー名にwww-keyを指定してる。

dnssec-keygen -a HMAC-MD5 -b 512 -r /dev/urandom -n HOST www-key

キーファイルを作成したら末尾がprivateのファイル内容から「Key: 」に続くキー内容を確認して/etc/named.confに設定する。
Dynamic DNSサービスで使用するドメインで書き換えられたくないホスト名があればdenyで指定する。
GnuDIPで既に同様の設定をしているなら必要ない。GnuDIPではキー名にgnudip-keyってのを使ってる。

(前略)
key "www-key" {
        algorithm hmac-md5;
        secret "WnbgsD/zItOzCrt1TTV2Z/p47ZJV2fXim0XvzW5aj0OFKUWQZ6ZK7t/GmJZTi5BjhgF6gScpIL5wK1bej/OAVA==";
};

zone "example.jp" {
        type master;
        file "example.jp";
        update-policy {
                deny www-key name ns.example.jp.;
                grant www-key subdomain example.jp.;
        };
};