LoginSignup
1
0

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-10-25

やりたいこと

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」運営の皆様に感謝の意を表します。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0