Aller au contenu

Les adresses IPv4

100 Comprendre ⏱ 55 min reseaulinuxipv4

À la fin, vous saurez

  • Citer les champs principaux de l'en-tête IPv4 et leur rôle
  • Convertir une adresse IPv4 entre notation décimale pointée et binaire
  • Calculer, à partir d'une adresse et d'un préfixe, l'adresse du réseau, la diffusion et le nombre d'hôtes
  • Expliquer pourquoi les classes A, B et C ont disparu au profit de CIDR
  • Reconnaître les adresses spéciales : boucle locale, lien local, privées, partagées, documentation, multidiffusion
  • Lire la sortie de ip addr et choisir l'adresse d'écoute d'un service

Prérequis

Testé avec curl 8.5.0 iproute2 6.1.0 noyau 7.0 (HWE) python 3.12.3 ubuntu 24.04 , vérifié le 5 octobre 2026

Pourquoi

Dans la configuration de Signalements, Camille tombe sur trois lignes qui se ressemblent et ne disent pas du tout la même chose :

gunicorn --bind 127.0.0.1:8000 ...
gunicorn --bind 0.0.0.0:8000 ...
gunicorn --bind 172.16.20.11:8000 ...

La première rend l'API injoignable depuis toute autre machine. La deuxième l'expose sur toutes les interfaces, y compris, sur une machine qui en a une, l'interface publique. La troisième ne l'expose que sur le réseau privé. Une erreur entre ces trois lignes, et l'on obtient soit un service mystérieusement injoignable, soit une API ouverte à Internet sans le savoir.

Ailleurs, un collègue propose de créer le réseau privé de la préproduction en 172.16.22.0/24 « pour ne pas gêner la production en 172.16.20.0/22 ». Il ne voit pas que la seconde plage contient déjà la première. Et dans un ticket, un client signale que son serveur a l'adresse 169.254.12.7 et « ne marche pas » : cette adresse dit, à elle seule, ce qui ne va pas.

Toutes ces situations se lisent en quelques secondes quand on sait lire une adresse IPv4. Cette leçon apprend à le faire, à la main et avec des outils.

Les concepts

Le paquet IPv4

La leçon 1 a placé IP au centre du sablier : c'est le seul protocole que tous les équipements d'Internet comprennent. Son en-tête, défini par la RFC 791 de septembre 1981, fait 20 octets sans options :

ChampTailleRôle
Version4 bits4 pour IPv4
IHL4 bitslongueur de l'en-tête, en mots de 32 bits (5 sans options, soit 20 octets)
DSCP et ECN8 bitsà l'origine Type of Service ; aujourd'hui classe de service (DSCP) et signalement de congestion (ECN)
Longueur totale16 bitstaille du paquet, en-tête compris : 65 535 octets au plus
Identification, drapeaux, décalage32 bitsfragmentation d'un paquet trop grand (leçon 6)
TTL (Time to Live)8 bitsdécrémenté par chaque routeur ; à zéro, le paquet est détruit (leçon 6)
Protocole8 bitsce que transporte le paquet : 6 TCP, 17 UDP, 1 ICMP
Somme de contrôle de l'en-tête16 bitsvérifiée et recalculée à chaque routeur
Adresse source32 bitsqui envoie
Adresse destination32 bitsà qui

Deux champs nous occupent dans cette leçon : les adresses, sur 32 bits chacune. Le TTL vaut 64 au départ sur Linux (/proc/sys/net/ipv4/ip_default_ttl) ; nous le retrouverons avec traceroute.

Une adresse, c'est un nombre de 32 bits

Une adresse IPv4 est un nombre entier entre 0 et 4 294 967 295 (2³² − 1). Pour le lire, on le découpe en quatre octets, chacun écrit en décimal de 0 à 255, séparés par des points : c'est la notation décimale pointée. L'adresse de sig-app-1, 172.16.20.11, est en réalité :

     172       16       20       11
