DDNSサービスを作ってみる

先日のエントリーの続き。

追記(2019/10/10)
PHP7(MySQLi)に対応しました。DDNSサービスを作ってみる(改)へどうぞ。

DDNSサービス構築の下調べ

まずは題名の通りの下調べ。さすがに全部一から自分でDDNSサービスを作るのはさすがに面倒というか、この広い世の中にはきっと先人が情報を公開してくれていると信じてあれこれ探してみました。

DDNSでぐぐっただけだとプロバイダや何かの団体が提供している無料DDNSサービスは沢山見つかります。また、そのサービスを自宅サーバーなどで使うためのDDNSクライアントの設定記事も同様に沢山見つかります。でも、そのDDNSサービスそのものを構築する具体的な方法まで踏み込んで書いてある記事はなかなか見つからないのです。

それは確かにそうなんだと思います。そもそも自分で自由になるDNSを持っている人は全体から見てかなりの少数派です。その少数派の中でもDDNSを自分で構築してみようという人は仕事でもない限りさらに少数派ということになるんでしょう。それから、私と同じ状況なのか、DDNSサービスの作り方を質問している人が結構いらっしゃるようです。ともあれ、実際にコーディングの参考になる情報を提供している記事が幾つか見つかりました。

DDNSサービスのコード達

見つけた上記の記事の中で一番参考にしたのは一番最初のげんきさんの記事でした。理由はPHPで書かれていたことと、私の目に読みやすいソースだったからです。そこで公開されているソースが

このふたつです。これらを元にPostgreSQLだったのをMySQLに書き直しました。また、ユーザー登録とホスト名の登録の処理を別々の処理に分けました。さらにユーザーやホスト名の削除も対応したり、DDNSで使うドメインの追加・削除、ユーザーの削除を追加。登録したホスト名とIPアドレスの一覧表示など追加しました。また、POSTによるIPアドレス更新だけでなくDynDNSで使われているGETによる更新にも対応しました。

他に共通ルーチンなどなど

私はWebプログラミング初心者(事実上初めて)なので、ひたすら自分が分かり易いように目的別にコードをどんどん分けて作成したらこんな数になりました。

主な処理の流れは、ユーザーの登録、ホスト名の登録、IPアドレスの更新の順番に行います。ドメイン名の登録は特権ユーザーのみ可能とします。登録は必ず メールで認証を行います。できるだけ移植性が高くなるように作成したのでサイト共通設定情報のコードを編集するだけでほとんどの場合は対応可能だと思います。

実は ./nic/update の中身はphpです。ここはDynDNSの仕様に合わせたかったので拡張子なしでphpを実行させています。そのために./nic/.htaccessをBASIC認証とともに以下のように記述しています。また、あらかじめダミーで./nic/.htpasswd も作成しておきます。

AuthType Basic
AuthName "Administrator's Pages"
AuthUserFile /home/www/http/ddns/nic/.htpasswd
AuthGroupFile /dev/null
Require valid-user
<Files "*">
        ForceType application/x-httpd-php
</Files>

作業用のファイルの置き場として ./temporary/ と ./nic/.temporary/ のふたつのディレクトリが必要です。

データベースは phpMyAdmin などで作成し、以下のSQL文を実行して各テーブルを作ります。

create table userdata (
username varchar(32),
password varchar(32),
email varchar(64),
timestamp varchar(20),
su tinyint(1)
);

create table hostdata (
username varchar(32),
domain varchar(32),
hostname varchar(64),
current_ip varchar(16),
last_access varchar(20),
last_update varchar(20),
registration_ip varchar(16),
registration_date varchar(20)
);

create table domain (
domain varchar(32) ,
username varchar(32),
timestamp varchar(20)
);

当然、あらかじめ nsupdate によるゾーン情報のアップデートができるようにbindの設定は済ませておく必要があります。

DDNSクライアント設定ファイル

DDNSのクライアントとしてDiCEが有名です。このDiCEに対応したプラグインファイルを用意しました。

メッセージやオプションの扱いが結構手抜きですが、これらのファイルをDiCEのインストールしてあるフォルダ内のplug-inフォルダにコピーすればとりあえず使えます。

ddclientの場合はddclient.confをこんな感じに設定します。ほぼDynDNS同じです。

use=web                                 # via web

login=(ユーザー名)
password=(パスワード)

script=/ddns/nic/update
server=www.sagamiya.com,                \
protocol=dyndns2                        \
(ホスト名).6db.net

適切に設定すればssl=yesも使えます。

DDNSサービス試用サイト

試用サイト廃止しました。

完成したDDNSサービスを試用するためのサイトを以下のリンクに用意しました。

SAGAMIYA DDNS Service (試用のみ)

これは自由に試してみて頂いて結構ですが、あくまでも試用目的のサイトですので何の保証もありません。万一このサービスを使用したことによる不利益や損失等が生じても、苦情は一切受け付けません。また、事前の予告無くサービスを中止したり、サービスに登録してあるデータを変更したり消去する可能性もあります。

