web-dev-qa-db-ja.com

PHP 2017年に実際のユーザーIPアドレスを取得する最も正確で安全な方法

2017年にPHP経由でユーザーのIPアドレスを取得する最も正確な方法は何ですか?

私はこれについて多くのSOの質問と回答を読みましたが、ほとんどの回答は古く、これらの方法は安全ではないとユーザーからコメントされています。

たとえば、次の質問(2011)をご覧ください。 PHPでクライアントIPアドレスを取得する方法?

ティムケネディの答えには、次のようなものを使用することを推奨しています。

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'];
}

しかし、私はたくさん読んだように、X_FORWARDED_FORは、以下のコメントが強調するように、安全ではありません。

それが何をするのか正確にわかっていない限り、上記のコードを使用しないでください!私はこれによる大規模なセキュリティホールを見てきました。クライアントは、X-Forwarded-ForまたはClient-IPヘッダーを必要な任意の値に設定できます。信頼できるリバースプロキシがない場合は、これらの値を使用しないでください。

私はそれが何をするのか正確には知りませんでしたので、リスクを冒したくありません。彼は、それは安全ではないと言いましたが、ユーザーのIPアドレスを取得する安全な方法を提供しませんでした。

シンプルな$_SERVER['REMOTE_ADDR'];、しかしこれは間違ったIPを返します。これをテストしましたが、実際のIPは次のパターンに従います:78.57.xxx.xxxが、次のようなIPアドレスを取得します:81.7.xxx.xxx

何かアイデアはありますか?

17
Infinity

短い答え:

$ip = $_SERVER['REMOTE_ADDR'];


2019$_SERVER['REMOTE_ADDR'];ユーザーのIPアドレスを取得する唯一の信頼できる方法ですが、プロキシサーバーの背後にある場合は誤った結果を表示する可能性があります。
他のすべてのソリューションは、セキュリティリスクを暗示するか、簡単に偽造することができます。

15
Pedro Lobito

セキュリティPOVからは、nothingですが、$_SERVER['REMOTE_ADDR']は信頼できます-残念ながら、これは単なる真実です。

HTTP_というプレフィックスが付いたすべての変数は、実際にはクライアントによって送信されたHTTPヘッダーであり、リクエストが異なるサーバーを通過している間にその情報を転送する他の方法はありません。
しかし、当然のことながら、クライアントはこれらのヘッダーを偽装できることを自動的に意味します。

クライアントをnever、ever信頼できます。

それ以外の場合...youプロキシまたはロードバランサーを制御する場合、元のヘッダーを削除するように構成することができますリクエスト。
そして、そのときだけ、たとえばX-Client-IPヘッダーですが、実際にはその時点で必要はありません... REMOTE_ADDRをその値に置き換えるようにWebサーバーを構成することもでき、プロセス全体が透過的になります。

これは、セキュリティに関連するものについては、どの年に関係なく常に当てはまります。REMOTE_ADDRのみを信頼してください。
最良のシナリオは、統計目的でHTTP_データを読み取ることですのみ、さらには次に-入力が少なくとも有効なIPアドレスであることを確認します。

9
Narf

Sysopsチームと協力する必要があります(または、その帽子をかぶっている場合は、調査する必要があります)。ヘッダーチェックは、リモートリクエスターがエンドユーザーではなくネットワークアプライアンスの1つである特定の方法でネットワークインフラストラクチャが構成されている場合に使用されます。

この種のことは、Webサーバーがペイロードを適切に処理するためにペイロードに問い合わせる必要があるロードバランサー、ファイアウォール、またはその他のアプライアンスの背後にあるときに発生します。たとえば、ロードバランサーがSSLを終了し、SSLなしでWebサーバーにリクエストを転送する場合です。これが発生すると、リモートアドレスがロードバランサーになります。同じことを行うファイアウォールアプライアンスでも発生します。

ほとんどの場合、デバイスは、リクエストに元のリモートIPアドレスを使用してヘッダー値を設定する構成を提供します。通常、ヘッダーは期待どおりのものですが、場合によっては異なるか、構成可能です。

さらに、Webサーバーの構成(Apache、nginxなど)によっては、共通のipヘッダーなどの特定のカスタムヘッダーをサポートしないか、現在サポートするように構成されている場合があります。

ポイントは、ネットワーク構成を調査して、元のリクエスターのIPがアプリケーションコードまでどのような形式であるかを確認する必要があることです。

7
Jeremy Giberson

事前に構築されたライブラリを使用する場合は、 Whip を使用できます。

事前に作成されたライブラリーを使用する方が、通常は、それらのほとんどがアクティブなコミュニティーによって徹底的にチェックされているため、より優れています。それらの一部、特に長い間使用されてきたものには、より多くの機能が組み込まれています。

