Quelle est la façon la plus précise de récupérer L'adresse IP correcte d'un utilisateur en PHP?

je sais qu'il y a une pléthore de $_SERVER variables en-têtes disponibles pour la récupération d'adresse IP. Je me demandais s'il y avait un consensus général sur la façon de récupérer le plus exactement L'adresse IP réelle d'un utilisateur (sachant bien qu'aucune méthode n'est parfaite) en utilisant ces variables?

j'ai passé un certain temps à essayer de trouver une solution en profondeur et j'ai trouvé le code suivant basé sur un certain nombre de sources. J'adorerais que quelqu'un poke des trous dans la réponse ou faire la lumière sur quelque chose peut-être plus précis.

edit includes optimisations from @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;
 }

Paroles d'Avertissement (mise à jour)

REMOTE_ADDR représente toujours la source la plus fiable d'une adresse IP. Les autres variables $_SERVER mentionnées ici peuvent très facilement être falsifiées par un client distant. Le le but de cette solution est de tenter de déterminer l'adresse IP d'un client assis derrière un proxy. Pour vos besoins généraux, vous pourriez envisager d'utiliser ceci en combinaison avec l'adresse IP retournée directement de $_SERVER['REMOTE_ADDR'] et de stocker les deux.

pour 99,9% des utilisateurs, Cette solution conviendra parfaitement à vos besoins. il ne vous protégera pas du 0,1% d'utilisateurs malveillants qui cherchent à abuser de votre système en injectant leurs propres en-têtes de demande. Si en comptant sur les adresses IP pour quelque chose d'essentiel pour la mission, recourez à REMOTE_ADDR et ne prenez pas la peine de s'occuper de ceux qui sont derrière un mandataire.

260
demandé sur Peter Mortensen 2009-10-28 05:03:26

16 réponses

voici un moyen plus court et plus propre d'obtenir l'adresse IP:

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

j'espère que ça aidera!


votre code semble déjà assez complet, Je ne vois pas de bugs possibles (à part les mises en garde habituelles sur L'IP), Je changerais la fonction validate_ip() pour m'appuyer sur l'extension du filtre cependant:

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

aussi votre HTTP_X_FORWARDED_FOR snippet peut être simplifié de ceci:

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

à ceci:

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

vous pouvez également vouloir valider les adresses IPv6.

213
répondu Alix Axel 2013-01-06 00:47:42

même alors cependant, obtenir la véritable adresse IP d'un utilisateur va être peu fiable. Tout ce qu'ils doivent faire est d'utiliser un serveur mandataire anonyme (un qui n'honore pas les en-têtes pour http_x_forwarded_for, http_forwarded, etc) et tout ce que vous obtenez est l'adresse IP de leur serveur mandataire.

vous pouvez alors voir s'il y a une liste d'adresses IP de serveur proxy qui sont anonymes, mais il n'y a aucun moyen d'être sûr que ce est à 100% précis aussi bien et le plus qu'il ferait est de vous faire savoir qu'il est un serveur proxy. Et si quelqu'un fait preuve d'intelligence, il peut mystifier les en-têtes pour les forwards HTTP.

disons que je n'aime pas l'université locale. Je trouve quelles adresses IP ils ont enregistré, et obtenir leur adresse IP banni sur votre site en faisant de mauvaises choses, parce que je me rends compte que vous honorez les transferts HTTP. La liste est sans fin.

il y a, comme vous l'avez deviné, des adresses IP internes comme le Réseau universitaire que j'ai mentionné auparavant. Beaucoup utilisent un 10.x.x.x format. Donc tout ce que vous savez, c'est qu'il a été transmis par un réseau partagé.

alors je ne vais pas beaucoup commencer dans elle, mais les adresses IP dynamiques sont le moyen de large bande plus. Si. Même si vous obtenez une adresse IP de l'utilisateur, attendez - vous à ce qu'elle change dans 2 à 3 mois, au plus tard.