最後に

試用サイトの感想や意見、バグ報告などありましたら大歓迎です。質問も解る範囲のことはお答えしたいと思いますが、反応に時間がかかるかもしれません。

それから、ここにあるコードの多くはげんきさんのコードをほぼそのまま使わせて頂きました。ありがとうございます。もしこれらのコードの利用&改変に問題ありましたら、トラックバックあるいはコメントでご連絡頂ければ善処いたします。

12件のコメント

  1. リファラから来ました.
    なんだかありがとうございます.
    ずいぶん前に書いた素人のスクリプトでお恥ずかしいのですが,
    使いやすく直していただいて感謝しています.

  2. げんきさん、コメントありがとうございます。
    こちらこそコードを使わせていただきましてありがとうございます。

  3. DDNSのスクリプト使わせてもらいます(*’▽’)

    中身改変してログイン維持つけたりしてて気づいたのですが、
    IPアドレスの更新回りでIPのチェックしてないのですね
    if (filter_var($ip_a, FILTER_VALIDATE_IP)) {
    echo “(ip_a) は IP アドレスとして有効です。”;
    }
    等でチェックしないとヤバイです。
    nsupdateで好きなコマンド実行出来ちゃいます( ;∀;)

  4. こぺろぺさん、コメントありがとうございます。IPアドレスのチェックしないと他のコマンドを流し込んで実行できるということですね。ご指摘ありがとうございます。近いうちに何とかしたいと思います。

  5. CentOS6にてダイナミックDNSを構築したくてこちらのサイトにきました。
    PHPもソースを公開していただいて大変ありがたく思っております。
    一点わからない項目があるのですが、ddnscommon.phpの$nsupdate_key = “/etc/namedb/Kxxxxx.+157+xxxxx.key”;の項目ですが、これはこの通りでいいのでしょうか?
    私のCentOS6の場合、 /var/named/chroot/etc/named?にはnsupdate_keyはありません。
    このファイルはどのような意味のファイルなのでしょうか。
    よろしければご教授いただければ幸いです。

  6. かーすけさん、コメントありがとうございます。

    $nsupdate_key を参照しているソース(例えばddnsupdate.php)を見てもらえれば分かると思いますが、これはnsupdateコマンドのパラメータです。nsupdateコマンド自体は$nsupdate_keyの定義の一つ上の行に、
    $nsupdate_cmd = “/usr/bin/nsupdate”;
    と定義してあります。
    nsupdateについては下記の別エントリで説明していますので参照してみてください。
    nsupdate

  7. Masashiさん
    早速ご回答いただきましてありがとうございます。

    設定ミスがあり一部エラーが出ていますが、ほぼこのままで動作しております。

    教えていただいた内容をあらためて見直してみたいと思います。
    ありがとうございました。

  8. お世話になっております。
    mysql5.6.25、php-5.6.10にて設定中で、以降悪戦苦闘しながら設定しております。

    ddnscommon.phpの$su_mailに記載していますが、ddnsadduser.phpを実行すると、$suにtrueもfalseも入らないため?かレジスト時にエラーがでて登録されません。
    215行目あたりをいろいろ変更しましたが解決できません。
    48と50行目のところのtrueとfalseを入れ替えると正常にレジストされますが、エラーの原因で何か考えられることはないでしょうか。

    また、nsupdateをlocalhostにだけ許可している場合は、$nsupdate_keyは、無視されると考えてよいのでしょうか。

    なお、タイムゾーンでエラーが出るので、ddnscommon.phpにdate_default_timezone_set(‘Asia/Tokyo’);
    を追加しました。

    質問ばかりで申し訳ございませんがよろしくお願いします。

  9. かーすけさん、このコードは2年前に書いてそのままずっと放っておいたので私も細かな所はよく覚えていません。

    基本はコードを読んでご自分で解釈して頂けたらと思います。
    ちなみにphp5.4、mysql5.1の環境です。

    ですので、変数のコンセプトだけお話します。
    メールアドレスの文字列の全部あるいは一部が$su_mailに入っている文字列と一致していればそのメールアドレスは特権ユーザーとして登録されます。DDNSに使うドメイン名を登録追加削除したり、他のユーザーの登録内容を見たりできる特権を持たせています。ユーザーが自分一人だということが確実ならば不要な機能です。($su = false; の部分を $su = true;と書き換えればこの機能は殺せます。)

    nsupdateの方は、allow-updateに指定できるのはipアドレスか、keyかのどちらか一方だけですので、指定した方でのみ判断されると思います。実際にご自分でnsupdateコマンドを打ってみて確かめてみてください。

  10. めんどくさがりやさん、コメントありがとうございます。
    私もめんどくさがりやなのでzip化の予定はありません。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です