HOWTO · PHP
Obtenir l'adresse IP de l'utilisateur en PHP
Ce tutoriel montre comment obtenir l'adresse IP de l'utilisateur en PHP
Sur cette page
Pour lire l’adresse réseau associée à une requête PHP, commencez par $_SERVER['REMOTE_ADDR']. Elle désigne le pair qui s’est connecté au serveur web. Si un proxy inverse se trouve devant l’application, ce pair peut être le proxy plutôt que le visiteur. Les en-têtes de requête liés aux proxys ne sont utilisables que si votre application dispose d’une configuration de confiance explicite pour le proxy qui les fournit et les valide.
Lire l’adresse du pair avec $_SERVER['REMOTE_ADDR']
$_SERVER est une superglobale PHP qui contient des informations sur le serveur et la requête. Son élément REMOTE_ADDR contient l’adresse du pair connecté au serveur qui traite la requête. En connexion directe, il s’agit généralement du client qui se connecte. Derrière un répartiteur de charge ou un proxy inverse, il s’agit souvent de l’adresse du proxy. La configuration du serveur web et du proxy détermine ce que PHP reçoit : cette valeur ne doit donc pas être présentée comme l’adresse garantie de l’utilisateur final.
Pour une requête locale, le pair peut être l’adresse de bouclage IPv6 ::1. Les adresses de bouclage désignent la machine locale ; ::1 est l’adresse de bouclage IPv6, équivalente à 127.0.0.1 en IPv4. La valeur exacte dépend du serveur local et de la connexion. Consultez cette explication de l’adresse de bouclage.
L’exemple exécutable ci-dessous définit une valeur de serveur représentative afin que la consultation soit autonome. Il conserve display_output à false : l’exemple effectue donc la consultation sans afficher de résultat. Dans une application, utilisez la valeur selon les besoins de votre réponse ou de vos journaux.
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
<?php
$_SERVER['REMOTE_ADDR'] = '::1';
$peerAddress = $_SERVER['REMOTE_ADDR'];
$display_output = false;
if ($display_output) {
echo "The connected peer is: " . $peerAddress . PHP_EOL;
}
?>
Pour une requête réelle, utilisez la valeur $_SERVER['REMOTE_ADDR'] fournie par le serveur plutôt que d’attribuer une valeur d’exemple. La référence du Manuel PHP sur les variables du serveur décrit les éléments disponibles dans $_SERVER.
Interpréter les en-têtes de proxy uniquement si le proxy est fiable
PHP peut exposer des en-têtes de requête sous forme d’éléments $_SERVER, par exemple HTTP_X_FORWARDED_FOR et HTTP_CLIENT_IP. Leur présence ne prouve pas qu’ils contiennent l’adresse du visiteur : un client peut envoyer ses propres valeurs d’en-tête, et un proxy peut les conserver, les compléter ou les remplacer. En particulier, HTTP_X_FORWARDED_FOR peut contenir une chaîne d’adresses séparées par des virgules, et non une seule adresse. Ne sélectionnez pas la première valeur en la présentant comme l’adresse réelle du client sans appliquer les règles de confiance documentées pour votre infrastructure.
N’utilisez une valeur transmise que si le pair connecté correspond à un proxy auquel votre application accorde explicitement sa confiance et si ce proxy est configuré pour supprimer ou valider les en-têtes de transfert fournis par les clients. La liste des proxys de confiance doit correspondre à votre déploiement ; ne reprenez pas des adresses d’exemple pour la production. Si le pair n’est pas fiable, utilisez REMOTE_ADDR. HTTP_CLIENT_IP présente le même problème de confiance et ne doit pas être utilisé comme réponse particulière pour les connexions Internet partagées.
Cet extrait exécutable représente un déploiement où le proxy de confiance remplace X-Forwarded-For par une seule adresse validée. Remplacez l’adresse de proxy d’exemple et la politique de validation par les valeurs définies pour votre infrastructure. Pour ces valeurs représentatives, il affiche l’adresse transmise sélectionnée ; il ne traite pas une chaîne comportant plusieurs proxys.
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
if (in_array($peerAddress, $trustedProxies, true)
&& isset($_SERVER['HTTP_X_FORWARDED_FOR'])
&& filter_var($_SERVER['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP) !== false) {
$clientAddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$clientAddress = $peerAddress;
}
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
La documentation de filter_var() explique la fonction de validation utilisée ici. Vérifier qu’une chaîne est une adresse IP ne permet pas d’établir qu’elle provient d’une source fiable ; cette décision repose sur la vérification du pair et la configuration du proxy. Si votre proxy transmet une chaîne d’adresses, utilisez un framework ou du code soigneusement vérifié qui parcourt cette chaîne conformément aux règles exactes de confiance applicables à votre déploiement.
Utiliser une expression conditionnelle pour un repli compact
Un bloc if/elseif/else lisible est généralement plus facile à vérifier, surtout s’il comprend un contrôle de confiance du proxy. Une expression conditionnelle peut exprimer le même choix de façon plus concise, mais elle ne rend pas sûr un en-tête non fiable. L’exemple exécutable ci-dessous vérifie la confiance accordée au proxy et applique la même politique décrite plus haut : une seule adresse, remplacée par le proxy. Les valeurs du serveur sont représentatives ; l’exemple affiche l’adresse transmise sélectionnée.
Le code et les libellés ou sorties affichés dans cette section restent en anglais.
<?php
$_SERVER['REMOTE_ADDR'] = '192.0.2.10';
$_SERVER['HTTP_X_FORWARDED_FOR'] = '198.51.100.24';
$trustedProxies = ['192.0.2.10'];
$peerAddress = $_SERVER['REMOTE_ADDR'];
$forwardedAddress = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? '';
$clientAddress = in_array($peerAddress, $trustedProxies, true)
&& filter_var($forwardedAddress, FILTER_VALIDATE_IP) !== false
? $forwardedAddress
: $peerAddress;
echo "Selected address: " . $clientAddress . PHP_EOL;
?>
Selected address: 198.51.100.24
L’ordre de repli est délibéré : acceptez l’adresse transmise et validée uniquement si le pair connecté figure dans la liste des proxys de confiance ; sinon, conservez l’adresse du pair connecté. Des parenthèses peuvent clarifier des expressions conditionnelles imbriquées, mais une succession de ternaires est plus difficile à maintenir et ne remplace pas les contrôles de confiance. Faites correspondre le comportement des en-têtes du proxy à la liste d’autorisation de l’application afin qu’un client ne puisse pas faire passer son propre en-tête pour une donnée fiable.