6-bo‘lim

IPv6

IPv4 manzillari nima uchun tugadi, IPv6 yozuvi va qisqartirish qoidalari, manzil turlari va ikki stekli ishlash.

🕑 9 daqiqa o‘qish 📄 842 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Manzillar haqiqatan tugadi
  2. Yozuv va qisqartirish
  3. Manzil turlari
  4. IPv6 bilan dasturlash
  5. O'tish nima uchun shuncha cho'zildi?
  6. Xulosa

1981-yilda IPv4 ta'riflanganda to'rt milliard manzil cheksiz ko'p tuyulgan edi. O'sha paytda internetga ulangan kompyuterlar soni yuzlab edi.

Bugun har bir odamda bir necha qurilma bor.

Manzillar haqiqatan tugadi #

Python
import ipaddress

v4 = ipaddress.IPv4Network("0.0.0.0/0")
v6 = ipaddress.IPv6Network("::/0")

print("IPv4 manzillari:", f"{v4.num_addresses:,}".replace(",", " "))
print("IPv6 manzillari:", f"{v6.num_addresses:.3e}")
print()
print("IPv4 - bitlar soni:", v4.max_prefixlen)
print("IPv6 - bitlar soni:", v6.max_prefixlen)
print("necha barobar ko'p:", f"2^{v6.max_prefixlen - v4.max_prefixlen}")

# Yer yuzidagi har kvadrat metrga nechta manzil to'g'ri keladi?
YER_YUZASI_M2 = 510_000_000 * 1_000_000   # 510 mln km2
print()
print("har kvadrat metrga:", f"{v6.num_addresses // YER_YUZASI_M2:.3e}")
Natija
IPv4 manzillari: 4 294 967 296
IPv6 manzillari: 3.403e+38

IPv4 - bitlar soni: 32
IPv6 - bitlar soni: 128
necha barobar ko'p: 2^96

har kvadrat metrga: 6.672e+23

Manzil uzunligi 32 bitdan 128 bitga o'tdi. Bu to'rt barobar emas - 2⁹⁶ barobar ko'p. Yer yuzining har kvadrat metriga 6,6×10²³ ta manzil to'g'ri keladi.

Nima uchun IPv5 yo'q?

5 raqami 1970-yillarda boshqa tajriba protokoliga (*Internet Stream Protocol*) berib yuborilgan edi.

Yangi versiya kelganda 5 band edi, shuning uchun u to'g'ridan- to'g'ri 6 raqamini oldi.

Yozuv va qisqartirish #

IPv6 manzil 128 bit - sakkizta guruh, har biri to'rtta o'n oltilik raqam. To'liq yozuv juda uzun, shuning uchun ikkita qisqartirish qoidasi bor:

  1. Guruh boshidagi nollar tashlab ketiladi: 0db8db8.
  2. Ketma-ket kelgan nol guruhlar :: bilan almashtiriladi - faqat bir marta.
Python
import ipaddress

manzillar = [
    "2001:0db8:0000:0000:0000:ff00:0042:8329",
    "2001:db8::ff00:42:8329",
    "fe80::1",
    "::1",
    "::",
]

for m in manzillar:
    a = ipaddress.IPv6Address(m)
    print("yozilgani :", m)
    print("qisqargani:", a.compressed)
    print("to'liq    :", a.exploded)
    print()
Natija
yozilgani : 2001:0db8:0000:0000:0000:ff00:0042:8329
qisqargani: 2001:db8::ff00:42:8329
to'liq    : 2001:0db8:0000:0000:0000:ff00:0042:8329

yozilgani : 2001:db8::ff00:42:8329
qisqargani: 2001:db8::ff00:42:8329
to'liq    : 2001:0db8:0000:0000:0000:ff00:0042:8329

yozilgani : fe80::1
qisqargani: fe80::1
to'liq    : fe80:0000:0000:0000:0000:0000:0000:0001

yozilgani : ::1
qisqargani: ::1
to'liq    : 0000:0000:0000:0000:0000:0000:0000:0001

yozilgani : ::
qisqargani: ::
to'liq    : 0000:0000:0000:0000:0000:0000:0000:0000

Birinchi ikki manzil bir xil ekaniga e'tibor bering - ular shunchaki turlicha yozilgan.

:: faqat bir marta ishlatiladi

Agar manzilda ikkita alohida nol guruhlari bo'lsa, ularning faqat bittasini :: bilan qisqartirish mumkin.

