Méně IPv4 v sítích: teoretický úvod aneb šetříme adresy

19. 2. 2025
Doba čtení: 12 minut

Sdílet

Ethernetové kabely v přepínači tvoří počítačovou síť
Autor: Depositphotos
Internetový protokol IPv6 si pomalu nachází cestu i do míst, kde bychom jej úplně nečekali. Ukážeme si, jak díky IPv6 ušetřit hromady IPv4 adres i tam, kde je ještě stále potřeba směrovat pakety protokolu IPv4.

Když plánujete či stavíte počítačovou síť, zpravidla narážíte na otázku „kolik adres budu potřebovat?“ – a pokud potřebujete IPv4, najít správnou odpověď není tak úplně jednoduché. V následujícím textu si proto ukážeme:

  • jak komunikace v IP/Ethernet síti zpravidla vypadá,
  • jak se liší komunikace na IP vrstvě když jsou obě strany uvnitř jednoho ethernetového segmentu sítě oproti situaci, kdy je jedna z nich „až za routerem“
  • k čemu jsou loopback (dummy) rozhraní
  • jak se obejít bez IPv4 adres na rozhraních lokální sítě a nepřijít při tom o IPv4 konektivitu

Hodí se znát alespoň základy OSI modelu, v tomto článku nás budou zajímat hlavně dvě jeho vrstvy: spojová (link layer), reprezentovaná Ethernetem, a síťová (network layer), reprezentovaná protokoly ARP, IPv4 a IPv6. V případě IP sítí se ještě hodí znát principy masky sítě.

Diagram OSI modelu

Diagram OSI modelu

Autor: Wikipedie, podle licence: Public Domain

Alice, Bob a router

Představme si typickou domácí nebo menší firemní síť postavenou na protokolu Ethernet, ke které jsou připojeny dva počítače uživatelů Alice a Bob. Pro jednoduchost budeme předpokládat, že má každý počítač veřejnou, globálně dostupnou, unikátní IPv4 adresu. Adresy, které počítače využívají, patří do IPv4 bloku 198.51.100.0 s maskou sítě 255.255.255.0, nebo také /24, který obsahuje 256 IPv4 adres: 198.51.100.0198.51.100.255. Každý počítač má i svou hardwarovou Ethernet MAC adresu.

Komunikace přímo propojených uzlů - Alice a Boba.

Alice a Bob komunikují napřímo 

Autor: Radek Zajíc
Alice IP 198.51.100.16, MAC ae:82:68:c1:77:03
Bob   IP 198.51.100.17, MAC f6:fe:90:5d:d3:ca

Když chce komunikovat Bob s Alicí, nejprve ověří, zda spolu mohou komunikovat napřímo. Adresy sítí, ke kterým zná váš počítač cestu, se udržují tzv. směrovací (routovací) tabulce. Bobův kernel se tedy podívá do své routovací tabulky a pokusí se zjistit, zda je počítač Alice, resp. jeho IP adresa, připojen(a) k síti, ke které zná Bob cestu.

Bobova routovací tabulka je krátká, je v ní jediný záznam – adresa a maska sítě, ke které je Bob přímo připojen:

bob@bob:~# ip route
198.51.100.0/24 dev from_bob proto kernel scope link src 198.51.100.17

Bobův kernel vezme cílovou adresu počítače Alice a pokusí se ze své routovací tabulky zjistit, kudy pakety k Alici poslat. Například v Linuxu používá různé triky: datovou strukturu typu trie, ve které hledá „list“ odpovídající žádané cílové adrese, případně postupně bere prvních N-bitů cílové adresy, v pořadí od „nejkonkrétnějších N/32 až po „nejméně konkrétní N/0, a hledá odpovídající záznamy v routovací tabulce. Jak to funguje u hardwarových routerů se můžete dočíst například v textu od Zbyňka Pospíchala na serveru Lupa.cz.

Výsledkem operace hledání odpovídajícího záznamu pro počítač Alice v Bobově routovací tabulce je, že je počítač Alice v síti 198.51.100.0/24, ke které je přímo připojen i Bob (záznam v tabulce neobsahuje parametr brány/gateway, reprezentovaný klíčovým slovem via  a IP adresou). Bobův kernel už ví, že s Alicí sdílí síť, a proto s ní začne komunikovat napřímo, bez prostředníků. Použije protokol ARP a vyšle do sítě všesměrovým vysíláním, neboli broadcastem, dotaz „Na jaké hardwarové (MAC) adrese je Alice?