10101100 00010000 00010100 00001011

La conversion d'un octet se fait avec les puissances de 2 : 172 = 128 + 32 + 8 + 4, donc les bits de poids 128, 32, 8 et 4 sont à 1 : 1010 1100. Avec un peu de pratique, les valeurs utiles se reconnaissent d'elles-mêmes : 128 = 1000 0000, 192 = 1100 0000, 224 = 1110 0000, 240 = 1111 0000, 248, 252, 254, 255 = 1111 1111.

Réseau et hôte : le préfixe

Une adresse IP ne désigne pas seulement une machine : elle dit aussi dans quel réseau elle se trouve. Les premiers bits de l'adresse identifient le réseau, les suivants identifient la machine (l'hôte) dans ce réseau. La frontière entre les deux s'appelle le préfixe, et on l'écrit après une barre oblique : 172.16.20.11/22 signifie « les 22 premiers bits désignent le réseau, les 10 derniers l'hôte ».

La même information s'écrit aussi sous la forme d'un masque de sous-réseau : un nombre de 32 bits dont les bits du réseau sont à 1 et ceux de l'hôte à 0. Pour /22 :

11111111 11111111 11111100 00000000   =   255.255.252.0

Le masque et le préfixe sont deux écritures de la même chose. On rencontre encore beaucoup de masques dans les vieux fichiers de configuration et les interfaces graphiques ; les outils modernes (ip, les fournisseurs de cloud) parlent en préfixes.

À partir d'une adresse et de son préfixe, on calcule trois choses :

  1. L'adresse du réseau : l'adresse avec tous les bits d'hôte à 0. C'est un ET logique entre l'adresse et le masque.
  2. L'adresse de diffusion du réseau : tous les bits d'hôte à 1.
  3. Le nombre d'adresses utilisables pour des hôtes : 2 puissance (nombre de bits d'hôte), moins 2, puisque l'adresse du réseau et celle de diffusion sont réservées.

Pour 172.16.20.11/22 :

adresse    10101100.00010000.000101|00.00001011   172.16.20.11
masque     11111111.11111111.111111|00.00000000   255.255.252.0
réseau     10101100.00010000.000101|00.00000000   172.16.20.0
diffusion  10101100.00010000.000101|11.11111111   172.16.23.255

Le réseau va donc de 172.16.20.0 à 172.16.23.255 : 2¹⁰ = 1 024 adresses, dont 1 022 utilisables. C'est le réseau privé pn-signalements du cours cloud. On remarque que la frontière tombe au milieu du troisième octet : c'est ce qui rend les préfixes qui ne sont pas des multiples de 8 un peu plus délicats à calculer de tête. Une astuce : pour /22, le troisième octet avance par pas de 2¹⁰⁻⁸ = 4 (20, 24, 28...), donc le réseau qui contient .20.x commence à .20.0 et finit à .23.255.

La fin des classes : CIDR

Pendant les douze premières années d'IPv4, il n'y avait pas de préfixe écrit : la taille du réseau se déduisait des premiers bits de l'adresse. La RFC 791 définissait trois classes :

ClassePremiers bitsPlagePréfixe impliciteHôtes par réseau
A00.0.0.0 à 127.255.255.255/816 777 214
B10128.0.0.0 à 191.255.255.255/1665 534
C110192.0.0.0 à 223.255.255.255/24254

L'idée était simple, et les routeurs pouvaient connaître la taille d'un réseau sans configuration. Elle s'est révélée désastreuse au début des années 1990. La RFC 4632 le résume : la classe C, avec 254 hôtes, est trop petite pour la plupart des organisations, et la classe B, avec 65 534, beaucoup trop grande. Tout le monde demandait des classes B, qui s'épuisaient, et la moitié de leurs adresses dormaient. Dans le même temps, chaque réseau de classe C attribué ajoutait une ligne aux tables de routage d'Internet, qui grossissaient plus vite que la mémoire des routeurs.