9
répondu Peter Mortensen 2014-04-16 07:58:09

Nous utilisons:

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

l'explosion de HTTP_X_FORWARDED_FOR est due à des problèmes étranges que nous avons eu en détectant des adresses IP lorsque Squid a été utilisé.

5
répondu gabrielk 2014-04-16 07:59:15

la plus grande question Est Dans quel but?

votre code est presque aussi complet qu'il pourrait l'être - mais je vois que si vous repérez ce qui ressemble à un en - tête ajouté par proxy, vous utilisez cela au lieu du CLIENT_IP, cependant si vous voulez cette information à des fins de vérification alors être averti-son très facile à truquer.

il est certain que vous ne devez jamais utiliser d'adresses IP pour aucune sorte d'authentification - même celles-ci peuvent être falsifiées.

You pourrait obtenir une meilleure mesure de l'adresse ip du client en poussant un flash ou Java applet qui se connecte de nouveau au serveur via un port non-http (qui révélerait donc des procurations transparentes ou des cas où les en-têtes injectés par proxy sont faux - mais gardez à l'esprit que, où le client ne peut se connecter via un proxy web ou le port sortant est bloqué, il n'y aura pas de connexion à partir de l'applet.

C.

2
répondu symcbean 2010-01-09 14:13:52

juste un VB.NET version de la réponse:

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
1
répondu Abacus 2014-04-16 08:03:12

je me rends compte qu'il y a des réponses beaucoup mieux et plus concises ci-dessus, et ce n'est pas une fonction ni le script le plus gracieux autour. Dans notre cas, nous avions besoin de produire à la fois le x_forwarded_for spoofable et le remote_addr plus fiable dans un simple commutateur per-say. Il fallait autoriser les blancs pour l'injection dans d'autres fonctions si-aucun ou si-singulier (plutôt que de simplement retourner la fonction préformatée). Il avait besoin d'un var "on or off" avec une étiquette(S) personnalisée (s) pour la plateforme paramètre. Il fallait aussi un moyen pour $ip d'être dynamique en fonction de la requête afin qu'il prenne la forme de forwarded_for.

aussi je n'ai vu personne s'adresser à isset () vs !empty() -- il est possible de ne rien entrer pour x_forwarded_for et pourtant de déclencher isset() truth résultant en blanc var, une façon de se déplacer est d'utiliser && et de combiner les deux comme conditions. Gardez à l'esprit que vous pouvez usurper des mots comme "PWNED" comme x_forwarded_for, alors assurez-vous que vous stérilisez à une vraie syntaxe ip si votre sortie quelque part protégée ou en DB.

aussi, vous pouvez tester en utilisant google translate si vous avez besoin d'un multi-proxy pour voir le tableau dans x_forwarder_for. Si vous voulez tester des en-têtes de mystification, consultez l'extension Chrome Client en-tête de mystification . Ce sera par défaut seulement remote_addr standard alors que derrière un proxy on.

Je ne sais pas où remote_addr pourrait être vide, mais il est là comme repli juste au cas.

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

pour rendre ces dynamiques pour une utilisation dans la fonction(s) ou requête/écho/vues ci-dessous, par exemple pour le log gen ou le rapport d'erreur, utilisez globals ou tout simplement echo em là où vous le souhaitez sans faire une tonne d'autres conditions ou static-schema-fonctions de sortie.

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

Merci pour toutes vos pensées. S'il vous plaît laissez-moi savoir si cela pourrait être mieux, encore un peu nouveau pour ces en-têtes :)

1
répondu dhaupin 2014-08-06 20:55:30

j'ai inventé cette fonction qui ne renvoie pas simplement l'adresse IP mais un tableau avec des informations IP.

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

Voici la fonction:

