Bir kullanıcının PHP'de doğru IP adresini almanın en doğru yolu nedir?


301

IP adresi almak için kullanılabilir $ _SERVER değişken başlıkları bir bolluk olduğunu biliyorum . En doğru şekilde bir kullanıcının gerçek IP adresi (iyi bir yöntem mükemmel olduğunu bilmeden) adı geçen değişkenleri kullanarak almak için genel bir fikir birliği olup olmadığını merak ediyordum?

Ben derinlemesine bir çözüm bulmak için biraz zaman geçirdim ve bir dizi kaynak dayalı aşağıdaki kodu ile geldi. Birisi cevapta delikler açarsa ya da belki daha doğru bir şeye biraz ışık tutabilirse çok sevinirim.

@Alix'ten optimizasyonları düzenle

 /**
  * Retrieves the best guess of the client's actual IP address.
  * Takes into account numerous HTTP proxy headers due to variations
  * in how different ISPs handle IP addresses in headers between hops.
  */
 public function get_ip_address() {
  // Check for shared internet/ISP IP
  if (!empty($_SERVER['HTTP_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_CLIENT_IP']))
   return $_SERVER['HTTP_CLIENT_IP'];

  // Check for IPs passing through proxies
  if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
   // Check if multiple IP addresses exist in var
    $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
    foreach ($iplist as $ip) {
     if ($this->validate_ip($ip))
      return $ip;
    }
   }
  }
  if (!empty($_SERVER['HTTP_X_FORWARDED']) && $this->validate_ip($_SERVER['HTTP_X_FORWARDED']))
   return $_SERVER['HTTP_X_FORWARDED'];
  if (!empty($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']) && $this->validate_ip($_SERVER['HTTP_X_CLUSTER_CLIENT_IP']))
   return $_SERVER['HTTP_X_CLUSTER_CLIENT_IP'];
  if (!empty($_SERVER['HTTP_FORWARDED_FOR']) && $this->validate_ip($_SERVER['HTTP_FORWARDED_FOR']))
   return $_SERVER['HTTP_FORWARDED_FOR'];
  if (!empty($_SERVER['HTTP_FORWARDED']) && $this->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.
  *
  * @access public
  * @param string $ip
  */
 public function validate_ip($ip) {
     if (filter_var($ip, FILTER_VALIDATE_IP, 
                         FILTER_FLAG_IPV4 | 
                         FILTER_FLAG_IPV6 |
                         FILTER_FLAG_NO_PRIV_RANGE | 
                         FILTER_FLAG_NO_RES_RANGE) === false)
         return false;
     self::$ip = $ip;
     return true;
 }

Uyarı Kelimeleri (güncelleme)

REMOTE_ADDRhala bir IP adresinin en güvenilir kaynağını temsil etmektedir . $_SERVERBurada sözü edilen diğer değişkenler, uzak bir istemci tarafından kolayca taklit edilebilir. Bu çözümün amacı, bir proxy'nin arkasında oturan bir istemcinin IP adresini belirlemeye çalışmaktır. Genel amaçlarınız için, bunu doğrudan $_SERVER['REMOTE_ADDR']her ikisinden döndürülen ve saklanan IP adresiyle birlikte kullanmayı düşünebilirsiniz .

Kullanıcıların% 99,9'u için bu çözüm ihtiyaçlarınıza mükemmel şekilde cevap verecektir. Sizi, kendi istek başlıklarını enjekte ederek sisteminizi kötüye kullanmak isteyen kötü niyetli kullanıcıların% 0,1'inden korumaz. Kritik bir görev için IP adreslerine güveniyorsanız, REMOTE_ADDRvekalet arkasındakilere hitap etmeyin.


2
Whatismyip.com sorusu için, bu komut dosyası gibi bir şey yaptıklarını düşünüyorum, yerel olarak çalıştırıyor musunuz? Neden dahili bir IP'niz varsa, bu durumda genel arayüz üzerinden hiçbir şey gönderilmiyorsa, bu yüzden php için bilgi yok
Matt

2
Bunu uygularken bunu aklınızda bulundurun: stackoverflow.com/questions/1672827/…
Kevin Peno

19
Tüm bu HTTP başlıklarının değiştirilmesinin gerçekten kolay olduğunu unutmayın: çözümünüzle, tarayıcımı rastgele bir IP'ye sahip bir X-Forwarded-For başlığı göndermek için yapılandırmam gerekiyor ve betiğiniz sahte bir adres döndürecek. Dolayısıyla, ne yapmaya çalıştığınıza bağlı olarak, bu çözüm sadece REMOTE_ADDR kullanmaktan daha az güvenilir olabilir.
gnomnain

14
OMFG, "güvenilmez ip"! İlk defa SO'da böyle bir saçmalık görüyorum. Tek güvenilir IP adresi REMOTE_ADDR
Common Sense

3
-1 bu kimlik sahtekarlığına karşı savunmasızdır. Yaptığınız tek şey kullanıcıya ip adresinin ne olması gerektiğini sormak.
kale

Yanıtlar:


268

IP adresini almanın daha kısa ve temiz bir yolu:

function get_ip_address(){
    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){
        if (array_key_exists($key, $_SERVER) === true){
            foreach (explode(',', $_SERVER[$key]) as $ip){
                $ip = trim($ip); // just to be safe

                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){
                    return $ip;
                }
            }
        }
    }
}

Umut ediyorum bu yardım eder!


Kodunuzu zaten oldukça eksiksiz gibi görünüyor, ben (her zamanki IP uyarıları dışında) içinde herhangi bir olası hata göremiyorum, ben validate_ip()olsa filtre uzantısı güvenmek için işlevi değiştirmek istiyorsunuz :

public function validate_ip($ip)
{
    if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false)
    {
        return false;
    }

    self::$ip = sprintf('%u', ip2long($ip)); // you seem to want this

    return true;
}

