自分で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に戻る