しかし、自分でコーディングして概念を学習したい場合は、大丈夫だと思います。スタンドアロンライブラリとしてパッケージ化し、オープンソースとしてリリースすることをお勧めします:)

編集:リモートIPは常に信頼できるとは限らないため、セキュリティメカニズムで使用することはお勧めしません。

5
aljo f

まず、誰かのソースIPアドレスが非表示にされている場合、そのIPアドレスを確実に決定することは不可能です。今日でも絶対に安全だと思われるものでさえ、すぐに抜け穴があります(まだ抜けていなければ)。そのため、以下の回答はすべて考慮する必要があります[〜#〜] untrusted [〜#〜]。つまり、すべての卵を入れたらこのバスケットは、誰かがそれを利用したり、何らかの方法で回避したりできるように準備してください。

IPトラッキングは常に進化しているので、誰かがIPトラッキングを回避する方法のすべてに触れることはできません。私が言うことは、IPアドレスが簡単に変更されたりマスクされたりする可能性があることを知っている限り、ログを記録するための便利なツールになり得るということです。

ここで、1つの大きなポイントは、パブリックIPアドレスとプライベートIPアドレスに違いがあるということです。 IPV4では、通常、ルーターには1つのパブリックIPアドレスが割り当てられます。これは、クライアント側のIPアドレスが表示されないため、サーバー側の言語が実際に取得できるものです。サーバーにとって、コンピューターはWebスペースとして存在しません。代わりに、ルーターが重要です。順番に、あなたのルーターはあなたのコンピューターを気にする唯一のものであり、そしてそれは プライベートIPアドレス (それに172。。*アドレスが属する)この作業を行います。これは、ルーターの背後にあるコンピューターに直接アクセスできないため、便利です。

プライベートIPアドレスにアクセスする場合は、JavaScript(クライアント側の言語)を使用する必要があります。その後、AJAXを介して非同期的にデータを保存できます。私の知る限り、これは現在のところWebRTC対応のChromeおよびFirefox。デモを見るには here を参照してください。

これをテストし、プライベートIPアドレスを返します。通常、これはパブリックIPアドレスと組み合わせて、ネットワーク内の個々のユーザーを追跡するために広告主によって使用されると思います。人々が回避策を思いつくか、または一般市民の抗議が彼らにWebRTC APIを無効にする機能を提供することを強制するので、それはすぐに役に立たなくなると確信しています。ただし、当面は、ChromeおよびFirefox。

もっと読む:

4
smcjones

実際の方法は、ユーザーIPが$ip = $_SERVER['REMOTE_ADDR'];

ユーザーがVPNまたはプロキシを使用している場合、元のIPは検出されません。

3
Narayan

クライアントIPアドレスの取得:

<?php
 echo   $ip = $_SERVER['REMOTE_ADDR'];
?>

注:これはライブサイトでのみ機能します。ローカルホストでは、IPは127.0.0.1のような内部IPアドレスの1つになるため、Return :: 1になります。

例:https://www.virendrachandak.com/demos/getting-real-client-ip-address-in-php。 php

ローカルIPを表示:いいね... 78.57.xxx.xxx

例:

<?php
$myIp= getHostByName(php_uname('n'));
 echo $myIp;
?>
2

これはどう -

public function getClientIP()
    {
        $remoteKeys = [
            'HTTP_X_FORWARDED_FOR',
            'HTTP_CLIENT_IP',
            'HTTP_X_FORWARDED',
            'HTTP_FORWARDED_FOR',
            'HTTP_FORWARDED',
            'REMOTE_ADDR',
            'HTTP_X_CLUSTER_CLIENT_IP',
        ];

        foreach ($remoteKeys as $key) {
            if ($address = getenv($key)) {
                foreach (explode(',', $address) as $ip) {
                    if ($this->isValidIp($ip)) {
                        return $ip;
                    }
                }
            }
        }

        return '127.0.0.0';
    }


    private function isValidIp($ip)
    {
        if (!filter_var($ip, FILTER_VALIDATE_IP,
                FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)
            && !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE)
        ) {
            return false;
        }

        return true;
    }
1
Selim Mahmud

私はこのコードを使用し、それは私のために機能します。ご覧ください。

<?php

// Gets client's IP.
$ip = getenv("HTTP_CLIENT_IP")?:
getenv("HTTP_X_FORWARDED_FOR")?:
getenv("HTTP_X_FORWARDED")?:
getenv("HTTP_FORWARDED_FOR")?:
getenv("HTTP_FORWARDED")?:
getenv("REMOTE_ADDR");

echo $ip;

?>

ここ 、実際の例。それが役に立てば幸い!

0
KAZZABE