Ayrıca HTTP_X_FORWARDED_FORsnippet'iniz bundan basitleştirilebilir:

// check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    // check if multiple ips exist in var
    if (strpos($_SERVER['HTTP_X_FORWARDED_FOR'], ',') !== false)
    {
        $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

        foreach ($iplist as $ip)
        {
            if ($this->validate_ip($ip))
                return $ip;
        }
    }

    else
    {
        if ($this->validate_ip($_SERVER['HTTP_X_FORWARDED_FOR']))
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
}

Buna:

// check for IPs passing through proxies
if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    $iplist = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);

    foreach ($iplist as $ip)
    {
        if ($this->validate_ip($ip))
            return $ip;
    }
}

IPv6 adreslerini de doğrulamak isteyebilirsiniz.


4
filter_varIP adresindeki bir sürü haksız imzasız int kontrolleri kaldırdığı için düzeltmeyi kesinlikle takdir ediyorum . Ben de IPv6 adreslerini de doğrulama seçeneği verdiğini seviyorum. HTTP_X_FORWARDED_FOROptimizasyonu da çok teşekkür ederiz. Birkaç dakika içinde kodu güncelleyeceğim.
Corey Ballou

33
-1 Bu, yaptığınız tek şey sahteciliğe açıktır, kullanıcıya ip adresinin ne olması gerektiğini sormaktır.
kale

7
@ Rock: Evet, biliyorum. OP bunun farkında ve cevabımda da bundan bahsettim. Ama yorum için teşekkürler.
Alix Axel

1
FYI: Alix Axel'in kodunun çalışması için FILTER_FLAG_IPV6'yı kaldırmak zorunda kaldım.
darkAsPitch

2
@ rubenrp81 TCP soket işleyicisi tek kurallı kaynaktır, diğer her şey saldırgan tarafından denetlenir. Yukarıdaki kod bir saldırganın hayalidir.
kale

12

Ancak o zaman bile, kullanıcının gerçek IP adresini almak güvenilir olmayacaktır. Tek yapmaları gereken, anonim bir proxy sunucusu (http_x_forwarded_for, http_forwarded, vb. İçin başlıklara uymayan) kullanmaktır ve elde ettiğiniz tek şey proxy sunucusunun IP adresidir.

