Quel est le moyen le plus précis d'obtenir l'adresse IP de l'utilisateur en 2017 via PHP?
J'ai lu beaucoup de SO questions et réponses à ce sujet, mais la plupart des réponses sont anciennes et les utilisateurs ont fait remarquer que ces méthodes sont dangereuses.
Par exemple, jetez un oeil à cette question (2011): Comment obtenir l'adresse IP du client en PHP?
La réponse de Tim Kennedy contient une recommandation d'utiliser quelque chose comme:
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
Mais comme j'ai beaucoup lu, j'ai vu qu'il était dangereux d'utiliser X_FORWARDED_FOR
, comme le souligne le commentaire ci-dessous:
N'utilisez PAS le code ci-dessus à moins de savoir EXACTEMENT ce qu'il fait! J'ai vu des trous de sécurité MASSIVE dus à cela. Le client peut définir le X-Forwarded-For ou l'en-tête Client-IP vers n'importe quelle valeur arbitraire it veut. Sauf si vous avez un proxy inverse de confiance, vous ne devriez en utiliser aucun de ces valeurs.
Comme je ne savais pas exactement ce que ça faisait, je ne veux pas prendre le risque. Il a dit que c'était dangereux, mais n'a pas fourni de méthode sûre pour obtenir l'adresse IP de l'utilisateur.
J'ai essayé le simple $_SERVER['REMOTE_ADDR'];
, mais cela retourne une mauvaise adresse IP. J'ai testé cela et mon adresse IP réelle suit ce modèle: 78.57.xxx.xxx
, mais j'obtiens une adresse IP telle que: 81.7.xxx.xxx
Alors avez-vous des idées?
Réponse courte:
$ip = $_SERVER['REMOTE_ADDR'];
À partir de 2019$_SERVER['REMOTE_ADDR'];
est le seule solution fiable pour obtenir l'adresse IP des utilisateurs, mais il peut afficher des résultats erronés s'il se trouve derrière un serveur proxy.
Toutes les autres solutions impliquent risques de sécurité ou peuvent être faciles à simuler.
D'un point de vue de sécurité, rien mais $_SERVER['REMOTE_ADDR']
est fiable - ce n'est que la vérité, malheureusement.
Toutes les variables précédées de HTTP_
sont en fait des en-têtes HTTP envoyés par le client, et il n’existe aucun autre moyen de transférer ces informations lorsque les demandes transitent par des serveurs différents.
Mais cela signifie naturellement que les clients peuvent usurper ces en-têtes.
Vous pouvez jamais, jamais faire confiance au client.
À moins que ce ne soit vous ... Si vous _ contrôlons le proxy ou l'équilibreur de charge, il est possible de le configurer pour qu'il supprime de tels en-têtes de la requête d'origine.
Ensuite, et seulement à ce moment-là, vous pourriez faire confiance à un ex. X-Client-IP
en-tête, mais en réalité, il n’est pas nécessaire de le faire à ce stade ... votre serveur Web peut également être configuré pour remplacer REMOTE_ADDR
par cette valeur et l’ensemble du processus devient transparent pour vous.
Ce sera toujours le cas, quelle que soit l’année dans laquelle nous nous trouvons… pour tout ce qui concerne la sécurité - ne faire confiance qu’à REMOTE_ADDR
.
Le meilleur scénario consiste à lire les données HTTP_
pour à des fins statistiques uniquement, et même dans ce cas, assurez-vous que l'entrée est au moins une adresse IP valide.
Vous devez collaborer avec votre équipe sysops (ou si vous portez ce chapeau aussi, vous devrez effectuer des recherches). La vérification d'en-tête est utilisée lorsque votre infrastructure réseau est configurée de certaines manières, lorsque le demandeur distant est l'un de vos appareils réseau au lieu de l'utilisateur final
Cela se produit lorsque votre ou vos serveurs Web se trouvent derrière un équilibreur de charge, un pare-feu ou un autre appareil qui doit interroger la charge utile pour la gérer correctement. Un exemple est lorsqu'un équilibreur de charge termine ssl et transmet la demande au serveur Web sans ssl. Lorsque cela se produit, l'adresse distante devient l'équilibreur de charge. Cela se produit également avec les appliances de pare-feu qui font la même chose.
Dans la plupart des cas, le périphérique propose une configuration permettant de définir une valeur d'en-tête dans la demande avec l'adresse IP distante d'origine. L'en-tête correspond généralement à ce à quoi vous vous attendiez, mais il peut parfois être différent ou même configurable.
De plus, selon la configuration de votre serveur Web (Apache, nginx ou autre), la prise en charge de certains en-têtes personnalisés, tels que l'en-tête ip commun, risque de ne pas être prise en charge.
Le point essentiel est que vous devrez étudier votre configuration réseau pour vous assurer que l'adresse IP du demandeur d'origine parvient jusqu'au code de votre application et sous quelle forme.
Si vous souhaitez utiliser une bibliothèque pré-construite, vous pouvez utiliser Whip .
Il est généralement préférable d’utiliser des bibliothèques préconfigurées, car la plupart d’entre elles auront été minutieusement vérifiées par une communauté active. Certains d'entre eux, en particulier ceux qui existent depuis longtemps, ont plus de fonctionnalités intégrées.
Mais si vous voulez coder vous-même pour apprendre le concept, alors tout va bien, je suppose. Je recommande de l'empaqueter en tant que bibliothèque autonome et de le publier en open-source :)
EDIT: je ne recommande pas d'utiliser l'IP distant dans les mécanismes de sécurité car ils ne sont pas toujours fiables.
Comme la vraie méthode consiste à vérifier que l’IP de l’utilisateur est $ip = $_SERVER['REMOTE_ADDR'];
Si l'utilisateur utilise VPN ou un proxy, il ne détectera pas l'adresse IP d'origine.
Obtenir l'adresse IP du client:
<?php
echo $ip = $_SERVER['REMOTE_ADDR'];
?>
Remarque:: Cela ne fonctionnerait que sur le site actif, car sur votre hôte local, votre adresse IP correspondrait à une (1) des adresses IP internes, comme 127.0.0.1 Donc, son retour :: 1
Exemple:https://www.virendrachandak.com/demos/getting-real-client-ip-address-in-php.php
Its Show Your Ip Local: J'aime ... 78.57.xxx.xxx
Exemple:
<?php
$myIp= getHostByName(php_uname('n'));
echo $myIp;
?>
Celui-ci, ça va -
public function getClientIP()
{
$remoteKeys = [
'HTTP_X_FORWARDED_FOR',
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR',
'HTTP_X_CLUSTER_CLIENT_IP',
];
foreach ($remoteKeys as $key) {
if ($address = getenv($key)) {
foreach (explode(',', $address) as $ip) {
if ($this->isValidIp($ip)) {
return $ip;
}
}
}
}
return '127.0.0.0';
}
private function isValidIp($ip)
{
if (!filter_var($ip, FILTER_VALIDATE_IP,
FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)
&& !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_PRIV_RANGE)
) {
return false;
}
return true;
}
J'utilise ce code, et cela fonctionne pour moi. Jetez un oeil à elle.
<?php
// Gets client's IP.
$ip = getenv("HTTP_CLIENT_IP")?:
getenv("HTTP_X_FORWARDED_FOR")?:
getenv("HTTP_X_FORWARDED")?:
getenv("HTTP_FORWARDED_FOR")?:
getenv("HTTP_FORWARDED")?:
getenv("REMOTE_ADDR");
echo $ip;
?>
Ici , un exemple de travail. J'espère que ça aide!