Comment utiliser correctement HTTP X FORWARDED?

D'accord, j'ai un petit problème d'authentification. Mon service web permet de se connecter à mon API via HTTP avec un nom d'utilisateur et un mot de passe, mais cette connexion peut également être limitée à une adresse IP spécifique.

Cela signifie que le $_SERVER['REMOTE_ADDR'] peut être incorrecte. Je sais déjà qu'on ne peut jamais vraiment se fier à une Information IP - Je n'ai la restriction que pour essayer d'ajouter une autre couche de sécurité.

S'il s'agit du aperçu d'une requête pour mon serveur web:

clientSERVER => clientPROXY => myPROXY => mySERVER

alors cela signifie que mySERVER affiche REMOTE_ADDR de myPROXY au lieu de celui du client et envoie l'adresse IP réelle du client comme HTTP_X_FORWARDED_FOR .

pour surmonter cela, mon service web a une liste d'adresses IP de "mandataire de confiance" et si REMOTE_ADDR est à partir d'une de ces adresses IP de confiance, alors il dit à mon service web que l'adresse IP réelle est la valeur de HTTP_X_FORWARDED_FOR .

maintenant le problème est avec clientPROXY. Cela signifie que (très souvent) mySERVER obtient la valeur HTTP_X_FORWARDED_FOR qui a plusieurs adresses IP. Selon la documentation HTTP_X_FORWARDED_FOR , la valeur est une liste d'adresses IP séparées par des virgules où la première adresse IP est celle du client réel et chaque autre adresse IP est celle d'un mandataire.

donc, si HTTP_X_FORWARDED_FOR a plusieurs valeurs et que mon service est limité IP, dois-je vérifier la' dernière ' valeur de HTTP_X_FORWARDED_FOR par rapport à ma liste D'adresses IP autorisée et ignorer simplement L'adresse IP du client?

je suppose que, dans un système, où je dois mettre la liste d'adresses IP autorisées, l'adresse IP doit être celle d'un proxy et pas une IP qui est derrière le proxy (depuis que pourrait être une IP localhost et changent souvent).

et HTTP_CLIENT_IP ?

23
demandé sur Thibault 2012-07-12 17:31:34

6 réponses

vous pouvez utiliser cette fonction pour obtenir la bonne adresse IP client:

public function getClientIP(){       
     if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)){
            return  $_SERVER["HTTP_X_FORWARDED_FOR"];  
     }else if (array_key_exists('REMOTE_ADDR', $_SERVER)) { 
            return $_SERVER["REMOTE_ADDR"]; 
     }else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
            return $_SERVER["HTTP_CLIENT_IP"]; 
     } 

     return '';
}
19
répondu Hrishikesh Mishra 2017-07-23 18:29:46

j'aime la réponse de Hrishikesh, à laquelle je n'ai que ceci à ajouter...parce que nous avons vu une chaîne délimitée par une virgule apparaître lorsque plusieurs mandataires le long du chemin ont été utilisés, nous avons trouvé nécessaire d'ajouter un explode et de saisir la valeur finale, comme ceci:

$IParray=array_values(array_filter(explode(',',$_SERVER['HTTP_X_FORWARDED_FOR'])));
return end($IParray);

le tableau_filter est là pour supprimer les entrées vides.

14
répondu user336828 2014-06-17 23:45:42

à la lumière de la dernière vulnérabilité httpoxy , il y a vraiment un besoin pour un exemple complet, Comment utiliser HTTP_X_FORWARDED_FOR correctement.

donc voici un exemple écrit en PHP, comment détecter une adresse IP client, si vous savez que le client peut être derrière un proxy et que vous savez que ce proxy peut être fiable. Si vous ne connaissez pas de mandataires de confiance, il vous suffit d'utiliser REMOTE_ADDR

<?php

function get_client_ip ()
{
    // Nothing to do without any reliable information
    if (!isset ($_SERVER['REMOTE_ADDR'])) {
        return NULL;
    }

    // Header that is used by the trusted proxy to refer to
    // the original IP
    $proxy_header = "HTTP_X_FORWARDED_FOR";

    // List of all the proxies that are known to handle 'proxy_header'
    // in known, safe manner
    $trusted_proxies = array ("2001:db8::1", "192.168.50.1");

    if (in_array ($_SERVER['REMOTE_ADDR'], $trusted_proxies)) {

        // Get the IP address of the client behind trusted proxy
        if (array_key_exists ($proxy_header, $_SERVER)) {

            // Header can contain multiple IP-s of proxies that are passed through.
            // Only the IP added by the last proxy (last IP in the list) can be trusted.
            $proxy_list = explode (",", $_SERVER[$proxy_header]);
            $client_ip = trim (end ($proxy_list));

            // Validate just in case
            if (filter_var ($client_ip, FILTER_VALIDATE_IP)) {
                return $client_ip;
            } else {
                // Validation failed - beat the guy who configured the proxy or
                // the guy who created the trusted proxy list?
                // TODO: some error handling to notify about the need of punishment
            }
        }
    }

    // In all other cases, REMOTE_ADDR is the ONLY IP we can trust.
    return $_SERVER['REMOTE_ADDR'];
}

print get_client_ip ();

?>
8
répondu Erki A 2017-12-18 14:28:20

vous pouvez également résoudre ce problème via la configuration D'Apache en utilisant mod_remoteip , en ajoutant ce qui suit à un conf.d fichier:

RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 172.16.0.0/12
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
1
répondu zeroimpl 2016-12-29 18:03:41

si vous l'utilisez dans une base de données, c'est un bon moyen:

définissez le champ ip dans la base de données à varchar (250), puis utilisez ceci:

$theip = $_SERVER["REMOTE_ADDR"];

if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
    $theip .= '('.$_SERVER["HTTP_X_FORWARDED_FOR"].')';
}

if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
    $theip .= '('.$_SERVER["HTTP_CLIENT_IP"].')';
}

$realip = substr($theip, 0, 250);

ensuite, il vous suffit de vérifier $realip par rapport au champ ip de la base de données

0
répondu mowgli 2014-08-14 20:13:26

HTTP_CLIENT_IP est le moyen le plus fiable d'obtenir l'adresse IP de l'utilisateur. Ensuite, HTTP_X_FORWARDED_FOR, suivi de REMOTE_ADDR. Cochez tous les trois, dans cet ordre, en supposant que le premier qui est défini ( isset($_SERVER['HTTP_CLIENT_IP']) retourne true si cette variable est définie) est correct. Vous pouvez vérifier indépendamment si l'utilisateur utilise un proxy en utilisant diverses méthodes. Cochez ce .

-4
répondu TheEnvironmentalist 2017-05-23 10:31:34