web-dev-qa-db-fra.com

Nginx: proxy inverse passant l'IP du client au serveur

Sur un proxy inverse nginx existant, je dois passer l'IP du client à un serveur (de nginx au frontend servi dans NG-Engine, et de celui-ci au backend), j'ai essayé beaucoup de sites, mais le serveur ne fait que recevoir 127.0.0.1. Informations supplémentaires (ajoutées après la question de Michael Hampton), notre infrastructure de machines virtuelles:

  1. Navigateur client (un autre VM ou bureau distant)
  2. (VM1) proxy inverse nginx (cela fonctionne, couche HTTPS que j'ai ajoutée au moins)
  3. (VM1) NgEngine au service du frontend maison
  4. (VM1) API RESTful servie par un backend maison Java/Spring (fonctionnant dans l'idée IntelliJ)
  5. (VM2..x) d'autres serveurs alimentant le backend en données (hors de question)

J'ai vérifié doc, essayé ici (y compris la suppression de l'en-tête X-Real-IP, comme ils le suggèrent dans cette autre question ). J'ai aussi essayé d'ajouter:

set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For

Mon nginx a un module real_ip (sortie de nginx -V ci-dessous), et voici mon nginx.conf ... Qu'est-ce que je fais mal?

user www-data;
worker_processes auto;
pid /run/nginx.pid;

events {
  worker_connections 768;
  # multi_accept on;
}

http {
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 65;
  types_hash_max_size 2048;
  # server_tokens off;

  server_names_hash_bucket_size 64;
  # server_name_in_redirect off;

  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
  ssl_prefer_server_ciphers on;

  gzip on;
  gzip_disable "msie6";

  server {
    listen 443 ssl;
    server_name          test-server;
    ssl_certificate      /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key  /etc/nginx/ssl/nginx.key;

    add_header              Strict-Transport-Security  "max-age=63072000; includeSubdomains; preload" always;
    add_header              X-Frame-Options            SAMEORIGIN;
    add_header              X-Content-Type-Options     nosniff;

    # allow nginx to start regardless of upstream endpoint state by using intermediary variable
    set                     $UPSTREAM_SERVICE          10.10.10.15:8080;

    location  / {
      proxy_pass               http://localhost:6789
      proxy_http_version       1.1;

      proxy_buffering          off;
      proxy_buffer_size        128k;
      proxy_busy_buffers_size  256k;
      proxy_buffers            4                   256k;
      proxy_set_header         Host                $Host;
      proxy_set_header         X-Real-IP           $remote_addr;
      proxy_set_header         X-Forwarded-For     $proxy_add_x_forwarded_for;
      proxy_set_header         X-Forwarded-Proto   $scheme;
      proxy_set_header         Upgrade             $http_upgrade;
      proxy_set_header         Connection          $http_connection;

    }
  }
}

Sortie de nginx -V:

nginx version: nginx/1.14.0 (Ubuntu)
built with OpenSSL 1.1.0g  2 Nov 2017
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-mcUg8N/nginx-1.14.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_Perl_module=dynamic --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-headers-more-filter --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-auth-pam --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-cache-purge --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-dav-ext --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-ndk --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-echo --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-fancyindex --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/nchan --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-lua --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/rtmp --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-uploadprogress --add-dy
namic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-upstream-fair --add-dynamic-module=/build/nginx-mcUg8N/nginx-1.14.0/debian/modules/http-subs-filter

Merci beaucoup et meilleures salutations

4
xCovelus

Sur un proxy inverse nginx existant, je dois transmettre l'IP du client à un serveur (tous deux fonctionnant dans le même système d'exploitation), j'ai essayé beaucoup de sites, mais le serveur ne fait que recevoir 127.0.0.1.

En tant que proxy inverse, votre serveur principal recevra toujours la connexion de votre processus nginx, qui dépend de votre *_pass directive, contiendra l'adresse IP de votre nginx (dans votre cas, 127.0.0.1).

En tant que tel, vous ne pouvez pas récupérer l'IP client en vérifiant l'adresse client, vous n'obtiendrez que l'adresse IP de votre serveur frontal.

Dans le proxy inverse et l'équilibrage de charge, euh, business, nous avons plusieurs façons d'extraire l'IP client du proxy inverse sur le backend:

  1. De facto non standard X-Forwarded-For Requête HTTP en-tête, contient tous les proxy passés et les adresses IP clientes demandeuses.
  2. Forwarded requête HTTP en-tête, est un nouveau moyen standardisé de remplacer X-Forwarded-For, contient également les adresses IP pour tous les proxys passés et le client demandeur.
  3. X-Real-IP En-tête de requête HTTP, ou tout en-tête de requête HTTP personnalisé, pour contenir arbitrairement l'adresse IP du client.

Vérifiez votre application principale si elle prend en charge l'un de ces en-têtes.


Mon nginx a un module real_ip

ngx_http_realip_module n'est pas utilisé dans ce cas. Il est utilisé si nginx se trouve derrière un proxy afin qu'il puisse valider et récupérer l'adresse IP réelle du client et la stocker dans une variable spécifiée.

2
mforsetti

Grâce aux deux commentaires, j'ai eu une idée plus claire de la manière de trouver la solution. J'ai été particulièrement utile le commentaire de mforsetti:

Vérifiez votre application principale si elle prend en charge l'un de ces en-têtes.

Et aussi:

[..], nous avons plusieurs façons d'extraire l'IP client du proxy inverse sur le backend: [..]

Utilisation de HttpServletRequest (demande):

request.getRemoteAddr();

était (et toujours) me donne l'IP proxy. J'ai donc décidé d'essayer manuellement d'obtenir le bon en-tête:

request.getHeader("X-Forwarded-For");

Et cela me donnait exactement l'adresse IP du client.

Merci beaucoup pour votre aide, sans cela, je ne serais pas en mesure de résoudre ce problème.

0
xCovelus