Daha sonra anonim bir proxy sunucusu IP adresi listesi olup olmadığını görebilirsiniz, ancak% 100 doğru olduğundan emin olmanın bir yolu yoktur ve en çok yaptığı şey bir proxy sunucusu olduğunu bildirmektir. Birisi akıllıysa, HTTP iletmeleri için üstbilgileri taklit edebilir.

Diyelim ki yerel kolejden hoşlanmıyorum. Hangi IP adreslerini kaydettiklerini anlıyorum ve kötü şeyler yaparak sitenizdeki IP adreslerini yasaklıyorum, çünkü HTTP'yi onurlandırdığınızı anladım. Liste sonsuz.

Sonra, tahmin ettiğiniz gibi, daha önce bahsettiğim kolej ağı gibi dahili IP adresleri var. Bir çok 10.xxx biçimi kullanın. Tek bildiğiniz şey, paylaşılan bir ağ için yönlendirildiğidir.

O zaman çok fazla çalışmaya başlamam, ancak dinamik IP adresleri artık genişbantın yoludur. Yani. Bir kullanıcı IP adresi alsanız bile, en uzun 2-3 ay içinde değişmesini bekleyin.


Giriş için teşekkürler. Şu anda oturumu ele geçirme sınırlamak için sınırlayıcı bir faktör olarak kendi sınıf C IP kullanarak oturum kimlik doğrulamasına yardımcı olmak için kullanıcının IP adresini kullanıyorum ama makul IP dinamik izin. Sahte IP'ler ve anonim proxy sunucuları, belirli bir grup kişi için uğraşmam gereken bir şeydir.
Corey Ballou

@cballou - Elbette bu amaçla REMOTE_ADDR kullanmak için doğru olanıdır. HTTP üstbilgilerine dayanan herhangi bir yaklaşım, üstbilgi dolandırıcılığına karşı savunmasızdır. Bir seans ne kadar sürer? Dinamik IP'ler hızlı değişmez.
MZB

Özellikle onları istiyorsam yaparlar (birçok sürücünün desteklediği mac adresini değiştirin). Sadece REMOTE_ADDR tek başına konuştuğu son sunucuyu elde etmek için yeterlidir. Yani bir proxy durumunda proxy IP'sini alırsınız.

8

Kullanırız:

/**
 * Get the customer's IP address.
 *
 * @return string
 */
public function getIpAddress() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        return trim($ips[count($ips) - 1]);
    } else {
        return $_SERVER['REMOTE_ADDR'];
    }
}

HTTP_X_FORWARDED_FOR üzerindeki patlama, Squid kullanıldığında IP adreslerini tespit ettiğimiz garip sorunlardan kaynaklanıyor .


Maalesef, patladığında ve benzerlerinde temelde aynı şeyi yaptığını fark ettim. Artı biraz ekstra. Bu yüzden cevabımın çok yardımcı olduğundan şüpheliyim. :)
gabrielk

Bu, localhost'un adresini döndürür
Scarl

3

Cevabım temelde @ AlixAxel'in cevabının sadece cilalı, tam olarak doğrulanmış ve tamamen paketlenmiş bir versiyonu:

<?php

/* Get the 'best known' client IP. */

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

                foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key)
                    {
                        if (array_key_exists($key, $_SERVER)) 
                            {
                                foreach (explode(',', $_SERVER[$key]) as $ip)
                                    {
                                        $ip = trim($ip);

                                        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
                                            {
                                                return $ip;
                                            };
                                    };
                            };
                    };

                return false;
            };
    };

$best_known_ip = getClientIP();

if(!empty($best_known_ip))
    {
        $ip = $clients_ip = $client_ip = $client_IP = $best_known_ip;
    }
else
    {
        $ip = $clients_ip = $client_ip = $client_IP = $best_known_ip = '';
    };

?>

değişiklikler:

  • İşlev adını basitleştirir ('camelCase' biçimlendirme stiliyle).

  • İşlevin kodunuzun başka bir bölümünde zaten bildirilmediğinden emin olmak için bir kontrol içerir.

  • 'CloudFlare' uyumluluğunu dikkate alır.

  • 'GetClientIP' işlevinin döndürülen değerine "IP ile ilgili" birden çok ad verir.

  • İşlev geçerli bir IP adresi döndürmezse, tüm değişkenlerin yerine boş bir dizeye ayarlanmasını sağlar null.

  • Sadece (45) kod satırı.


