IP アドレスが偽装可能か確認してみよう
PHP フレームワークでのクライアント IP アドレス取得メソッドの実装について で、CakePHP, CodeIgniter, Symfony, Zend Framework でのクライアント IP アドレス取得メソッドについてみてみました。
今回は、実際に自分のサーバで IP アドレスが偽装可能か確認してみましょう。
まず、サーバに検証用のソースを置きます。
CodeIgniter だと、こんなコードになります。
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Ip_address extends CI_Controller { function __construct() { parent::__construct(); } function index() { echo $this->input->ip_address(); } } /* End of file ip_address.php */ /* Location: ./application/controllers/ip_address.php */
タイムリー?にも、プロキシ経由でもリアルIPを取得するPHPコードスニペット:phpspot開発日誌 という記事がありました。そこで紹介されているコードは以下のようなものでした。
<?php if (!empty($_SERVER["HTTP_CLIENT_IP"])) { //check for ip from share internet $ip = $_SERVER["HTTP_CLIENT_IP"]; } elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) { // Check for the Proxy User $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; } else { $ip = $_SERVER["REMOTE_ADDR"]; } // This will print user's real IP Address // does't matter if user using proxy or not. echo $ip;
ここでは、上記のファイルを show_ip.php という名前にして、サーバに転送することにします。
次に、テスト用のコードを書きましょう。
サーバに
- 追加ヘッダなし
- X-FORWARDED-FOR ヘッダ付き
- CLIENT-IP ヘッダ付き
- X-FORWARDED-FOR および CLIENT-IP ヘッダ付き
のリクエストを送るコードです。
test.php:
<?php $uri = 'http://www.example.jp/show_ip.php'; // no additional headers $page = file_get_contents($uri); echo 'No headers: '; echo $page, "\n"; // send X-FORWARDED-FOR $opt = array( 'http'=> array( 'header' => 'X-FORWARDED-FOR: 88.88.88.88', ) ); $context = stream_context_create($opt); $page = file_get_contents($uri, 0, $context); echo 'X-FORWARDED-FOR: '; echo $page, "\n"; // send CLIENT-IP $opt = array( 'http'=> array( 'header' => 'CLIENT-IP: 99.99.99.99', ) ); $context = stream_context_create($opt); $page = file_get_contents($uri, 0, $context); echo 'CLIENT-IP: '; echo $page, "\n"; // send X-FORWARDED-FOR and CLIENT-IP $opt = array( 'http'=> array( 'header' => array('X-FORWARDED-FOR: 88.88.88.88', 'CLIENT-IP: 99.99.99.99', ) ) ); $context = stream_context_create($opt); $page = file_get_contents($uri, 0, $context); echo 'Both: '; echo $page, "\n";
さあ、このコードを手許の PC から実行してみましょう。
例えば、こんな結果になりました。
この環境では、リバースプロキシがあり CLIENT-IP ヘッダは通りませんが、X-FORWARDED-FOR は通るようです。
そもそも、カンマ区切りで IP アドレスが複数ありますね。これをそのまま IP アドレスだとして処理したらまずいことになりますね。