Sabab oddiy: ikki marta ishlatilsa, qaysi :: nechta nolni yashirayotganini aniqlab bo'lmaydi.

Shuning uchun 2001:0:0:1:0:0:0:1 ni 2001::1::1 deb yozib bo'lmaydi - bu xato. To'g'risi: 2001:0:0:1::1.

Manzil turlari #

IPv6 da xususiy/ommaviy bo'linish boshqacha tashkil qilingan:

Python
import ipaddress

manzillar = {
    "2606:2800:220:1:248:1893:25c8:1946": "ommaviy sayt",
    "fe80::215:5dff:feae:a236": "havola-mahalliy",
    "fd00:1234::1": "noyob mahalliy (ichki)",
    "ff02::1": "ko'p manzilli - shu havoladagi hamma",
    "::1": "loopback",
}

for m, izoh in manzillar.items():
    a = ipaddress.IPv6Address(m)
    turlar = []
    if a.is_loopback:
        turlar.append("loopback")
    if a.is_link_local:
        turlar.append("havola-mahalliy")
    if a.is_multicast:
        turlar.append("ko'p manzilli")
    if a.is_private:
        turlar.append("xususiy")
    if a.is_global:
        turlar.append("global")
    print(f"{m}")
    print(f"   izoh : {izoh}")
    print(f"   turi : {', '.join(turlar)}")
Natija
2606:2800:220:1:248:1893:25c8:1946
   izoh : ommaviy sayt
   turi : global
fe80::215:5dff:feae:a236
   izoh : havola-mahalliy
   turi : havola-mahalliy, xususiy
fd00:1234::1
   izoh : noyob mahalliy (ichki)
   turi : xususiy
ff02::1
   izoh : ko'p manzilli - shu havoladagi hamma
   turi : ko'p manzilli, global
::1
   izoh : loopback
   turi : loopback, xususiy
ff02::1 uchun "global" chiqdi - bunga ishonmang

Bu - kutubxonaning ichki qoidasi natijasi, protokol haqiqati emas.

Python da is_global shunchaki is_private ning teskarisi sifatida hisoblanadi. ff02::1 esa xususiy diapazonlar ro'yxatiga kiritilmagan - shuning uchun "global" chiqdi.

Aslida ff02:: bilan boshlanadigan manzillar havola doirasidagi ko'p manzilli guruhdir: ular birinchi marshrutizatordan nariga o'tmaydi.

Xulosa: kutubxona javobi bilan protokol qoidasi har doim ham bir xil emas. Shubha tug'ilsa - standartga qarang.

Asosiy turlar:

PrefiksTuriIPv4 dagi o'xshashi
2000::/3Global unicastOmmaviy manzillar
fc00::/7Noyob mahalliy10.x, 192.168.x
fe80::/10Havola-mahalliy169.254.x
ff00::/8Ko'p manzilliTarqatish o'rniga
::1Loopback127.0.0.1
IPv6 da tarqatish (broadcast) yo'q

IPv4 da 192.168.1.255 ga yuborilgan paketni hamma oladi - hatto qiziqmaganlar ham.

IPv6 da bundan voz kechildi. O'rniga ko'p manzilli guruhlar ishlatiladi:

ManzilKim eshitadi
ff02::1Havoladagi barcha qurilmalar
ff02::2Faqat marshrutizatorlar

Farqi shuki, qurilma o'zi qiziqadigan guruhga obuna bo'ladi. Qolganlari paketni umuman ko'rmaydi va ularning protsessori bekorga band bo'lmaydi.

IPv6 bilan dasturlash #

Soket kodi deyarli o'zgarmaydi - faqat oila AF_INET6 bo'ladi:

Python
import socket

PORT = 9200

# AF_INET6 - IPv6 soketi. Manzil ::1 - IPv6 dagi loopback.
server = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("::1", PORT))
server.listen(1)

mijoz = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
mijoz.connect(("::1", PORT))
ulanish, kim = server.accept()

mijoz.sendall("IPv6 orqali salom".encode())
print("server oldi:", ulanish.recv(1024).decode())

# IPv6 manzili to'rt elementli: (manzil, port, oqim, qamrov)
print("mijoz manzili elementlari:", len(mijoz.getsockname()))
print("manzil:", mijoz.getpeername()[0])
print("port  :", mijoz.getpeername()[1])

