PHPでクライアントのIPアドレスを取得する方法

2010年06月09日に質問されました。  ·  閲覧回数 1.7M回  ·  ソース

Anup Prakash picture
2010年06月09日

PHPを使用してクライアントIPアドレスを取得するにはどうすればよいですか?

IPアドレスを使用して自分のWebサイトにログインしたユーザーを記録したい。

回答

Emil Vikström picture
2010年06月09日
1358

何をするにしても、クライアントから送信されたデータを信頼しないように注意してください。 $_SERVER['REMOTE_ADDR']には、接続側の実際のIPアドレスが含まれます。 それはあなたが見つけることができる最も信頼できる値です。

ただし、プロキシサーバーの背後にある可能性があります。その場合、プロキシが$_SERVER['HTTP_X_FORWARDED_FOR']を設定している可能性がありますが、この値は簡単に偽装されます。 たとえば、プロキシを持たない誰かが設定したり、IPをプロキシの背後にあるLANからの内部IPにすることができます。

これは、 $_SERVER['HTTP_X_FORWARDED_FOR']を保存する場合は、必ず$_SERVER['REMOTE_ADDR']保存することを意味します。 たとえば、データベースの異なるフィールドに両方の値を保存します。

IPを文字列としてデータベースに保存する場合は、 45文字以上のスペースがあることを確認してください。 IPv6は今後も存続し、これらのアドレスは古いIPv4アドレスよりも大きくなります。

(IPv6は通常最大39文字を使用しますが、 IPv6表記もあります。したがって、何をしているのかがわかっている場合は39文字を使用できますが、設定して忘れたいだけです。45を使用してください)。

Tim Kennedy picture
2008年09月11日
473

$_SERVER['REMOTE_ADDR']は、実際には実際のクライアントIPアドレスが含まれていない場合があります。これは、たとえば、プロキシを介して接続されたクライアントのプロキシアドレスを提供するためです。 ただし、IPで何をしているのかによっては、それが本当に必要なことかもしれません。 誰かのプライベートRFC1918アドレスは、トラフィックの発信元を確認したり、ユーザーが最後に接続したIPを思い出したり、プロキシまたはNATゲートウェイのパブリックIPの方が多いと言っても、役に立たない場合があります。保存するのに適しています。

X-Forwarded-ForようないくつかのHTTPヘッダーがあり、さまざまなプロキシによって設定される場合とされない場合があります。 問題は、それらが誰でも設定できる単なるHTTPヘッダーであるということです。 それらの内容についての保証はありません。 $_SERVER['REMOTE_ADDR']は、Webサーバーが接続を受信し、応答が送信される実際の物理IPアドレスです。 それ以外は恣意的で自発的な情報です。 この情報を信頼できるシナリオは1つだけです。つまり、このヘッダーを設定するプロキシを制御しているということです。 ヘッダーがどこにどのように設定されているかを100%知っている場合にのみ意味し、重要なことに注意する必要があります。

そうは言っても、ここにいくつかのサンプルコードがあります:

if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
    $ip = $_SERVER['REMOTE_ADDR'];
}

