CloudFlare ve PHP üzerinden ziyaretçi IP adreslerini kaydetme


82

Bunu $_SERVER['REMOTE_ADDR']yapmak için PHP'yi kullanarak web siteme erişen kullanıcıları / ziyaretçileri izlemeye ve günlüğe kaydetmeye çalışıyorum . PHP'de IP adresi izleme için tipik bir yöntem.

Bununla birlikte, önbelleğe almak için CloudFlare kullanıyorum ve IP adreslerini CloudFlare'ninki gibi alıyorum:

108.162.212. * - 108.162.239. *

Hala CloudFlare kullanırken gerçek kullanıcıların / ziyaretçilerin IP adresini almak için doğru bir yöntem nedir?

Yanıtlar:


241

Bulut patlaması için mevcut olan ekstra sunucu değişkenleri şunlardır:

$_SERVER["HTTP_CF_CONNECTING_IP"] gerçek ziyaretçi ip adresi, istediğin bu

$_SERVER["HTTP_CF_IPCOUNTRY"] ziyaretçi ülkesi

$_SERVER["HTTP_CF_RAY"]

$_SERVER["HTTP_CF_VISITOR"] bu, http veya https olup olmadığını bilmenize yardımcı olabilir

bunu şu şekilde kullanabilirsiniz:

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

Bunu yaparsanız ve ziyaret edilen IP adresinin geçerliliği önemliyse, $_SERVER["REMOTE_ADDR"]gerçekten geçerli bir cloudflare IP adresi içerdiğini doğrulamanız gerekebilir , çünkü herhangi biri doğrudan sunucu IP'sine bağlanabildiyse başlıkta sahte olabilir.


16
REMOTE_ADDR'yi gerçek IP ile değiştirmek için +1, böylece kodda başka hiçbir değişiklik gerekmez.
aalaap

11
Güvenlik önemliyse, isteğin bir Cloudflare IP Aralığından ( cloudflare.com/ips ) gelip gelmediğini kontrol etmelisiniz . Mesela bu Joomla! Eklenti: github.com/piccaso/joomla-cf/blob/master/cf/cf.php
Florian Fida

Cloudflare ayrıca kendi sitelerinde de bu koda sahiptir. support.cloudflare.com/hc/en-us/articles/…
C0nw0nk

En iyi yanıt, ama aynı zamanda HTTP_CF_IPCOUNTRY'yi de dahil ettiğim için tebrikler, buna daha önce rastlamamıştım.
David Bell

http_cf_connecting_ip bazen şöyle şeyler verir: 2a01: 6500: a043: 33a6: b36a: 7259: 4de5: 2500 herhangi bir fikriniz var mı?
michael

15

Güncelleme : CloudFlare, mod_cloudflareapache için bir modül yayınladı , modül, cloudflare tarafından erişilenler yerine gerçek ziyaretçi IP Adreslerini kaydedecek ve görüntüleyecektir! https://www.cloudflare.com/resources-downloads#mod_cloudflare (Cevap: olimortimer )

Apache çalışma zamanına erişiminiz yoksa, aşağıdaki betiği kullanabilirsiniz, bu, bağlantının cloudflare üzerinden olup olmadığını kontrol etmenize ve kullanıcıların ipini almanıza olanak tanır.

Başka bir soru " CloudFlare DNS / doğrudan IP tanımlayıcısı " için kullandığım cevabımı yeniden yazıyorum

Cloudflare'nın ips'leri halka açık olarak saklanır, böylece buradan onları görüntüleyebilir ve ipin cloudflare'den gelip gelmediğini kontrol edebilirsiniz (bu, gerçek ip'i http başlığından almamızı sağlar HTTP_CF_CONNECTING_IP).

Bunu cf olmayan tüm bağlantıları devre dışı bırakmak için kullanıyorsanız veya tam tersi, bir common.php veya pagestart.php gibi diğer her komut dosyasından önce çağrılan tek bir php komut dosyasına sahip olmanızı öneririm.

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

Komut dosyasını kullanmak oldukça basit:

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

Bu komut dosyası size gerçek ip adresini ve isteğin CF olup olmadığını gösterecektir!


Doğru cevap budur, ancak IP'leri düzenli olarak güncellemeniz gerektiğini unutmayın. Yukarıdaki kodda bulunanlar zaten geçersizdir ve bu nedenle kod başarısız olacaktır. En son IP'leri buradan alabilirsiniz: cloudflare.com/ips İdeal olarak, bunları bir dosyada saklamalısınız , böylece yalnızca harici dosyayı güncellemeniz veya daha da iyisi, periyodik olarak buradan alınız
rafark

