Was ist der genaueste Weg, um die korrekte IP -Adresse eines Benutzers in PHP abzurufen?

StackOverflow https://stackoverflow.com/questions/1634782

  •  06-07-2019
  •  | 
  •  

Frage

Ich weiß, dass es eine Vielzahl von gibt $ _Server Variablen Header für das Abrufen von IP -Adressen verfügbar. Ich habe mich gefragt, ob es einen allgemeinen Konsens darüber gibt, wie die reale IP -Adresse eines Benutzers mit diesen Variablen am genauesten abgerufen werden kann.

Ich habe einige Zeit damit verbracht, eine ausführliche Lösung zu finden, und habe den folgenden Code basierend auf einer Reihe von Quellen entwickelt. Ich würde es lieben, wenn jemand bitte Löcher in die Antwort stecken oder etwas Licht auf etwas geben könnte, das vielleicht genauerer ist.

Bearbeiten enthält Optimierungen von @Alix

 /**
  * 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;
 }

Warnwörter (Update)

REMOTE_ADDR repräsentiert immer noch die zuverlässigste Quelle einer IP -Adresse. Das andere $_SERVER Hier erwähnte Variablen können sehr einfach von einem Remote -Client gefälscht werden. Der Zweck dieser Lösung besteht darin, die IP -Adresse eines Kunden zu bestimmen, der hinter einem Proxy sitzt. Für Ihre allgemeinen Zwecke können Sie dies in Kombination mit der IP -Adresse in Betracht ziehen, die direkt von zurückgegeben wurde $_SERVER['REMOTE_ADDR'] und beide speichern.

Für 99,9% der Benutzer entspricht diese Lösung perfekt zu Ihren Anforderungen. Es wird Sie nicht vor den 0,1% der böswilligen Benutzer schützen, die Ihr System missbrauchen möchten, indem sie ihre eigenen Anfrage -Header injizieren. Wenn Sie sich auf IP -Adressen für etwas Missionkritikiges verlassen, gehen Sie auf REMOTE_ADDR Und die Machen Sie sich nicht, dass Sie sich an die hinter einem Stellvertreter kümmern.

War es hilfreich?

Lösung

Hier ist eine kürzere und sauberere Möglichkeit, die IP -Adresse zu erhalten:

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

Ich hoffe, es hilft!


Ihr Code scheint bereits ziemlich vollständig zu sein, ich kann keine möglichen Fehler darin sehen (abgesehen von den üblichen IP -Vorbehalten), würde ich die ändern validate_ip() Funktion, um sich jedoch auf die Filtererweiterung zu verlassen:

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

Auch dein HTTP_X_FORWARDED_FOR Snippet kann daraus vereinfacht werden:

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

Dazu:

// 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;
    }
}

Möglicherweise möchten Sie auch IPv6 -Adressen validieren.

Andere Tipps

Selbst dann ist es unzuverlässig, die echte IP -Adresse eines Benutzers zu erhalten. Sie müssen lediglich einen anonymen Proxy -Server verwenden (eines, der die Header für http_x_forwarded_for, http_forded usw. nicht ärgert), und alles, was Sie erhalten, ist die IP -Adresse ihres Proxy -Servers.

Sie können dann sehen, ob es eine Liste von Proxy -Server -IP -Adressen gibt, die anonym sind. Es gibt jedoch keine Möglichkeit, sicherzustellen, dass dies auch 100% genau ist. Das Beste, was es tun würde, ist, dass Sie wissen, dass es sich um einen Proxy -Server handelt. Und wenn jemand klug ist, kann er Header für HTTP -Stürmer fälschen.

Nehmen wir an, ich mag das örtliche College nicht. Ich finde heraus, welche IP -Adressen sie registriert haben, und lasse ihre IP -Adresse auf Ihrer Website verboten, indem sie schlechte Dinge tun, weil ich herausfindet, dass Sie die HTTP -Stürmer ehren. Die Liste ist endlos.

Dann gibt es, wie Sie vermutet haben, interne IP -Adressen wie das College -Netzwerk, das ich zuvor aufgenommen habe. Vieles verwenden ein 10.xxx -Format. Sie würden also nur wissen, dass es für ein gemeinsam genutztes Netzwerk weitergeleitet wurde.

Dann werde ich nicht viel damit eingehen, aber dynamische IP -Adressen sind die Art des Breitbands mehr. So. Selbst wenn Sie eine Benutzer -IP -Adresse erhalten, erwarten Sie, dass sich sie in 2 bis 3 Monaten am längsten ändert.

Wir gebrauchen:

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

Der explodierte auf http_x_forwarded_for ist auf seltsame Probleme, die wir bei IP -Adressen erkannt hatten, wenn Tintenfisch wurde benutzt.

Meine Antwort ist im Grunde nur eine polierte, vollständig validierte und vollverpackte Version von @alixaxels Antwort:

<?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 = '';
    };

?>

Änderungen:

  • Es vereinfacht den Funktionsnamen (mit dem Formatierungsstil "Kamelcase").

  • Es enthält einen Scheck, um sicherzustellen, dass die Funktion in einem anderen Teil Ihres Codes nicht bereits deklariert wird.

  • Es berücksichtigt "Cloudflare" -Kompatibilität.

  • Es initialisiert mehrere "IP-bezogene" Variablennamen zum zurückgegebenen Wert der Funktion 'getClientip'.

  • Wenn die Funktion eine gültige IP -Adresse nicht zurückgibt null.

  • Es sind nur (45) Codezeilen.

Die größte Frage ist für welchen Zweck?

Ihr Code ist fast so umfassend, wie er sein könnte - aber ich sehe, dass Sie dies anstelle des Client_ip verwenden. Wenn Sie diese Informationen für Prüfungszwecke wünschen, dann werden Sie gewarnt - es ist sehr einfach fälschen.

Natürlich sollten Sie niemals IP -Adressen für irgendeine Art von Authentifizierung verwenden - selbst diese können gefälscht werden.

Sie könnten eine bessere Messung der Client-IP-Adresse erhalten, indem Sie einen Flash- oder Java-Applet herausdrücken, der über einen Nicht-HTTP-Port mit dem Server eine Verbindung zum Server herstellt (der daher transparente Proxies oder Fälle aufzeigt, in denen die Proxy-Injected Header falsch sind-aber falsch- Denken Sie daran, dass der Client, bei dem nur über einen Web -Proxy oder der ausgehende Port blockiert ist, keine Verbindung von der Applet enthält.

C.

Nur a Vb.net Version der Antwort:

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

Mir ist klar, dass es oben viel bessere und prägnantere Antworten gibt, und dies ist weder eine Funktion noch das anmutigste Drehbuch. In unserem Fall mussten wir sowohl die füpfbare x_forwarded_for als auch die zuverlässigere Remote_ADDR in einem simplen Schalter pro Say ausgeben. Es mussten Rohlinge für die Einspritzung in andere Funktionen if-none oder if-Singular (anstatt nur die vorformatierte Funktion zurückgeben) zu ermöglichen. Es mussten ein "Ein- oder Aus-" -Var mit einem pro-Schalter-benutzerdefinierten Etikett für Plattformeinstellungen benötigt. Es war auch eine Möglichkeit, dass $ IP je nach Anfrage dynamisch ist, damit es formed_for angenommen wird.

Außerdem habe ich gesehen, wie jemand Isset () vs! Leer () ansprach - es ist möglich, nichts für x_forwarded_for einzugeben und dennoch ISSET () Wahrheit auszulösen, was zu leerem Var führt. Eine Möglichkeit, sich umzugehen, besteht darin, beide Bedingungen zu verwenden und zu kombinieren. Beachten Sie, dass Sie Wörter wie "pwned" als x_forwarded_for fälschen können. Stellen Sie also sicher, dass Sie eine echte IP -Syntax sterilisieren, wenn Sie irgendwo geschützt sind oder in DB.

Außerdem können Sie mit Google Translate testen, wenn Sie ein Multi-Prixy benötigen, um das Array in x_forwarder_for zu sehen. Wenn Sie Header zum Testen fälschen möchten, sehen Sie sich dies an Chrome Client Header Parodie Verlängerung. Dies wird standardmäßig für Standard Remote_Addr hinter Anon Proxy standardmäßig.

Ich weiß jeden Fall nicht, in dem Remote_Addr leer sein könnte, aber es ist als Fallback für alle Fälle da.

// 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 = '';
}

Um diese Dynamik für die Verwendung in Funktionen (n) oder Abfrage/Echo/Ansichten unten zu machen, sagen Sie beispielsweise für die Protokollgen- oder Fehlerberichterstattung, verwenden Funktionen.

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

Vielen Dank für all Ihre tollen Gedanken. Bitte lassen Sie mich wissen, ob dies besser sein könnte, immer noch ein bisschen neu für diese Header :)

Ich habe diese Funktion entwickelt, die die IP -Adresse nicht einfach zurückgibt, sondern ein Array mit IP -Informationen.

// 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;
}

Hier ist die Funktion:

/**
 * 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;
}

Wie bereits jemand sagte, liegt der Schlüssel hier aus dem Grund, warum Sie die IPs des Benutzers speichern möchten.

Ich werde ein Beispiel aus einem Registrierungssystem geben, an dem ich arbeite, und natürlich die Lösung, um STH in dieser alten Diskussion beizutragen, die häufig bei meinen Suchanfragen kommt.

Viele PHP -Registrierungsbibliotheken verwenden IP Fehlgeschlagene Versuche basierend auf der IP des Benutzers zu drosseln/zu sperren. Betrachten Sie diese Tabelle:

-- 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
...

Wenn dann ein Benutzer versucht, eine Anmeldung oder etwas mit der Wartung in Zusammenhang zu stellen, wie ein Kennwortreset, wird eine Funktion am Start aufgerufen:

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";
   }

Sagen Sie zum Beispiel, $this->token->get('attempts_before_ban') === 10 und 2 Benutzer kommen für dieselben IPs wie in den vorherigen Codes der Fall wie in den vorherigen Codes wo Kopfzeilen gefälscht werden können, dann nach jeweils 5 Versuchen Beide sind verboten! Sogar das Schlimmste, wenn alle aus demselben Stellvertreter stammen, werden nur die ersten 10 Benutzer protokolliert und der gesamte Rest wird verboten!

Das Kritische hier ist, dass wir einen eindeutigen Index in der Tabelle benötigen attempts Und wir können es von einer Kombination wie:

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

wo jwt_load kommt von einem HTTP -Cookie, der dem folgt JSON Web Token Technologie, in der wir nur die speichern verschlüsselt Nutzlast das sollte enthalten einen willkürlichen/eindeutigen Wert für jeden Benutzer. Natürlich sollte die Anfrage geändert werden an: "SELECT count(*) FROM {$this->token->get('table_attempts')} WHERE ip = ? AND jwt_load = ?" und die Klasse sollte auch a initiieren private $jwt.

Ich frage mich, ob Sie vielleicht in umgekehrter Reihenfolge den explodierten http_x_forwarded_for über den explodierten http_x_forwarded_for machen sollten Es ist wahrscheinlicher, dass die IP -Adresse eines der zurückgegebenen Stellvertreter erhalten wird, was möglicherweise weiterhin die Sitzung der Sitzung ermöglichen könnte, da viele Benutzer diesen Proxy durchlaufen können.

Danke dafür, sehr nützlich.

Es würde jedoch helfen, wenn der Code syntaktisch korrekt wäre. Wie es ist, gibt es eine {zu viele um Zeile 20. Was ich fürchte, bedeutet, dass niemand dies tatsächlich ausprobiert hat.

Ich mag verrückt sein, aber nachdem ich es an ein paar gültigen und ungültigen Adressen ausprobiert habe, war die einzige Version von Validate_ip (), die funktionierte:

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

Hier ist eine modifizierte Version, wenn Sie verwenden Wolkenflare Caching -Layer -Dienste

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

Nur ein weiterer sauberer Weg:

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

Aus Symfonys Anfrageklassehttps://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);
}

Sie haben Ihre eigene Frage so ziemlich beantwortet! :)

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

Quelle

/**
 * 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);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top