La réponse fut CIDR (Classless Inter-Domain Routing), en 1993 (RFC 1519, remplacée par la RFC 4632 en 2006) : le préfixe devient explicite et peut avoir n'importe quelle longueur. On attribue un /22 à qui a besoin de mille adresses, et un fournisseur d'accès peut annoncer à Internet un seul /16 pour tous ses clients, au lieu de 256 lignes de classe C. C'est l'agrégation des routes.

Les classes n'existent plus que dans le vocabulaire (« une classe C » pour dire « un /24 ») et dans quelques réflexes anciens. Une adresse en 10. n'est pas « forcément en /8 », une adresse en 192.168. n'est pas « forcément en /24 » : seul le préfixe configuré fait foi.

Les adresses spéciales

Toutes les adresses ne sont pas utilisables partout. L'IANA tient le registre des adresses à usage particulier, établi par la RFC 6890. Les plages à connaître :

PlageNomUsage
0.0.0.0/8« cet hôte sur ce réseau »0.0.0.0 comme adresse source d'une machine qui n'a pas encore d'adresse (DHCP), et comme adresse d'écoute « toutes les adresses »
10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16privées (RFC 1918)réseaux internes, jamais routées sur Internet (leçon 7)
100.64.0.0/10espace partagé (RFC 6598)réseaux internes des opérateurs qui font du NAT à grande échelle (leçon 7)
127.0.0.0/8boucle locale (loopback)la machine elle-même, toute la plage
169.254.0.0/16lien local (RFC 3927)adresses auto-attribuées sans serveur DHCP ; services de métadonnées des fournisseurs de cloud
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24documentation (RFC 5737)exemples dans les livres et les cours, comme celui-ci
198.18.0.0/15tests de performancebancs d'essai d'équipements réseau
224.0.0.0/4multidiffusionun paquet pour un groupe d'abonnés (ex. 224.0.0.251 pour mDNS)
240.0.0.0/4réservéjamais attribué
255.255.255.255/32diffusion limitéetout le réseau local, sans passer un routeur

Quelques remarques :

  • La boucle locale est un /8 entier : 127.0.0.2 ou 127.5.5.5 désignent aussi la machine elle-même sous Linux. Seule 127.0.0.1 est configurée sur l'interface lo, mais le noyau traite toute la plage comme locale (nous le vérifierons).
  • Les adresses de lien local en 169.254. ont deux visages. Sur un poste ou un serveur, une adresse de ce type attribuée automatiquement signifie presque toujours que le DHCP a échoué : la machine s'est donné une adresse au hasard pour pouvoir au moins parler à ses voisins immédiats. C'est le cas du ticket de l'introduction. Dans le cloud, en revanche, la plage sert volontairement aux services de métadonnées : 169.254.169.254 chez la plupart des fournisseurs, 169.254.42.42 chez Scaleway, comme l'a montré le cours Le cloud : les fondamentaux. Ces adresses ne sont jamais routées au-delà du lien, ce qui garantit que seule l'instance elle-même atteint son service de métadonnées.
  • Les plages de documentation existent pour que les exemples ne visent jamais une machine réelle. Ce cours les utilise systématiquement : 203.0.113.10 est l'adresse du répartiteur de Signalements dans nos exemples, et n'appartient à personne.

L'épuisement des adresses

Quatre milliards d'adresses semblaient beaucoup en 1981. En retirant les plages spéciales, il en reste environ 3,7 milliards pour Internet, soit moins d'une par habitant de la planète, et bien moins d'une par appareil connecté. Le stock s'est épuisé par étapes :

  • Le 3 février 2011, l'IANA a distribué ses cinq derniers blocs /8 libres, un à chacun des cinq registres régionaux (RIR) qui attribuent les adresses dans le monde.
  • Le 25 novembre 2019, le RIPE NCC, registre de l'Europe, du Moyen-Orient et d'une partie de l'Asie centrale, a fait sa dernière attribution d'un bloc /22. Depuis, il ne distribue plus que des adresses récupérées, par blocs de /24, à de nouveaux membres inscrits sur une liste d'attente.

