Quand le code fonctionne, mais que le réseau dit non
Dans ma tête, le firewall vivait dans la catégorie « affaires de réseau ». Moi, j’écris le programme; quelqu’un d’autre filtre les connexions. Cette séparation tient jusqu’au moment où mon application passe du poste du développeur à trois serveurs séparés.
Une connexion TCP vers SQL Server ne dit pas seulement « port 1433 ». Elle possède cinq éléments : protocole, adresse source, port source temporaire, adresse destination et port destination. Le client commence par envoyer un paquet SYN. Le serveur qui écoute répond SYN-ACK; le client confirme avec ACK. Seulement ensuite, SQL Server et son client échangent leur protocole applicatif.
APP01:49172 ── SYN ─────→ DB01:1433
← SYN-ACK ──
── ACK ─────→
⇄ données SQL
Un firewall stateful voit la connexion sortir selon une règle autorisée et se rappelle son état. Il permet les paquets de réponse vers le port temporaire sans exiger une règle ouverte pour tous les ports entrants. Si le premier SYN est bloqué ou silencieusement jeté, le client attend et réessaie jusqu’au timeout. Si aucun service n’écoute et que la machine répond RST, l’échec peut être presque immédiat. « Timeout » et « connexion refusée » donnent donc des indices différents.
Dans une architecture Web, le trajet devrait être explicite :
- navigateur vers
WEB01sur TCP 443; WEB01versAPP01sur le port du service;APP01versDB01sur TCP 1433;- aucun accès direct du navigateur vers
DB01; - administration depuis un sous-réseau précis seulement.
La règle utile est aussi précise : source APP01 → destination DB01 → TCP 1433. « Ouvrir SQL » depuis partout transforme une dépendance interne en surface d’attaque. Le compte SQL doit encore s’authentifier et posséder peu de droits; le firewall ne remplace pas l’autorisation du service.
Le nom ajoute une étape. Si DB01 ne se résout pas ou pointe vers l’ancienne adresse, le paquet ne rejoint même pas le firewall attendu. Une instance SQL nommée peut utiliser un port dynamique découvert par un autre service, ce qui complique les règles. Pour une production segmentée, un port fixe documenté rend le trajet plus prévisible.
Mon diagnostic suit les couches plutôt que de relire immédiatement le code :
nslookup DB01 → le nom donne-t-il la bonne IP?
ping DB01 → la route répond-elle? (si ICMP est permis)
telnet DB01 1433 → la connexion TCP s'ouvre-t-elle?
netstat -an sur DB01 → un service écoute-t-il sur 1433?
journal du firewall → quelle règle accepte ou refuse le SYN?
Un ping bloqué ne prouve pas que TCP est bloqué, et un telnet réussi ne prouve pas que l’authentification SQL marchera. Chaque test répond à une question limitée. Je note aussi la machine qui lance réellement l’appel : dans ASP.NET, c’est souvent le serveur Web ou son compte, pas le navigateur de la personne.
Les pannes intermittentes peuvent venir d’un état expiré, d’un équipement redondant aux règles différentes ou d’un pool de serveurs dont un seul n’a pas la route. Les horloges synchronisées et un identifiant de corrélation permettent d’aligner le log applicatif avec celui du firewall. Sans heure commune, deux traces de la même tentative ressemblent à deux incidents.
Je vais traiter les flux réseau comme du code de configuration : source, destination, port, justification, propriétaire et date de révision. Le test couvre l’autorisation et le refus attendu depuis une autre machine. La prochaine fois qu’une connexion échoue, je suivrai le SYN jusqu’au service avant de réécrire une méthode qui fonctionne peut-être très bien.