ライン

ポイント:自分でDynamic DNSを動作させることが可能に

ライン

 はじめに

GnuDIP

 久々に Dynamic IP DNS serviceを試します。
使ってみたことの無いGnuDIPですが、試してみようと思います。
サーバは、FreeBSDでBIND9と連動するように構築します。
クライアントは、FreeBSDではなく、デビアン系Linuxで、Raspberry PIで動かすようにしました。
本当に、ラズパイは便利なんです。

 導入と設定

導入

 まずはサーバ側の導入です。
FreeBSDのportsは準備されていないみたいなので、マニュアル導入となります。
リリースは、GnuDIP Release 2.3.5++という版を利用します。
zenno.comのページ(ページは最後のリンクを参照のこと)の通りにやってみます。

# cd /usr/local/www
# mkdir GnuDIP
# cd GnuDIP
# fetch http://gnudip2.sourceforge.net/gnudip-www/gnudip-2.3.5-www.tar.gz
# tar pzxvf gnudip-2.3.5-www.tar.gz
# cd gnudip-2.3.5-www/gnudip-www/src/gnudip-2.3.5/gnudip/lib
# mv dbprefs.pm dbprefs.pm.orig
# mv dbusers.pm dbusers.pm.orig
# ln -s ./dbprefs_flat.pm ./dbprefs.pm
# ln -s ./dbusers_flat.pm ./dbusers.pm

 かなり階層が深いです。上記でファイルを消してシンボリックを張り直しているのは、MySQLで利用するのではなく、ファイルベースでの管理にする際にはこうするもののようでした。

# cd ../etc
# rm Kgnudip-key.+157+*
# dnssec-keygen -a hmac-md5 -b 128 -n HOST gnudip-key
Kgnudip-key.+157+4XXX3
# chmod 400 Kgnudip-key.+157+*
# chown www:www *
# chmod 660 gnudip.conf
# vi gnudip.conf

 元々は、

# BIND 9
nsupdate = /usr/bin/nsupdate -v
nsupdate = -k /usr/local/gnudip/etc/Kgnudip-key.+157+36000.private

となっていました。

nsupdate = -k /usr/local/www/GnuDIP/gnudip-2.3.5-www/gnudip-www/src/gnudip-2.3.5
/gnudip/etc/Kgnudip-key.+157+4XXX3.private

のように、作成されたファイル名に変更しました。

 まず、ウェブ用のadminを作成しました。

# cd ../sbin
# ./gdipadmin.pl admin PASSWORD
Updated username admin with password PASSWORD and set as ADMIN
# cd ../run
# chown -R www:www *

 さて、ちょっとディレクトリ構造が長すぎてつらいので、手を入れることにしました。

# ln -s /usr/local/www/GnuDIP/gnudip-2.3.5-www/gnudip-www/src/gnudip-2.3.5/gnudip /usr/local/gnudip

こんな状態で先に進めます。

 次はBIND9側の設定です。
FreeBSDは、9.x系まではbind9がOSに含まれていますので、特に導入は不要です。
 ページに書かれたように、以下を作成しました。

# mkdir /etc/namedb/inc
# vi /etc/namedb/inc/gnudip-keyfile

以下のような内容をファイルに書き込みました。

key gnudip-key {
  algorithm hmac-md5;
  secret "(※)";
};

secretの間には、/usr/local/www/GnuDIP/gnudip-2.3.5-www/gnudip-www/src/gnudip-2.3.5/gnudip/etcの

# grep Key: Kgnudip-key.+157+*.private

で得られるKey: 以降を入れればOKです。

# cd /etc/namedb
# vi named.conf

設定ファイルには、

include "/etc/namedb/inc/gnudip-keyfile";
..
zone "dip.example.jp" {
        type master;
        file "dynamic/dip.example.jp.zone";
        allow-query { any; };
        update-policy
        { grant gnudip-key subdomain dip.example.jp; };
};

みたいにして記述を加えました。

このサブドメインが親のexample.jpのサブドメインとして別管理になるように、example.jp.zoneに以下を加えます。