Les conséquences sont tangibles : une adresse IPv4 publique se paie (les fournisseurs de cloud la facturent à part, comme l'a montré la leçon 8 du cours cloud), elle s'achète et se revend sur un marché, et l'on économise les adresses par la traduction d'adresses (leçon 7). La solution de long terme est IPv6, avec ses adresses de 128 bits (leçon 8).

En pratique

Les sorties ont été produites sur le poste Ubuntu 24.04 de Camille, avec LC_ALL=C.UTF-8 ; les adresses de son réseau ont été remplacées par des adresses de l'exemple.

Lire ip addr

$ ip -4 addr show wlo1
2: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    altname wlp0s20f3
    inet 192.168.1.23/24 brd 192.168.1.255 scope global dynamic noprefixroute wlo1
       valid_lft 4854sec preferred_lft 4854sec

-4 limite l'affichage aux adresses IPv4. La ligne qui commence par inet se lit ainsi, d'après ip-address(8) :

  • 192.168.1.23/24 : l'adresse et son préfixe. Le poste est dans le réseau 192.168.1.0/24, celui de la box.
  • brd 192.168.1.255 : l'adresse de diffusion du réseau, calculée à partir du préfixe.
  • scope global : l'adresse est valable au-delà de la machine. scope host désigne une adresse utilisable seulement sur la machine (la boucle locale) ; scope link, une adresse valable sur le lien seulement (lien local).
  • dynamic : l'adresse a été obtenue par DHCP et a une durée de vie ; valid_lft (valid lifetime) dit combien de secondes il reste avant l'expiration du bail, que le client DHCP renouvellera avant.
  • noprefixroute : le noyau n'a pas ajouté lui-même la route vers le réseau 192.168.1.0/24 ; c'est NetworkManager, le gestionnaire réseau du poste de travail, qui s'en charge avec sa propre priorité. Sur un serveur configuré par netplan et systemd-networkd, cette mention est en général absente.

L'interface de boucle locale, elle, a une adresse fixe :

$ ip -4 addr show lo
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

Une interface peut porter plusieurs adresses : il suffit d'en ajouter (sudo ip addr add 172.16.20.50/22 dev ens2, sur une machine de laboratoire). Chacune apparaît sur sa propre ligne inet. C'est ainsi qu'une machine porte une adresse de service en plus de sa propre adresse. Une adresse ajoutée par ip addr add disparaît au redémarrage : la configuration permanente passe par netplan sur Ubuntu Server, ou par le fournisseur de cloud via DHCP.

Calculer avec Python

Le module ipaddress de la bibliothèque standard de Python fait tous les calculs de cette leçon, sans rien installer :

$ python3 -c 'import ipaddress as i; n=i.ip_network("172.16.20.0/22"); print(n.netmask, n.network_address, n.broadcast_address, n.num_addresses)'
255.255.252.0 172.16.20.0 172.16.23.255 1024
$ python3 -c 'import ipaddress as i; a=i.ip_interface("172.16.20.11/22"); print(a.ip, a.network, a.netmask)'
172.16.20.11 172.16.20.0/22 255.255.252.0

ip_network désigne un réseau, ip_interface une adresse avec son préfixe, comme on la configure sur une interface. Si vous passez une adresse d'hôte à ip_network, Python refuse, et l'erreur est instructive :

$ python3 -c 'import ipaddress as i; i.ip_network("172.16.20.11/22")' 2>&1 | tail -1
ValueError: 172.16.20.11/22 has host bits set
$ python3 -c 'import ipaddress as i; print(i.ip_network("172.16.20.11/22", strict=False))'
172.16.20.0/22

Le message dit exactement ce qui ne va pas : un réseau s'écrit avec ses bits d'hôte à zéro. Pour voir les bits :

$ python3 -c 'import ipaddress as i; print(".".join(f"{o:08b}" for o in i.ip_address("172.16.20.11").packed)); print(".".join(f"{o:08b}" for o in i.ip_network("172.16.20.0/22").netmask.packed))'
10101100.00010000.00010100.00001011
11111111.11111111.11111100.00000000

Et pour tester l'appartenance d'une adresse à un réseau, la question du collègue de l'introduction :

$ python3 -c 'import ipaddress as i; print(i.ip_address("172.16.24.1") in i.ip_network("172.16.20.0/22"), i.ip_address("172.16.23.200") in i.ip_network("172.16.20.0/22"))'
False True

172.16.23.200 est dans le réseau de production, 172.16.24.1 n'y est pas. Le réseau 172.16.22.0/24 proposé pour la préproduction est donc inclus dans celui de la production : c'est un chevauchement, qui empêchera de relier un jour les deux réseaux. La méthode overlaps() le dit directement (exercice 3).

Note

Certaines distributions fournissent aussi la commande ipcalc (paquet ipcalc sur Debian et Ubuntu), qui affiche ces informations en couleur. Elle n'est pas installée par défaut ; le module Python, si.

Que veut dire « privé » ?

Le même module classe les adresses selon le registre de l'IANA :

$ python3 -c 'import ipaddress as i; print(i.ip_address("100.64.0.1").is_private, i.ip_address("100.64.0.1").is_global, i.ip_address("203.0.113.10").is_private)'
False False True

Deux surprises. Une adresse de documentation comme 203.0.113.10 est considérée comme « privée » : pour Python, is_private veut dire « non joignable globalement selon le registre », et pas « dans les plages de la RFC 1918 ». Et l'espace partagé 100.64.0.0/10 n'est ni privé ni global : la documentation de Python le traite explicitement comme une exception. Si vous écrivez un contrôle de sécurité (« refuser les adresses internes »), lisez la documentation de la fonction que vous utilisez : le mot « privé » n'a pas le même sens partout.

Écouter sur 127.0.0.1 ou sur 0.0.0.0

Revenons aux trois lignes de Gunicorn de l'introduction, et vérifions le comportement avec le petit serveur HTTP de Python, sur un port de test :

$ python3 -m http.server 8123 --bind 127.0.0.1 &
$ ss -ltn 'sport = :8123'
State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0      5          127.0.0.1:8123      0.0.0.0:*
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8123/
200
$ curl -sS http://127.0.0.2:8123/
curl: (7) Failed to connect to 127.0.0.2 port 8123 after 0 ms: Couldn't connect to server

Le serveur écoute sur 127.0.0.1 seulement : même une autre adresse de la boucle locale, 127.0.0.2, est refusée. A fortiori, une autre machine ne peut pas le joindre. Arrêtez-le (kill %1) et relancez-le sur 0.0.0.0 :

$ python3 -m http.server 8123 --bind 0.0.0.0 &
$ ss -ltn 'sport = :8123'
State  Recv-Q Send-Q Local Address:Port Peer Address:PortProcess
LISTEN 0      5            0.0.0.0:8123      0.0.0.0:*
$ curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.2:8123/
200

0.0.0.0 comme adresse d'écoute signifie « toutes les adresses IPv4 de la machine », présentes et futures : la boucle locale, l'adresse du réseau privé, et l'adresse publique s'il y en a une. C'est une adresse joker, pas une adresse de destination. La bonne pratique sur un serveur est donc l'adresse la plus étroite qui rende le service : 127.0.0.1 si seul un proxy local doit le joindre, l'adresse privée si un répartiteur de charge passe par le réseau privé, et 0.0.0.0 seulement quand un pare-feu en amont contrôle effectivement l'exposition.

Arrêtez le serveur avant de passer à la suite (kill %1).

La boucle locale est un /8

Le noyau considère bien toute la plage 127.0.0.0/8 comme locale, ce que montre la table de routage local, que le noyau gère lui-même :

$ ip route get 127.5.5.5
local 127.5.5.5 dev lo src 127.0.0.1 uid 1000
    cache <local>
$ ip route show table local | grep -E "^(local|broadcast) 127"
local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1

ip route get demande au noyau quelle route il emprunterait pour une adresse, sans rien envoyer ; nous nous en servirons beaucoup à la leçon 5.

Sous le capot

Un ET logique par paquet. Pour décider si une destination est sur son réseau local, une machine fait, pour chaque route, un ET bit à bit entre l'adresse de destination et le masque de la route, et compare le résultat à l'adresse du réseau. C'est une opération que les processeurs exécutent en un cycle, et que les routeurs matériels implémentent dans des mémoires spécialisées. CIDR a rendu la recherche un peu plus subtile, puisque plusieurs routes de longueurs différentes peuvent correspondre : on garde la plus longue, ce qui est l'objet de la leçon 5.

L'adresse appartient à la machine, pas à l'interface. Sous Linux, une adresse IP est configurée sur une interface, mais le noyau, par défaut, répond à une requête qui vise n'importe laquelle de ses adresses, quelle que soit l'interface par laquelle elle arrive (ce que la littérature appelle le modèle d'hôte « faible »). C'est un comportement à connaître : une machine avec une interface publique et une interface privée peut accepter, sur l'interface publique, un paquet destiné à son adresse privée, si un routeur le lui envoie. Les pare-feu et certains réglages du noyau (rp_filter, arp_ignore) servent à resserrer ce comportement.

Pourquoi 0.0.0.0 « écoute partout ». Lors de bind(2), l'adresse INADDR_ANY (qui vaut 0.0.0.0) dit au noyau de ne pas filtrer sur l'adresse de destination : toute connexion qui arrive sur le bon port, quelle que soit l'adresse locale visée, est remise à cette socket. Une socket liée à une adresse précise ne reçoit que les connexions qui visent cette adresse. C'est ce que décrit ip(7).

Pièges courants

Confondre adresse de réseau et adresse d'hôte. 172.16.20.0/22 est un réseau ; 172.16.20.11/22 est une adresse dans ce réseau. Beaucoup d'outils (Python, Terraform, les API des fournisseurs) refusent l'une à la place de l'autre, avec un message comme has host bits set.

Supposer le préfixe d'après la classe. Une adresse en 10. n'est pas en /8, une adresse en 192.168. n'est pas en /24 : seul le préfixe configuré compte. Un ancien script qui « devine » le masque produira une mauvaise adresse de diffusion et une mauvaise route.

Des plages qui se chevauchent. Les réseaux d'un même ensemble (production, préproduction, réseau de l'entreprise relié par VPN, réseaux des conteneurs Docker) doivent être disjoints, sinon on ne pourra jamais les relier. Docker, par exemple, prend par défaut des plages dans 172.17.0.0/16 et au-delà pour ses réseaux : une machine dont le réseau d'entreprise est en 172.18.0.0/16 aura des surprises. Tenez un registre des plages utilisées.

Exposer un service par 0.0.0.0 sans le savoir. Beaucoup de serveurs de développement, de bases de données et d'images de conteneurs écoutent par défaut sur toutes les adresses. Vérifiez toujours avec ss -ltn ce qui écoute réellement, et où.

Ignorer une adresse en 169.254.. Sur un serveur ou un poste, elle signale un échec DHCP ; ce n'est pas une adresse avec laquelle on peut travailler.

Utiliser des adresses publiques réelles dans des exemples ou des tests. Une adresse inventée « au hasard » appartient presque toujours à quelqu'un. Dans la documentation, les tests et les fichiers d'exemple, utilisez les plages de la RFC 5737.

Sécurité

  • L'adresse d'écoute est la première ligne de défense. Un service lié à 127.0.0.1 est inaccessible depuis le réseau, quel que soit l'état du pare-feu. Un service lié à 0.0.0.0 ne doit sa protection qu'au pare-feu et au groupe de sécurité : la moindre erreur de configuration l'expose. Des milliers de bases de données se retrouvent chaque année ouvertes sur Internet de cette façon.
  • Une adresse source ne prouve rien. N'importe qui peut écrire n'importe quelle adresse source dans un paquet. Les opérateurs bien tenus filtrent en sortie les adresses qui ne leur appartiennent pas (BCP 38), mais pas tous. Une liste blanche d'adresses IP est une mesure utile, jamais une authentification.
  • Les adresses de métadonnées sont sensibles. Une application qui va chercher des URL fournies par l'utilisateur (aperçu de lien, import d'image) peut être détournée vers 169.254.169.254 ou 169.254.42.42 pour lire les métadonnées de l'instance : c'est l'attaque SSRF vue dans le cours cloud. Une liste de refus doit couvrir la boucle locale, le lien local, les plages privées et partagées, et vérifier l'adresse après résolution DNS.
  • « Privé » n'est pas « sûr ». Les plages privées ne sont pas routées sur Internet, mais une machine compromise du même réseau privé, un VPN mal configuré ou une redirection de port les atteint. On authentifie et on chiffre aussi à l'intérieur.

