CloudFlareとPHPでの訪問者のIPアドレスのログ


82

PHPを使用して自分のWebサイトにアクセスしているユーザー/訪問者を追跡およびログに記録しようとし$_SERVER['REMOTE_ADDR']ています。PHPでのIPアドレス追跡の一般的な方法。

しかし、私はキャッシュなどにCloudFlareを使用しており、CloudFlareのようにIPアドレスを受信して​​います。

108.162.212。*-108.162.239。*

CloudFlareを使用しながら実際のユーザー/訪問者のIPアドレスを取得する正しい方法は何でしょうか?

回答:


241

クラウドフレアで利用できる追加のサーバー変数は次のとおりです。

$_SERVER["HTTP_CF_CONNECTING_IP"] 実際の訪問者のIPアドレス、これはあなたが望むものです

$_SERVER["HTTP_CF_IPCOUNTRY"] 訪問者の国

$_SERVER["HTTP_CF_RAY"]

$_SERVER["HTTP_CF_VISITOR"] これは、httpまたはhttpsのどちらであるかを知るのに役立ちます

あなたはそれをこのように使うことができます:

if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) {
  $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}

これを行い、訪問先IPアドレスの有効性が重要である場合$_SERVER["REMOTE_ADDR"]、サーバーIPに直接接続できれば誰でもヘッダーを偽造できるため、に実際の有効なクラウドフレアIPアドレスが含まれていることを確認する必要があります。


16
REMOTE_ADDRを実際のIPに置き換えるための+1。したがって、コードに他の変更を加える必要はありません。
aalaap 2014年

11
セキュリティが重要な場合は、リクエストがCloudflare IP範囲(cloudflare.com/ips)からのものどうか確認する必要があります。たとえば、このJoomla!プラグイン:github.com/piccaso/joomla-cf/blob/master/cf/cf.php
Florian Fida

Cloudflareもこのコードを彼らのサイトにリストしています。support.cloudflare.com/hc/en-us/articles/...
C0nw0nk

ベストアンサーですが、HTTP_CF_IPCOUNTRYを含めたことに対する称賛もありますが、これまでに出会ったことはありませんでした。
デビッドベル

http_cf_connecting_ipは、次のようなものを提供することがあります。2a01:6500:a043:33a6:b36a:7259:4de5:2500なぜですか?
マイケル

15

更新:CloudFlareはmod_cloudflareapacheのモジュールをリリースしました。モジュールは、cloudflareによってアクセスされたものではなく、実際の訪問者のIPアドレスをログに記録して表示します。https://www.cloudflare.com/resources-downloads#mod_cloudflare(回答者:olimortimer

以下のスクリプトを使用してapacheランタイムにアクセスできない場合は、これにより、接続がcloudflareを介して行われたかどうかを確認し、ユーザーにIPを取得できます。

別の質問「CloudFlareDNS /直接IP識別子」に使用した回答を書き直しています

CloudflareのIPはパブリックに保存されているので、ここでそれらを表示し、IPがcloudflareからのものであるかどうかを確認できます(これにより、httpヘッダーから実際のIPを取得できますHTTP_CF_CONNECTING_IP)。

これを使用してすべての非cf接続を無効にする場合、またはその逆の場合は、common.phpやpagestart.phpなどの他のすべてのスクリプトの前に呼び出される単一のphpスクリプトファイルを用意することをお勧めします。

function ip_in_range($ip, $range) {
    if (strpos($range, '/') == false)
        $range .= '/32';

    // $range is in IP/CIDR format eg 127.0.0.1/24
    list($range, $netmask) = explode('/', $range, 2);
    $range_decimal = ip2long($range);
    $ip_decimal = ip2long($ip);
    $wildcard_decimal = pow(2, (32 - $netmask)) - 1;
    $netmask_decimal = ~ $wildcard_decimal;
    return (($ip_decimal & $netmask_decimal) == ($range_decimal & $netmask_decimal));
}

function _cloudflare_CheckIP($ip) {
    $cf_ips = array(
        '199.27.128.0/21',
        '173.245.48.0/20',
        '103.21.244.0/22',
        '103.22.200.0/22',
        '103.31.4.0/22',
        '141.101.64.0/18',
        '108.162.192.0/18',
        '190.93.240.0/20',
        '188.114.96.0/20',
        '197.234.240.0/22',
        '198.41.128.0/17',
        '162.158.0.0/15',
        '104.16.0.0/12',
    );
    $is_cf_ip = false;
    foreach ($cf_ips as $cf_ip) {
        if (ip_in_range($ip, $cf_ip)) {
            $is_cf_ip = true;
            break;
        }
    } return $is_cf_ip;
}

function _cloudflare_Requests_Check() {
    $flag = true;

    if(!isset($_SERVER['HTTP_CF_CONNECTING_IP']))   $flag = false;
    if(!isset($_SERVER['HTTP_CF_IPCOUNTRY']))       $flag = false;
    if(!isset($_SERVER['HTTP_CF_RAY']))             $flag = false;
    if(!isset($_SERVER['HTTP_CF_VISITOR']))         $flag = false;
    return $flag;
}

function isCloudflare() {
    $ipCheck        = _cloudflare_CheckIP($_SERVER['REMOTE_ADDR']);
    $requestCheck   = _cloudflare_Requests_Check();
    return ($ipCheck && $requestCheck);
}