2

En büyük soru hangi amaç için?

Kodunuz neredeyse olabildiğince kapsamlı - ancak proxy eklenmiş bir üstbilgiye benzeyen bir şey görürseniz, CLIENT_IP'in INSTEAD'ini kullandığınızı görürsünüz, ancak bu bilgileri denetim amacıyla istiyorsanız o zaman uyarılırsınız - çok kolay sahte.

Kesinlikle herhangi bir kimlik doğrulama işlemi için IP adreslerini asla kullanmamalısınız - bu adresler bile sahte olabilir.

Http olmayan bir bağlantı noktası üzerinden sunucuya geri bağlanan bir flaş veya java uygulaması dışarı iterek istemci ip adresinin daha iyi bir ölçümünü elde edebilirsiniz (bu nedenle şeffaf proxy'leri veya proxy enjekte edilen başlıkların yanlış olduğu durumları gösterir - ancak istemcinin SADECE bir web proxy üzerinden bağlanabileceği veya giden bağlantı noktasının engellendiği durumlarda, uygulamadan bağlantı olmayacağını unutmayın.

C.


Dikkate alarak ben sadece bir PHP çözüm arıyorum, $_SERVER['CLIENT_IP']eğer ifade başka ikinci olarak eklemek öneririz ?
Corey Ballou

Hayır - yalnızca döndürülen verilere herhangi bir önem vermek istiyorsanız, ağ bitiş noktası adresini (istemci IP) ve proxy eklenmiş başlıklarda farklı bir değer öneren herhangi bir şeyi korumak iyi bir fikir olacaktır (ör. 192.168.1.x adresinin
birçoğuna

1

Yukarıda çok daha iyi ve daha özlü cevaplar olduğunu ve bu bir işlev ne de çevresinde en zarif komut dosyası olduğunu anlıyorum. Bizim durumumuzda, hem taklit edilebilir x_forwarded_for hem de daha güvenilir remote_addr'yi basit bir anahtar başına çıktıya ihtiyacımız vardı. Boşlukların (eğer hiç biçimlendirilmemiş işlevi döndürmektense), yoksa -veya-tekil ise diğer işlevlere enjekte etmelerine izin verilmesi gerekiyordu. Platform ayarları için anahtar başına özelleştirilmiş etiket (ler) ile bir "açık veya kapalı" varya ihtiyacı vardı. Ayrıca $ ip'in forwarded_for biçimini alabilmesi için isteğe bağlı olarak dinamik olması için bir yola ihtiyacı vardı.

Ayrıca kimsenin adresini isset () vs! Unutmayın, "PWNED" gibi kelimeleri x_forwarded_for olarak taklit edebilirsiniz, bu nedenle çıktınız korunan bir yere veya DB'ye gerçek bir ip sözdizimiyle sterilize ettiğinizden emin olun.

Ayrıca, diziyi x_forwarder_for'da görmek için bir çoklu proxy'ye ihtiyacınız varsa google translate kullanarak test edebilirsiniz. Test etmek için spoof başlıkları istiyorsanız, bunu Chrome İstemci Header Spoof uzantısına bakın. Bu, varsayılan olarak anon proxy'sinin arkasındayken standart remote_addr olarak ayarlanır.

Ben remote_addr boş olabilir, ama her ihtimale karşı orada olduğu gibi herhangi bir durumda bilmiyorum.

// proxybuster - attempts to un-hide originating IP if [reverse]proxy provides methods to do so
  $enableProxyBust = true;

if (($enableProxyBust == true) && (isset($_SERVER['REMOTE_ADDR'])) && (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) && (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))) {
    $ip = end(array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']))));
    $ipProxy = $_SERVER['REMOTE_ADDR'];
    $ipProxy_label = ' behind proxy ';
} elseif (($enableProxyBust == true) && (isset($_SERVER['REMOTE_ADDR']))) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $ipProxy = '';
    $ipProxy_label = ' no proxy ';
} elseif (($enableProxyBust == false) && (isset($_SERVER['REMOTE_ADDR']))) {
    $ip = $_SERVER['REMOTE_ADDR'];
    $ipProxy = '';
    $ipProxy_label = '';
} else {
    $ip = '';
    $ipProxy = '';
    $ipProxy_label = '';
}

Bunları aşağıdaki işlevlerde veya sorgu / eko / görünümlerde kullanmak üzere dinamik yapmak için, günlük gen veya hata raporlaması için diyelim, bir sürü başka koşul veya statik şema çıktısı yapmadan globalleri kullanın veya istediğiniz yerde yankılayın fonksiyonlar.

function fooNow() {
    global $ip, $ipProxy, $ipProxy_label;
    // begin this actions such as log, error, query, or report
}

Tüm harika düşünceleriniz için teşekkür ederiz. Lütfen bunun daha iyi olup olmadığını bana bildirin, bu başlıklar için hala yeni :)