En production

  • Planifiez l'adressage avant de créer les réseaux. Une plage par environnement et par région, sans chevauchement avec le réseau de l'entreprise ni avec les plages par défaut des outils (Docker, Kubernetes). La leçon 4 donne la méthode. Changer de plage après coup oblige à tout reconstruire.
  • Les adresses publiques sont rares et facturées. On les réserve aux points d'entrée (répartiteurs de charge, passerelles), comme dans l'architecture de Signalements du cours cloud, où les instances n'ont plus d'adresse publique.
  • Fixez les adresses des services, pas des machines. Une machine remplacée change souvent d'adresse ; un nom DNS, une IP flexible ou une adresse de répartiteur restent stables. Les adresses IP en dur dans une configuration applicative sont une dette.
  • Chez Lyneko, le réseau privé des applications et les plages des clusters Kubernetes sont choisis pour ne jamais chevaucher les réseaux des clients reliés par VPN : c'est la première question posée avant de créer un environnement.

Exercices

1. Convertir (niveau 100). Écrivez en binaire 192.168.1.23 et 255.255.255.192. Quel préfixe correspond à ce masque ?

Solution

192.168.1.23 = 11000000.10101000.00000001.00010111 (192 = 128 + 64, 168 = 128 + 32 + 8, 23 = 16 + 4 + 2 + 1). 255.255.255.192 = 11111111.11111111.11111111.11000000 : 26 bits à 1, donc /26. Vérification : python3 -c 'import ipaddress as i; print(i.ip_network("0.0.0.0/255.255.255.192").prefixlen)'.