dip                   NS      (プライマリのDNSのFQDN).
dip                   A        (委譲先で動作させているIPアドレス)

良くあるサブドメインの委譲を受けた状態になるわけです。

 ゾーンファイル以降の記述

dynamic/dip.example.jp.zone

 さて続きです。

# vi dynamic/dip.example.jp.zone 

とりあえず、次のようにしてみました。

$ORIGIN .
$TTL 3600               ; 1 hour
dip.example.jp         IN SOA  dip.example.jp. postmaster.example.jp. (
                                2014012500 ; serial
                                600        ; refresh (10 minutes)
                                300        ; retry (5 minutes)
                                604800     ; expire (1 week)
                                0       ; minimum (none)
                                )
                        NS      dip.example.jp.
                        A       192.168.99.99※←上記のアドレスのIPアドレス

普通に作成していれば大丈夫です。

Apacheの設定

Apacheのhttpd.confには以下のようなイメージで使えるようにしました。

Alias /html "/usr/local/gnudip/html"
<Directory "/usr/local/gnudip/html/">
    AllowOverride All
    Options None
    Order allow,deny
    Allow from all
    DirectoryIndex help.html
</Directory>

ScriptAlias /gnudip/ "/usr/local/gnudip/cgi-bin/"
<Directory "/usr/local/gnudip/cgi-bin/">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>

 apache24の場合には、

Alias /html "/usr/local/gnudip/html"
<Directory "/usr/local/gnudip/html/">
    AllowOverride All
    Options None
    Require all granted
    Allow from all
    DirectoryIndex help.html
</Directory>

ScriptAlias /gnudip/ "/usr/local/gnudip/cgi-bin/"
<Directory "/usr/local/gnudip/cgi-bin/">
    AllowOverride None
    Options None
    Require all granted
    Allow from all
</Directory>

のようになります。

LoadModule cgi_module libexec/apache24/mod_cgi.so

のように、CGIのモジュールも有効にすることを忘れずに。

# service apache22 restart

上記のようにサービスを再起動しました。これで http://〜/gnudip/gnudip.cgi でログインできるはずです。
※以降で記載していますが、SSL化が必要とお考えの方は、作業追加してください※

 テスト

nsupdate

 追加できるかを手動で試してみることに。

# sudo -u www nsupdate -v -k /usr/local/gnudip/etc/Kgnudip-key.+157+4XXX3.private
> update add test.dip.example.jp. 0 A 127.0.0.1
> show
> send
> quit

/etc/namedb/dynamic の以下にdip.example.jp.zone.jnlというファイルができるようになったと思います。
ping で test.dip.example.jp で応答が返ってくることを確認します。
 次に、一度停止してみて、ゾーンファイルへ反映されたことを確認しておきます。

# rndc stop

これにより、ゾーンファイルが更新されたことを確認します。

$ORIGIN dip.example.jp.
$TTL 0 ; 0 seconds
test                  A       127.0.0.1

ゾーンファイルが更新されたことを確認し、再起動しておきます。

# service named start

これで動作テストは完了です。

クライアントとの通信のための設定

 続けて必要な設定をサーバ側に追加しておきます。

/etc/serviceにあるかを確認しましたが、私のマシンはありませんでしたので追加しました。

gnudip          3495/tcp   #GnuDIP

として、/etc/inetd.confに以下を書き込む。

gnudip  stream  tcp     nowait  www  /usr/local/gnudip/sbin/gdipinet.pl      gdipinet.pl

inetdが上がっていない場合にはその設定を/etc/rc.confに追加してください。

# inetd
inetd_enable="YES"
inetd_flags="-wW -C 60"

…みたいな感じです。

# service inetd start
Starting inetd.

起動しました。

また、ポートがあがっているかを確認してみます。

# netstat -a | egrep 'Proto|LISTEN' |grep gnudip
#Proto Recv-Q Send-Q Local Address          Foreign Address        (state)# 便宜的にここでは記載しました#
tcp4       0      0 *.gnudip               *.*                    LISTEN

Listenしています。

