自分でDDNSを実現化(サブドメインの活用)
はじめに
DDNSを使う場合は、どこかに委託する必要があります。その時、自分が使っているドメインが使えないことが多いです。
そこで、自分のサブドメインを払い出し、払い出し先が動的IPアドレスで運用する場合でも可能なDDNSを構築してみました。
ネームサーバの変更をできるだけすばやく伝達することが必要です。
解決するために、apache, bind, rp-pppoe, php, w3m で実現しました。
この手法を使うためには下記のような条件を満たすことが必要です。
A:固定IPアドレスを取得している事(1個以上)
B:ドメイン名を持っている事
C:プライマリネームサーバを運営している事
関係図
プライマリ-------------------セカンダリ
固定IP 動的IP
ドメイン サブドメイン
準備
A:プライマリネームサーバからサブドメインを払い出す。
B:動的IPアドレス側にネームサーバを立ち上げて、プライマリネームサーバに対してのセカンダリネームサーバを立ち上げる。
C:プログラムインストール
プライマリ(primary.usi.nu) セカンダリ(dns.second.usi.nu)
IP(aaa.bbb.ccc.ddd 固定) IP(192.168.182.168 ダミー)
VineLinux3.2 VineLinux2.6
apache2-2.0.55-0vl1.2 rp-pppoe-3.5-0vl1
mod_ssl-apache2-2.0.55-0vl1.2 bind-8.3.1-0vl3
apache2-apr-2.0.55-0vl1.2 bind-utils-8.3.1-0vl3
php-apache2-4.4.4-0vl1 w3m-0.3.2.2-0vl0.26.1
bind-9.2.4-0vl1 php-4.2.3-0vl5
bind-utils-9.2.4-0vl1
php-4.4.4-0vl1
php-apache2-4.4.4-0vl1
php-pear-4.4.4-0vl1
D:プライマリネームサーバに /usr/local/ddns のディレクトリを作り、ddns に777の権利を与える
drwxrwxrwx 2 root root 4096 Nov 25 15:07 ddns
動作手順
A:セカンダリのIPアドレスが変更される
B:セカンダリがプライマリにhttpで伝える
C:プライマリは与えられたアドレスを更新する
D:セカンダリは変更されたアドレスを更新する
E:すべてのネームサーバに変更が更新される
1:ネームサーバを設定する
ダイナミックDNSを実現する為の設定を行う。
named.conf に追加するサブドメインの設定を追加する
---- /etc/named.conf プライマリ----
zone "second.usi.nu" {
type master;
file "second.zone";
allow-update { any; }; // <--- この行がDDNSを許可しているので「重要」
};
---- EOF ----
zoneファイルに、サブドメインを委譲する記述をする
保存場所は /var/named/primary.zone
---- primary.zone プライマリ----
second.usi.nu. IN NS primary.usi.nu. ;1台目のネームサーバ
IN NS dns.second.usi.nu. ;2台目のネームサーバ
primary IN A aaa.bbb.ccc.ddd. ;1台目のネームサーバの設定
---- EOF ----
サブドメインの設定をする
保存場所は /var/named/second.zone
---- second.zone プライマリ----
A $ORIGIN second.usi.nu.
B $TTL 86400
C @ 1D IN SOA primary.usi.nu. postmaster.primary.usi.nu. (
D 0 ; serial
E 3H ; refresh
F 15M ; retry
G 1W ; expiry
H 1D ) ; minimum
I
J IN NS dns.second.usi.nu.
K IN NS primary.usi.nu.
L IN MX 10 dns.second.usi.nu.
M IN MX 20 primary.usi.nu.
N
O $ORIGIN second.usi.nu.
P
Q localhost IN A 127.0.0.1
R
S dns IN A 192.168.192.168
---- EOF ----
行解説 通常のネームサーバ設定は省略
C プライマリサーバを設定。
J / K プライマリネームサーバとセカンダリネームサーバを設定
L メールサーバをセカンダリに設定。番号を10に設定しているので優先的に使われる
M メールサーバをプライマリに設定。番号を20に設定しているので10番が異常の場合に使われる。
S dnsにダミー番号を登録した
ネームサーバをリロード
# rndc reload
逆引きはプロバイダが管理しているので、これは委譲してもらえないので設定をしない。
2:Apache2を設定する
通常のポート(80)はWebサイトとして使いたいので別のポートを利用する。
1024番以上は利用者の好みで使えるので、今回は1179番を利用する。
保存場所は
tar なら /usr/local/apache2/conf/httpd.conf
rpm なら /etc/httpd/conf/httpd.conf
---- httpd.conf プライマリ----
Listen aaa.bbb.ccc.ddd:80
Listen aaa.bbb.ccc.ddd:1179
<VirtualHost aaa.bbb.ccc.ddd:1179>
ServerAdmin administrata@usi.nu
DocumentRoot /var/www/ddns
ServerName praimary.usi.nu
ErrorLog /var/log/httpd/error_log
CustomLog /var/log/httpd/access_log common
</VirtualHost>
---- EOF ----
この設定だと、DDNSのファイルは /var/www/ddns に入れることになる。
書き込むことはないが、全員が読み込めるようにしておく
# cd /var/www/
# mkdir ddns
# ls -l
drwxr-xr-x 2 nobody nobody 4096 Nov 29 11:34 ddns/
再起動する
# /etc/rc.d/init.d/httpd2 restart
3:セカンダリにネームサーバを追加する。
プライマリネームサーバが変更されたことをセカンダリも認識した方が環境が良くなる。
保存場所 /etc/named.conf
---- named.conf セカンダリ----
zone "second.usi.nu" {
type slave;
file "second.zone.sl";
masters {
aaa.bbb.ccc.ddd;
};
};
---- EOF ----
4:アドレス変更したかどうかの確認をする
下記ファイルをセットする
保存場所は /root/ipaddress.php4
---- ipaddress.php4 セカンダリ----
A <?php
B // dim
C $url="dns.second.usi.nu";
D $ddns="primary.usi.nu";
E $port="1179";
F // echo "dim ok\n";
G
H $wan=exec("/sbin/ifconfig ppp0 |grep inet | cut -d : -f 2 | cut -d \ -f 1");
I $nowip=gethostbyname($url);
J // echo $wan . " & " . $nowip . "\n";
K
L if ($wan != $nowip) {
M
N $atai="http://" . $ddns . ":" . $port . "/ddns.php4?zone=" .
O $url . "&rev=" . $wan;
P // echo $atai . "\n";
Q // echo "IP address renew!\n";
R system ("/usr/bin/w3m -dump '" . $atai . "'");
S // echo "DNS renew! Just wait 15 second.\n";
T sleep(15);
U system ("/usr/sbin/ndc reload");
V }
W ?>
---- EOF ----
変数解説
$url----- 自サーバのドメイン名。このアドレスとIPアドレスを関連付ける。
$ddns---- プライマリネームサーバ。ドメインの管理サーバ。
$port---- プライマリネームサーバにアドレスを送るときに使うポート番号。
$wan----- ppp0で得たIPアドレス。
$nowip--- 現在のドメインと関連付けられているIPアドレスを取得。
$atai---- プライマリネームサーバに変更されたアドレスを送る値を生成。
行解説
A / W phpの最初と終わり
C - E 変数設定
H 現在のグローバルIPアドレスを取得
I 現在ネームサーバが認識しているIPアドレスを取得
L HとIで取得した値が違っているかどうかを確認
N / O プライマリネームサーバに送る値を生成。
R w3m を使ってプライマリネームサーバに新しいIPアドレスを送信
T ネームサーバの更新を15秒間待つ
U プライマリネームサーバの値を取得しセカンダリサーバの値を更新する。
5:プライマリネームサーバの更新
プライマリネームサーバは、セカンダリネームサーバより新しいIPアドレスを送信される。
送信された情報は ddns.php4 にて処理される。
保存場所は、 /var/www/dns/ddns.php4
---- ddns.php4 プライマリ----
0A <?php
0B $burauza=$_SERVER["HTTP_USER_AGENT"];
0C
0D if (preg_match("/w3m/",$burauza)) {
0E
0F // /usr/local/ddns
0G // dim
0H $zone= $_GET["zone"] ;
0I $rev= $_GET["rev"];
0J $sv="dns.taiyudenki.co.jp";
0K $dir="/usr/local/ddns/";
0L
0M list($a,$b,$c,$d) = split('[.]',$rev);
0N $rev2 = ($d . "." . $c . "." . $b . "." . $a);
0O
0P $delzone = "update delete " . $zone . ". IN A\n";
0Q // $delrev = "update delete " . $rev2 . ".in-addr.arpa. IN PTR\n";
0R
0S $addzone = "update add " . $zone . ". 10080 IN A " . $rev . "\n";
0T // $addrev = "update add " . $rev2 . ".in-addr.arpa. 10080 IN PTR " . $zone . ".\n";
0U
0V $fl=fopen($dir . "dns2rev.txt","w");
0W fwrite($fl,"server " . $sv . "\n");
0X fwrite($fl, $delzone . "\n");
0Y // fwrite($fl, $delrev . "\n");
0Z fwrite($fl, $addzone . "\n");
AA // fwrite($fl, $addrev . "\n");
AB fclose($fl);
AC
AD system ("/usr/bin/nsupdate " . $dir . "dns2rev.txt");
AE
AF $fo=fopen($dir . $zone ,"w");
AG fwrite($fo, $rev);
AH fclose($fo);
AI
AJ } else {
AK ?>
AL <html>
AM <head>
AN <title>Dynamic DNS chaing ?</title>
AO </head>
AP
AQ <body>
AR Dynamic DNS chaing program<br>
AS Brwser no access.<br>
AT <br>
AU by sysop<br>
AV </body>
AW </html>
AX <?php }; ?>
---- EOF ----
変数解説
$burauza----- セカンダリのブラウザを取得
$zone-------- セカンダリのURLを取得
$rev--------- セカンダリのIPアドレスを取得
$sv---------- プライマリサーバのURL
$dir--------- ネームサーバ更新ファイル置き場
$a,$b,$c,$d-- IPアドレスをそれぞれのクラスに分解
$rev2-------- セカンダリよりもらった値を逆転した値
$delzone----- 旧の設定
$addzone----- 新しい設定
$fl---------- 変更する値を格納したファイルを管理
$fo---------- 変更した結果のIPアドレスを格納しているファイルの管理
行解説
0A / AX phpの最初と終わり
0B セカンダリのブラウザ名を取得
0D ブラウザがw3mかどうかを判定
0H - 0K 変数設定
0M IPアドレスを各クラスに分解
0N IPアドレスを逆展開
0P 現在のURLの設定を削除する為の値を設定
0S 最新のURLとIPアドレスを設定する為の値
0V 設定ファイルを作成の為に dns2fev.txt をオープン
0W ddnsサーバを設定ファイルに記述
0X 削除設定を設定ファイルに記述
0Z 新規の設定を設定ファイルに記述
AB 設定ファイルをクローズ
AD 設定ファイルをネームサーバに反映
AF - AH 変更が完了したことをファイルに記録。ファイル名にURL、値にIPアドレス
AJ - AW ブラウザが w3m 以外の場合に出すエラーメッセージ
6:rp-pppoeを起動する時にアドレスをチェックプログラムを起動する
rp-pppoeを起動させるファイルが、/etc/rc.d/init.d/adsl である。
IPアドレスが変更されるのは、このファイルにStartスイッチを与えたときなので、
そこにアドレスが変更されたときに移動するファイルをCallするようにする。
---- /etc/rc.d/init.d/adsl(抜粋) セカンダリ----
case "$1" in
start)
echo -n "Bringing up ADSL link"
$START
if [ $? = 0 ] ; then
touch /var/lock/subsys/adsl
echo_success
/usr/bin/php /root/ipaddress.php4 #追加
else
echo_failure
fi
echo ""
;;
---- EOF ----
7:rp-pppoeが起動しなくても、プロバイダの都合で勝手にIPアドレスを変更された時に対応。
10分おきに cron にて確認する。
---- cron セカンダリ----
*/10 * * * * /usr/bin/php /root/ipaddress.php4 > /dev/null &
---- EOF ----
8:メールの転送
IPアドレスが変更されてもすぐに全世界のネームサーバに連絡が行く訳ではありません。
そこで、ネームサーバを設定する時に補助のメールサーバを設定した。
補助のメールサーバはセカンダリのIPアドレスを常に最新(最大タイムラグ10分)で知っているので、補助に設定した。
メールがプライマリに北場合にセカンダリに転送することが必要なので、postfixに設定をする
---- /etc/postfix/transport プライマリ----
secound.usi.nu smtp:dns.secound.usi.nu # 追加
---- EOF ----
転送を反映させる
#postmap /etc/postfix/transport
#postfix reload
以上
履歴---------
2005/05/14 初版
2005/05/15 URLの見直しとファイルに存在位置を明記
2006/10/05 細かい部分を訂正
Let's PC の Topに戻る
ホームページのTopに戻る