2. Calculer un réseau (niveau 100). Pour l'adresse 10.42.37.200/20, donnez l'adresse du réseau, l'adresse de diffusion, la première et la dernière adresse d'hôte, et le nombre d'hôtes.

Solution

/20 : 12 bits d'hôte, la frontière est dans le troisième octet, qui avance par pas de 2⁴ = 16 (0, 16, 32, 48...). 37 est entre 32 et 47. Réseau : 10.42.32.0/20 ; diffusion : 10.42.47.255 ; premier hôte 10.42.32.1, dernier 10.42.47.254 ; 2¹² − 2 = 4 094 hôtes. Vérification avec ipaddress.ip_interface("10.42.37.200/20").network puis .broadcast_address et .num_addresses.

3. Le chevauchement (niveau 100). La production utilise 172.16.20.0/22. Parmi 172.16.22.0/24, 172.16.24.0/22 et 172.16.16.0/21, lesquels peuvent servir à la préproduction ? Vérifiez avec la méthode overlaps() de ipaddress.

Solution

172.16.22.0/24 est inclus dans 172.16.20.0/22 (qui va de .20.0 à .23.255) : refusé. 172.16.24.0/22 va de .24.0 à .27.255 : disjoint, accepté. 172.16.16.0/21 va de .16.0 à .23.255 : il contient la production, refusé. Vérification : python3 -c 'import ipaddress as i; p=i.ip_network("172.16.20.0/22"); [print(r, p.overlaps(i.ip_network(r))) for r in ["172.16.22.0/24","172.16.24.0/22","172.16.16.0/21"]]' affiche True, False, True.