V ideálním případě dostane od Alice odpověď s její hardwarovou adresou.

f6:fe:90:5d:d3:ca > ff:ff:ff:ff:ff:ff, ARP:
    Request who-has 198.51.100.16 tell 198.51.100.17
ae:82:68:c1:77:03 > f6:fe:90:5d:d3:ca, ARP:
    Reply 198.51.100.16 is-at ae:82:68:c1:77:03

Následující komunikace mezi Alicí a Bobem už probíhá napřímo – podíváme-li se na pakety tcpdumpem nebo Wiresharkem, uvidíme, že v ethernetovém rámci figurují MAC adresy Alice a Boba a v IP paketech pak budou jejich IPv4 adresy.

Pohled Wiresharkem na komunikaci Alice a Boba. Na linkové vrstvě vidíme, že spolu komunikují přímo počítače Alice a Boba.

Pohled Wiresharkem na komunikaci Alice a Boba

Autor: Radek Zajíc

Co se ale stane, pokud bude Bob chtít komunikovat například s Google DNS na adrese 8.8.8.8? Protože v routovací tabulce neexistuje záznam s cestou k  8.8.8.8, pokud se Bob pokusí použít příkaz ping, se zlou se potáže.

bob@bob:~# ping 8.8.8.8
ping: connect: Network is unreachable

Aby mohl Bob komunikovat s počítači mimo vlastní síť, potřebuje do sítě umístit router, tedy zařízení, které je kromě sítě s Bobem a Alicí připojeno ještě do Internetu. Routeru můžeme přidělit například adresu 198.51.100.1/24. V síti už máme tři zařízení.

Malá síť s třemi uzly, Alicí, Bobem a Routerem, které spolu mohou komunikovat přímo, bez prostředníka.

Síť s Alicí, Bobem a Routerem

Autor: Radek Zajíc
Router IP 198.51.100.1,  MAC 1e:51:b8:7a:97:80
Alice  IP 198.51.100.16, MAC ae:82:68:c1:77:03
Bob    IP 198.51.100.17, MAC f6:fe:90:5d:d3:ca

Bobovu routovací tabulku ještě musíme doplnit o záznam ukazující na tzv. next-hop router pro veškerý ostatní provoz, kterému se obvykle říká výchozí brána. To je záznam, který má adresu sítě i masku sítě rovnou nule a parametr via  s adresou routeru:

bob@bob:~# ip route add 0.0.0.0/0 via 198.51.100.1
bob@bob:~# ip route
default via 198.51.100.1 dev from_bob
198.51.100.0/24 dev from_bob proto kernel scope link src 198.51.100.17

Záznam s nulovou adresou i maskou sítě zde má textový alias „default“. Pokud použijeme příkaz route, uvidíme, že jsme skutečně přidali záznam  0.0.0.0/0:

bob@bob:~# route -n
Kernel IP routing table
Destination  Gateway      Genmask       Flags Iface
0.0.0.0      198.51.100.1 0.0.0.0       UG    from_bob
198.51.100.0 0.0.0.0      255.255.255.0 U     from_bob

Nyní už Bobův kernel ví, kudy ke Google DNS běží zajíc. I v tomto případě se Bob nejprve pokusí vyhledat 8.8.8.8 ve své routovací tabulce – a jediný záznam, který bude použitelný, je právě výchozí brána. Ta je v síti, ke které má Bob přímý přístup, proto podobně jako při komunikaci s Alicí nejprve zjistí hardwarovou adresu brány. Komunikaci s 8.8.8.8  na síťové vrstvě následně povede Bob s  8.8.8.8, ale na linkové vrstvě vidíme, že spolu ve skutečnosti komunikuje Bob s Routerem, a Router se pak stará o komunikaci směrem z/do Internetu:

Pohled Wiresharkem na komunikaci Boba s 8.8.8.8: na síťové vrstvě komunikuje Bob s 8.8.8.8, ale na linkové si rámce vyměňují Bob s Routerem

Pohled Wiresharkem na komunikaci Boba s 8.8.8.8

Autor: Radek Zajíc

Nedostatek IPv4 adres a směrování provozu