/**
 * 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
répondu Philipp 2015-02-04 17:57:21

ma réponse est fondamentalement juste une version polie, entièrement validée et entièrement emballée de la réponse de @AlixAxel:

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

?>

Changements:

  • il simplifie le nom de la fonction (avec le style de formatage 'camelCase').

  • il inclut un contrôle pour s'assurer que la fonction n'est pas déjà déclarée dans une autre partie de votre code.

  • il tient compte de la compatibilité "CloudFlare".

  • il initialise de multiples noms de variables "IP-related" à la valeur retournée, de la fonction "getClientIP".

  • il assure que si la fonction ne retourne pas une adresse IP valide, toutes les variables sont définies à une chaîne vide, au lieu de null .

  • c'est seulement (45) lignes de code.

1
répondu James Anderson Jr. 2017-12-07 14:31:27

je me demande si peut-être vous devriez itérer au-dessus de l'explosion HTTP_X_FORWARDED_FOR dans l'ordre inverse, puisque mon expérience a été que l'adresse IP de l'utilisateur finit à la fin de la liste séparée par des virgules, donc à partir du début de l'en-tête, vous êtes plus susceptible d'obtenir l'adresse ip de l'un des mandataires retournés, ce qui pourrait éventuellement permettre le détournement de session que de nombreux utilisateurs peuvent venir à travers ce mandataire.

0
répondu Chris Withers 2010-01-15 08:05:14

Merci pour cela, très utile.

cela aiderait cependant si le code était syntaxiquement correct. Il y en a trop autour de la ligne 20. Qui, je le crains signifie que personne ne fait essayé.

je suis peut-être fou, mais après l'avoir essayé sur quelques adresses valides et Invalides, la seule version de validate_ip() qui a fonctionné était celle-ci:

    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
répondu Mark Boon 2012-05-24 22:28:33

Voici une version modifiée si vous utilisez CloudFlare caching layer Services

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
répondu jmserra 2014-04-16 08:02:34

Juste un autre moyen propre:

  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
répondu Liko 2014-06-16 20:45:54

de la classe de demande de Symfony 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);
}
0
répondu luchaninov 2016-02-16 16:33:55

comme quelqu'un l'a dit précédemment, la clé ici est pour quelle raison vous voulez stocker les ips de l'utilisateur.

je vais donner un exemple d'un système d'enregistrement sur lequel je travaille et bien sûr la solution juste pour contribuer sth dans cette vieille discussion qui vient fréquemment dans Mes recherches.

de nombreuses bibliothèques d'enregistrement php utilisent ip pour activer/bloquer les tentatives échouées basées sur l'ip de l'utilisateur. Considérez ce tableau:

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

ensuite, quand un utilisateur essaie de faire une connexion ou quelque chose liée à l'entretien comme un mot de passe réinitialiser, une fonction est appelée au début:

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

dire, par exemple, $this->token->get('attempts_before_ban') === 10 et 2 utilisateurs viennent pour les mêmes ips que dans les codes précédents où les en-têtes peuvent être mystifiés , puis après 5 tentatives chaque les deux sont interdits ! Même le pire, si tous viennent du même proxy alors seuls les 10 premiers utilisateurs seront être connecté et tout le reste sera banni!

la critique ici est que nous avons besoin d'un index unique sur la table attempts et nous pouvons l'obtenir d'une combinaison comme:

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

jwt_load provient d'un cookie http qui suit le JSON Web token technologie où nous stockons seulement le crypté charge utile que devrait contenir une valeur arbitraire / unique pour chaque utilisateur. Bien sûr, la requête doit être modifiée en: "SELECT count(*) FROM {$this->token->get('table_attempts')} WHERE ip = ? AND jwt_load = ?" et la classe doit également lancer un private $jwt .

0
répondu centurian 2017-05-27 11:22:13

vous avez à peu près répondu à votre propre question! :)

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

Source

-1
répondu Alex Weber 2014-04-16 07:54:51
/**
 * 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);
}
-6
répondu Meketrefe 2010-01-13 16:31:14