4. Lire des adresses (niveau 100). Que vous apprend chacune de ces adresses vues sur un serveur ou dans un journal ? (a) 169.254.12.7/16 sur l'interface principale d'un serveur ; (b) une connexion entrante depuis 100.72.4.9 ; (c) Gunicorn lancé avec --bind 0.0.0.0:8000 sur une instance qui a une adresse publique ; (d) une requête d'une application vers 169.254.42.42.

Solution

(a) Adresse de lien local auto-attribuée : le serveur n'a pas obtenu de bail DHCP. On regarde le client DHCP, le lien, le serveur DHCP. (b) Une adresse de l'espace partagé 100.64.0.0/10 : la connexion vient de derrière le NAT d'un opérateur (CGNAT, leçon 7), ou d'un réseau interne qui utilise cette plage. (c) L'API écoute sur toutes les adresses, y compris l'adresse publique : seule la configuration du pare-feu ou du groupe de sécurité la protège ; mieux vaut lier Gunicorn à l'adresse privée ou à 127.0.0.1. (d) Le service de métadonnées de Scaleway : légitime pour cloud-init ou un agent, suspect s'il s'agit d'une application web qui suit des URL fournies par l'utilisateur (SSRF).

Récapitulatif

  • L'en-tête IPv4 (RFC 791) fait 20 octets sans options : version, longueur, TTL, protocole, somme de contrôle, et surtout les adresses source et destination de 32 bits.
  • Une adresse IPv4 est un nombre de 32 bits écrit en quatre octets décimaux ; le préfixe (/22) ou le masque (255.255.252.0) sépare la partie réseau de la partie hôte.
  • Adresse du réseau : bits d'hôte à 0 ; diffusion : bits d'hôte à 1 ; hôtes : 2^(bits d'hôte) − 2.
  • Les classes A, B, C ont été abandonnées en 1993 au profit de CIDR : préfixe explicite de longueur quelconque, et agrégation des routes.
  • Plages à reconnaître : privées (10/8, 172.16/12, 192.168/16), partagée (100.64/10), boucle locale (127/8), lien local (169.254/16, échec DHCP ou métadonnées), documentation (192.0.2/24, 198.51.100/24, 203.0.113/24).
  • Le stock IPv4 est épuisé (IANA en 2011, RIPE NCC en 2019) : les adresses publiques se paient et s'économisent.
  • Écouter sur 127.0.0.1 : la machine seule ; sur une adresse précise : cette interface ; sur 0.0.0.0 : toutes les adresses, publique comprise. Choisissez la plus étroite.
  • ip addr montre adresses, préfixes, portée et bail ; le module Python ipaddress fait tous les calculs.

Pour aller plus loin

  • Le registre IANA des adresses IPv4 à usage particulier, qui fait autorité sur les plages spéciales.
  • La RFC 4632, section 3, pour l'histoire et la mécanique de CIDR et de l'agrégation.
  • La documentation du module ipaddress de Python, pour les calculs dans vos scripts.
  • La leçon suivante, qui découpe une plage en sous-réseaux et construit le plan d'adressage de Signalements.
Voir ma constellation →

Sources