IPv4

De Justine's wiki
Aller à la navigation Aller à la recherche


Introduction à IPv4 - Notes en vrac

Protocole sans connexion; il réside au niveau de la couche 3 OSI et la couche Internet (qui s'appelle maintenant couche réseau) du modèle TCP/IP.

La couche réseau a pour rôle l'adressage et le routage. Routage = déterminer la route d'un paquet IP pour arriver à destination. Pour faire ça on a besoin  de l'adressage pour identifier les machines qui participent au transport des paquets en question.

Types de communication:
Unicast : one-to-one
Multicast : one-to-many
Broadcast : one-to-all

 

Contrairement à Ethernet ou la communication se fait sur un lien local, IP permet la communication inter-réseaux, entre réseaux de technologies différentes.

Attention : IPv6 est bien le successeur d'IPv4; IPv5 n'as jamais vraiment existé.

On utilise en général le terme "mot" pour désigner les octets séparés par des points (Dans 192.168.1.2, 192 est un mot).

Une adresse IP n'identifie pas un hôte spécifique de manière unique : un hôte peut avoir deux adresses; deux équipements peuvent avoir la même adresse en étant dans deux réseaux différents; on peut avoir des sous-interfaces avec plusieurs adresses sur une interface; etc.

Les adresses APIPA sont des adresses autoconfigurées de lien local, avec un algorithme de prévention des conflits.

NetId == Adresse réseau

On fait un Adresse Ip AND Netmmask pour obtenir l'adresse réseau (ou NetID); de la même manière on fait un NetID OR (NOT NetMask) pour obtenir l'adresse de broadcast.

Tout ça pour dire que l'adresse réseau a la partie hôte à 0, et que l'adresse de broadcast à la partie hôte à 1 (en binaire); mais c'est bel et bien ce que fait l'ordinateur de façon plus "bas niveau".

En-tête et fragmentation

Détails de l'en-tête IPv4: Chaque ligne représente un "mot" de 32 bits.

  • Version : sur 4 bits, donne la version d'IP (0100 pour IPv4)
  • IHL : sur 4 bits, Internet Header length, donne la taille de l'en-tête (nbre de mots de 32 bits). En théorie de 0 à15, en pratique de 5 à 15 (certains mots sont obligatoires)
  • TOS : sur un octet : Type of Service, identifie la qualité de service
  • Total length : sur 2 octets, donne la taille totale du datagramme (de 0 à 216-1 soit 65535, taille max d'un paquet) en octets
  • Identification : sur 2 octets, numéro identifiant de manière unique des fragments dans les tuples * (adr src/ adr dest/ protocole) lorsqu'il y'a fragmentation; n'as une valeur significative que si il y'a une fragmentation.
  • Flags : Sur 3 bits, appellés U (Unused, ce bit ne sert à rien pour l'instant), DF (Don't Fragment), MF (More fragments)
          -Si DF == 1, ne pas fragmenter; si besoin de fragmenter, détruire et répondre en ICMP
          -Si MF == 1, ce datagramme est un fragment, d'autres arrivent (Le dernier fragment a cette valeur à 0)
  • Fragment offset : sur 13 bits, c'est la place de ce fragment par rapport au premier (Attention, la place est exprimée en mots de 8 octets, et non en 1er, 2e, 3e...). Ainsi, la valeur que j'ai ici est égale à "Où commencent les données contenues dans ce paquet, par rapport à l'ensemble des données originales".
  • TTL : entier sur un octet, permet d'éviter que les paquets circulent sans fin sur le réseau. A la création du datagramme, le TTL est initialisé à une valeur N (64 est la valeur recommandée par les RFC). Chaque routeur lit ensuite la valeur et la décrémente de 1. Si la nouvelle valeur est == 0, le paquet est supprimé et c'est au protocole de la couche d'au-dessus de gérer ça (TCP le gère mais pas UDP). Selon Cisco et Wikipédia, un paquet détruit provoque l'envoi d'un message ICMP Time Exceeded; en réalité ce n'est pas toujours le cas, pour des raisons de sécurité (ce n'est pas obligatoire).
  • Protocole : sur un octet, identifie le protocole de la couche du dessus auquel passer les données du datagramme. La liste des protocoles était avant définie par des RFC, aujourd'hui elle est sur le site de l'IANA
  • Header Checksum : somme de contrôle de l'en-tête du datagramme (sauf la partie checksum, bien sûr). À la création du datagramme, on calcule la somme de contrôle: soit sur tous les champs de l'en-tête sauf le checksum, soit sur tous les champs de l'en-tête avec le checksum mais mis à 0. L'en-tête est découpée en mots de 16 bits, et on fait une somme hexadecimale des mots de 16 bits; on fait ensuite un complément à 1 (càd que l'on inverse tous les bits: 1 devient 0 et vice-versa) du résultat, ce qui nous donne une valeur qui est placée dans la partie checksum. Par la suite, sur chaque routeur traversé par le paquet, on refait un calcul du checksum, mais celui-ci est différent : on découpe l'en-tête en mots de 16 bits, puis l'on fait une somme hexadécimale; on fait le complément à 1 qui donne un résultat. Si ce résultat est 0, tout va bien; sinon le paquet a été modifié. Le routeur décrémente ensuite le TTL, et refait le calcul du nouveau checksum comme si le datagramme venait d'être créé. L'en-tête est mise à jour et le datagramme est transféré. Les routeurs performants ont du hardware spécialisé.
  • Les adresses source et dest sur 32 bits.
  • Les options sont généralement non utilisées.

Les champs les plus importants sont les adresses, Protocole, Checkssum, TTL, et les champs sur la fragmentation.

  • (NB : un tuple est un ensemble ordonné de n objets,  appelés « composantes » ou « éléments » ou « termes » du n-uplet [ex: couple/biplet, triplet, quadruplet etc... sont des tuples]), soit pas forcément deux, même en python un tuple peut contenir trois, quatre, ... , valeurs.

Les adresses IPV4 sont codées sur 32 bits, soit 4 octets : 192.168.0.1/24
Ces adresses sont notées en décimal avec les octets séparés par des points. Les premières et dernières adresses sont le réseau et le broadcast.
Les adresses étaient divisées en différentes classes A, B, C

  Cette division n’as officiellement plus cours mais elle est restées dans les mœurs, de plus les adresses privées ou réservées sont toujours valables.

Adresses privées : 10.x.x.x/8
172.16.x.x – 172.32.x.x/12
192.168.x.x/16

Quelques notes en vrac, cf : IPv4

Fragmentation IPv4 et MTU

Les données qui proviennent de la couche supérieure sont déjà fragmentées, et chaque fragment donne un paquet IPv4 d'une certaine taille. Les réseaux pour être efficaces ont besoin de taille de trames limitées. C'est la MTU : Maximum Transmission Unit, qui est définie au niveau des réseaux pour assurer performance et stabilité.

Le MTU couvre la taille totale du paquet IPv4 (données + en-tête IP); le MTU IP ne prend pas en compte l'en-tête + queue de trame Ethernet. La taille maximale d'un datagramme IP est de 64 ko. Cependant les couches du dessous peuvent avoir des MTU plus petits : Ethernet avec 1500 octets (juste pour son payload), ADSL avec 1468 octets, FDDI avec 4470 octets (pour rappel, Ethernet ne fragmente pas ses datagrammes). La taille d'un paquet IP est donc limitée par la couche 2, ce qui fait qu'avec IP + Ethernet, mon paquet IP aura une en-tête de taille allant entre 20 et 60 octets, et un payload de 1500 - 20 (1480) maximum à 1500 - 60 (1440) minimum.

Pour résumer:

  • Ethernet a un MTU de 1500 octets
  • Header IPv4 : de 20 à 60 octets
  • Charge utile IPv4 : 1480 octets max
  • Taille de la trame Ethernet : Payload IPv4 + Header IPv4 + Header Ethernet + CRC Checksum Ethernet
  • Avec un paquet IPv4 total de 1472 octets : 1472 + 20 + 18 = 1510 octets

Marche à suivre :

  • Découpage des données en plusieurs datagrammes au départ en fonction du MTU;
  • Lors de la traversée d'un réseau au MTU plus petit, découpage d'un datagramme en plusieurs datagrammes (fragmentation)

Attention : Les données ne sont pas "défragmentées" par les routeurs intermédiaires : le datagramme est envoyé tel quel, la défragmentation n'est faite qu'à l'arrivée.

Il faut parfois configurer le MTU, dans l'OS des machines du réseau; ce processus est spécifique à chaque OS. Dans Linux, cela se fait au niveau de l'interface. On fait cela notamment dans le cadre des VPN (dans lesquels on encapsule un paquet IP dans un autre paquet IP, avec du chiffrement): on a alors 2 headers IPv4, généralement de 20 octets. En faisant ça cela peut générer de la fragmentation, ce qui peut poser des problèmes, par exemple quand les paquets sont refragmentés plusieurs fois en cours de route. Cela peut donc se mélanger, surtout si il y'a un VPN inconnu sur le réseau qui va fragmenter lui aussi, par exemple à cause d'un FAI qui utilise du VPN sans nous informer. Il faut alors réduire la taille du MTU pour garder de la place pour les headers qui seront rajoutés par les VPN.

En cas de soucis, on va essayer de détecter le MTU su tout le lien, en générant par exemple des paquets ICMP de plus en plus gros :  dès que ça bloque, on estime la taille. Si notre lien entier a un MTU maximum X, on va retirer nos 2 headers IPV4 (soit 40 octets), et on va configurer au niveau du VPN un MTU à X-40 octets.

Adresses réservées

Address block Address range Number of addresses Scope Description
0.0.0.0/8 0.0.0.0–0.255.255.255 16777216 (224) Software Current network[1] (only valid as source address).
10.0.0.0/8 10.0.0.0–10.255.255.255 16777216 Private network Used for local communications within a private network.[2]
100.64.0.0/10 100.64.0.0–100.127.255.255 4194304 Private network Shared address space[3] for communications between a service provider and its subscribers when using a carrier-grade NAT.
127.0.0.0/8 127.0.0.0–127.255.255.255 16777216 Host Used for loopback addresses to the local host.[1]
169.254.0.0/16 169.254.0.0–169.254.255.255 65536 Subnet Used for link-local addresses[4] between two hosts on a single link when no IP address is otherwise specified, such as would have normally been retrieved from a DHCP server.
172.16.0.0/12 172.16.0.0–172.31.255.255 1048576 Private network Used for local communications within a private network.[2]
192.0.0.0/24 192.0.0.0–192.0.0.255 256 Private network IETF Protocol Assignments.[1]
192.0.2.0/24 192.0.2.0–192.0.2.255 256 Documentation Assigned as TEST-NET-1, documentation and examples.[5]
192.88.99.0/24 192.88.99.0–192.88.99.255 256 Internet Reserved.[6] Formerly used for IPv6 to IPv4 relay[7] (included IPv6 address block 2002::/16).
192.168.0.0/16 192.168.0.0–192.168.255.255 65536 Private network Used for local communications within a private network.[2]
198.18.0.0/15 198.18.0.0–198.19.255.255 131072 Private network Used for benchmark testing of inter-network communications between two separate subnets.[8]
198.51.100.0/24 198.51.100.0–198.51.100.255 256 Documentation Assigned as TEST-NET-2, documentation and examples.[5]
203.0.113.0/24 203.0.113.0–203.0.113.255 256 Documentation Assigned as TEST-NET-3, documentation and examples.[5]
224.0.0.0/4 224.0.0.0–239.255.255.255 268435456 Internet In use for IP multicast.[9] (Former Class D network).
240.0.0.0/4 240.0.0.0–255.255.255.254 268435456 Internet Reserved for future use.[10] (Former Class E network).
255.255.255.255/32 255.255.255.255 1 Subnet Reserved for the "limited broadcast" destination address.[1][11]

Source : https://en.wikipedia.org/wiki/Reserved_IP_addresses

Découpage en sous-réseaux de taille régulière

Trouver le masque de sous-réseau nécessaire

Un sous-réseau peut facilement être découpé en sous-réseaux de taille régulière. Premièrement, je dois savoir de combien d'hôtes je vais avoir besoin (que ce soit au total ou par sous-réseau) et du nombre de sous-réseaux nécessaires. Une fois que je le sais, je vais devoir déduire combien de bits emprunter je devrais emprunter à la partie hôte pour faire mes sous-réseaux, et je devrais également vérifier que chaque sous-réseau me laisse assez de place pour acceuillir tous mes hôtes.

La formule pour savoir le nombre de bits emprunter à la partie hôte est simple:

2n

Ici, n sera le nombre de bits à emprunter à la partie hôtes pour faire mes sous-réseaux. Je vais faire monter ce chiffre jusqu'à avoir une valeur suffisante. Par exemple, si je dois faire 9 sous-réseaux, je sais que 23 = 8; 3 bits ne suffiront pas. Cependant, 2⁴ = 16, ce qui est suffisant. Je prendrais donc 4 bits à la partie hôte. Je pourrais ajouter ce chiffre au masque de mon réseau de base. Ensuite, pour vérifier si je pourrais accueillir tous mes hôtes, la formule est la suivante :

2h -2 = Nombres d'hôtes possibles par sous-réseau

Ici, h est le nombre de bits restants dans ma partie hôte. Je sais que chaque sous-réseau pourra avoir 2h adresses, j'en enlève deux pour tenir compte de l'adresse réseau et du broadcast. Je peux ensuite si je le désire multiplier ce résultat par le nombre de sous-réseaux pour obtenir le nombre total d'hôtes que je pourrais accueillir.

Un exemple : Je dispose du réseau 172.16.0.0/16 et je dois faire 8 sous-réseaux, qui devront chacun acceuillir 62 machines:

  • Je sais que 2³ = 8; j'aurais besoin de prendre 3 bits à la partie hôte
  • Mon masque de base est /16, auquel j'ajoute donc 3 : mes sous-réseaux seront en /19
  • Je dois avoir 62 hôtes par sous-réseau; j'utilise ma formule : 2⁶-2 = 62
  • Je sais donc qu'il me faut au moins 6 bits de partie hôte pour avoir assez de place : ici j'en ai 13, je suis large !

En déduire un plan d'adressage du réseau

Je possède donc toutes les informations dont j'ai besoin pour établir mon plan du réseau : le nombre de bits dont j'ai besoin pour mes sous-réseaux et mes hôtes, ainsi que le masque de sous-réseau que j'utiliserais. Il va désormais me falloir partir de mon réseau existant pour créer un plan d'adressage concret. Pour cela:

b signifie un bit à 0 ou à 1 , peu importe
| Masque "de base"
||Masque de sous-réseau

  • Prendre l'adresse réseau de base en binaire, et déterminer ou s'arrête le masque de base  : bbbb bbbb.bbbb bbbb|.bbbb bbbb. bbbb bbbb
  • Sur cette même adresse, déterminer ou s'arrête le masque de sous-réseau. bbbb bbbb.bbbb bbbb|.bbbb bbbb.|| bbbb bbbb
  • Retirer tous les bits situés entre ces deux masques, et laisser un trou à la place. En binaire, on peut alors considérer qu'il s'agit d'un seul chiffre, en principe zéro, au départ. bbbb bbbb.bbbb bbbb|.bbbb bbbb.|| bbbb bbbb
  • Incrémenter de 1 ce groupe de bits, autant de fois que j'ai de sous-réseaux. Je dois tomber pile sur le nombre de sous-réseaux prévus.
  • Il suffit alors de réintégrer ce nombre modifié dans l'adresse, en le remettant dans le vide qu'il avait laissé. J'ai alors toutes les adresses réseau de tous mes sous-réseaux
  • Pour l'adresse du premier hôte, il suffit de mettre tous les bits de la partie hôte à 0 sauf le dernier
  • Pour l'adresse du dernier hôte, il suffit de mettre tous les bits de la partie hôte à 1 sauf le dernier
  • Pour l'adresse de broadcast, il suffit de mettre tous les bits de la partie hôte à 1.

Représentation graphique de la chose :

Ici, je n'ai représenté que 4 bits par octet au lieu de 8 pour faire plus simple, mais le principe est là. Bien entendu, une fois que j'ai mon adresse de sous-réseau en binaire, je reconvertit en décimal chaque octet individuellement. En suivant la démarche donnée plus haut, je peux alors établir un plan d'adressage complet.

 




VLSM (Variable Length Subnet Mask)

Tous les masques sont au format CIDR !!!!

Ce découpage est bien, mais il n'est pas encore très précis : tous les sous-réseaux font la même taille. La technique du VLSM permet de remédier à cela. Elle consiste à découper un réseau en sous-réseaux de tailles différentes. Chaque sous-réseau ainsi obtenu pour acceuillir un nombre total d'adresses (Hôtes + réseau + bcast ) qui sera une puissance de 2, la plus "serrée" possible. Ainsi, un réseau pourra être découpé en 4 sous-réseaux qui recevront respectivement 16, 32, 8 et 64 adresses, par exemple. Il faut juste s'assurer qu'à chaque fois j'ai assez de place pour mettre toutes mes machines ainsi que l'adresse de réseau et l'adresse de broadcast. Les étapes sont les suivantes :

  • D'abord, il faut établir de quel réseau de base je dispose, ainsi que de combien de sous-réseaux j'ai besoin, et du nombre d'hôtes pour chacun de ces sous-réseaux.
  • Pour chaque sous-réseau, je détermine le nombre d'adresses que je vais utiliser, en faisant une puissance de 2. Par exemple si j'ai besoin d'un sous-réseau à 56 adresses, je sais que 2⁶ = 64 : ce sous-réseau aura 64 adresses, avec 6 bits dans sa partie hôte. Appellons ce nombre de bits h, avec h1 pour le premier réseau, etc. Le nombre d'adresses correspondant à 2h sera ici noté a.
  • Je peux déterminer si j'ai assez de place pour tout faire rentrer en additionnant tous mes a (appellons cette somme A). J'enlève à la partie hôte le nombre n de bits dont j'aurais besoin pour mes adresses de sous-réseaux (connu avec la formule 2n >= nombre de sous-réseaux nécessaires, avec n le nombre de bits) et je regarde si j'ai encore assez de place pour coder A sur le nombre de bits restants.
  • Ensuite, je trie ces sous-réseaux du plus grand au plus petit, en fonction du nombre d'adresses disponibles par sous-réseau, et à côté de chaque sous-réseau je note le nombre a correspondant, calculé plus tôt.
  • J'attribue à chaque sous-réseau un masque, que je connais en faisant 32 - h
  • Je pars de la partie hôte de mon adresse réseau de base, qui est donc au départ à 0 partout.
  • Ensuite:
    • Pour le premier sous-réseau, son adresse de sous-réseau sera la même que celle de l'adresse réseau de base.
    • Sa première adresse attribuable sera l'adresse de sous-réseau + 1
    • Sa dernière adresse attribuable sera l'adresse de sous-réseau + (a - 2)
    • Son adresse de broadcast sera l'adresse de sous-réseau + (a - 1)
  • Puis:
    • Je fais + 1 pour avoir l'adresse de sous-réseau du sous-réseau suivant.
    • J'y ajoute 1 pour avoir la première adresse attribuable
    • J'y ajoute a - 2 pour avoir sa dernière adresse attribuable.
    • J'y ajoute a - 1 pour avoir l'adresse de broadcast.
    • Etc.
  • Cette évolution se poursuit. Si je suis à cours de place dans mon octet, j'incrémente l'octet situé à la gauche de celui-ci de 1, je remet mon octet à 0, et je continue. Si l'octet à gauche est plein, j'incrémente celui qui est encore à gauche et je remet les octets à sa droite à 0. Etc
  • Je peux alors attribuer mes adresses aux machines.