Internet je síť vzájemně propojených menších sítí. Aby spolu tyto sítě mohly komunikovat, je v místech, kde se setkávají různé síťové segmenty, vždy přítomen alespoň jeden router. Routery při komunikaci mezi sebou mohou používat stejné mechanismy, jako když se potkají Alice a Bob – tedy mají přiděleny IPv4 adresy a pro zjišťování, kdo má jakou hardwarovou adresu, použijí protokol ARP. Znalejší čtenáři toto zjednodušení, které v některých typech sítí tak úplně neplatí, zajisté prominou.

Dva propojené routery, které používají pro komunikaci mezi sebou adresy ze sítě 192.0.2.0/24.

Dva routery s propojovací IPv4 sítí 192.0.2.0/24

Autor: Radek Zajíc

Aby spolu mohly dva routery komunikovat, zpravidla existuje propojovací IPv4 síť, kterou routery sdílí. V obrázku výše jde o síť  192.0.2.0/24. Tato síť musí mít k dispozici dostatek využitelných IPv4 adres, aby si každý router mohl „urvat“ jednu pro sebe. Samozřejmě by každá taková propojovací síť mohla mít masku 255.255.255.0, a v devadesátých letech, před zavedením beztřídního směrování, tomu tak nejspíš i bylo. Vyhrazení bloku 256 adres pro dvě přímo propojená zařízení v síti ale zní jako plýtvání adresami, kterých je nedostatek. Díky beztřídnímu směrování je dnes naštěstí možné používat i sítě s menším počtem dostupných adres.

Protokol IPv4 v sobě historicky měl zapečené omezení, kdy první a poslední adresu z každé IPv4 sítě nebylo možné použít: první adresa, např. 198.51.100.0 v síti s maskou 255.255.255.0, byla vyhrazena pro adresu sítě a poslední, např. 198.51.100.255, pro „directed broadcast“, komunikaci se všemi uzly v síti. Pokud například v Linuxu vyzkoušíte ping na poslední adresu sítě s maskou /24, příkaz ping se s vámi odmítne bavit:

bob@bob:~# ping 198.51.100.255
ping: Do you want to ping broadcast? Then -b. If not, check your local firewall rules

Proto je dodnes na některých místech pro komunikaci mezi routery nejmenší použitelná IPv4 síť s maskou /30 : taková IPv4 síť má přesně dvě rezervované a dvě dostupné IPv4 adresy. Právě tolik, aby jednu z dostupných adres mohl dostat každý router na své straně.

Už v roce 2000 se ale objevil standard RFC 3021, který zavádí pro „point-to-point spoje“, typicky přímé linky mezi dvěma routery, podporu pro masku sítě /31. Ta pojme přesně dvě IPv4 adresy. Taková konfigurace nepodporuje „directed broadcast“ a obě adresy jsou využitelné. Pro broadcast provoz se dá stále využívat „link local broadcast“ s adresou 255.255.255.255, případně historická broadcastová adresa  0.0.0.0.

Populární platformy hardwarových routerů podporu masky /31 mají již velmi dlouho – na uvedeném RFC se koneckonců spolupodíleli i autoři z Cisco Systems. Podporu najdeme i v Linuxu, ale například velmi populární RouterOS, byť pod pokličkou používá linuxové jádro, s ní oficiálně přijde až ve verzi 7.18, která vyjde později než tento článek.

Existují i případy, kdy konfigurujete jednu jedinou adresu s maskou /32 v případě IPv4 resp. /128 v případě IPv6. Typické využití je na rozhraních typu loopback, v Linuxu zpravidla nazývaných dummy. Takové rozhraní samo o sobě nemá konektivitu do žádné další sítě. Adresa nakonfigurovaná na loopback rozhraní je používána například při zasílání ICMPv4 zpráv Time Exceeded, ale také jako odchozí adresa pro běžné pakety iniciované procesy běžícími na zařízení.

Pokud je k síťovému uzlu (počítači, resp. routeru), více síťových cest, ale zároveň k němu chceme přistupovat pomocí jedné adresy nezávisle na tom, kterou z cest použijeme, nakonfigurujeme tuto adresu na rozhraní typu loopback a pomocí routovacích protokolů zařídíme, že je tato adresa viditelná přes všechny síťové cesty. Tyto síťové cesty ale často mají své vlastní adresování s maskou /31, /30, nebo větší.

Nešlo by to ještě lépe?

