PHPでグローバルIPアドレスを取得してieserver.netのDynamicDNSを更新する

More than 1 year has passed since last update.


やりたいこと

PHPから家サーバ・プロジェクト(ieserver.net)様提供のDynamicDNSにIPアドレスを登録したい。

Perl版更新スクリプトのサンプルが提供されているので、

それをPHPでリライトする感じでいきたい。


注意事項

グローバルIPアドレスの取得のために外部サービスを利用するので、頻繁に実行しないこと。

サービス提供者、他の利用者の迷惑になります。


動作確認環境、使用ライブラリ等


  • Fedora 24 (Server Edition) 64bit

  • PHP 5.6.27



  • 外部IPアドレス表示サービス


    • ieserver.net IPアドレス確認画面

    • WTF is my IP?!?!??

    • My External IP address




Perl版コードの解析


  1. IPキャッシュの内容を取得

  2. IPアドレス確認URLへアクセスし、自身のグローバルIPを取得

  3. もし、グローバルIPアドレスがIPキャッシュの内容と同一か、オールゼロ(取得失敗)であれば、プログラムを終了

  4. 登録用スクリプトにアクセスして登録を試みる

  5. レスポンスの内容にグローバルIPアドレスが含まれていれば、登録成功したと見なす。


PHPに書き換え


ddns_update.php

<?php

# 戻り値の定義
define("DDNS_NOCHANGE", 0);
define("DDNS_SUCCESS", 1);
define("DDNS_FAILED", 2);
define("DDNS_IPCHK_FAIL", 3);
define("DDNS_UPDATE_FAIL", 4);

function ddns_update($account, $domain, $password, &$outside_ip){

$ip_cache = '/tmp/php.ip.cache';

# 一時ファイルがなければ作る。前回のグローバルIPアドレスが記録される
if(!file_exists($ip_cache)){ touch($ip_cache); }

# 現在のグローバルIPアドレスを取得する
$ip_urls = array(
"http://ieserver.net/ipcheck.shtml",
"https://wtfismyip.com/text",
"https://myexternalip.com/raw",
);
$outside_ip = "";
foreach($ip_urls as $ip_url)
{
$outside_ip = trim(file_get_contents($ip_url));
if($outside_ip != "" AND $outside_ip != "0.0.0.0") { break; }
}
if($outside_ip == "" OR $outside_ip == "0.0.0.0") { return DDNS_IPCHK_FAIL; }

# 前回のグローバルIPアドレスを取得する
$recent_ip = trim(file_get_contents($ip_cache));

# 現在のIPアドレスが前回のものと同じ場合は、変更なしとして関数を抜ける
if($outside_ip == $recent_ip) { return DDNS_NOCHANGE; }

# 登録用スクリプトにアクセスして更新を試みる
$result = file_get_contents(sprintf(
'https://ieserver.net/cgi-bin/dip.cgi?username=%1$s&domain=%2$s&password=%3$s&updatehost=1',
$account, $domain, $password
));

# 戻り値の取得に失敗した場合は、エラーとして関数を抜ける
if($result == false) { return DDNS_UPDATE_FAIL; }

# 戻り値に現在のグローバルIPアドレスが含まれていなければ、エラーとして関数を抜ける
if(strpos($result, $outside_ip) === false) { return DDNS_UPDATE_FAIL; }

# 一時ファイルに、現在のグローバルIPアドレスを書き込む
file_put_contents(DDNS_TEMP_FILE, trim($outside_ip), LOCK_EX);

# 成功として関数を抜ける
return DDNS_SUCCESS;
}


使い方


driver.php

<?php

require 'ddns_update.php';

$result = ddns_update("example", "orz.hm", "password", $ip);

switch($result) {
case DDNS_NOCHANGE:
echo "IPアドレスは前回と同じです。\n"; break;

case DDNS_SUCCESS:
echo "IPアドレスを更新しました。IPアドレスは ${ip} です。\n"; break;

case DDNS_IPCHK_FAIL:
case DDNS_UPDATE_FAIL:
echo "IPアドレスの更新に失敗しました。\n"; break;
}



簡単な解説

サンプルのPerlスクリプトをPHPに起こして、ログ書き出しを省いてステータスを取得できるよう手を加えた。

新しいIPアドレスの取得も可能となり、他プログラムとの連携もしやすくなっていると思う。

ログが必要な場合は、関数側か使用する側のどちらかに手を加えればよい。

20161029追記

ieserver.netオフィシャルのIPアドレス表示が調子悪い時があるみたいなので

ieserver.netでの取得に失敗した場合は、順番に他サービスを参照することで、IPアドレス取得の信頼性の向上を図ることにした。

具体的な手法としては、配列に格納された各サービスのURLを順番に参照し、

最初に取得できたデータをIPアドレスとして用いる。


謝辞

DynamicDNSサービスを提供して頂いている家サーバ・プロジェクト様に深謝の意を表します。

また、グローバルIPアドレス取得サービスを提供して頂いている「wtfismyip.com」および「My External IP address」運営の皆様に感謝の意を表します。