エンジニア

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

投稿日:2013年5月28日 更新日:

サーバー担当の山内です。
クライアントの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の中身は変わる場合があります。

採用情報

ワンダープラネットでは、一緒に働く仲間を幅広い職種で募集しております。

-エンジニア
-,

© WonderPlanet Inc.