I když je díky masce sítě /31 možné jeden /24 blok adres rozkrájet na až 128 propojovacích sítí mezi routery, pořád tento mechanismus konzumuje drahé IPv4 adresy. Proto se už v roce 2008 objevil návrh využít v IPv4 routovacích tabulkách jako „next-hop“ gateway IPv6 adresy routerů. Návrh byl v roce 2009 publikován jako RFC 5549, aby byl následně v roce 2020 nahrazen novější verzí RFC 8950.

Primárním účelem bylo využít tento princip pro komunikaci mezi BGP routery, ale mechanismus je to použitelný i na sítích, kde BGP neprovozujeme. Do linuxového jádra se podpora dostala na jaře 2019 v kernelu 5.2.

Princip je vlastně geniálně jednoduchý: zatímco v klasickém způsobu routování konfigurujeme IPv4 adresu „next-hop“ routeru a hardwarovou adresu tohoto routeru si zařízení zjistí pomocí ARP protokolu, v případě IPv6 next-hopu použijeme IPv6 adresu sousedního routeru – může být globální, ULA, ale i link-local – a hardwarovou adresu routeru si zařízení zjistí pomocí IPv6 – ICMPv6 Neighbor Discovery.

Aby komunikace dobře fungovala, musí na každém zařízení, které tento princip využívá, stále být nakonfigurovaná alespoň jedna IPv4 adresa – ta ale může být na síťovém zařízení typu loopback.

Pro příklad si představme síť se dvěma linuxovými uzly, Routerem a Charliem.

Charlie a Router: dva síťové uzly propojené sítí bez globálních IP adres. Pro komunikaci a konfiguraci routování využívají IPv6 link-local adresy.

Charlie a Router: dva síťové uzly propojené sítí bez globálních IP adres

Autor: Radek Zajíc
Router  MAC 36:7a:aa:d0:cb:38, LL fe80::347a:aaff:fed0:cb38, dummy0 IP 203.0.113.64/32
Charlie MAC 4a:b1:9e:68:13:61, LL fe80::48b1:9eff:fe68:1361, dummy0 IP 203.0.113.65/32

Na routeru nakonfigurujeme veřejnou IPv4 adresu na rozhraní  dummy0.

operator@router:~# ip -4 a s dev dummy0
76: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500
    inet 203.0.113.64/32 scope global dummy0

Charlie si také nakonfiguruje svou adresu na rozhraní dummy0. Zároveň zkontrolujeme routovací tabulku u Charlieho – ta zůstává prázdná, komunikace s Internetem nefunguje.

charlie@charlie:~# ip -4 a s dev dummy0
3: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500
    inet 203.0.113.65/32 scope global dummy0

charlie@charlie:~# ip route

charlie@charlie:~# ping 8.8.8.8
ping: connect: Network is unreachable

Nyní Charlie nakonfiguruje výchozí bránu s využitím IPv6. Jeho IPv4 routovací tabulka bude obsahovat jediný záznam, výchozí bránu. Zde je důležité zmínit, že záznam v tabulce musí pro správnou funkčnost obsahovat i IPv4 adresu z rozhraní dummy0, a to v parametru src. Pokud je pro IPv6 next-hop použita link-local adresa, musí routovací tabulka obsahovat i parametr dev  určující zařízení, skrze které je link-local adresa dostupná.

charlie@charlie:~# ip -4 route add 0.0.0.0/0 via inet6 \
    fe80::347a:aaff:fed0:cb38 dev from_charlie src 203.0.113.65

charlie@charlie:~# ip -4 route
default via inet6 fe80::347a:aaff:fed0:cb38 dev from_charlie src 203.0.113.65

Na straně routeru můžeme pro zpřístupnění Charlieho použít například „device route“:

operator@router:~# ip route | grep 203.0.113.65
203.0.113.65 dev to_charlie scope link

operator@router:~# arp -n | grep 203.0.113.65
203.0.113.65  ether  4a:b1:9e:68:13:61  C  to_charlie

V takovém případě bude router stále používat protokol ARP pro zjištění, jakou hardwarovou adresu má IPv4 adresa uzlu Charlie.

10:19:01.537002 ARP, Request who-has 203.0.113.65 tell 203.0.113.64, length 28
10:19:01.537006 ARP, Reply 203.0.113.65 is-at 4a:b1:9e:68:13:61, length 28

