WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

FuelPHPでロードバランサーを経由してきたクライアントのIPを取得する

サーバー担当の山内です。
クライアントのIPを取得しようとして$_SERVER['REMOTE_ADDR']を参照していたのですが、
AWSのELB(ロードバランサー)配下のEC2に置いた途端にELBのIPしかとれなくなってしまいまして……
このような経緯からFuelPHPのreal_ip()メソッドを使ってみることに。
そして、これがうまくいきました!

$real_ip = Input::real_ip();

コントローラにこう書けば、変数$real_ipにクライアントのリアルなIPが入ります。
real_ip()は何を参照しているのか?real_ip()の中身を覗いてみます。

/core/classes/input.php

/**  
 * Get the real ip address of the user. Even if they are using a proxy.  
 *  
 * @param string the default to return on failure  
 * @param bool exclude private and reserved IPs  
 * @return string the real ip address of the user  
 */  
public static function real_ip($default = '0.0.0.0', $exclude_reserved = false)  
{  
    $server_keys = array('HTTP_X_CLUSTER_CLIENT_IP',  
            'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'REMOTE_ADDR');  
  
    foreach ($server_keys as $key)  
    {  
        if ( ! static::server($key))  
        {  
            continue;  
        }  
  
        $ips = explode(',', static::server($key));  
        array_walk($ips, function (&$ip) {  
            $ip = trim($ip);  
        });  
  
        $ips = array_filter($ips, function($ip) use($exclude_reserved) {  
            return filter_var($ip, FILTER_VALIDATE_IP, $exclude_reserved ?  
                   FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE : null);  
        });  
  
        if ($ips)  
        {  
            return reset($ips);  
        }  
    }  
  
    return \Fuel::value($default);  
}  

real_ip()は、$server_keysに設定されたヘッダを順番にチェックし、
取得したIPを1つだけ返す処理をします。

real_ip()内部で使われているserver()は、渡した引数の数が0個の場合は$SERVERを、
それ以外の場合は渡した引数をキーとして$
SERVERの一部を返すメソッドです。

/core/classes/input.php

/**  
* Fetch an item from the SERVER array  
*  
* @param string The index key  
* @param mixed The default value  
* @return string|array  
*/  
public static function server($index = null, $default = null)  
{  
    return (func_num_args() === 0) ?  
           $_SERVER : \Arr::get($_SERVER, strtoupper($index), $default);  
}  

real_ip()も$SERVERを参照しているということですね。
ところで、この$
SERVERに含まれるHTTP_X_FORWARDED_FORは、
プロキシやロードバランサーを経由してきたときに付加されるヘッダです。
環境にもよりますが、SSLの有無でも$_SERVERの中身は変わる場合があります。