Aller au contenu

Sous-réseaux publics vs privés sur AWS : comment un sous-réseau devient réellement public

AWS n'a aucune case « public » sur un sous-réseau. Un sous-réseau est public quand sa table de routage pointe 0.0.0.0/0 vers une passerelle Internet et que l'instance porte une IP publique. Voici le mécanisme exact et comment auditer le vôtre.

Il n’existe aucun attribut « public » sur un sous-réseau AWS. Un sous-réseau est public pour une seule raison : la table de routage qui lui est associée contient une route 0.0.0.0/0 dont la cible est une passerelle Internet. C’est tout le mécanisme. Le reste — l’étiquette « Public subnet » de l’assistant VPC, l’attribution automatique d’IP publique, la convention de nommage dans votre Terraform — n’est que de la convention par-dessus cette unique route.

Ce qui se passe

Trois conditions doivent être réunies avant qu’une instance dans un sous-réseau puisse parler directement à Internet, et on n’en vérifie souvent qu’une seule :

  1. Le VPC a une passerelle Internet (IGW) attachée. L’IGW est un objet au niveau du VPC; il ne fait rien tant qu’aucune route ne pointe vers lui.
  2. La table de routage du sous-réseau contient 0.0.0.0/0 -> igw-xxxx. Si le sous-réseau n’a pas d’association explicite, il hérite de la table de routage principale du VPC — qui a cette route, ou pas. Cet héritage est la source de la plupart des expositions accidentelles et des isolements accidentels.
  3. L’instance possède une adresse IPv4 publique — attribuée automatiquement au lancement (attribut MapPublicIpOnLaunch du sous-réseau) ou via une Elastic IP. L’IGW fait une traduction un-pour-un entre l’IP publique et l’IP privée de l’instance; sans IP publique, il n’y a rien à traduire et le trafic entrant n’a aucune adresse à joindre.

Un sous-réseau privé, c’est simplement un sous-réseau dont la table de routage n’a pas de route vers l’IGW. S’il a besoin d’une sortie Internet, sa route par défaut pointe plutôt vers une passerelle NAT située dans un sous-réseau public — les compromis de cette pièce sont couverts dans NAT Gateway vs instance NAT. Les groupes de sécurité et les NACL filtrent ensuite ce que le routage a permis; ils ne rendent jamais un sous-réseau public ou privé à eux seuls.

Quoi vérifier en premier

  • Quelle table de routage le sous-réseau utilise-t-il vraiment? Association explicite ou retombée sur la table principale — la console le montre dans l’onglet Route table du sous-réseau.
  • Cette table a-t-elle 0.0.0.0/0 vers un igw-? Pas vers un nat-, pas en trou noir.
  • L’instance a-t-elle une IP publique en ce moment? Arrêter puis redémarrer une instance libère l’IP publique auto-attribuée (les Elastic IP persistent).
  • MapPublicIpOnLaunch est-il réglé comme vous le pensez? Sans lui, les nouvelles instances d’un sous-réseau « public » démarrent injoignables, sans avertissement.
  • La table principale porte-t-elle une route IGW? Si oui, chaque sous-réseau jamais associé explicitement est routable depuis Internet — en général, c’est une surprise.

Comment vérifier

Chemin console : VPC > Subnets > sélectionner le sous-réseau > Route table, puis VPC > Route tables > Routes. En ligne de commande :

# Quelle table de routage sert ce sous-réseau (retombe sur la principale si vide)
aws ec2 describe-route-tables \
  --filters "Name=association.subnet-id,Values=subnet-0abc123" \
  --query 'RouteTables[].Routes[]'

# La table principale du VPC — ce dont héritent les sous-réseaux non associés
aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=vpc-0abc123" "Name=association.main,Values=true" \
  --query 'RouteTables[].Routes[]'

# Le sous-réseau distribue-t-il des IP publiques au lancement?
aws ec2 describe-subnets --subnet-ids subnet-0abc123 \
  --query 'Subnets[].MapPublicIpOnLaunch'

# Y a-t-il seulement une IGW attachée au VPC?
aws ec2 describe-internet-gateways \
  --filters "Name=attachment.vpc-id,Values=vpc-0abc123"