1

Ben sadece IP adresi değil IP bilgileri ile bir dizi döndüren bu işlevi ile geldi.

// Example usage:
$info = ip_info();
if ( $info->proxy ) {
    echo 'Your IP is ' . $info->ip;
} else {
    echo 'Your IP is ' . $info->ip . ' and your proxy is ' . $info->proxy_ip;
}

İşte işlevi:

/**
 * Retrieves the best guess of the client's actual IP address.
 * Takes into account numerous HTTP proxy headers due to variations
 * in how different ISPs handle IP addresses in headers between hops.
 *
 * @since 1.1.3
 *
 * @return object {
 *         IP Address details
 *
 *         string $ip The users IP address (might be spoofed, if $proxy is true)
 *         bool $proxy True, if a proxy was detected
 *         string $proxy_id The proxy-server IP address
 * }
 */
function ip_info() {
    $result = (object) array(
        'ip' => $_SERVER['REMOTE_ADDR'],
        'proxy' => false,
        'proxy_ip' => '',
    );

    /*
     * This code tries to bypass a proxy and get the actual IP address of
     * the visitor behind the proxy.
     * Warning: These values might be spoofed!
     */
    $ip_fields = array(
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED',
        'HTTP_X_CLUSTER_CLIENT_IP',
        'HTTP_FORWARDED_FOR',
        'HTTP_FORWARDED',
        'REMOTE_ADDR',
    );
    foreach ( $ip_fields as $key ) {
        if ( array_key_exists( $key, $_SERVER ) === true ) {
            foreach ( explode( ',', $_SERVER[$key] ) as $ip ) {
                $ip = trim( $ip );

                if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
                    $forwarded = $ip;
                    break 2;
                }
            }
        }
    }

    // If we found a different IP address then REMOTE_ADDR then it's a proxy!
    if ( $forwarded != $result->ip ) {
        $result->proxy = true;
        $result->proxy_ip = $result->ip;
        $result->ip = $forwarded;
    }

    return $result;
}

1

Birinin daha önce söylediği gibi, buradaki anahtar, kullanıcının ips'lerini saklamak istediğiniz nedendir.

Üzerinde çalıştığım bir kayıt sisteminden bir örnek vereceğim ve elbette aramalarımda sıkça gelen bu eski tartışmaya katkıda bulunmak için çözüm sunacağım.

Birçok php kayıt kütüphanesi ip kullanarak kullanıcının ip tabanlı başarısız denemeleri kısmak / kilitlemek. Bu tabloyu düşünün:

-- mysql
DROP TABLE IF EXISTS `attempts`;
CREATE TABLE `attempts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `ip` varchar(39) NOT NULL, /*<<=====*/
  `expiredate` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 -- sqlite
...

Ardından, kullanıcı bir oturum açma veya parola sıfırlama gibi hizmetle ilgili herhangi bir şey yapmaya çalıştığında, başlangıçta bir işlev çağrılır:

public function isBlocked() {
      /*
       * used one of the above methods to capture user's ip!!!
       */
      $ip = $this->ip;
      // delete attempts from this ip with 'expiredate' in the past
      $this->deleteAttempts($ip, false);
      $query = $this->dbh->prepare("SELECT count(*) FROM {$this->token->get('table_attempts')} WHERE ip = ?");
      $query->execute(array($ip));
      $attempts = $query->fetchColumn();
      if ($attempts < intval($this->token->get('attempts_before_verify'))) {
         return "allow";
      }
      if ($attempts < intval($this->token->get('attempts_before_ban'))) {
         return "captcha";
      }
      return "block";
   }

Örneğin diyelim ki $this->token->get('attempts_before_ban') === 102 kullanıcı, önceki kodlarda başlıkların taklit edilebildiği gibi aynı ips için geliyor , 5 denemeden sonra her ikisi de yasaklandı ! Daha da kötüsü, hepsi aynı proxy'den geliyorsa, sadece ilk 10 kullanıcı günlüğe kaydedilir ve geri kalanı yasaklanır!

Burada kritik olan, tabloda benzersiz bir dizine ihtiyacımız var attemptsve bunu aşağıdaki gibi bir kombinasyondan alabiliriz:

 `ip` varchar(39) NOT NULL,
 `jwt_load varchar(100) NOT NULL

burada , her kullanıcı için rasgele / benzersiz bir değer içermesi gereken şifrelenmiş yükü depoladığımız json web token teknolojisini jwt_loadizleyen bir http çerezinden gelir . Tabii ki istek şu şekilde değiştirilmelidir: ve sınıf a'yı da başlatmalıdır ."SELECT count(*) FROM {$this->token->get('table_attempts')} WHERE ip = ? AND jwt_load = ?"private $jwt


0

Deneyimim, kullanıcının IP adresinin virgülle ayrılmış listenin sonunda sona ermesi, dolayısıyla başlığın başlangıcından itibaren, döndürülen proxy'lerden birinin ip adresini alma olasılığı daha yüksektir, bu da birçok kullanıcının bu proxy'den gelebileceği için oturumun ele geçirilmesine neden olabilir.


1
HTTP_X_FORWARDED_FOR üzerindeki wikipedia sayfasını okuduktan sonra: en.wikipedia.org/wiki/X-Forwarded-For ... Önerilen siparişin kodunuzda olduğu gibi gerçekten sağdan sola olduğunu görüyorum. Ancak, günlüklerimizden görebiliyorum, bunun vahşi vekiller tarafından saygı görmediği birçok durum var ve kontrol etmek istediğiniz ip adresi listenin her iki ucunda da olabilir.
Chris Withers

1
Ya da ortada, bazı vekillerin soldan sağa sıraya saygı göstermesi ve diğerlerinin yapmaması durumunda olduğu gibi.
Brilliand

0

Bunun için teşekkürler, çok faydalı.

Kod sözdizimsel olarak doğru olsaydı yardımcı olacaktır. Korkarım ki {20 hattı etrafında çok fazla var. Korkarım ki kimse bunu denemedi.

Ben deli olabilir, ancak birkaç geçerli ve geçersiz adreslerde denedikten sonra, çalışan validate_ip () tek sürümü bu oldu:

    public function validate_ip($ip)
    {
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE) === false)
            return false;
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE) === false)
            return false;
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) === false && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) === false)
            return false;

        return true;
    }

0

CloudFlare önbellek katmanı Hizmetlerini kullanıyorsanız değiştirilmiş bir sürüm

function getIP()
{
    $fields = array('HTTP_X_FORWARDED_FOR',
                    'REMOTE_ADDR',
                    'HTTP_CF_CONNECTING_IP',
                    'HTTP_X_CLUSTER_CLIENT_IP');

    foreach($fields as $f)
    {
        $tries = $_SERVER[$f];
        if (empty($tries))
            continue;
        $tries = explode(',',$tries);
        foreach($tries as $try)
        {
            $r = filter_var($try,
                            FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 |
                            FILTER_FLAG_NO_PRIV_RANGE |
                            FILTER_FLAG_NO_RES_RANGE);

            if ($r !== false)
            {
                return $try;
            }
        }
    }
    return false;
}

0

Cevabın sadece bir VB.NET sürümü:

Private Function GetRequestIpAddress() As IPAddress
    Dim serverVariables = HttpContext.Current.Request.ServerVariables
    Dim headersKeysToCheck = {"HTTP_CLIENT_IP", _
                              "HTTP_X_FORWARDED_FOR", _
                              "HTTP_X_FORWARDED", _
                              "HTTP_X_CLUSTER_CLIENT_IP", _
                              "HTTP_FORWARDED_FOR", _
                              "HTTP_FORWARDED", _
                              "REMOTE_ADDR"}
    For Each thisHeaderKey In headersKeysToCheck
        Dim thisValue = serverVariables.Item(thisHeaderKey)
        If thisValue IsNot Nothing Then
            Dim validAddress As IPAddress = Nothing
            If IPAddress.TryParse(thisValue, validAddress) Then
                Return validAddress
            End If
        End If
    Next
    Return Nothing
End Function

3
Soruda

0

Bir başka temiz yol:

  function validateIp($var_ip){
    $ip = trim($var_ip);

    return (!empty($ip) &&
            $ip != '::1' &&
            $ip != '127.0.0.1' &&
            filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false)
            ? $ip : false;
  }

  function getClientIp() {
    $ip = @$this->validateIp($_SERVER['HTTP_CLIENT_IP']) ?:
          @$this->validateIp($_SERVER['HTTP_X_FORWARDED_FOR']) ?:
          @$this->validateIp($_SERVER['HTTP_X_FORWARDED']) ?:
          @$this->validateIp($_SERVER['HTTP_FORWARDED_FOR']) ?:
          @$this->validateIp($_SERVER['HTTP_FORWARDED']) ?:
          @$this->validateIp($_SERVER['REMOTE_ADDR']) ?:
          'LOCAL OR UNKNOWN ACCESS';

    return $ip;
  }

0

Symfony's Request sınıfından https://github.com/symfony/symfony/blob/1bd125ec4a01220878b3dbc3ec3156b073996af9/src/Symfony/Component/HttpFoundation/Request.php

const HEADER_FORWARDED = 'forwarded';
const HEADER_CLIENT_IP = 'client_ip';
const HEADER_CLIENT_HOST = 'client_host';
const HEADER_CLIENT_PROTO = 'client_proto';
const HEADER_CLIENT_PORT = 'client_port';

/**
 * Names for headers that can be trusted when
 * using trusted proxies.
 *
 * The FORWARDED header is the standard as of rfc7239.
 *
 * The other headers are non-standard, but widely used
 * by popular reverse proxies (like Apache mod_proxy or Amazon EC2).
 */
protected static $trustedHeaders = array(
    self::HEADER_FORWARDED => 'FORWARDED',
    self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR',
    self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST',
    self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO',
    self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT',
);

/**
 * Returns the client IP addresses.
 *
 * In the returned array the most trusted IP address is first, and the
 * least trusted one last. The "real" client IP address is the last one,
 * but this is also the least trusted one. Trusted proxies are stripped.
 *
 * Use this method carefully; you should use getClientIp() instead.
 *
 * @return array The client IP addresses
 *
 * @see getClientIp()
 */
public function getClientIps()
{
    $clientIps = array();
    $ip = $this->server->get('REMOTE_ADDR');
    if (!$this->isFromTrustedProxy()) {
        return array($ip);
    }
    if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) {
        $forwardedHeader = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]);
        preg_match_all('{(for)=("?\[?)([a-z0-9\.:_\-/]*)}', $forwardedHeader, $matches);
        $clientIps = $matches[3];
    } elseif (self::$trustedHeaders[self::HEADER_CLIENT_IP] && $this->headers->has(self::$trustedHeaders[self::HEADER_CLIENT_IP])) {
        $clientIps = array_map('trim', explode(',', $this->headers->get(self::$trustedHeaders[self::HEADER_CLIENT_IP])));
    }
    $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from
    $firstTrustedIp = null;
    foreach ($clientIps as $key => $clientIp) {
        // Remove port (unfortunately, it does happen)
        if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) {
            $clientIps[$key] = $clientIp = $match[1];
        }
        if (!filter_var($clientIp, FILTER_VALIDATE_IP)) {
            unset($clientIps[$key]);
        }
        if (IpUtils::checkIp($clientIp, self::$trustedProxies)) {
            unset($clientIps[$key]);
            // Fallback to this when the client IP falls into the range of trusted proxies
            if (null ===  $firstTrustedIp) {
                $firstTrustedIp = $clientIp;
            }
        }
    }
    // Now the IP chain contains only untrusted proxies and the client IP
    return $clientIps ? array_reverse($clientIps) : array($firstTrustedIp);
}

