R04 - Sous-réseaux (FLSM) et VLSM

Objectif

Découper un réseau en plusieurs sous-réseaux à la main, en taille égale (FLSM) ou sur mesure (VLSM), puis vérifier avec le script. Ton cours original détaillé : cours-vlsm.


1. Pourquoi découper ?

Problème d’un grand réseau « à plat »Solution apportée par le découpage
Tout le monde voit tout le monde (compta ↔ Wi-Fi invité)Isolation : on filtre entre sous-réseaux
Chaque broadcast dérange toutes les machinesDomaines de broadcast plus petits
Impossible d’appliquer des règles par serviceUne règle de pare-feu par sous-réseau
Gaspillage d’adressesVLSM : chaque service a juste ce qu’il faut

2. Le principe : emprunter des bits

On décale la frontière du masque vers la droite : chaque bit emprunté à la partie hôte double le nombre de sous-réseaux et divise par 2 leur taille.

flowchart LR
  A["/24<br/>1 réseau<br/>254 hôtes"] -->|"+1 bit"| B["/25<br/>2 réseaux<br/>126 hôtes"]
  B -->|"+1 bit"| C["/26<br/>4 réseaux<br/>62 hôtes"]
  C -->|"+1 bit"| D["/27<br/>8 réseaux<br/>30 hôtes"]
  D -->|"+1 bit"| E["/28<br/>16 réseaux<br/>14 hôtes"]
FormuleSignification
Sous-réseaux = 2^nn = bits empruntés
Hôtes = 2^h − 2h = bits hôte restants
Nombre magique = 256 − octet du masque= pas entre deux sous-réseaux

3. FLSM : parts égales (méthode en 5 étapes)

Énoncé : découper 192.168.1.0/24 en 4 sous-réseaux égaux.

  1. Besoin : 4 sous-réseaux → 2² = 4 → 2 bits empruntés.
  2. Nouveau masque : /24 + 2 = /26 = 255.255.255.192.
  3. Nombre magique : 256 − 192 = 64.
  4. Réseaux : .0, .64, .128, .192.
  5. Plages :
#Réseau1re IPDernière IPBroadcast
1192.168.1.0/26.1.62.63
2192.168.1.64/26.65.126.127
3192.168.1.128/26.129.190.191
4192.168.1.192/26.193.254.255

4. VLSM : parts sur mesure

Règle d'or

On traite les besoins du plus GROS au plus PETIT. Chaque bloc doit commencer sur un multiple de sa taille - sinon les gros blocs ne rentrent plus.

Méthode

flowchart TD
  A[Lister les besoins en hôtes] --> B[Trier du plus grand au plus petit]
  B --> C["Pour chaque besoin : plus petit h<br/>tel que 2^h − 2 ≥ besoin"]
  C --> D["Masque = /(32 − h), taille du bloc = 2^h"]
  D --> E["Placer le bloc à la 1re adresse libre"]
  E --> F["Adresse libre suivante = broadcast + 1"]
  F --> G{Encore un besoin ?}
  G -- oui --> C
  G -- non --> H[Vérifier : pas de chevauchement,<br/>tout est dans le réseau de départ]

Exemple complet

192.168.1.0/24 pour : Commercial 100, Compta 50, Serveurs 25, Liaison routeurs 2.

ServiceBesoinMasqueRéseauPlage utilisableBroadcastLibres
Commercial100/25 (126)192.168.1.0.1 → .126.12726
Compta50/26 (62)192.168.1.128.129 → .190.19112
Serveurs25/27 (30)192.168.1.192.193 → .222.2235
Liaison2/30 (2)192.168.1.224.225 → .226.2270

Convention fréquente : la passerelle prend la dernière adresse utilisable (ex. .126) ou la première (.1). Choisis une convention et garde-la partout.


5. Exercices corrigés

Ex. 1 - 10.0.0.0/24 en 8 sous-réseaux égaux.

Ex. 2 - 172.16.0.0/24 : services de 60, 12 et 2 hôtes.

Ex. 3 (type projet) - 10.10.0.0/22 pour : Production 300, Commerce 120, RH 25, Direction 10, Admin 10, 2 liaisons.

6. Erreurs classiques

ErreurConséquence
Commencer par le plus petit besoinBlocs mal alignés, chevauchements
Oublier le « − 2 »Un service se retrouve à court d’1 ou 2 adresses
Oublier que la passerelle consomme une IPIdem
Bloc qui ne commence pas sur un multiple de sa tailleMasque invalide pour cette adresse

7. Script : calculateur VLSM

Fichier : scripts/reseaux/vlsm.py

python3 vlsm.py 192.168.1.0/24 Commercial=100 Compta=50 Serveurs=25 Liaison=2
#!/usr/bin/env python3
"""vlsm.py — Calculateur VLSM : du plus gros besoin au plus petit."""
import ipaddress
import math
import sys
 
 
def prefixe_necessaire(nb_hotes: int) -> int:
    # plus petit nombre de bits hôte tel que 2^bits - 2 >= besoin
    bits_hote = max(2, math.ceil(math.log2(nb_hotes + 2)))
    return 32 - bits_hote
 
 
def calculer_vlsm(reseau_depart: str, besoins: dict) -> None:
    reseau = ipaddress.ip_network(reseau_depart, strict=True)
    adresse_courante = int(reseau.network_address)
    for nom, nb_hotes in sorted(besoins.items(), key=lambda b: b[1], reverse=True):
        prefixe = prefixe_necessaire(nb_hotes)
        sous_reseau = ipaddress.ip_network(f"{ipaddress.ip_address(adresse_courante)}/{prefixe}")
        if not sous_reseau.subnet_of(reseau):
            sys.exit(f"Erreur : plus assez d'adresses pour '{nom}'")
        hotes = list(sous_reseau.hosts())
        print(f"{nom:<14}{nb_hotes:>5}  {str(sous_reseau):<19}{hotes[0]} -> {hotes[-1]}"
              f"  broadcast {sous_reseau.broadcast_address}")
        adresse_courante = int(sous_reseau.broadcast_address) + 1
 
 
if __name__ == "__main__":
    besoins_saisis = {a.split("=")[0]: int(a.split("=")[1]) for a in sys.argv[2:]}
    calculer_vlsm(sys.argv[1], besoins_saisis)

Voir aussi