Adresse IP client en PHP : comment éviter les erreurs en 2025

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

La chasse à l'IP : pourquoi $_SERVER['REMOTE_ADDR'] ne suffit plus en 2025 ?

\n\n

Imaginez : vous lancez un super projet éducatif en PHP. Tout fonctionne, les utilisateurs sont ravis. Mais vous décidez d'ajouter le suivi des visiteurs, la géolocalisation ou, par exemple, une protection contre le bourrage de votes. Et là, surprise ! Vous découvrez que la moitié de vos visiteurs "uniques" partagent la même adresse IP : 127.0.0.1 ou 10.0.0.1. Ça vous dit quelque chose ?

\n\n

Le problème de l'adresse IP réelle du client en PHP est un classique qui reste toujours d'actualité. La question sur Stack Overflow cumule des milliers de vues, et les débutants (et même les plus expérimentés) continuent de tomber dans les mêmes pièges. En 2025, avec Cloudflare, AWS, Nginx et une multitude de CDN comme standard de facto, se fier uniquement à $_SERVER['REMOTE_ADDR'] revient à lire dans le marc de café.

\n\n

Dans cet article, nous ne nous contenterons pas de vous donner une fonction toute faite. Nous allons décortiquer l'anatomie des en-têtes HTTP, apprendre à distinguer le vrai du faux et créer une méthode sécurisée et fiable pour obtenir l'adresse IP d'un visiteur en PHP, qui ne vous fera pas défaut en 2025. C'est parti !

\n\n

REMOTE_ADDR : votre fidèle compagnon, mais aveugle

\n\n

Commençons par les bases. $_SERVER['REMOTE_ADDR'] est l'adresse IP de la machine connectée directement à votre serveur web. Si votre site est hébergé sur un serveur dédié sans proxy, c'est bien l'IP du client. Simple et fiable.

\n\n

Mais dans le monde moderne, c'est rarement le cas. Le plus souvent, une chaîne entière se dresse entre l'utilisateur et votre script PHP :

\n
    \n
  • CDN (Cloudflare, Fastly)
  • \n
  • Équilibreur de charge (Nginx, HAProxy)
  • \n
  • Proxy inverse (Varnish, Nginx)
  • \n
  • Hébergement mutualisé
  • \n
\n\n

Et là, REMOTE_ADDR affiche l'IP du dernier maillon (par exemple, votre équilibreur de charge), et non celle de l'utilisateur réel. Pour un site éducatif, c'est une catastrophe : vous ne pourrez pas distinguer un étudiant de Paris d'un étudiant de New York, et votre système anti-spam bloquera tout le monde sans distinction.

\n\n

En-têtes HTTP : où se cache la véritable IP ?

\n\n

Pour transmettre l'IP réelle du client, les serveurs proxy ajoutent des en-têtes HTTP spécifiques. Les plus courants en 2025 sont :

\n\n

1. X-Forwarded-For (XFF)

\n

L'en-tête classique. Il peut contenir une chaîne d'IP : client_ip, proxy1_ip, proxy2_ip. La première IP de la liste est celle du véritable client. Mais attention : cet en-tête peut être falsifié par n'importe quel attaquant si votre infrastructure ne le nettoie pas.

\n\n

2. X-Real-IP

\n

L'en-tête favori de Nginx. Il contient une seule IP, la vraie. Plus simple et plus sûr, mais il n'est pas supporté par tous les proxies.

\n\n

3. CF-Connecting-IP (Cloudflare)

\n

Un en-tête spécifique à Cloudflare. Si vous utilisez leur CDN, c'est l'option la plus fiable. Mais seulement si vous faites confiance à Cloudflare (et vous devriez, ils sont fiables).

\n\n
\n Important : Ne faites jamais confiance aux en-têtes X-Forwarded-For et X-Real-IP provenant de sources inconnues. Un attaquant peut y injecter n'importe quelle IP, et votre système la considérera comme réelle.\n
\n\n

La meilleure pratique en 2025 : une défense en profondeur

\n\n

Alors, que faire ? Nous ne pouvons pas simplement prendre la première IP de X-Forwarded-For — c'est dangereux. Mais nous ne pouvons pas non plus ignorer les proxies. La solution est une liste blanche de proxies de confiance.

\n\n

L'idée est simple : nous connaissons les adresses IP de nos équilibreurs de charge et de notre CDN. Si la requête vient d'eux, nous faisons confiance aux en-têtes. Sinon, nous utilisons REMOTE_ADDR.

\n\n

Voici une classe PHP fonctionnelle qui implémente cette logique :

\n\n
<?php\n\nclass ClientIP\n{\n    /**\n     * Liste des adresses IP et sous-réseaux (CIDR) de confiance.\n     * Ajoutez ici les IP de vos proxies, CDN, équilibreurs de charge.\n     */\n    private static array $trustedProxies = [\n        '127.0.0.1',          // localhost\n        '10.0.0.0/8',         // réseaux privés\n        '172.16.0.0/12',                

Blogs

Book Recommendations