Chapitre 4 — La couche réseau : IP et routage#
La couche réseau (couche 3 OSI) est le niveau où les paquets voyagent de leur source à leur destination à travers des réseaux hétérogènes. Elle définit l’adressage logique (IP), le routage et la fragmentation.
IPv4 — Structure de l’en-tête#
L’en-tête IPv4 fait 20 octets minimum (sans options). Chaque champ a un rôle précis dans le routage et la fragmentation des paquets.
Description des champs IPv4#
Champ |
Taille |
Valeur / Rôle |
|---|---|---|
Version |
4 bits |
4 pour IPv4 |
IHL |
4 bits |
Internet Header Length en mots de 32 bits (min=5 → 20 octets) |
DSCP |
6 bits |
Differentiated Services : priorité QoS |
ECN |
2 bits |
Explicit Congestion Notification |
Longueur totale |
16 bits |
Taille de l’en-tête + données (max 65 535 octets) |
Identification |
16 bits |
Identifiant pour rassembler les fragments |
Flags |
3 bits |
Bit DF (Don’t Fragment), MF (More Fragments) |
Fragment Offset |
13 bits |
Position du fragment dans le paquet original |
TTL |
8 bits |
Time To Live : décrémenté de 1 par chaque routeur (max 255) |
Protocole |
8 bits |
Protocole encapsulé : 1=ICMP, 6=TCP, 17=UDP |
Checksum |
16 bits |
Somme de contrôle de l’en-tête uniquement |
IP source |
32 bits |
Adresse de l’émetteur |
IP destination |
32 bits |
Adresse du destinataire |
def decoder_entete_ipv4(data: bytes) -> dict:
"""Décode les 20 premiers octets d'un en-tête IPv4."""
if len(data) < 20:
raise ValueError("Données trop courtes pour un en-tête IPv4")
version_ihl = data[0]
version = (version_ihl >> 4) & 0x0F
ihl = version_ihl & 0x0F
dscp_ecn = data[1]
dscp = (dscp_ecn >> 2) & 0x3F
ecn = dscp_ecn & 0x03
longueur = struct.unpack(">H", data[2:4])[0]
identification= struct.unpack(">H", data[4:6])[0]
flags_offset = struct.unpack(">H", data[6:8])[0]
flags = (flags_offset >> 13) & 0x07
offset = flags_offset & 0x1FFF
ttl = data[8]
protocole = data[9]
checksum = struct.unpack(">H", data[10:12])[0]
src = socket.inet_ntoa(data[12:16])
dst = socket.inet_ntoa(data[16:20])
protos = {1: "ICMP", 6: "TCP", 17: "UDP", 41: "IPv6", 89: "OSPF"}
flags_str = []
if flags & 0x02: flags_str.append("DF")
if flags & 0x01: flags_str.append("MF")
return {
"Version": version,
"IHL": f"{ihl} × 4 = {ihl*4} octets",
"DSCP": dscp,
"ECN": ecn,
"Longueur": f"{longueur} octets",
"Identification": f"0x{identification:04X}",
"Flags": ", ".join(flags_str) if flags_str else "aucun",
"Frag. Offset": offset,
"TTL": ttl,
"Protocole": f"{protocole} ({protos.get(protocole, '?')})",
"Checksum": f"0x{checksum:04X}",
"Source": src,
"Destination": dst,
}
# Exemple d'en-tête IPv4 : paquet TCP de 192.168.1.10 vers 8.8.8.8, TTL=64
en_tete = struct.pack(">BBHHHBBH4s4s",
0x45, # Version=4, IHL=5
0x00, # DSCP=0, ECN=0
60, # Longueur totale
0x1234, # Identification
0x4000, # Flags: DF, Offset=0
64, # TTL
6, # Protocole: TCP
0x0000, # Checksum (factice)
socket.inet_aton("192.168.1.10"),
socket.inet_aton("8.8.8.8"),
)
print("Décodage d'un en-tête IPv4 :")
print("-" * 40)
for champ, valeur in decoder_entete_ipv4(en_tete).items():
print(f" {champ:<20} : {valeur}")
Décodage d'un en-tête IPv4 :
----------------------------------------
Version : 4
IHL : 5 × 4 = 20 octets
DSCP : 0
ECN : 0
Longueur : 60 octets
Identification : 0x1234
Flags : DF
Frag. Offset : 0
TTL : 64
Protocole : 6 (TCP)
Checksum : 0x0000
Source : 192.168.1.10
Destination : 8.8.8.8
CIDR et sous-réseaux#
Notation CIDR#
La notation CIDR (Classless Inter-Domain Routing) exprime un réseau par son adresse de base et le nombre de bits du masque : 192.168.1.0/24.
Le masque /24 signifie que les 24 premiers bits identifient le réseau et les 8 bits restants identifient les hôtes.
import ipaddress
def analyser_reseau(notation_cidr: str) -> dict:
"""Analyse un réseau CIDR et retourne toutes ses propriétés."""
net = ipaddress.ip_network(notation_cidr, strict=False)
return {
"Réseau": str(net),
"Adresse réseau": str(net.network_address),
"Masque": str(net.netmask),
"Masque inversé": str(net.hostmask),
"Broadcast": str(net.broadcast_address),
"Nb hôtes utiles": net.num_addresses - 2 if net.prefixlen < 31 else net.num_addresses,
"Premier hôte": str(net.network_address + 1) if net.prefixlen < 31 else str(net.network_address),
"Dernier hôte": str(net.broadcast_address - 1) if net.prefixlen < 31 else str(net.broadcast_address),
"Classe tradition.": "A" if net.prefixlen <= 8 else "B" if net.prefixlen <= 16 else "C" if net.prefixlen <= 24 else "sous-réseau",
}
reseaux = ["10.0.0.0/8", "172.16.0.0/12", "192.168.1.0/24",
"192.168.1.64/26", "10.10.5.0/29", "172.20.0.0/16"]
for r in reseaux:
info = analyser_reseau(r)
print(f"\n{'═'*50}")
print(f" {r}")
for k, v in info.items():
print(f" {k:<22} : {v}")
══════════════════════════════════════════════════
10.0.0.0/8
Réseau : 10.0.0.0/8
Adresse réseau : 10.0.0.0
Masque : 255.0.0.0
Masque inversé : 0.255.255.255
Broadcast : 10.255.255.255
Nb hôtes utiles : 16777214
Premier hôte : 10.0.0.1
Dernier hôte : 10.255.255.254
Classe tradition. : A
══════════════════════════════════════════════════
172.16.0.0/12
Réseau : 172.16.0.0/12
Adresse réseau : 172.16.0.0
Masque : 255.240.0.0
Masque inversé : 0.15.255.255
Broadcast : 172.31.255.255
Nb hôtes utiles : 1048574
Premier hôte : 172.16.0.1
Dernier hôte : 172.31.255.254
Classe tradition. : B
══════════════════════════════════════════════════
192.168.1.0/24
Réseau : 192.168.1.0/24
Adresse réseau : 192.168.1.0
Masque : 255.255.255.0
Masque inversé : 0.0.0.255
Broadcast : 192.168.1.255
Nb hôtes utiles : 254
Premier hôte : 192.168.1.1
Dernier hôte : 192.168.1.254
Classe tradition. : C
══════════════════════════════════════════════════
192.168.1.64/26
Réseau : 192.168.1.64/26
Adresse réseau : 192.168.1.64
Masque : 255.255.255.192
Masque inversé : 0.0.0.63
Broadcast : 192.168.1.127
Nb hôtes utiles : 62
Premier hôte : 192.168.1.65
Dernier hôte : 192.168.1.126
Classe tradition. : sous-réseau
══════════════════════════════════════════════════
10.10.5.0/29
Réseau : 10.10.5.0/29
Adresse réseau : 10.10.5.0
Masque : 255.255.255.248
Masque inversé : 0.0.0.7
Broadcast : 10.10.5.7
Nb hôtes utiles : 6
Premier hôte : 10.10.5.1
Dernier hôte : 10.10.5.6
Classe tradition. : sous-réseau
══════════════════════════════════════════════════
172.20.0.0/16
Réseau : 172.20.0.0/16
Adresse réseau : 172.20.0.0
Masque : 255.255.0.0
Masque inversé : 0.0.255.255
Broadcast : 172.20.255.255
Nb hôtes utiles : 65534
Premier hôte : 172.20.0.1
Dernier hôte : 172.20.255.254
Classe tradition. : B
Découpage en sous-réseaux (subnetting)#
def decouper_reseau(reseau: str, nouveau_prefixe: int) -> list:
"""Découpe un réseau en sous-réseaux de taille identique."""
net = ipaddress.ip_network(reseau, strict=False)
sous_reseaux = list(net.subnets(new_prefix=nouveau_prefixe))
return sous_reseaux
print("Découpage de 192.168.1.0/24 en /26 (64 hôtes chacun) :")
print("-" * 60)
for sr in decouper_reseau("192.168.1.0/24", 26):
print(f" {str(sr):<22} → hôtes: {str(sr.network_address + 1)}"
f" – {str(sr.broadcast_address - 1)}")
print("\nDécoupage de 10.0.0.0/8 en /10 :")
print("-" * 60)
for sr in decouper_reseau("10.0.0.0/8", 10):
n = ipaddress.ip_network(str(sr))
print(f" {str(sr):<20} ({n.num_addresses - 2:>8,} hôtes utiles)")
Découpage de 192.168.1.0/24 en /26 (64 hôtes chacun) :
------------------------------------------------------------
192.168.1.0/26 → hôtes: 192.168.1.1 – 192.168.1.62
192.168.1.64/26 → hôtes: 192.168.1.65 – 192.168.1.126
192.168.1.128/26 → hôtes: 192.168.1.129 – 192.168.1.190
192.168.1.192/26 → hôtes: 192.168.1.193 – 192.168.1.254
Découpage de 10.0.0.0/8 en /10 :
------------------------------------------------------------
10.0.0.0/10 (4,194,302 hôtes utiles)
10.64.0.0/10 (4,194,302 hôtes utiles)
10.128.0.0/10 (4,194,302 hôtes utiles)
10.192.0.0/10 (4,194,302 hôtes utiles)
IPv6#
IPv6 (RFC 2460) répond à l’épuisement des adresses IPv4. Il utilise des adresses de 128 bits (contre 32 bits pour IPv4), soit 2¹²⁸ ≈ 3.4 × 10³⁸ adresses.
Format d’adresse IPv6#
Une adresse IPv6 est écrite en 8 groupes de 4 chiffres hexadécimaux séparés par : :
2001:0db8:0000:0042:0000:8a2e:0370:7334
Règles d’abréviation :
Omettre les zéros initiaux dans chaque groupe :
2001:db8:0:42:0:8a2e:370:7334Remplacer une suite de groupes nuls par
::(une seule fois) :2001:db8:0:42::8a2e:370:7334
Types d’adresses IPv6#
Type |
Préfixe |
Exemple |
Usage |
|---|---|---|---|
Unicast global |
|
|
Adressage Internet public |
Unicast link-local |
|
|
Communication sur le lien local uniquement |
Unicast unique-local |
|
|
Équivalent des IP privées RFC 1918 |
Multicast |
|
|
Diffusion vers un groupe |
Loopback |
|
|
Interface de bouclage |
Non spécifiée |
|
|
Source avant l’attribution d’une adresse |
import ipaddress
def analyser_ipv6(adresse: str) -> dict:
"""Analyse une adresse IPv6."""
try:
addr = ipaddress.ip_address(adresse)
except ValueError as e:
return {"erreur": str(e)}
types = []
if addr.is_loopback: types.append("loopback")
if addr.is_link_local: types.append("link-local")
if addr.is_private: types.append("privée/unique-local")
if addr.is_global: types.append("globale")
if addr.is_multicast: types.append("multicast")
if addr.is_unspecified: types.append("non spécifiée")
return {
"Adresse compressée": str(addr),
"Adresse complète": addr.exploded,
"Type(s)": ", ".join(types) if types else "inconnu",
"Version": addr.version,
}
adresses_test = [
"::1",
"fe80::1",
"2001:db8::1",
"ff02::1",
"fd00::cafe:1",
"2001:4860:4860::8888", # Google DNS
]
print(f"{'Adresse':<30} {'Type':<25} {'Complète'}")
print("─" * 95)
for a in adresses_test:
info = analyser_ipv6(a)
print(f"{info.get('Adresse compressée','?'):<30} "
f"{info.get('Type(s)','?'):<25} "
f"{info.get('Adresse complète','?')}")
Adresse Type Complète
───────────────────────────────────────────────────────────────────────────────────────────────
::1 loopback, privée/unique-local 0000:0000:0000:0000:0000:0000:0000:0001
fe80::1 link-local, privée/unique-local fe80:0000:0000:0000:0000:0000:0000:0001
2001:db8::1 privée/unique-local 2001:0db8:0000:0000:0000:0000:0000:0001
ff02::1 globale, multicast ff02:0000:0000:0000:0000:0000:0000:0001
fd00::cafe:1 privée/unique-local fd00:0000:0000:0000:0000:0000:cafe:0001
2001:4860:4860::8888 globale 2001:4860:4860:0000:0000:0000:0000:8888
Auto-configuration SLAAC#
SLAAC (Stateless Address Autoconfiguration, RFC 4862) permet à une interface IPv6 de se configurer automatiquement sans serveur DHCP :
Le routeur envoie des Router Advertisements (RA) avec le préfixe réseau
L’hôte combine ce préfixe avec son identifiant d’interface (dérivé de la MAC via EUI-64 ou généré aléatoirement)
Une vérification de duplication (DAD) est effectuée en multicast
def eui64_depuis_mac(mac: str) -> str:
"""
Génère l'identifiant d'interface EUI-64 depuis une adresse MAC 48 bits.
Règle : insertion de ff:fe au milieu et inversion du bit Universal/Local.
"""
octets = [int(x, 16) for x in mac.split(":")]
octets[0] ^= 0x02 # Inversion du bit U/L
eui64 = octets[:3] + [0xff, 0xfe] + octets[3:]
return ":".join(f"{x:02x}" for x in eui64)
def slaac_adresse(prefixe_reseau: str, mac: str) -> str:
"""Calcule l'adresse SLAAC à partir du préfixe réseau et de la MAC."""
iid = eui64_depuis_mac(mac)
net = ipaddress.ip_network(prefixe_reseau, strict=False)
# Combiner le préfixe /64 avec l'IID
prefixe_int = int(net.network_address)
iid_bytes = bytes(int(x, 16) for x in iid.split(":"))
iid_int = int.from_bytes(iid_bytes, "big")
adresse_int = prefixe_int | iid_int
return str(ipaddress.ip_address(adresse_int))
exemples = [
("2001:db8::/64", "00:1a:2b:3c:4d:5e"),
("2001:db8::/64", "aa:bb:cc:dd:ee:ff"),
("fd00:cafe::/64", "08:00:27:ab:cd:ef"),
]
print("Auto-configuration SLAAC (EUI-64) :")
print("-" * 60)
for prefixe, mac in exemples:
iid = eui64_depuis_mac(mac)
adresse = slaac_adresse(prefixe, mac)
print(f" MAC : {mac}")
print(f" EUI-64 : {iid}")
print(f" Adresse : {adresse}")
print()
Auto-configuration SLAAC (EUI-64) :
------------------------------------------------------------
MAC : 00:1a:2b:3c:4d:5e
EUI-64 : 02:1a:2b:ff:fe:3c:4d:5e
Adresse : 2001:db8::21a:2bff:fe3c:4d5e
MAC : aa:bb:cc:dd:ee:ff
EUI-64 : a8:bb:cc:ff:fe:dd:ee:ff
Adresse : 2001:db8::a8bb:ccff:fedd:eeff
MAC : 08:00:27:ab:cd:ef
EUI-64 : 0a:00:27:ff:fe:ab:cd:ef
Adresse : fd00:cafe::a00:27ff:feab:cdef
NAT — Network Address Translation#
Le NAT permet à plusieurs machines avec des adresses IP privées de partager une (ou quelques) adresse(s) IP publique(s).
NAT Masquerade / PAT#
Le PAT (Port Address Translation), aussi appelé NAT overload ou masquerade, est la forme la plus courante. Il utilise les numéros de ports TCP/UDP pour distinguer les connexions.
Avantages et inconvénients du NAT#
Aspect |
Pour |
Contre |
|---|---|---|
Économie d’adresses |
Partage d’une IP publique entre N hôtes |
Brise le modèle end-to-end d’Internet |
Sécurité |
Cache la topologie interne |
Les connexions entrantes nécessitent du port forwarding |
Déploiement |
Simple, transparent |
Complique les protocoles embarquant des IPs (FTP, SIP) |
Performance |
— |
Surcoût de traitement (état, translation) |
Routage IP#
Table de routage#
Un routeur décide du prochain saut (next hop) pour chaque paquet en consultant sa table de routage selon la règle du plus long préfixe (longest prefix match).
import ipaddress
class TableRoutage:
"""Simulation d'une table de routage avec longest prefix match."""
def __init__(self):
self.routes = []
def ajouter_route(self, reseau: str, next_hop: str, interface: str,
metrique: int = 1, source: str = "static"):
net = ipaddress.ip_network(reseau, strict=False)
self.routes.append({
"réseau": net,
"next_hop": next_hop,
"interface": interface,
"métrique": metrique,
"source": source,
})
# Tri par longueur de préfixe décroissante
self.routes.sort(key=lambda r: r["réseau"].prefixlen, reverse=True)
def router(self, ip_dest: str) -> dict | None:
"""Applique le longest prefix match."""
dest = ipaddress.ip_address(ip_dest)
for route in self.routes:
if dest in route["réseau"]:
return route
return None
def afficher(self):
print(f"{'Réseau':<22} {'Next-Hop':<18} {'Interface':<12} {'Métrique':<10} {'Source'}")
print("─" * 80)
for r in self.routes:
print(f" {str(r['réseau']):<20} {r['next_hop']:<18} "
f"{r['interface']:<12} {r['métrique']:<10} {r['source']}")
# Exemple de table de routage d'un routeur d'entreprise
table = TableRoutage()
table.ajouter_route("0.0.0.0/0", "203.0.113.254", "eth0", metrique=10, source="static")
table.ajouter_route("10.0.0.0/8", "10.255.255.1", "eth1", metrique=1, source="static")
table.ajouter_route("10.1.0.0/16", "10.1.0.1", "eth2", metrique=1, source="OSPF")
table.ajouter_route("10.1.5.0/24", "10.1.5.254", "eth2", metrique=1, source="OSPF")
table.ajouter_route("192.168.1.0/24", "192.168.1.1", "eth3", metrique=1, source="connected")
table.ajouter_route("192.168.2.0/24", "192.168.1.254", "eth3", metrique=2, source="RIP")
table.ajouter_route("127.0.0.0/8", "127.0.0.1", "lo", metrique=0, source="connected")
print("Table de routage :")
table.afficher()
print("\nRésolution de routes (longest prefix match) :")
print("-" * 55)
tests = ["10.1.5.42", "10.1.99.1", "10.2.3.4", "192.168.2.50",
"8.8.8.8", "127.0.0.1"]
for ip in tests:
route = table.router(ip)
if route:
print(f" {ip:<18} → {str(route['réseau']):<22} via {route['next_hop']:<18} ({route['source']})")
else:
print(f" {ip:<18} → PAS DE ROUTE (paquet dropped)")
Table de routage :
Réseau Next-Hop Interface Métrique Source
────────────────────────────────────────────────────────────────────────────────
10.1.5.0/24 10.1.5.254 eth2 1 OSPF
192.168.1.0/24 192.168.1.1 eth3 1 connected
192.168.2.0/24 192.168.1.254 eth3 2 RIP
10.1.0.0/16 10.1.0.1 eth2 1 OSPF
10.0.0.0/8 10.255.255.1 eth1 1 static
127.0.0.0/8 127.0.0.1 lo 0 connected
0.0.0.0/0 203.0.113.254 eth0 10 static
Résolution de routes (longest prefix match) :
-------------------------------------------------------
10.1.5.42 → 10.1.5.0/24 via 10.1.5.254 (OSPF)
10.1.99.1 → 10.1.0.0/16 via 10.1.0.1 (OSPF)
10.2.3.4 → 10.0.0.0/8 via 10.255.255.1 (static)
192.168.2.50 → 192.168.2.0/24 via 192.168.1.254 (RIP)
8.8.8.8 → 0.0.0.0/0 via 203.0.113.254 (static)
127.0.0.1 → 127.0.0.0/8 via 127.0.0.1 (connected)
Protocoles de routage#
Routage statique vs dynamique
Le routage statique est configuré manuellement par l’administrateur. Simple mais ne s’adapte pas aux pannes. Le routage dynamique utilise des protocoles qui échangent des informations de topologie et recalculent les routes automatiquement.
Protocole |
Type |
Algorithme |
Métrique |
Usage |
|---|---|---|---|---|
RIP v2 |
IGP, Distance Vector |
Bellman-Ford |
Nombre de sauts (max 15) |
Petits réseaux (obsolescent) |
OSPF |
IGP, Link State |
Dijkstra |
Bande passante (coût) |
Réseaux d’entreprise |
IS-IS |
IGP, Link State |
Dijkstra |
Coût |
FAI, backbone |
EIGRP |
IGP, Hybrid |
DUAL |
Bande passante + délai |
Réseaux Cisco |
BGP-4 |
EGP, Path Vector |
Best-path |
Attributs de politique |
Inter-AS, Internet |
ICMP — Ping et Traceroute#
ICMP (Internet Control Message Protocol, RFC 792) transporte des messages de contrôle et d’erreur pour IP. Il est encapsulé directement dans les paquets IP (protocole 1).
Messages ICMP courants#
Type |
Code |
Description |
|---|---|---|
0 |
0 |
Echo Reply (réponse ping) |
3 |
0–15 |
Destination Unreachable |
8 |
0 |
Echo Request (ping) |
11 |
0 |
Time Exceeded (TTL expiré — utilisé par traceroute) |
12 |
0 |
Parameter Problem |
Simulation de ping et traceroute#
import struct
import socket
def construire_icmp_echo_request(identifiant: int, sequence: int,
payload: bytes = b"Hello ICMP!") -> bytes:
"""
Construit un paquet ICMP Echo Request (Type=8, Code=0).
Le checksum est calculé correctement.
"""
type_icmp = 8
code = 0
checksum = 0
en_tete = struct.pack(">BBHHH", type_icmp, code, checksum, identifiant, sequence)
paquet = en_tete + payload
# Calcul du checksum Internet (RFC 1071)
if len(paquet) % 2:
paquet += b'\x00'
total = 0
for i in range(0, len(paquet), 2):
mot = (paquet[i] << 8) + paquet[i+1]
total += mot
while total >> 16:
total = (total & 0xFFFF) + (total >> 16)
checksum = ~total & 0xFFFF
en_tete_final = struct.pack(">BBHHH", type_icmp, code, checksum, identifiant, sequence)
return en_tete_final + payload
def decoder_icmp(data: bytes) -> dict:
"""Décode un paquet ICMP."""
type_icmp, code, checksum, ident, seq = struct.unpack(">BBHHH", data[:8])
types_icmp = {
0: "Echo Reply", 3: "Destination Unreachable",
8: "Echo Request", 11: "Time Exceeded",
}
return {
"Type": f"{type_icmp} ({types_icmp.get(type_icmp, '?')})",
"Code": code,
"Checksum": f"0x{checksum:04X}",
"ID": ident,
"Séquence": seq,
"Payload": data[8:].decode("ascii", errors="replace"),
}
# Construction d'un Echo Request
paquet = construire_icmp_echo_request(identifiant=1234, sequence=1)
print("ICMP Echo Request construit :")
print(f" Hex : {paquet.hex(' ')}\n")
decodage = decoder_icmp(paquet)
for k, v in decodage.items():
print(f" {k:<12} : {v}")
ICMP Echo Request construit :
Hex : 08 00 17 a7 04 d2 00 01 48 65 6c 6c 6f 20 49 43 4d 50 21
Type : 8 (Echo Request)
Code : 0
Checksum : 0x17A7
ID : 1234
Séquence : 1
Payload : Hello ICMP!
Résumé#
Points clés du chapitre 4
L”en-tête IPv4 fait 20 octets minimum et contient les adresses src/dst, le TTL, le protocole encapsulé et les bits de fragmentation.
CIDR (
/24,/26…) remplace les classes A/B/C historiques et permet un adressage flexible.IPv6 utilise 128 bits (contre 32), l’auto-configuration SLAAC remplace DHCP pour le cas simple.
NAT/PAT partage une IP publique entre plusieurs hôtes privés grâce aux ports TCP/UDP.
Le longest prefix match détermine le next-hop dans la table de routage.
ICMP fournit les messages de contrôle : ping (Echo Request/Reply) et traceroute (TTL + Time Exceeded).
Concept |
Taille |
Exemple |
|---|---|---|
En-tête IPv4 |
20–60 octets |
version, TTL, protocole, src, dst |
Adresse IPv4 |
32 bits |
192.168.1.1/24 |
Adresse IPv6 |
128 bits |
2001:db8::1/64 |
TTL initial |
64 ou 128 |
Linux=64, Windows=128 |
MTU Ethernet |
1500 octets |
fragmentation si > MTU |