// Use when handling ip's
function getRequestIP() {
    $check = isCloudflare();

    if($check) {
        return $_SERVER['HTTP_CF_CONNECTING_IP'];
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

スクリプトを使用するのは非常に簡単です。

$ip = getRequestIP();
$cf = isCloudflare();

if($cf) echo "Connection is through cloudflare: <br>";
else    echo "Connection is not through cloudflare: <br>";

echo "Your actual ip address is: ". $ip;
echo "The server remote address header is: ". $_SERVER['REMOTE_ADDR'];

このスクリプトは、実際のIPアドレスと、要求がCFであるかどうかを示します。


これは正解ですが、IPを定期的に更新し続ける必要があることに注意してください。上記のコードの現在のものはすでに無効であるため、コードは失敗します。最新のIPはここで入手できます:cloudflare.com/ips 理想的には、これらをファイルに保存して、外部ファイルを更新するだけでよいか、さらに良いことに、ここから定期的にフェッチする必要があります:cloudflare.com/ips-v4
rafark20年

11

この質問に答えてから、CloudFlareはmod_cloudflareApache向けにリリースしました。これは、CloudFlareアドレスではなく実際の訪問者のIPアドレスをログに記録して表示します。

https://www.cloudflare.com/resources-downloads#mod_cloudflare


2019-サポートされなくなりましmod_cloudflareたが、使用できます。と呼ばれる新しいものがありmod_remoteipます。参考:support.cloudflare.com/hc/en-us/articles/...
sinaza

以下のため@sinazaおそらく最高は、私の答えとして、新しい答えを作成するにはmod_cloudflare4年前からだった
olimortimer

@sjagr編集内容に関しては、彼らは間違っている-私はもともと掲示ようCloudFlareは、実際にCloudFlareのである
olimortimer

10

Cloudflareは、次の単純なワンライナーを使用CF-Connecting-IPして$user_ip、定義されている場合に格納できる追加のリクエストヘッダーをサーバーに送信します。

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

これに伴う問題は、それが単なるヘッダーであるため、誰でも好きなIPに設定できることです。これは、セキュリティ上の大きな脆弱性です。
rafark

@rafarkサーバーが適切に構成されていてCloudflareの背後にある場合は違います。
サイナン

はい、もちろん。これは、それ自体は良い解決策ですが、チェックはまだのように、HTTP_CF_CONNECTING_IPを使用する前になされるべきであるして、Callumの答え
rafark

@rafark私も同意しますが、これはApache構成に別の形式ですでに存在する非常に多くのPHPコードです(私は願っています)。このコードは簡単なデバッグを可能にするためのものであり、攻撃者がデバッグ環境にアクセスできる場合は対処すべきもっと重要な問題があります。
サイナン

2

HTTP_CF_CONNECTING_IPをREMOTE_ADDRに変換するのは難しいでしょう。したがって、apache(.htaccess)の自動付加を使用してそれを行うことができます。その$_SERVER['REMOTE_ADDR']ため、すべてのPHPスクリプトでが正しい値を持っているかどうかを考える必要はありません。

.htaccessコード

php_value auto_prepend_file "/path/to/file.php"

phpコード(file.php)

<?php

define('CLIENT_IP', isset($_SERVER['HTTP_CF_CONNECTING_IP']) ? $_SERVER['HTTP_CF_CONNECTING_IP'] : $_SERVER['REMOTE_ADDR']);

詳細はこちら


1

HTTP_CF_CONNECTING_IPは、cloudflareを使用している場合にのみ機能します。サイトを転送したり、cloudflareを削除したりすると、値が忘れられるため、このコードを使用してください。

$ip=$_SERVER["HTTP_CF_CONNECTING_IP"];
if (!isset($ip)) {
  $ip = $_SERVER['REMOTE_ADDR'];
}

1

Laravelで次の行を追加しますAppServiceProvider

...
use Symfony\Component\HttpFoundation\Request;


...
public function boot()
{
    Request::setTrustedProxies(['REMOTE_ADDR'], Request::HEADER_X_FORWARDED_FOR);
}

これで、を使用して実際のクライアントIPを取得できますrequest()->ip()

詳しくはこちらをご覧ください


0

magento 1.xユーザー(まだmagento 2.0を試していません)の場合は、https: //tall-paul.co.uk/2012/03/13/magento-show-remote-ip-in-cloudflare-the-を確認してください。 right-way / app / etc / local.xmlを変更し、次を追加する必要があります:HTTP_CF_CONNECTING_IP


0

CloudFlareを使用している場合、サーバーとユーザー間のすべてのリクエストはCloudFlareサーバーを介してルーティングされます。

この場合、ユーザーの実際のIPアドレスを取得する方法は2つあります。

  1. CloudFlareサーバーによって追加された追加のサーバーヘッダーを介して
  2. サーバーにCloudFlareApache / NGINXモジュールを追加します。

方法1:追加のサーバーヘッダーを介してIPを取得する

次のコードを使用して、ユーザーのIPアドレスを取得できます。

$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"]) $_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);

それはどのように機能していますか?

CloudFlareは、次のようにリクエストにいくつかのサーバー変数を追加します。

$_SERVER["HTTP_CF_CONNECTING_IP"] -ユーザーの実際のIPアドレス

$_SERVER["HTTP_CF_IPCOUNTRY"] -ユーザーのISO2国

$_SERVER["HTTP_CF_RAY"] loggin用の特別な文字列

上記のコードでは、$_SERVER["HTTP_CF_CONNECTING_IP"]が設定されているかどうかを確認しています。存在する場合は、ユーザーのIPアドレスとして考慮し、そうでない場合は、デフォルトのコードを$_SERVER['REMOTE_ADDR']

方法2:サーバーにCloudflareモジュールをインストールする

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.