Une instance dans un sous-réseau réellement public montre une entrée GatewayId: igw-... pour 0.0.0.0/0 et une PublicIpAddress dans describe-instances. La référence complète des attributs se trouve dans la documentation Amazon VPC.

Le runbook

  1. Décidez d’abord du rôle du sous-réseau, puis faites correspondre le routage. Répartiteurs de charge, passerelles NAT et hôtes bastions vont dans les sous-réseaux publics; serveurs applicatifs et bases de données dans les privés. Pour un nouveau VPC, suivez un plan par zone de disponibilité comme celui de conception de sous-réseaux multi-AZ plutôt que d’improviser.
  2. Créez des tables de routage explicites pour chaque palier. Une table « publique » avec la route IGW, une table « privée » par AZ pointant vers la passerelle NAT de cette AZ. Associez chaque sous-réseau explicitement et laissez la table principale avec la seule route locale, pour qu’un sous-réseau non associé soit isolé par défaut plutôt qu’exposé.
  3. Réglez MapPublicIpOnLaunch délibérément. Activez-le sur les sous-réseaux publics où les instances doivent être joignables dès le lancement (aws ec2 modify-subnet-attribute --subnet-id subnet-0abc123 --map-public-ip-on-launch); laissez-le désactivé partout ailleurs et utilisez des Elastic IP pour tout ce qui doit garder une adresse stable.
  4. Pour rendre privé un sous-réseau public, procédez dans l’ordre. Déplacez ou recréez les charges qui ont besoin d’être jointes de l’extérieur, basculez l’association vers la table privée, puis retirez les IP publiques. Changer la route sous une instance en service coupe immédiatement ses sessions Internet établies.
  5. Confirmez avec un vrai paquet. Depuis une instance du sous-réseau, curl -m 5 https://checkip.amazonaws.com — via une IGW, la réponse est l’IP publique de l’instance elle-même; via NAT, c’est l’EIP de la passerelle NAT. Cette seule commande vous dit quel chemin vous empruntez réellement.

Quand c’est la mauvaise approche

Rendre un sous-réseau public parce que « l’application a besoin d’Internet » est l’erreur classique — les charges qui ne font que sortir vont dans des sous-réseaux privés derrière une NAT ou, pour le trafic vers les services AWS, derrière des points de terminaison VPC. À l’inverse, tout forcer en privé est une erreur quand le rôle du composant est justement d’accepter du trafic Internet; un ALB face à Internet dans un sous-réseau privé ne fonctionne tout simplement pas. Et si votre vrai problème est une instance injoignable, vérifiez les groupes de sécurité avant de toucher au routage — une route correcte avec un groupe de sécurité fermé donne exactement le même symptôme vu de l’extérieur.

Erreurs fréquentes

  • Se fier au nom du sous-réseau (« public-a ») au lieu de lire la table de routage.
  • Laisser la route IGW sur la table principale, ce qui rend silencieusement routable chaque futur sous-réseau.
  • Croire qu’une IP publique survit à un arrêt/redémarrage — les adresses auto-attribuées non; seules les Elastic IP persistent.
  • Placer une passerelle NAT dans un sous-réseau privé — elle a elle-même besoin d’une route IGW, donc elle doit vivre dans un sous-réseau public.

Prévention

  • Gardez la table principale vide de tout sauf la route locale; associez tous les sous-réseaux explicitement.
  • Étiquetez tables de routage et sous-réseaux avec leur palier (public, private-app, private-data) et vérifiez chaque trimestre que les étiquettes correspondent aux routes.
  • Imposez la structure via Terraform ou CloudFormation pour qu’une nouvelle AZ ou un nouveau sous-réseau hérite des bonnes associations au lieu d’un montage manuel.
  • Alertez sur toute nouvelle route 0.0.0.0/0 -> igw via AWS Config ou CloudTrail — ce changement devrait être rare et délibéré.

La distinction public/privé tient à une seule entrée de routage, et c’est exactement pourquoi elle mérite un audit explicite plutôt qu’une confiance aveugle dans les conventions de nommage. Si personne dans votre équipe ne possède vraiment l’environnement AWS de bout en bout, c’est la racine de la plupart de ces problèmes — Stack Harbor opère des comptes AWS au quotidien sous Opérations AWS, et vous pouvez réserver une revue AWS.