PHPを使用して自分のWebサイトにアクセスしているユーザー/訪問者を追跡およびログに記録しようとして$_SERVER['REMOTE_ADDR']います。PHPでのIPアドレス追跡の一般的な方法。
しかし、私はキャッシュなどにCloudFlareを使用しており、CloudFlareのようにIPアドレスを受信しています。
108.162.212。*-108.162.239。*
CloudFlareを使用しながら実際のユーザー/訪問者のIPアドレスを取得する正しい方法は何でしょうか?
PHPを使用して自分のWebサイトにアクセスしているユーザー/訪問者を追跡およびログに記録しようとして$_SERVER['REMOTE_ADDR']います。PHPでのIPアドレス追跡の一般的な方法。
しかし、私はキャッシュなどにCloudFlareを使用しており、CloudFlareのようにIPアドレスを受信しています。
108.162.212。*-108.162.239。*
CloudFlareを使用しながら実際のユーザー/訪問者のIPアドレスを取得する正しい方法は何でしょうか?
クラウドフレアで利用できる追加のサーバー変数は次のとおりです。
$_SERVER["HTTP_CF_CONNECTING_IP"]実際の訪問者のIPアドレス、これはあなたが望むものです
$_SERVER["HTTP_CF_IPCOUNTRY"]訪問者の国
$_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に直接接続できれば誰でもヘッダーを偽造できるため、実際に有効なcloudflareIPアドレスが含まれていることを確認する必要があります。
更新: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であるかどうかを示します。
この質問に答えてから、CloudFlareはmod_cloudflareApache用にリリースしました。これは、CloudFlareアドレスではなく実際の訪問者のIPアドレスをログに記録して表示します。
https://www.cloudflare.com/resources-downloads#mod_cloudflare
Cloudflareは、次の単純なワンライナーを使用して、定義されている場合にCF-Connecting-IP保存できる追加のリクエストヘッダーをサーバーに送信します。$user_ip
$user_ip = (isset($_SERVER["HTTP_CF_CONNECTING_IP"])?$_SERVER["HTTP_CF_CONNECTING_IP"]:$_SERVER['REMOTE_ADDR']);
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']);
詳細はこちら
HTTP_CF_CONNECTING_IPは、cloudflareを使用している場合にのみ機能します。サイトを転送したり、cloudflareを削除したりすると、値が忘れられるため、このコードを使用してください。
$ip=$_SERVER["HTTP_CF_CONNECTING_IP"];
if (!isset($ip)) {
$ip = $_SERVER['REMOTE_ADDR'];
}
Laravelで次の行を追加しますAppServiceProvider:
...
use Symfony\Component\HttpFoundation\Request;
...
public function boot()
{
Request::setTrustedProxies(['REMOTE_ADDR'], Request::HEADER_X_FORWARDED_FOR);
}
これで、を使用して実際のクライアントIPを取得できますrequest()->ip()。
詳細はこちらをご覧ください。
CloudFlareを使用している場合、サーバーとユーザー間のすべてのリクエストはCloudFlareサーバーを介してルーティングされます。
この場合、ユーザーの実際のIPアドレスを取得する方法は2つあります。
次のコードを使用して、ユーザーの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']
Cloudflareには、ドメインの[ネットワーク管理]ページのヘッダーで「疑似IPv4」アドレスを使用するオプションがあります。サーバーに送信されるヘッダーを追加または上書きするオプションがあります。

ドキュメントから:
疑似IPv4とは何ですか?
Cloudflareは、IPv6の採用を加速するための一時的な手段として、IPv4アドレスを期待するレガシーアプリケーションでIPv6アドレスをサポートする疑似IPv4を提供します。目標は、クラスE IPv4アドレス空間を使用して、IPv6アドレスごとにほぼ一意のIPv4アドレスを提供することです。これは、実験的なものとして指定されており、通常はトラフィックを認識しません。詳細については、こちらをご覧ください。
オプション
- ヘッダーの追加:
Cf-Pseudo-IPv4ヘッダーのみを追加します- ヘッダーの上書き:既存のヘッダー
Cf-Connecting-IPとX-Forwarded-Forヘッダーを疑似IPv4アドレスで上書きします。注:特別な必要がない限り、このセットを「オフ」のままにしておくことをお勧めします。
この機能の詳細については、Cloudflareのこの記事を参照してください。ここでは、IPv4にある32ビット空間でIPv6の128ビットアドレス空間に対応する方法についてもう少し詳しく説明しています。
疑似IPv4とともにIPv6アドレスを知りたい場合、CloudflareはCf-Connecting-IPv6疑似IPv4が有効になっているときにヘッダーを追加します。これは、IPv6ネットワーク上にあるデバイスから発信されているトラフィックの量を測定するために使用できます。これは、IPv4の制限にまだ拘束されているシステムの更新に投資する前に、管理を示すための確実な数値が必要な場合に役立ちます。
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
オンラインでcloudflareのIP範囲を確認してから(いつでも変更される可能性があるため)、cloudflareからのものかどうかを確認することをお勧めします。
ソースがCloudflareの場合$_SERVER['HTTP_CF_CONNECTING_IP']、クライアントリクエストのIPアドレスを取得するために使用できますが、リクエストヘッダー内の任意のユーザーが送信してだましてしまう可能性があるため、すべてのリクエストに使用するのは安全ではありません。
次のコードを使用して、クライアントリクエストの実際のIPアドレスを取得できます。
function _getUserRealIP() {
$ipaddress = '';
if(isset($_SERVER['REMOTE_ADDR']))
$ipaddress = $_SERVER['REMOTE_ADDR'];
else 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
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
function _readCloudflareIps()
{
$file = file("https://www.cloudflare.com/ips-v4",FILE_IGNORE_NEW_LINES);
return $file;
}
function _checkIpInRange($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 _checkIsCloudflare($ip) {
$cf_ips = _readCloudflareIps();
$is_cf_ip = false;
foreach ($cf_ips as $cf_ip) {
if (_checkIpInRange($ip, $cf_ip)) {
$is_cf_ip = true;
break;
}
}
return $is_cf_ip;
}
function getRealIp()
{
$httpIp = _getUserRealIP();
$check = _checkIsCloudflare($httpIp);
if ($check) {
return $_SERVER['HTTP_CF_CONNECTING_IP'];
}else{
return $httpIp;
}
}
この関数をコードにインポートした後、次のgetRealIp()ような関数を呼び出す必要があります。
$userIp = getRealIp();
echo $userIp();