PF等フィルタ設定を加えている方は、3495のポートを通すように追加が必要になりますので、忘れずに加えてください。
なお、TCP Wrapperの考慮のために、(/etc/hosts.allowに)

gdipinet.pl: .jp : allow
gdipinet.pl: ALL : deny

を加えています。
また、/var/log/messagesにアクセスされるごとに

MMM DD HH:MM:SS HOST gnudip-net: XXX.YYY.ZZZ.bbb - User test.dip.example.jp remains at ip XXX.YYY.ZZZ.bbb

のように記録が残り、ちょっとうるさくなります。
/usr/local/gnudip/etc/gnudip.confのlogger_inetの行を変更してあげることで特定ファイルへの書き出しに変更できます。

logger_inet = /usr/bin/logger -p local5.info -t gnudip-net

のように変更しています。
そして、/etc/syslog.confにも

local5.info                                     /var/log/gnudip.log

を加えています。ログは、事前にtouchを入れて、chmod 644/chown wwwで用意ください。
syslogのデーモンはHUPシグナルを送りこんであげてください。
※いつもながらに、書くのが面倒になってきて雑になるモード…気が向いたら直すかも

 クライアント

Raspberry PIに組み込み

 さて、今度はクライアント側の話です。
通常、MS Windows環境で生活していますが、常時動いているマシンがいいので、今回Raspberry PIで動作させる前提にしました。

他の用途でRaspberry PIを利用する際には、異なる方法を検討することにしますが、とりあえず今回はこれで進めます。

# cd /usr/local
# mkdir dip
# cd dip
# wget http://gnudip2.sourceforge.net/gnudip-www/latest/gnudip/html/client/UNIX/gdipc/bin/gdipc.pl
--2014-01-26 18:10:33--  http://gnudip2.sourceforge.net/gnudip-www/latest/gnudip/html/client/UNIX/gdipc/bin/gdipc.pl
gnudip2.sourceforge.net (gnudip2.sourceforge.net) をDNSに問いあわせています... 216.34.181.96
gnudip2.sourceforge.net (gnudip2.sourceforge.net)|216.34.181.96|:80 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 21280 (21K) [text/plain]
`gdipc.pl' に保存中

100%[======================================>] 21,280       114K/s 時間 0.2s

2014-01-26 18:10:33 (114 KB/s) - `gdipc.pl' へ保存完了 [21280/21280]

取得できました。以下、test.dip.example.jp を追加する例です。

# perl gdipc.pl -c
Using Update Configuration Mode
Configuration file name: /root/.GnuDIP2
Username: test
Domain: dip.example.jp
Connect by direct TCP (d) or web server (w) [d]:
GnuDIP Server - host[:port]: dip.example.jp
Password: PASSWORD
Cache File [/root/.GnuDIP2.cache.test.dip.example.jp]:
Minimum Seconds Between Updates [0]: 0
Maximum Seconds Between Updates [2073600]:

とかにしてみました。

# perl gdipc.pl
====  gdipc.pl running:  Sun Jan 26 19:12:39 2014  ====
Configuration file name: /root/.GnuDIP2
Cache file name: /root/.GnuDIP2.cache.test.dip.example.jp
Attempting update at dip.example.jp ...
Server sent invalid response to login attempt for test.dip.example.jp

エラーです。サーバ側のログを見ても同様でした。

Jan 26 21:54:37 HOST gnudip-net: IP - Invalid login attempt from IP: user test.dip.example.jp

こんなメッセージです。

ウェブGUI上からドメインとユーザの追加を行う

ユーザ作成していませんでしたね。
ウェブ画面上で、先ほど作成した admin のアカウントでログインします。
※SSL化していないのが気持ちが悪い人は、先のその手を入れてください。このページ上は割愛します。類似作業は、いくつもあるし

http://dip.example.jp/gnudip/gnudip.cgi
Add Domainで利用したい「dip.example.jp」のように追加します。
以下に入力し、追加してください。
メニューに戻り、今度は Add Userを利用し、ユーザを追加してください。
上記までの例では、testというユーザで追加することになります。
パスワードも同じものになるように追加してください。

