Nginx
Nginx est un serveur Web modulaire qui fonctionne très bien en reverse proxy et possède de nombreuses possibilités. De plus il est très léger, je vous invite à consulter leur site : www.nginx.org
La problématique
Un client avait un site internet assez mal écrit avec beaucoup d’url en dur dans le code et qui aurait nécessité beaucoup trop de temps pour le remettre en conformité. l’idée est de ré-écrire les urls dans les pages transmises par le serveur Web, en l’occurrence un serveur Apache (pas à jour !). Nous aurions pu utiliser un vrai reverse proxy (Kemp, F5..) afin de faire la même chose mais le client n’en dispose pas et l’investissement pour une seule machine virtuelle était un peu surdimensionné. Si la machine était dans Azure, nous aurions pu utiliser les nombreuses briques présentes dans la solution de Cloud Microsoft. l’idée est donc de ré-écrire les pages à la volées lors de la transmission avec le client.
Solution mise en place
Nous avons choisi d’installer un serveur Nginx sur une machine virtuelle Centos 7, cette installation est donc reproductible chez vous sur un système Centos, Red Hat ou Fedora
Installation de Nginx
Nginx est présent dans les dépots Centos mais la version proposée ne dispose pas du module de substitution dont nous avons besoin. Il faut donc passer par la compilation, et donc installer les outils nécessaires comme ci-dessous :
yum install gcc-c++ \ pcre-devel \ zlib-devel \ make \ wget \ openssl-devel \ libxml2-devel \ libxslt-devel \ gd-devel \ perl-ExtUtils-Embed \ GeoIP-devel \ gperftools-devel \ git
Ensuite on récupère les sources de Nginx depuis le site de Nginx :
cd /tmp wget http://nginx.org/download/nginx-1.10.1.tar.gz tar -xvf nginx-1.10.1.tar.gz
Comme l’extension “http subsitution filter” module n’est pas un module “officiel”, il faut le récupérer sur le GitHub de yaoweibin :
git clone git://github.com/yaoweibin/ngx_http_substitutions_filter_module.git
Ensuite on configure le make :
cd nginx-1.10.1 ./configure \ --user=nginx \ --group=nginx \ --prefix=/etc/nginx \ --sbin-path=/usr/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf \ --pid-path=/var/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-http_gzip_static_module \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-pcre \ --with-file-aio \ --with-http_realip_module \ --without-http_scgi_module \ --without-http_uwsgi_module \ --without-http_fastcgi_module \ --add-module=/tmp/ngx_http_substitutions_filter_module
On lance le make
make make install
Configuration de Nginx
Il faut créer un compte dédié a Nginx, faire tourner un serveur Web en root étant largement déconseillé (oui oui, il parait) :
useradd -r nginx
Comme notre Nginx est une version compilée, nous devons créer un fichier de service conforme à systemd :
echo "[Unit] Description=The NGINX HTTP and reverse proxy server After=syslog.target network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/var/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx ExecReload=/bin/kill -s HUP $MAINPID ExecStop=/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target" > /lib/systemd/system/nginx.service
Comme on est pas des gros bourrins, on configure firewalld via firewall-cmd :
firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --reload
Et bien sur on vérifie que les règles sont appliquées :
iptables-save | grep 80
Création de la règles de réécriture
Par défaut, le fichier de configuration Nginx est situé dans le dossier que nous avons mentionné dans la partie “—prefix=/etc/nginx”, nginx.conf Remplacez la partie “server {…}” par celle ci :
server { listen 80; server_name localhost old.domainquonveut.com; access_log /var/log/nginx/oldsite.access.log main; error_log /var/log/nginx/oldsite.error.log main; location / { proxy_pass http://ancienserveur:80; #ipduserveur proxy_set_header Host www.vhostduapache.com; proxy_set_header Accept-Encoding ""; subs_filter www.domaineendurdanslecodequinousplaitpas.com old.domainquonveut.com gi; subs_filter www.domaineendurdanslecodequinousplaitpas.fr old.domainquonveut.fr gi; } }
- proxy_pass : c'est l'option qui permet de forwarder le traffic entrant vers le serveur Apache
- proxy_set_header : c'est l'option qui permet de modifier le header envoyé au serveur Web
- Host : dans notre cas on veut changer le Host présent dans le header afin de corrigé celui appelé par l'utilisateur.
- Accept-Encoding : On utilise également "Accept-Encoding "";" afin de forcer le serveur Apache a ne pas utiliser la compression gzip des pages, car sinon, le module ne pourra pas ré-récrire les objets.
- subs_filter : la syntaxe est très simple "stringquidoitdisparaitre" "stringquidoitapparaitre" gi le paramètre gi sert à indiquer que nous souhaitons ré-écrire tout (toute les occurrences), le i pour case insensitive, afin de le récupérer sans tenir compte de la casse.
- Niveau ressources, ca sert à rien de compressor deux fois la même donnée, ca sera pas plus petit (bah ouais...)
- Le module de substitution ne gère pas la décompression à la volée, puisqu'il analyse les fichiers plats et remplace les occurrences des strings qu'on souhaite dégager.
- Lorsqu'on mets en place un reverse proxy, on peut vouloir mettre en cache certains éléments pour décharger les serveurs web, afin de pas leurs demander 10 fois à la seconde la même image (le logo de la boite par example), dès lors si les serveurs web envoient du flux compressé, il ne pourra pas le faire correctement.
Les cas d’usage
Utiliser ce type de module peut être interressant, par example, sur un Wordpress de test. En effet, Wordpress stocke dans la base l’url d’accès, et l’envoie dans quelques pages, rien de bien méchant! Du coup, avec cette petite manipulation, vous pouvez avoir un Wordpress de test qui serait une copie 100% identique à votre prod’, juste avec un petit copier coller de la VM ou une autre technique :)
Dans le cas de mon blog, si je souhaite mettre en place une copie de mon site avec par example comme url “test.deneuve.xyz” sans rien toucher (en dehors d’une petite copie) je devrai faire un nginx.conf tel que :
server { listen 80; server_name localhost test.deneuve.xyz; access_log /var/log/nginx/test.access.log main; error_log /var/log/nginx/test.error.log main; location / { proxy_pass http://192.168.1.150:80; #ipduserveurbidon proxy_set_header Host etienne.deneuve.xyz; proxy_set_header Accept-Encoding ""; subs_filter etienne.deneuve.xyz test.deneuve.xyz gi; } }