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