83 votes

nginx real_ip_header et X-Forwarded-For semble erroné

La description wikipedia de l'en-tête HTTP X-Forwarded-For est :

X-Forwarded-For : client1, proxy1, proxy2, ...

La documentation de nginx pour la directive real_ip_header se lit, en partie :

Cette directive définit le nom de l'en-tête utilisé pour le transfert de l'adresse IP de remplacement.
Dans le cas d'un X-Forwarded-For, ce module utilise la fonction dernier ip dans l'en-tête X-Forwarded-For pour le remplacement. (C'est moi qui souligne)

Ces deux descriptions semblent en contradiction l'une avec l'autre. Dans notre scénario, le X-Forwarded-For est exactement comme décrit -- l'adresse IP "réelle" du client est l'entrée la plus à gauche. De même, le comportement de nginx est d'utiliser l'en-tête droite -qui, évidemment, est juste un de nos serveurs proxy.

Ma compréhension de X-Real-IP est que c'est supposée à utiliser pour déterminer le réel adresse IP du client -- no le mandataire. Est-ce que j'ai raté quelque chose, ou est-ce un bogue dans nginx ?

Et, au-delà de ça, est-ce que quelqu'un a des suggestions sur la façon de rendre la X-Real-IP l'en-tête affiche le gauche -la valeur la plus élevée, comme l'indique la définition de l'expression X-Forwarded-For ?

127voto

Nick M Points 1286

Je pense que la clé pour résoudre les problèmes de X-Forwarded-For lorsque plusieurs IP sont enchaînés est l'option de configuration récemment introduite, real_ip_recursive (ajouté dans nginx 1.2.1 et 1.3.0). De la docs nginx realip :

Si la recherche récursive est activée, une adresse client originale qui correspond à l'une des adresses de confiance est remplacée par la dernière adresse non fiable envoyée dans le champ d'en-tête de la demande.

Par défaut, nginx saisissait la dernière adresse IP de la chaîne, car c'était la seule qui était supposée être fiable. Mais avec la nouvelle real_ip_recursive et avec de multiples set_real_ip_from vous pouvez définir plusieurs proxys de confiance et il récupérera la dernière IP non fiable.

Par exemple, avec cette configuration :

set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

Et un en-tête X-Forwarded-For résultant en :

X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1

nginx va maintenant choisir 123.123.123.123 comme adresse IP du client.

Quant à la raison pour laquelle nginx ne choisit pas simplement l'adresse IP la plus à gauche et exige que vous définissiez explicitement des proxys de confiance, c'est pour empêcher l'usurpation d'adresse IP.

Disons que l'adresse IP réelle d'un client est 123.123.123.123 . Supposons également que le client est mal intentionné, et qu'il essaie d'usurper son adresse IP pour être 11.11.11.11 . Ils envoient une demande au serveur avec cet en-tête déjà en place :

X-Forwarded-For: 11.11.11.11

Étant donné que les mandataires inversés ajoutent simplement des IP à cette chaîne X-Forwarded-For, disons que cela ressemble à ceci lorsque nginx y accède :

X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1

Si vous vous contentiez de saisir l'adresse la plus à gauche, le client pourrait facilement usurper son adresse IP. Mais avec l'exemple de configuration de nginx ci-dessus, nginx ne fera confiance qu'aux deux dernières adresses comme proxies. Cela signifie que nginx choisira correctement 123.123.123.123 comme adresse IP, bien que cette IP usurpée soit en fait la plus à gauche.

1 votes

Par défaut, l'en-tête real_ip_header semble être X-Real-IP, conformément à la directive sur la protection des données. nginx.org/fr/docs/http/ngx_http_realip_module.html Cela signifie-t-il qu'un utilisateur malveillant peut simplement envoyer une requête avec un X-Real-IP aléatoire qui sera utilisé comme $remote_addr dans nginx (et éventuellement transmis à l'application) ?

1 votes

@gansbrest Non, car set_real_ip_from limite les hôtes de confiance.

0 votes

Vous devez également inclure le $remote_addr (IP du proxy avant nginx qui dans des circonstances normales n'est pas inclus dans X-Forwarded-For ) dans l'en-tête set_real_ip_from ainsi que les autres proxies dans X-Forwarded-For en-tête.

11voto

Shane Madden Points 112034

L'analyse syntaxique des X-Forwarded-For est en effet défectueux dans le module real_ip de nginx.

len = r->headers_in.x_forwarded_for->value.len;
ip = r->headers_in.x_forwarded_for->value.data;

for (p = ip + len - 1; p > ip; p--) {
  if (*p == ' ' || *p == ',') {
    p++;
    len -= p - ip;
    ip = p;
    break;
  }
}

Il commence à l'extrême droite de la chaîne d'en-tête, et dès qu'il voit un espace ou une virgule, il arrête de chercher et colle la partie à droite de l'espace ou de la virgule dans la variable IP. Donc, il traite la le plus récent comme l'adresse du proxy client initial adresse.

Ce n'est pas agréable selon la spécification ; c'est le danger de ne pas l'avoir explicité en termes douloureusement évidents dans une RFC.

A part : Il est difficile de trouver une bonne source primaire sur le format, qui a été défini à l'origine par Squid. documentation confirme le classement ; le plus à gauche est le client original, le plus à droite est l'appendice le plus récent. Je suis fortement tentée d'ajouter un fichier [citation nécessaire] à cette page wikipédia. Un édition anonyme semble être l'autorité d'internet sur le sujet.

Si possible, pouvez-vous faire en sorte que vos proxies intermédiaires cessent de s'ajouter à la fin de l'en-tête, ne laissant que l'adresse réelle du client ?

0 votes

Merci pour la réponse, @Shane. En fait, en atteignant nginx, un X-Forwarded-For existe déjà. (il s'agit de l'adresse IP correcte du client) nginx Il ajoute ensuite l'adresse IP de notre équilibreur de charge (le saut précédent) à l'adresse de l'utilisateur. X-Forwarded-For en-tête. (en ajoutant vraisemblablement ce qu'il considère comme l'"adresse distante"). S'il ne le faisait pas, je pourrais simplement utiliser la fonction X-Forwarded-For comme précédemment. (nous avons récemment migré vers nginx)

0 votes

@Kirk Donc, quand nginx reçoit l'en-tête, c'est juste l'adresse du client original ? Mais lorsqu'il la traite, elle est ajoutée à l'en-tête du serveur proxy qui se connecte ? Cela ne colle pas - le seul moment où il devrait toucher cet en-tête est lorsqu'il envoie la connexion à un autre proxy via un fichier proxy_pass - et même là, seulement avec proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; en place.

0 votes

Même le W3C se trompe : leur documentation indique que "les proxies doivent ajouter l'adresse IP de l'initiateur de la demande à l'adresse de l'utilisateur". fin d'une liste séparée par des virgules dans un champ d'en-tête HTTP X-Forwarded-For", il devrait préciser que débutant .

7voto

user558061 Points 116

X-Real-IP est l'adresse IP du client réel auquel le serveur parle (le "vrai" client du serveur), qui, dans le cas d'une connexion par proxy, est le serveur proxy. C'est pourquoi X-Real-IP contiendra la dernière IP de l'en-tête X-Forwarded-For.

2 votes

D'accord, mais, pour moi, ce n'est tout simplement pas une information utile. Je veux obtenir l'adresse IP originale du client - c'est crucial et, d'après tout ce que j'ai lu, c'est le but de ces en-têtes. Pourquoi voudrais-je connaître l'adresse IP de nos serveurs proxy ?

1 votes

Si ce n'est pas utile pour vous, alors ce n'est pas pour vous. Personne ne vous oblige à utiliser X-Real-IP. Si vous avez besoin de l'adresse IP de l'utilisateur dans votre application, faites en sorte que votre application analyse X-Forwarded-For (ce qui n'est pas toujours fiable car certains proxys (appareils de sécurité Internet/pare-feu) ne définissent pas X-Forwarded-For). Dans le contexte de nginx, X-Forwarded-For n'est pas important car il ne parle pas à ces clients de toute façon, à part la dernière entrée (le X-Real-IP) qui est le client de nginx. Si vous n'en avez pas besoin, ne l'activez pas, désactivez-la ou ignorez-la :/.

4 votes

Non, ce que je veux dire c'est, pourquoi X-Real-IP renvoyer l'adresse IP de mon propre serveur proxy jamais être utile ?

0voto

Scott Kirkwood Points 967

C'est plus un avertissement qu'une réponse...

J'ai essayé d'ajouter quelques serveurs de cache Nginx à plusieurs endroits de la carte sans me rendre compte que mon serveur principal (source des données) est déjà derrière un serveur de cache Nginx qui fonctionne localement. Parfois, le serveur local est configuré pour exécuter Apache et Nginx est placé devant lui pour faire office de cache.

L'ajout d'un deuxième serveur de cache Nginx distinct entraînerait la création de deux serveurs de cache et donc votre HTTP_X_REAL_IP o HTTP_X_FORWARDED_FOR semble erroné, montrant l'IP d'un des serveurs au lieu de l'IP du visiteur.

Dans mon cas, j'ai résolu ce problème en configurant le nouveau serveur de cache pour qu'il prenne les données directement du port Apache (port 7080 dans mon cas) en contournant le cache Nginx local du serveur source/main.

Une autre solution serait de supprimer le HTTP_X_REAL_IP au serveur de cache local.

J'utilisais le panneau Plesk en fait.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X