編集者注:上記のコードを使用すると、セキュリティに影響があります。 クライアントは、すべてのHTTPヘッダー情報(つまり、 $_SERVER['HTTP_... )を任意の値に設定できます。 そのため、 $_SERVER['REMOTE_ADDR']を使用する方がはるかに信頼性が高くなります。これは、ユーザーが設定できないためです。

差出人: http

lemon picture
2010年06月09日
213
josh123a123 picture
2014年10月09日
124

これは、ユーザーのIPアドレスを取得するための良い方法のよりクリーンなコードサンプルです。

$ip = $_SERVER['HTTP_CLIENT_IP'] ? $_SERVER['HTTP_CLIENT_IP'] : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR']);

エルビス演算子を使用する短いバージョンを次に示します。

$_SERVER['HTTP_CLIENT_IP'] ? : ($_SERVER['HTTP_X_FORWARDED_FOR'] ? : $_SERVER['REMOTE_ADDR']);

これは、issetを使用して通知を削除するバージョンです(ありがとう、@ shasi kanth):

$ip = isset($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
Kyle Cronin picture
2008年09月11日
93

$_SERVER['REMOTE_ADDR']変数に含まれている必要があります。

algorhythm picture
2014年07月07日
58

私のお気に入りのソリューションは、Zend Framework2の使用方法です。 また、 $_SERVERプロパティHTTP_X_FORWARDED_FORHTTP_CLIENT_IPREMOTE_ADDRも考慮しますが、信頼できるプロキシを設定するためのクラスを宣言し、1つのIPアドレスを返しません。配列。 私はこれがそれに最も近い解決策だと思います:

class RemoteAddress
{
    /**
     * Whether to use proxy addresses or not.
     *
     * As default this setting is disabled - IP address is mostly needed to increase
     * security. HTTP_* are not reliable since can easily be spoofed. It can be enabled
     * just for more flexibility, but if user uses proxy to connect to trusted services
     * it's his/her own risk, only reliable field for IP address is $_SERVER['REMOTE_ADDR'].
     *
     * @var bool
     */
    protected $useProxy = false;

    /**
     * List of trusted proxy IP addresses
     *
     * @var array
     */
    protected $trustedProxies = array();

    /**
     * HTTP header to introspect for proxies
     *
     * @var string
     */
    protected $proxyHeader = 'HTTP_X_FORWARDED_FOR';

    // [...]

    /**
     * Returns client IP address.
     *
     * @return string IP address.
     */
    public function getIpAddress()
    {
        $ip = $this->getIpAddressFromProxy();
        if ($ip) {
            return $ip;
        }

        // direct IP address
        if (isset($_SERVER['REMOTE_ADDR'])) {
            return $_SERVER['REMOTE_ADDR'];
        }

        return '';
    }

    /**
     * Attempt to get the IP address for a proxied client
     *
     * @see http://tools.ietf.org/html/draft-ietf-appsawg-http-forwarded-10#section-5.2
     * @return false|string
     */
    protected function getIpAddressFromProxy()
    {
        if (!$this->useProxy
            || (isset($_SERVER['REMOTE_ADDR']) && !in_array($_SERVER['REMOTE_ADDR'], $this->trustedProxies))
        ) {
            return false;
        }

        $header = $this->proxyHeader;
        if (!isset($_SERVER[$header]) || empty($_SERVER[$header])) {
            return false;
        }

        // Extract IPs
        $ips = explode(',', $_SERVER[$header]);
        // trim, so we can compare against trusted proxies properly
        $ips = array_map('trim', $ips);
        // remove trusted proxy IPs
        $ips = array_diff($ips, $this->trustedProxies);

        // Any left?
        if (empty($ips)) {
            return false;
        }

        // Since we've removed any known, trusted proxy servers, the right-most
        // address represents the first IP we do not know about -- i.e., we do
        // not know if it is a proxy server, or a client. As such, we treat it
        // as the originating IP.
        // @see http://en.wikipedia.org/wiki/X-Forwarded-For
        $ip = array_pop($ips);
        return $ip;
    }

    // [...]
}

ここで完全なコードを参照してください: https

K.Suthagar picture
2016年12月29日
51

インターネットの背後にはさまざまなタイプのユーザーがいるため、さまざまな部分からIPアドレスを取得したいと考えています。 それらは:

1. $_SERVER['REMOTE_ADDR'] -これには、クライアントの実際のIPアドレスが含まれます。 これは、ユーザーから見つけることができる最も信頼できる値です。

2. $_SERVER['REMOTE_HOST'] -これにより、ユーザーが現在のページを表示しているホスト名が取得されます。 ただし、このスクリプトを機能させるには、httpd.conf内でホスト名ルックアップを構成する必要があります。

3. $_SERVER['HTTP_CLIENT_IP'] -これは、ユーザーが共有インターネットサービスからの場合にIPアドレスを取得します。

4. $_SERVER['HTTP_X_FORWARDED_FOR'] -これは、ユーザーがプロキシの背後にいるときにユーザーからIPアドレスを取得します。

したがって、この次の組み合わせ関数を使用して、異なる位置で表示しているユーザーから実際のIPアドレスを取得できます。

// Function to get the user IP address
function getUserIP() {
    $ipaddress = '';
    if (isset($_SERVER['HTTP_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_X_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_X_FORWARDED'];
    else if(isset($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        $ipaddress = $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
        $ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
    else if(isset($_SERVER['HTTP_FORWARDED']))
        $ipaddress = $_SERVER['HTTP_FORWARDED'];
    else if(isset($_SERVER['REMOTE_ADDR']))
        $ipaddress = $_SERVER['REMOTE_ADDR'];
    else
        $ipaddress = 'UNKNOWN';
    return $ipaddress;
}
manuelbcd picture
2015年01月29日
39

以下は私が見つけた最も高度な方法であり、私は過去にすでにいくつかの他の方法を試しました。 訪問者のIPアドレスを確実に取得することは有効です(ただし、ハッカーはIPアドレスを簡単に改ざんする可能性があることに注意してください)。

function get_ip_address() {

    // Check for shared Internet/ISP IP
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && validate_ip($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }

    // Check for IP addresses passing through proxies
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {

        // Check if multiple IP addresses exist in var
        if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false) {
            $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            foreach ($iplist as $ip) {
                if (validate_ip($ip))
                    return $ip;
            }
        }
        else {
            if (validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
                return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED']) && validate_ip($_SERVER['HTTP_X_FORWARDED']))
        return $_SERVER['HTTP_X_FORWARDED'];
    if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
        return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
    if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
        return $_SERVER['HTTP_FORWARDED_FOR'];
    if (!empty($_SERVER['HTTP_FORWARDED']) && validate_ip($_SERVER['HTTP_FORWARDED']))
        return $_SERVER['HTTP_FORWARDED'];

    // Return unreliable IP address since all else failed
    return $_SERVER['REMOTE_ADDR'];
}

/**
 * Ensures an IP address is both a valid IP address and does not fall within
 * a private network range.
 */
function validate_ip($ip) {

    if (strtolower($ip) === 'unknown')
        return false;

    // Generate IPv4 network address
    $ip = ip2long($ip);

    // If the IP address is set and not equivalent to 255.255.255.255
    if ($ip !== false && $ip !== -1) {
        // Make sure to get unsigned long representation of IP address
        // due to discrepancies between 32 and 64 bit OSes and
        // signed numbers (ints default to signed in PHP)
        $ip = sprintf('%u', $ip);

        // Do private network range checking
        if ($ip >= 0 && $ip <= 50331647)
            return false;
        if ($ip >= 167772160 && $ip <= 184549375)
            return false;
        if ($ip >= 2130706432 && $ip <= 2147483647)
            return false;
        if ($ip >= 2851995648 && $ip <= 2852061183)
            return false;
        if ($ip >= 2886729728 && $ip <= 2887778303)
            return false;
        if ($ip >= 3221225984 && $ip <= 3221226239)
            return false;
        if ($ip >= 3232235520 && $ip <= 3232301055)
            return false;
        if ($ip >= 4294967040)
            return false;
    }
    return true;
}
kainosnous picture
2010年06月09日
30

答えは、 $_SERVER変数を使用することです。 たとえば、 $_SERVER["REMOTE_ADDR"]はクライアントのIPアドレスを返します。

Stergios Zg. picture
2019年06月23日
16

迅速な解決策(エラーなし)

function getClientIP()
{
    $ipaddress = 'UNKNOWN';
    $keys=array('HTTP_CLIENT_IP','HTTP_X_FORWARDED_FOR','HTTP_X_FORWARDED','HTTP_FORWARDED_FOR','HTTP_FORWARDED','REMOTE_ADDR');
    foreach($keys as $k)
    {
        if (isset($_SERVER[$k]) && !empty($_SERVER[$k]) && filter_var($_SERVER[$k], FILTER_VALIDATE_IP))
        {
            $ipaddress = $_SERVER[$k];
            break;
        }
    }
    return $ipaddress;
}