このページは、日本語化ができるそうなので、やってみてください。
公開してくれている人はいないみたい。GPL v2だし、利用者増える機会なのに。
/usr/local/gnudip/lib/htmlgen.pm のファイルは、もろにHTMLな内容になっているので、わかりやすそうですね。

ラズパイの作業の続き

さて、クライアント側のラズベリーPCに戻ってきて、作業を再開します。

Attempting update at dip.example.jp ...
Update to address 192.168.1.2 from 0.0.0.0 successful for test.dip.example.jp

しかし、ローカルのIPアドレスを登録されてもなぁ…。NATの外側を登録して欲しいのに。

# perl gdipc.pl -g :3495

などとすると、外側のIPアドレスで登録してくれるようになりました。

# perl gdipc.pl -g :3495
====  gdipc.pl running:  Tue Dec 30 13:04:30 2014  ====
Configuration file name: /root/.GnuDIP2
Cache file name: /root/.GnuDIP2.cache.test.dip.example.jp
Attempting update at dip.example.jp ...
Update to address XXX.YYY.ZZZ.aaa from 0.0.0.0 successful for test.dip.example.jp

のようになります。コマンドのヘルプは以下の通り。

gdipc.pl \
  { -h | -v | -i [ -r] | [ -f configfile ] [ -c | -r | \
      [ -o outfile | -a appendfile | -l logfile ] \
      [ -g sendport:recvport ] [ -d repeatseconds] \
      [ -w waitseconds] [ -q "addressquerycommand" ] ] \
      [ -x "addresschangedcommand" ] }
With no arguments, update server if address changed or time
expired.
-h: Print this usage message.
-v: Show version information.
-i: Prompt and read standard input rather than a configuration
    file.
-f: Specify a particular configuration file.
    This will otherwise be .GnuDIP2 in the directory
    specified by the HOME environment variable, or gdipc.conf
    in the directory of the binary if HOME is not set.
-c: Specify contents to write to configuration file.
-r: Send an offline request to the server to remove your DNS hostname.
-d: Run as a daemon. Perform client action immediately and then every
    "repeatseconds" seconds.
-o: Specify log file to overwrite on each run with output from script.
-a: Specify log file to append on each run with all output from script.
-l: Specify log file for daemon mode. Overwrite on first run, then
    append.
-w: Timeout in seconds when waiting for address validation packet.
    Defaults to 1 second. Decimal point and fraction (e.g. "0.5") is
    allowed.
-g: Client is behind a gateway. Request GnuDIP server to register
    address it sees connection from, and pass it back in response.
    Specify port to send address validation packet to and port gateway
    will forward it to.
-q: Command to invoke to determine IP address to report to GnuDIP
    server. Command must write address to standard output. When used
    with -g, address is sent to server.
-x: Command to invoke if address changed. This command can be used to
    to take any actions required when the address changes. All
    validated addresses are passed as arguments.

 さて、自動化をします。まず、スクリプトを置きました。/var/local/dip上にrootのみが実行できるパーミッションで作成。

#!/bin/sh
cd /usr/local/dip
/usr/bin/perl ./gdipc.pl -g :3495 1>/dev/null

エラーが出る前提なので、喰わして消しているだけ。
/etc/crontabには

17,37,57 * * * * root   /usr/local/dip/dipcron.sh

のように20分毎にアクセスするようにしました。

 感想

 2014年の始めに運用を開始し、年末に再度異なるサーバで構築し直しました。
何事もなく、便利に使えています。

 このページに記載を忘れていた内容は、今回の構築の際に加えているので少しはマシになったのではと思います。

【改訂履歴】作成: 2014/ 1/25 更新: 2014/12/30
【参考リンク】

GnuDIP Dynamic DNS クライアント
GnuDIP Dynamic DNS サーバ
GnuDIP Release 2.3.5 - INSTALL File
PukiWiki de ZENNOコム/FreeBSD/gnudip
GnuDIP で DDNS (Dynamic DNS)
2013-06-25 - にゃののん日記【GnuDIPでDynamicDNSサービスを作ってみる】

Copyright © 1996,1997-2006,2007- by F.Kimura,