Une équipe de sécurité lit sur la défense en profondeur et décide que le VPC doit avoir des Network ACL configurées « correctement » — pas le défaut tout-permettre, mais des règles de refus explicites empilées sur les groupes de sécurité. La première règle NACL bloque un port malveillant évident. La deuxième règle est plus spécifique. À la cinquième règle, un apt-get update depuis l’une des instances en sous-réseau privé commence à pendre. L’astreinte est paginée. La cause s’avère être la NACL qui bloque le trafic de retour sur un port éphémère — les NACL sont sans état, et l’équipe a oublié qu’autoriser le sortant sur le port 443 nécessite aussi une règle entrante pour la plage de ports éphémères. L’instinct est de dire que les NACL sont cassées. Elles ne le sont pas — elles sont sans état et se comportent exactement comme documenté. La leçon est que les NACL sont le mauvais outil pour la plupart des charges, et que le bon endroit pour cette défense en profondeur est ailleurs.
Ce qui se passe
Les groupes de sécurité (SG) opèrent au niveau ENI. Chaque instance EC2, base de données RDS, fonction Lambda dans un VPC, cible ALB et endpoint VPC d’interface a un ou plusieurs SG attachés. Un SG est un ensemble de règles qui disent « autoriser l’entrée depuis cette source sur ce port » ou « autoriser la sortie vers cette destination sur ce port ». Les SG sont avec état — si vous autorisez l’entrée sur le port 443, le trafic de retour repasse sans règle de sortie explicite. Les SG sont autoriser-seulement — il n’y a pas de règle de refus. Le défaut sortant est tout-autoriser ; le défaut entrant est tout-refuser (n’autoriser rien sauf permission explicite). Les SG peuvent référencer d’autres SG par ID comme source — autoriser l'entrée depuis sg-app-tier sur le port 5432 plutôt que depuis un CIDR. C’est la propriété qui fait des SG la bonne primitive pour les règles au niveau application : la règle se lit « les serveurs applicatifs peuvent parler à la base de données », pas « la plage IP 10.20.16.0/20 peut parler à la base de données ».
Les Network ACL (NACL) opèrent au niveau sous-réseau. Chaque sous-réseau est associé à exactement une NACL (la NACL par défaut autorise tout, entrée et sortie). Une NACL est une liste ordonnée de règles — la règle 100 s’évalue avant la règle 200 — et la première règle qui correspond gagne. Les NACL sont sans état — si vous autorisez l’entrée sur le port 443, vous devez aussi autoriser la sortie sur la plage de ports éphémères (32768-65535 sur Linux, 49152-65535 sur Windows) pour la réponse. Les NACL peuvent refuser — vous pouvez écrire une règle qui refuse le trafic depuis un CIDR spécifique. Les NACL ne peuvent pas référencer d’autres NACL ou SG comme sources — seulement des plages CIDR. C’est la propriété qui rend les NACL maladroites pour la plupart des règles au niveau application : il faut mapper chaque source à une plage CIDR, et les règles deviennent obsolètes chaque fois que la source change.
L’ordre d’évaluation :
- Sortant depuis l’instance A : règle sortante du SG sur l’ENI de A → règle sortante de la NACL sur le sous-réseau de A → routage → règle entrante de la NACL sur le sous-réseau de B → règle entrante du SG sur l’ENI de B.
- Entrant vers A sur le chemin de retour : NACL entrante sur le sous-réseau de A (doit autoriser le port éphémère si la NACL est restrictive) → règle entrante du SG sur l’ENI de A (avec état, autorise automatiquement si la sortie a été autorisée) → l’instance reçoit.
Le piège du port éphémère est à l’étape 2. Le SG connaît la conversation ; il laisse passer la réponse automatiquement. La NACL ne la connaît pas ; elle voit un paquet entrant frais sur un port à numéro élevé et demande « est-ce que j’ai une règle pour ça ? ». Si les règles entrantes de la NACL n’autorisent que le port 443 et que vous avez oublié la plage éphémère, la réponse est éliminée.
Comment vérifier
La matrice de décision pour savoir quel outil utiliser pour quel contrôle :
| Contrôle | SG | NACL |
|---|---|---|
| Les serveurs applicatifs peuvent parler à la base de données | oui (référencer le SG) | mauvais outil |
| Bloquer tout le trafic depuis un CIDR malveillant spécifique | possible avec une révocation explicite, mais mieux de refuser au bord | oui (règle de refus) |
| Autoriser seulement HTTPS entrant vers l’ALB | oui | oui mais redondant avec le SG |
| Bloquer le sortant vers un CIDR risqué spécifique | révoquer ou ne pas ajouter | oui (règle de refus) |
| Isoler deux sous-réseaux pour qu’ils ne puissent pas du tout se parler | possible avec règles SG mais le SG devrait être sur chaque instance | oui (refus au niveau sous-réseau) |
| Mettre en quarantaine un sous-réseau pendant une réponse à incident | possible en modifiant chaque SG | oui (un changement de NACL met le sous-réseau en quarantaine) |
| Autoriser l’entrée seulement depuis un CIDR partenaire connu | oui | oui |
Le motif qui émerge : les SG gèrent les règles au niveau application (quels services peuvent parler à quels), les NACL gèrent les contrôles grossiers au niveau sous-réseau (quelles plages de sous-réseaux peuvent parler à quels sous-réseaux du tout, plus les règles de liste de refus que les SG ne peuvent pas exprimer).
Inspecter les règles SG existantes :
# SG sur une instance spécifique
aws ec2 describe-instances \
--instance-ids i-0123456789abcdef0 \
--query 'Reservations[].Instances[].SecurityGroups[].[GroupId,GroupName]' \
--output table
# Ce qu'un SG autorise
aws ec2 describe-security-groups \
--group-ids sg-app-tier \
--query 'SecurityGroups[].IpPermissions[].[FromPort,ToPort,IpProtocol,IpRanges,UserIdGroupPairs]' \
--output json
Inspecter les NACL existantes :
aws ec2 describe-network-acls \
--filters Name=vpc-id,Values=vpc-0123456789abcdef0 \
--query 'NetworkAcls[].[NetworkAclId,IsDefault,Entries[].[RuleNumber,Egress,Protocol,RuleAction,CidrBlock,PortRange]]' \
--output json
La NACL par défaut autorise tout en entrée et tout en sortie — règle 100 (autoriser tout) et règle * (refus par défaut). La plupart des VPC en production laissent les NACL au défaut et font tout le travail avec les SG. L’exception est quand un régime de conformité spécifique exige des règles de refus au niveau sous-réseau, ou quand un incident exige une quarantaine de sous-réseau.
La correction
La procédure pour concevoir SG et NACL ensemble :
-
Par défaut SG pour tout ce qui est une règle au niveau application. « L’app peut parler à la base de données », « l’ALB peut parler à l’app », « le bastion peut parler à l’app en SSH ». Les références SG-à-SG font que ces règles se lisent naturellement et restent correctes quand les instances sources changent.
-
Nommez les SG par rôle, pas par service.
sg-app-tier,sg-db-tier,sg-bastion,sg-alb. Passg-i-0123456789abcdef0nisg-app-1. Les noms apparaissent dans chaque analyse de flow log et chaque revue d’incident ; des noms lisibles coupent le temps d’investigation. -
Utilisez les NACL pour deux choses seulement :
- Règles de liste de refus. Si un CIDR spécifique doit être bloqué à l’échelle de l’organisation (une plage connue malveillante, un ancien partenaire de peering qui ne devrait avoir aucune joignabilité), ajoutez-le à la NACL à un numéro de règle bas (par exemple 50) pour qu’il s’évalue en premier.
- Quarantaine de sous-réseau. Pendant un incident, le moyen le plus rapide d’isoler un sous-réseau est un changement de NACL — modifier la NACL du sous-réseau pour refuser tout et le sous-réseau entier est hors-ligne en secondes. La restauration est un seul retour de règle. La même isolation via SG nécessite de modifier le SG de chaque instance, ce qui est lent et risqué.
-
Laissez la NACL par défaut tranquille. Ou, si votre référence de sécurité exige des NACL non-défaut, écrivez-les en gardant les règles d’autorisation des ports éphémères à l’esprit :
# Créer une NACL non-défaut pour les sous-réseaux privés aws ec2 create-network-acl --vpc-id vpc-0123456789abcdef0 # Autoriser HTTPS entrant pour le trafic de retour des appels sortants # (le SG gère déjà la conversation ; ceci permet juste le paquet au sous-réseau) aws ec2 create-network-acl-entry \ --network-acl-id acl-private \ --rule-number 100 \ --protocol tcp \ --rule-action allow \ --ingress \ --cidr-block 0.0.0.0/0 \ --port-range From=443,To=443 # CRITIQUE : autoriser la plage de ports éphémères pour le trafic de retour aws ec2 create-network-acl-entry \ --network-acl-id acl-private \ --rule-number 110 \ --protocol tcp \ --rule-action allow \ --ingress \ --cidr-block 0.0.0.0/0 \ --port-range From=32768,To=65535 # Autoriser le sortant sur ce dont les apps ont besoin aws ec2 create-network-acl-entry \ --network-acl-id acl-private \ --rule-number 100 \ --protocol tcp \ --rule-action allow \ --egress \ --cidr-block 0.0.0.0/0 \ --port-range From=443,To=443 -
Testez les changements de NACL depuis une vraie instance avant de basculer en production. Exécutez
curl https://example.comdepuis une instance EC2 dans le sous-réseau ; si ça pend, la NACL bloque le retour éphémère. Le mode de panne est toujours des timeouts silencieux, pas des messages d’erreur.
L’anti-motif qu’on voit le plus : une recommandation d’audit de sécurité qui dit « durcir les NACL » est implémentée comme une NACL non-défaut avec des règles qui miroitent les SG, la plage de ports éphémères est oubliée, et apt-get update ainsi que les requêtes DNS échouent par intermittence. La bonne réponse à cette constatation d’audit est de la pousser en arrière : les SG appliquent déjà les règles au niveau application ; les NACL ajoutant une deuxième couche sans état créent surtout de la douleur opérationnelle et attrapent rarement un vrai attaquant que les SG ont raté.
L’autre règle qu’on tient : les règles SG sont de l’infrastructure-as-code, les règles NACL encore plus. Un VPC en production où les SG et NACL sont édités depuis la console est un VPC où le prochain incident prend deux heures de plus parce que personne ne connaît l’état courant.
Pour le plan de sous-réseaux qui définit à quoi s’appliquent les NACL, voir Conception de sous-réseaux multi-AZ. Pour l’analyse des flow logs qui fait remonter quelles règles déclenchent, voir Analyse des Flow Logs VPC.
Stack Harbor conçoit et audite les topologies VPC en production dans le cadre de Gestion AWS et des Environnements infogérés en continu. Si un audit de sécurité vous a remis un projet de durcissement de NACL, commencez par une consultation d’infrastructure.