Migration du reverse proxy de l’entreprise vers NPMplus
Une migration restée en échec, reprise : deux causes prouvées, bascule en production, CrowdSec.
Seul, chez OMB Informatique, prestataire informatique où je suis en alternance : un collègue avait fait une première tentative, restée en échec. Complément le 12 octobre 2026 (envoi de fichiers bloqué par CrowdSec). Les applications internes et les détails d’exposition ne sont pas nommés sur cette page.
Compétences mises en œuvre
| Compétence | Ce que j’ai fait | Preuve |
|---|---|---|
| Répondre aux incidents et aux demandes d’assistance et d’évolution | ||
| Traiter des demandes concernant les applications | Diagnostic des deux causes qui empêchaient la gestion commerciale de fonctionner derrière le nouveau proxy (en-tête Host, en-tête nosniff), puis d’un envoi de fichiers refusé par le pare-feu applicatif | choix techniques, tests, bilan |
| Mettre à disposition des utilisateurs un service informatique | ||
| Déployer un service | Bascule du reverse proxy en production, redirection HTTP vers HTTPS, version figée, CrowdSec activé (moteur, pare-feu applicatif, bouncer) | mise en œuvre |
| Accompagner les utilisateurs dans la mise en place d’un service | Utilisateurs prévenus de la manipulation à faire si leur page de connexion tournait en boucle (cache du navigateur) | mise en œuvre, étape 6 |
| Réaliser les tests d’intégration et d’acceptation d’un service | Tests en lecture seule avant la bascule, tests depuis l’intérieur et depuis l’extérieur après, bannissement d’une adresse testé avec un téléphone | tests |
Contexte et besoin
OMB rend accessibles depuis Internet plusieurs applications internes, dont la gestion commerciale. Un reverse proxy reçoit les connexions HTTPS, porte les certificats et transmet chaque demande au bon serveur. Trois générations de proxy cohabitaient sur la même machine virtuelle (SWAG, NPM, NPMplus), sur les mêmes ports : une seule peut tourner à la fois, et c’était encore l’ancienne.
La migration vers NPMplus était commencée par un collègue, mais la gestion commerciale répondait « 503 » derrière le nouveau proxy ; sa configuration avait été laissée en l’état. Le besoin : finir la migration (interface web, certificats renouvelés automatiquement, CrowdSec intégré) sans couper les utilisateurs, et comprendre pourquoi la première tentative échouait.
Objectifs et contraintes
Objectifs
- Toutes les applications servies par l’ancien proxy fonctionnent derrière NPMplus, en interne et depuis l’extérieur.
- Le HTTP est redirigé vers le HTTPS ; les certificats se renouvellent seuls.
- Les adresses malveillantes sont bannies (CrowdSec), à la place du filtrage par pays de l’ancien proxy.
- Tout reste modifiable dans l’interface, et documenté pour les collègues.
Contraintes
- La production : tests en lecture seule avant la bascule ; sauvegarde à froid avant toute modification ; retour arrière = relancer l’ancienne pile.
- Les secrets : la clé du bouncer va dans le gestionnaire de mots de passe, jamais dans une note ; aucun lien de session de l’application n’est collé dans un ticket ou un échange.
- Une application qu’on ne modifie pas : la gestion commerciale est un logiciel d’éditeur ; c’est le proxy qui s’adapte.
Analyse et choix techniques
| Question | Mon choix | Pourquoi |
|---|---|---|
| Pourquoi « 503 » ? | Prouver la cause par trois requêtes directes vers le serveur de l’application, en ne changeant que l’en-tête Host | Le serveur de l’application choisit sa cible d’après Host : le nom interne répond 200, le nom public 503. L’ancien proxy envoyait le nom interne sans qu’on l’écrive ; NPMplus envoie le nom public |
| Comment corriger Host ? | L’option « Spoof Host Header » de NPMplus, et rien dans l’onglet Advanced ni dans l’engrenage | La ligne ajoutée par mon collègue dans Advanced était ignorée par nginx (niveau serveur, écrasé par le bloc location) ; dans l’engrenage, la version de nginx embarquée aurait envoyé deux en-têtes Host (code source vérifié) |
| Pourquoi la connexion tourne en boucle ? | Lire la console du navigateur plutôt que les journaux du proxy | NPMplus ajoute « nosniff » à tous les sites ; l’application sert un script annoncé comme JSON, que le navigateur refuse alors. Retiré pour ce seul site, les autres protections restent |
| Quelle version de NPMplus ? | Figée dans la pile Portainer, mise à jour par une procédure écrite | Une mise à jour automatique pouvait casser l’application sans prévenir |
| Quel filtrage ? | CrowdSec : moteur (lit les journaux), pare-feu applicatif (inspecte chaque requête), bouncer dans NPMplus (applique) | CrowdSec décide, le bouncer applique : il faut vérifier les deux, sinon on se croit protégé |
| Envoi de fichiers refusé (12 octobre) | Une configuration du pare-feu applicatif propre à OMB, plutôt que de le désactiver sur ce site | Désactiver aurait été plus simple ; le choix est de garder la protection |
Ce que j’en retiens : changer de reverse proxy change ce que voit le serveur derrière (l’en-tête Host) et ce que voit le navigateur devant (les en-têtes de sécurité ajoutés). Une requête directe avec curl prouve le premier en une minute ; la console du navigateur (F12) donne le second.
Mise en œuvre
- Diagnostic (5 octobre) : comparaison de la configuration de l’ancien proxy, qui marchait, et de celle du nouveau, qui échouait, code source de NPMplus et de nginx à l’appui.
- Preuve (6 octobre) : trois requêtes curl vers le serveur de l’application, en lecture seule, avec trois valeurs de Host : 200, 200, 503. Écriture d’une configuration complète de secours, non utilisée.
- Sauvegarde à froid des dossiers de NPMplus et de CrowdSec, archive vérifiée.
- Configuration du site dans NPMplus : schéma HTTPS vers le serveur, Spoof Host Header activé, Advanced et engrenage vides ; fichier généré relu (une seule ligne Host).
- Bascule (6 octobre, 13 h 30) dans Portainer : arrêt de l’ancienne pile, démarrage de NPMplus ; les accès publics arrivent bien sur le nouveau proxy.
- Seconde cause : la connexion tourne en boucle ; console du navigateur, script refusé à cause de « nosniff » ; une seule ligne dans Advanced pour retirer cet en-tête sur ce site. Utilisateurs prévenus : Ctrl + F5 si leur page boucle encore (cache de l’ancien en-tête).
- Finitions : redirection HTTP vers HTTPS, version de NPMplus figée (sauvegarde avant), autres applications vérifiées.
- CrowdSec : chemin des journaux corrigé (celui vu par le conteneur, pas celui de la machine), pare-feu applicatif actif, clé du bouncer créée et rangée, adresse de l’API locale corrigée (le port du tutoriel était déjà pris par une autre application).
- Capitalisation : deux modes opératoires, copiés dans le wiki interne.
- Complément (12 octobre) : envoi de fichiers refusé (403) par le pare-feu applicatif ; alerte identifiée à la seconde près ; configuration propre à OMB, protection gardée.
Tests et recette
| Test | Résultat |
|---|---|
| Trois requêtes directes vers le serveur de l’application (Host interne, adresse, nom public) | 200, 200, 503 : la cause est prouvée avant de toucher à la production |
| Fichier de configuration généré par NPMplus | Une seule ligne Host, avec la valeur attendue |
| Après la bascule : en-tête « nosniff » sur le script refusé | Absent (curl) ; page de connexion saine après rechargement sans cache |
| Connexion à l’application : en interne, depuis l’extérieur (4G), sur d’autres postes ; autres applications | Fonctionne partout |
| HTTP vers HTTPS | Redirection 301 en gardant le chemin ; certificat Let’s Encrypt valide |
| Version figée | docker inspect : la version attendue, même empreinte que celle qui tournait |
| CrowdSec lit les journaux | 45 lignes lues, 45 analysées ; bouncer vu comme valide avec sa date de dernier contact |
| Bannissement d’une adresse 4G à la main | Page de blocage sur le téléphone, les autres accès intacts ; adresse débannie ensuite |
| Envoi de fichiers, pare-feu applicatif actif | Réussi ; aucune nouvelle alerte après l’essai |
Bilan critique
Ce qui a coincé. La ligne Host ajoutée dans l’onglet Advanced n’avait jamais été appliquée : nginx ignore une directive du niveau serveur quand le bloc location en définit lui-même. Le second piège ne laissait aucune erreur réseau : la page « tournait », et seule la console du navigateur a montré le script refusé. Enfin, un navigateur qui avait gardé l’ancien en-tête en cache continuait de boucler après la correction, d’où la consigne donnée aux utilisateurs.
Côté CrowdSec, deux erreurs de tutoriel : le chemin des journaux écrit tel qu’il est sur la machine, alors que le conteneur le voit ailleurs (aucune ligne lue), et un port d’API déjà occupé chez nous par une autre application. L’ordre compte aussi : le pare-feu applicatif avant le bouncer, sinon toutes les requêtes sont refusées.
Les limites que j’assume.
- Deux réglages restent à confirmer par des tests chez OMB : le renouvellement automatique des certificats, et le réglage du pare-feu applicatif pour l’envoi de fichiers. Les détails qui touchent à la sécurité de l’entreprise restent dans ses documents internes.
- Une version figée demande une procédure de mise à jour, écrite dans le mode opératoire.
Ce que je referais autrement. J’ouvrirais la console du navigateur dès le premier symptôme sans erreur réseau, au lieu de chercher d’abord dans les journaux du proxy : la seconde cause aurait été trouvée en quelques minutes.
Outils et aides. Les choix et les décisions sont les miens, ainsi que les étapes écrites à la première personne. Un assistant IA (Claude Code) a lu le code source de nginx et de NPMplus avec moi, exécuté une partie des requêtes de test et m’a aidé à rédiger les modes opératoires, que j’ai relus et testés.
Documents et productions associés
- Mode opératoire 1 · Passer une application sur NPMplus
- Mode opératoire 2 · Activer CrowdSec dans NPMplus
- Suivi de projet
- Configuration de secours
