ダイナミックDNSを使用してサーバを公開している場合・・・
プロバイダより割り当てられたグローバルIPとドメイン名をダイナミックDNSで関連付けることでサーバの外部への公開が可能となります。
が、固定IPでない限り割り当てられるグローバルIPはルータを再起動したときに変わってしまいますのでダイナミックDNSの登録を修正しないといけないのです。
自宅サーバに付きまとうこの問題を簡単に解決してくれるソフトが「DICE」なんですが、お名前ドットコムはこのDICEからのIP更新を拒否ってくれています。
なので、グローバルIPが更新されたら新しいIPを取得した上でお名前ドットコムのサイト上から手動でメンテする必要があるのです。
IP変化時にメールで通知してくれるスクリプトを作成する
ということで、新しいIPを自宅サーバからメールで通知してくれるようにスクリプトを作成してみます。
手順としては
- 外部のサイトを利用して、現在自サーバに割り当てられたグローバルIPを取得する
- 適当なファイルに保存しておいた、それまでのグローバルIPと新しいそれを比較する
- 変更があった場合、ファイルの値を更新すると共に任意の宛て先にメールで通知する。この処理はcronで定期実行するものとする
といった順番になります。ちなみに3番のメール送信ですが、グローバルIPが変わる=名前解決ができない状況となるため外部のメールサーバを中継してメール送信する仕組みが不可欠となります。
自分の場合はもともとOP25B対策としてGmailを中継する仕組みにしているので問題なくできましたが。
では早速参りましょう。
現在のグローバルIPを取得する
外部サイトに接続して現在のIPを取得してみます。試しにコマンドでやってみましょう。
$ wget -qO- forts.jp/ip
ファイルをダウンロードするときなどによく使う「wget」コマンドですがここではqオプションとOオプションを併せて使用しています。
-qオプションは画面に何も表示しないためのオプション、-Oは出力先の指定を表すオプションで-O-とすると標準出力となるのだとか。
ちなみにブラウザを使ってforts.jp/ipにアクセスすると現在のグローバルIPが表示されます。この結果を取得するわけですね。
古いIPと新しいIPを比較する
ファイルに保存しておいた古いIPと新しいIPを比較します。
newip=`wget -qaO- forts.jp/ip` oldip=`/usr/local/bin/old_ip.txt` if [$oldip != $newip ] then 処理 fi
変数newipにはさっきの手順で得られる現在のIPを格納します。比較対象の古いIPは/usr/local/bin/old_ip.txtに保存しておき、その値を読み込みます。
両者を比較して一致しない場合(!=が不一致を表す)、所定の処理を行うようにします。ちなみに初めて比較を行う場合は/usr/local/bin/old_ip.txtファイルを事前に作成しておかないとエラーになるのは言うまでもありません。(自分は見事に嵌りましたが)
ファイルの値を更新してメール送信を行う
IP変更が確認された場合の処理を記述します。
echo "$newip" > /usr/local/bin/old_ip.txt mail -s "Current IP Address" 送信先アドレス < /usr/local/bin/old_ip.txt
1行目でファイルold_ip.txtの値を書き換えています。2行目でメールを任意のアドレスへと送信、本文に新しいIPアドレスを記載します。(先ほど書き換えたold_ip.txtの内容を記述します)
それでは一連の動作を纏めて/usr/local/bin/ipcheck.shとして保存します。
vi /usr/local/bin/ipcheck.sh ↓以下のとおり記述して「:wq」で保存する !/bin/sh newip=`wget -qO- forts.jp/ip` oldip=`cat /usr/local/bin/old_ip.txt` if [ $oldip != $newip ] then echo "$newip" > /usr/local/bin/old_ip.txt mail -s "Current IP Address" 送信先アドレス < /usr/local/bin/old_ip.txt fi
これでスクリプトが出来上がりました。最後にcronに登録しましょう。
chmod 700 /usr/local/bin/ipcheck.sh vi /etc/cron.d/ipcheck */15 * * * * 実行するユーザ /usr/local/bin/ipcheck.sh
1行目でスクリプトに実行権限を付与し、cronで定期実行するための設定ファイルを2行目で作成します。内容に記述するのが3行目となります。
最初の*/15が「15分毎に」を意味する項目、つまり毎日毎時0、15、30、45分になるとスクリプトを自動で走らせるようにします。
15分じゃ長い!というかたはたとえば「*/5」にすれば5分毎に動かすことができますので参考までに。
実行結果とまとめ
上記のとおりスクリプトの作成とcronの設定ができたところでテストを行ってみました。途中書いたんですが、初めてスクリプトを走らせる場合、事前に/usr/local/bin/old_ip.txtを作成しておかないと比較のしようがなくてエラーになります。
メール送信まで確認したいので今回は「1.2.3.4」というありえないアドレスを記載してold_ip.txtを作成しました。これならどんなIPと比較しても変更したとみなされてメールが飛ぶことでしょう。ドキドキしながら時計を見つめて待つこと数分・・・
無事、正しいIPがメールで飛んできました。外出先でも確認できるよう、携帯アドレス宛に飛ばしたメールが無事着信。あとは本当にIPが更新されたときに動いてくれれば問題なしです。サーバもルータも自宅なので、すぐに試すことはできませんが・・・
※ちなみにスクリプトを作成してからこの記事をアップするまでにIPが更新されたようで、いきなり携帯にメールが飛んできてビックリしました。が、無事アドレス変更を検知して新しいIPを通知してくれることが確認できましたのでヨカッタヨカッタ。
それではポイントを纏めておきましょう。
- wgetコマンドに-qオプションを用いて画面に非表示 + -O-オプションで結果を標準出力する
- if ~ fi構文で新旧のIPを比較し、一致しない(!=で表す)場合に処理を走らせる
- Gmail経由で設定したPostfixを用いて、本来動かないメールサーバでも中から外へメールを送ることが可能
- cronの設定で*/○を用いると○おきに動作を行う
といった具合です。
Gmailでなくても、プロバイダなど外部のメールサーバを中継する仕組みであれば使うことは可能ではないかと思います。
自分的にはwgetにオプションを組み合わせて使ったのは初めてだったので勉強になりましたし、cronの○分おきに実行~というのも新しい試みでした。
DICEが使えないのはとても痛いですが、この方法でしばらくはIP更新を察知しつつ、迅速にDNSレコードを手動更新すればサーバが繋がらない時間を減らせるのでは・・・と少しばかりですが期待しています。