Tanımsız mülk: $ sunucu
C47

0

Kimsenin filter_input'tan bahsetmediğine şaşırdım, bu yüzden Alix Axel'nin cevabı tek satırlı:

function get_ip_address(&$keys = ['HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'HTTP_CLIENT_IP', 'REMOTE_ADDR'])
{
    return empty($keys) || ($ip = filter_input(INPUT_SERVER, array_pop($keys), FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))? $ip : get_ip_address($keys);
}

-1

Kendi sorunuzu hemen hemen cevapladınız! :)

function getRealIpAddr() {
    if(!empty($_SERVER['HTTP_CLIENT_IP']))   //Check IP address from shared Internet
    {
        $IPaddress = $_SERVER['HTTP_CLIENT_IP'];
    }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']))   //To check IP address is passed from the proxy
    {
        $IPaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    else
    {
        $IPaddress = $_SERVER['REMOTE_ADDR'];
    }
    return $IPaddress;
}

Kaynak


-6
/**
 * Sanitizes IPv4 address according to Ilia Alshanetsky's book
 * "php|architect?s Guide to PHP Security", chapter 2, page 67.
 *
 * @param string $ip An IPv4 address
 */
public static function sanitizeIpAddress($ip = '')
{
if ($ip == '')
    {
    $rtnStr = '0.0.0.0';
    }
else
    {
    $rtnStr = long2ip(ip2long($ip));
    }

return $rtnStr;
}

//---------------------------------------------------

/**
 * Returns the sanitized HTTP_X_FORWARDED_FOR server variable.
 *
 */
public static function getXForwardedFor()
{
if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
    {
    $rtnStr = $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
elseif (isset($HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR']))
    {
    $rtnStr = $HTTP_SERVER_VARS['HTTP_X_FORWARDED_FOR'];
    }
elseif (getenv('HTTP_X_FORWARDED_FOR'))
    {
    $rtnStr = getenv('HTTP_X_FORWARDED_FOR');
    }
else
    {
    $rtnStr = '';
    }

// Sanitize IPv4 address (Ilia Alshanetsky):
if ($rtnStr != '')
    {
    $rtnStr = explode(', ', $rtnStr);
    $rtnStr = self::sanitizeIpAddress($rtnStr[0]);
    }

return $rtnStr;
}

//---------------------------------------------------

/**
 * Returns the sanitized REMOTE_ADDR server variable.
 *
 */
public static function getRemoteAddr()
{
if (isset($_SERVER['REMOTE_ADDR']))
    {
    $rtnStr = $_SERVER['REMOTE_ADDR'];
    }
elseif (isset($HTTP_SERVER_VARS['REMOTE_ADDR']))
    {
    $rtnStr = $HTTP_SERVER_VARS['REMOTE_ADDR'];
    }
elseif (getenv('REMOTE_ADDR'))
    {
    $rtnStr = getenv('REMOTE_ADDR');
    }
else
    {
    $rtnStr = '';
    }

// Sanitize IPv4 address (Ilia Alshanetsky):
if ($rtnStr != '')
    {
    $rtnStr = explode(', ', $rtnStr);
    $rtnStr = self::sanitizeIpAddress($rtnStr[0]);
    }

return $rtnStr;
}

//---------------------------------------------------

/**
 * Returns the sanitized remote user and proxy IP addresses.
 *
 */
public static function getIpAndProxy()
{
$xForwarded = self::getXForwardedFor();
$remoteAddr = self::getRemoteAddr();

if ($xForwarded != '')
    {
    $ip    = $xForwarded;
    $proxy = $remoteAddr;
    }
else
    {
    $ip    = $remoteAddr;
    $proxy = '';
    }

return array($ip, $proxy);
}
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.