11

Bu soru sorulup yanıtlandığından beri CloudFlare, CloudFlare mod_cloudflareadresi yerine gerçek ziyaretçi IP adresini günlüğe kaydedip görüntüleyen Apache için yayınladı :

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


2019 - Artık desteklemiyorlar mod_cloudflare, ancak kullanılabilir. Adında yeni bir şey var mod_remoteip. Referans: support.cloudflare.com/hc/en-us/articles/…
sinaza

@sinaza, cevabım mod_cloudflare4 yıl öncesine ait olduğu için muhtemelen yeni bir cevap oluşturmak için en iyisi
olimortimer

@sjagr, düzenlemelerinizle ilgili olarak, yanlışlar - CloudFlare aslında Cloudflare, ilk yayınladığım gibi
olimortimer

10

Cloudflare , bu basit tek satırlık programı kullanarak, tanımlanırsa CF-Connecting-IPsaklayabileceğimiz bazı ek istek başlıklarını sunucunuza gönderir $user_ip:

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

Bununla ilgili sorun şu ki, bu sadece basit bir başlık, yani herkes onu istediği IP'ye ayarlayabilir ki bu büyük bir güvenlik açığıdır.
rafark

@rafark Sunucunuz uygun şekilde yapılandırılmışsa ve Cloudflare arkasında değilse.
Sainan

Evet tabi ki. Bu haddi zatında iyi bir çözümdür ancak çekler hala olduğu gibi HTTP_CF_CONNECTING_IP kullanmadan önce yapılmalıdır Callum cevabı
rafark

@rafark Ben de katılıyorum ama bu Apache yapılandırmanızda başka bir biçimde zaten mevcut olan çok fazla PHP kodu (umarım) ve bu kod daha kolay hata ayıklamaya izin verir ve bir saldırgan hata ayıklama ortamınıza erişebilirse başa çıkmanız gereken daha önemli sorunlarınız var.
Sainan

2

HTTP_CF_CONNECTING_IP'yi REMOTE_ADDR'ye dönüştürmek zor olurdu. Bunu yapmak için apache (.htaccess) auto prepending kullanabilirsiniz. Böylece $_SERVER['REMOTE_ADDR']tüm PHP betiklerinde doğru değere sahip olup olmadığını düşünmenize gerek kalmaz .

.htaccess kodu

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

php kodu (dosya.php)

<?php

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

Buradan daha fazla bilgi edinin


1

HTTP_CF_CONNECTING_IP yalnızca cloudflare kullanıyorsanız çalışır, belki sitenizi aktarırsanız veya cloudflare'yi kaldırırsanız değeri unutursunuz, bu yüzden bu kodu kullanın.

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

1

Laravel'de şu satırı ekleyin AppServiceProvider:

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


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

Şimdi kullanarak gerçek istemci IP'si alabilirsiniz request()->ip().

Daha fazlasını buradan okuyun .



0

CloudFlare kullandığınızda, sunucunuz ve kullanıcılar arasındaki tüm talepleriniz CloudFlare sunucuları aracılığıyla yönlendirilir.

Bu durumda Kullanıcının Gerçek IP Adresini almanın iki yöntemi vardır:

  1. CloudFlare Sunucuları tarafından eklenen Ekstra Sunucu Başlıkları aracılığıyla
  2. Sunucunuza bir CloudFlare Apache / NGINX Modülü eklemek.

Yöntem 1: Fazladan Sunucu Başlıkları aracılığıyla IP alın

Kullanıcının IP Adresini almak için aşağıdaki kodu kullanabilirsiniz:

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

Nasıl çalışıyor?

CloudFlare, isteğe aşağıdaki gibi bazı ekstra sunucu değişkenleri ekler:

$_SERVER["HTTP_CF_CONNECTING_IP"] - Kullanıcının Gerçek IP Adresi

$_SERVER["HTTP_CF_IPCOUNTRY"] - Kullanıcının ISO2 Ülkesi

$_SERVER["HTTP_CF_RAY"] Oturum açma amaçlı özel bir dize

Yukarıdaki kodda, $_SERVER["HTTP_CF_CONNECTING_IP"]ayarlanmış olup olmadığını kontrol ediyoruz . Eğer oradaysa, kullanıcının IP Adresi olarak kabul edeceğiz, aksi takdirde varsayılan kodu şu şekilde kullanacağız:$_SERVER['REMOTE_ADDR']

Yöntem 2: Sunucunuza Cloudflare Modülünü Kurma

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.