Lepší ale je, když do IPv4 routovací tabulky routeru vložíme podobný IPv6 next-hop, jako si u sebe přidal Charlie:

operator@router:~# ip route add 203.0.113.65 via \
  inet6 fe80::48b1:9eff:fe68:1361 dev to_charlie

operator@router:~# ip route | grep 203.0.113.65
203.0.113.65 via inet6 fe80::48b1:9eff:fe68:1361 dev to_charlie

Nyní router už nepoužije ARP, ale ICMPv6 Neighbor Discovery, a závislost na protokolech z rodiny IPv4 úplně odpadne.

10:21:29.516907 IP6 fe80::347a:aaff:fed0:cb38 > ff02::1:ff68:1361:
  ICMP6, neighbor solicitation, who has fe80::48b1:9eff:fe68:1361, length 32
10:21:29.516914 IP6 fe80::48b1:9eff:fe68:1361 > fe80::347a:aaff:fed0:cb38:
  ICMP6, neighbor advertisement, tgt is fe80::48b1:9eff:fe68:1361, length 32

Podobně Charlie, pokud chce komunikovat s Google DNS, použije pro zjištění hardwarové adresy routeru ICMPv6 Neighbor Discovery a hardwarovou adresu routeru si uloží do tabulky IPv6 sousedů.

charlie@charlie:~# ip -6 neigh
fe80::347a:aaff:fed0:cb38 dev from_charlie lladdr 36:7a:aa:d0:cb:38 router REACHABLE

Všimněte si, že IPv6 se zde používá jen a pouze pro zjištění hardwarové adresy routeru, další komunikace na síťové vrstvě vypadá stejně jako v případě IPv4 next-hopu.

Charlie použije na síťové vrstvě IPv6 - konkrétně ICMPv6 Neighbor Solicitation pro zjištění hardwarové adresy Routeru. Další komunikace s 8.8.8.8 už na síťové vrstvě používá IPv4.

Pohled Wiresharkem na IPv6 next-hop pro IPv4

Autor: Radek Zajíc

Pro úplnost dodejme, že IPv4 routovací tabulka v Linuxu může současně obsahovat libovolné podporované typy záznamů, například device route, v tomto případě pro PPPoE WAN, IPv4 next hop, i IPv6 next hop:

root@router:~# ip route | egrep '(default|203.0.113.65)'
default dev ppp0 scope link metric 9
default via 192.0.2.1 dev wan1 metric 10
203.0.113.65 via inet6 fe80::48b1:9eff:fe68:1361 dev to_charlie

K čemu je to dobré

Primárním účelem je zjednodušit konfiguraci síťových zařízení – byť to tak na první pohled nevypadá. Tento způsob konfigurace umožňuje na síťové vrstvě zcela eliminovat propojovací IPv4 sítě, které už nepotřebujete. Tím si zjednodušíte plánování adresních rozsahů, ušetříte vzácné adresy – veřejné i privátní – protože je vůbec nepotřebujete, a snížíte počet změn, které musíte na routerech provést.

V datacentrech lze tento režim konfigurace využít třeba pro připojení serverů, které v extrémním případě mohou používat „unnumbered“ adresování – tedy na odchozím rozhraní nemusí mít vůbec žádné globáně routovatelné IPv4 ani IPv6 adresy. Pro komunikaci s výchozí branou/routerem si pro IPv4 i IPv6 vystačí s IPv6 link-local adresami, a pro odchozí provoz budou používat jednu IPv6 a jednu IPv4 adresou, v obou případech nakonfigurovanou na rozhraní dummy0, kterou budou oznamovat nadřazeným routerům.

zabbix_tip

IPv6 next-hop je zajímavou alternativou i pro síťové konfigurace, kdy potřebujete jednu IPv4 adresu naroutovat na stroj kdesi v síti, ale nechcete kvůli tomu propojovací segmenty mezi všemi mezilehlými routery očíslovat IPv4 adresami.

V další části článku si ukážeme konkrétní příklady, jak „unnumbered BGP“ včetně automatické detekce BGP peerů a IPv4 over IPv6-next-hop nakonfigurovat na routerech a na serverech s Linuxem a routovacím démonem Bird 2.

Autor článku

Radek Zajíc se profesně věnuje světu Linuxu, sítím a telekomunikacím. Snaží se rozšiřovat služby dostupné pomocí protokolu IPv6 a aktivně se věnuje popularizaci tohoto protokolu.