mijoz.close()
ulanish.close()
server.close()
Natija
server oldi: IPv6 orqali salom
mijoz manzili elementlari: 4
manzil: ::1
port  : 9200

Bitta farq bor: IPv4 da manzil ikki elementli (manzil, port), IPv6 da esa to'rt elementli. Qo'shimcha ikkitasi oqim belgisi va qamrov identifikatori uchun.

Aynan shuning uchun manzil[0] va manzil[1] deb yozgan kod ikkala versiyada ham ishlaydi, manzil == (ip, port) deb taqqoslagan kod esa IPv6 da buziladi.

Ikkala versiyani birga qo'llab-quvvatlash

Manzilni qo'lda yozish o'rniga getaddrinfo ishlatiladi - u nom uchun mavjud barcha variantlarni qaytaradi:

YondashuvNatija
AF_INET qattiq yozilganFaqat IPv4
AF_INET6 qattiq yozilganFaqat IPv6
getaddrinfo + AF_UNSPECIkkalasi ham

Zamonaviy mijozlar Happy Eyeballs usulini qo'llaydi: IPv6 va IPv4 ga deyarli bir vaqtda ulanib ko'radi va qaysi biri tezroq javob bersa, o'shani ishlatadi.

Shu tufayli IPv6 sekin ishlayotgan tarmoqda ham sayt tez ochiladi.

O'tish nima uchun shuncha cho'zildi? #

IPv6 1998-yilda standart bo'lgan. 2012-yilda "World IPv6 Launch" o'tkazildi. Shunga qaramay bugun ham ko'p tarmoqlarda faqat IPv4 ishlaydi.

Sabab - ular bir-biri bilan gaplasha olmaydi:

MuammoNatija
IPv6 qurilma IPv4 serverga to'g'ridan-to'g'ri ulana olmaydiIkkalasi kerak
Eski qurilmalar IPv6 ni bilmaydiAlmashtirish qimmat
NAT IPv4 ni "yetarli" qilib qo'ydiShoshilishga sabab yo'q

Uchinchi qator eng muhimi: NAT (10-bo'lim) muammoni yumshatdi va shu bilan o'tishni ham sekinlashtirdi.

Amaldagi yechim - ikki stek (dual stack): qurilmada ikkala protokol ham bir vaqtda ishlaydi va kerak bo'lganini tanlaydi.

Amaliy topshiriq
  1. Manzil hajmi misolini ishga tushiring.
  2. 2001:0db8:0000:0000:0000:0000:0000:0001 ni qo'lda qisqartiring, keyin tekshiring.
  3. 2001:0:0:1:0:0:0:1 ni to'g'ri qisqartiring.
  4. Ikkita :: yozib ko'ring va qanday xato chiqqanini yozing.
  5. Manzil turlari misoliga o'z manzilingizni qo'shing.
  6. ip -6 addr bilan kompyuteringizdagi IPv6 manzillarni ko'ring.
  7. fe80:: bilan boshlanadiganini toping - u nima uchun kerak?
  8. IPv6 soket misolini ishga tushiring.
  9. ::1 ni 127.0.0.1 ga almashtiring - qanday xato chiqdi?
  10. IPv4 va IPv6 manzil kortejlari farqini tushuntiring.

Xulosa #

  • IPv4 da 32 bit, IPv6 da 128 bit - 2⁹⁶ barobar ko'p manzil.
  • IPv6 yozuvi sakkiz guruhdan iborat; nollar tashlanadi va :: bilan qisqartiriladi.
  • :: manzilda faqat bir marta ishlatilishi mumkin.
  • 2000::/3 - global, fc00::/7 - ichki, fe80::/10 - havola-mahalliy.
  • IPv6 da tarqatish yo'q - uning o'rnida ko'p manzilli guruhlar.
  • ff02::1 - havoladagi hamma, ff02::2 - faqat marshrutizatorlar.
  • Kutubxona bergan belgi (is_global) protokol haqiqatiga har doim mos kelmaydi.
  • Soket kodi deyarli bir xil: AF_INET o'rniga AF_INET6.
  • IPv6 manzil korteji to'rt elementli, IPv4 niki - ikkita.
  • Amalda ikki stek ishlatiladi; mijozlar Happy Eyeballs bilan tezrog'ini tanlaydi.

Keyingi bo'limda transport qatlamiga ko'tarilamiz va eng sodda protokoldan - UDP dan boshlaymiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.