1. Préambule

Un proxy inverse (reverse-proxy) est un type de serveur, habituellement placé en frontal des serveurs web. Ainsi, le client web passe par cet intermédiaire pour accéder aux applications des serveurs internes. Le reverse-proxy peut fournir différentes fonctionnalités intéressantes comme une fonction de cache, des fonctions de répartition de charges, des fonctions de sécurité (WAF), le chiffrement TLS et la compression.

2. Introduction

Si vous fonctionnez dans une architecture où vous disposez d’un reverse-proxy situé en amont de vos serveurs applicatifs classiques, alors vous avez certainement remarqué que l’adresse IP source présente dans les fichiers journaux de vos serveurs applicatifs est celle de votre serveur mandataire inversé et non celle du client réel.

anakin@tatooine:~$ sudo cat /var/log/apache2/access.log
192.0.2.10 - - [05/Feb/2019:00:00:40 +0100] "GET / HTTP/1.0" 200 6458

Nous constatons dans l’exemple précédent que l’adresse IP indiquée est celle du serveur mandataire inverse et non celle de la source réel de la requête http. Heureusement, le reverse-proxy peut générer deux en-têtes http permettant de fournir aux serveurs web présents en arrière-plan l’adresse IP de l’émetteur de la requête http originale : X-Forwarded-For et X-Real-IP.

Le RFC 7239 définit plus précisément le fonctionnement du mécanisme Forwarded. À noter qu’il existe également un en-tête Forwarded qui permettrait d’ajouter un mécanisme d’authentification (token) qui garantirait l’identité du reverse-proxy. X-Forwarded-For fournit l’adresse IP du client d’origine ainsi que l’adresse des différents répartiteurs de charge ou serveurs mandataires inversés sollicités. Concernant l’en-tête X-Real-IP, je n’ai pas trouvé d’informations précises sur son mode de fonctionnement. Il semblerait qu’il permette de fournir l’adresse IP du client qui est pour le reverse-proxy, l’hôte qui lui a envoyé la requête.

3. Configurations

a. Le reverse-proxy

Dans un premier temps, il est nécessaire de configurer le reverse-proxy (basé ici sur nginx) afin qu’il ajoute les en-têtes nécessaires aux requêtes http qu’il transmettra aux serveurs web situés en arrière-plan. Ces derniers pourront ainsi utiliser l’une des deux en-têtes pour récupérer l’adresse IP réelle de l’émetteur.

vador@mustafar:~$ sudo nano /etc/nginx/sites-available/reverse
location / {

      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 https;

 }

b. Le cas d’un serveur Apache en arrière-plan

Dans un second temps, nous allons nous occuper des serveurs situés à l’arrière-plan. Si vous diposez de serveurs fonctionnant avec le service Apache alors voici les différentes étapes nécessaires pour permettre à celui-ci de récupérer l’information désirée :

anakin@tatooine:~$ sudo a2enmod remoteip

Puis nous allons configurer ce module :

anakin@tatooine:~$ sudo nano /etc/apache2/conf-available/remoteip.conf
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 192.0.2.10

anakin@tatooine:~$ sudo a2enconf remoteip

Nous allons maintenant spécifié dans la configuration globale du service web que nous souhaitons que ce soit l’adresse IP du client et non du serveur mandataire inversé qui soient pris en compte dans les logs :

anakin@tatooine:~$ sudo nano /etc/apache2/apache2.conf
LogFormat "%v:%p %a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%a %l %u %t \"%r\" %>s %O" common

Ici l’important est le %a. Si l’on s’en réfère à la documentation officielle de Apache 2, cette variable permet d’afficher l’adresse IP distante et non celle du reverse-proxy dans les fichiers journaux.

Enfin il est nécessaire de recharger la configuration de notre service Apache :

anakin@tatooine:~$ sudo systemctl reload apache2

Un petit tour dans les logs du serveur :

anakin@tatooine:~$ sudo cat /var/log/apache2/access.log
69.89.31.134 - - [05/Feb/2019:00:00:40 +0100] "GET / HTTP/1.0" 200 6458

c. Le cas d’un serveur nginx en arrière-plan

Il se peut que vous ayez plutôt un autre service nginx en arrière-plan. Dans ce cas, la configuration n’est pas la même que celle du service Apache. Voici les étapes nécessaires si vous avez fait le choix d’utiliser ce service :

yoda@dagobah:~$ sudo nano /etc/nginx/nginx.conf
log_format specialLog '$remote_addr forwarded for $http_x_real_ip - $remote_user [$time_local]  '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent"';

yoda@dagobah:~$ sudo systemctl reload nginx

Un petit tour dans les logs du serveur :

yoda@dagobah:~$ sudo cat /var/log/nginx/access.log
69.89.31.134 forwarded for 69.89.31.134 - - [05/Feb/2019:00:00:40 +0100]  "GET / HTTP/1.1" 200 728 "-" "-"

4. Conclusion

Voilà ! Si vous avez des remarques, des corrections ou des précisions à apporter sur mon article, n’hésitez pas ! Ce sera avec plaisir que je les prendrai en compte.

Enjoy :D