3-bo‘lim
Ethernet, MAC manzil va ARP
Kadr tuzilishi, MAC manzil nima va uning bitlari nimani anglatadi, kalit qanday ishlaydi va ARP qanday qilib IP dan MAC ni topadi.
Ushbu bo‘lim mundarijasi
Eng pastki amaliy qatlamdan boshlaymiz. Bu yerda kompyuterlar bir-birini IP manzil bilan emas, butunlay boshqa manzil bilan topadi.
Kanal qatlami nima qiladi? #
Uning vazifasi juda tor: bitta tarmoq ichida, qo'shnidan qo'shniga bir bo'lak ma'lumot yetkazish. Boshqa shaharga yo'l topish uning ishi emas - u bilan 3-qatlam shug'ullanadi.
Bu qatlamdagi ma'lumot bo'lagi kadr (frame) deb ataladi.
| Kanal qatlami qiladi | Qilmaydi |
|---|---|
| Qo'shni qurilmaga yetkazish | Uzoq tarmoqqa yo'l topish |
| Kadr buzilganini aniqlash | Yo'qolgan kadrni qayta yuborish |
| Kimga mo'ljallanganini belgilash | Qaysi dasturga tegishlini bilish |
Ethernet kadri #
Ethernet - eng keng tarqalgan kanal protokoli. Uning sarlavhasi hayratlanarli darajada sodda: bor-yo'g'i 14 bayt.
Kadrni qo'lda yig'ib ko'ramiz:
import struct
# Qo'lda yig'ilgan Ethernet kadri (sarlavha + kichik foydali yuk)
manzil = bytes.fromhex("aabbccddeeff") # kimga
jonatuvchi = bytes.fromhex("001a2b3c4d5e") # kimdan
tur = struct.pack("!H", 0x0800) # 0x0800 = ichida IPv4
yuk = b"...IP paketi..."
kadr = manzil + jonatuvchi + tur + yuk
print("kadr uzunligi:", len(kadr), "bayt")
print("o'n oltilik ko'rinishi:")
h = kadr.hex()
for i in range(0, len(h), 48):
oxir = min(i + 48, len(h))
qator = " ".join(h[j:j + 2] for j in range(i, oxir, 2))
print(" " + qator)
kadr uzunligi: 29 bayt
o'n oltilik ko'rinishi:
aa bb cc dd ee ff 00 1a 2b 3c 4d 5e 08 00 2e 2e 2e 49 50 20 70 61 6b 65
74 69 2e 2e 2e
Birinchi 6 bayt - kimga, keyingi 6 bayt - kimdan, keyin 08 00 -
"ichida IPv4 bor". Qolgani - foydali yuk.
!H nima degani?struct.pack("!H", 0x0800) - sonni ikki baytga aylantiradi.
H- ikki baytli musbat son (unsigned short)!- tarmoq tartibi (network byte order), ya'ni eng katta bayt oldinda
Bu juda muhim: protsessorlar sonlarni xotirada turlicha saqlaydi, tarmoqda esa yagona tartib kelishib olingan. Tarmoq tartibi har doim "katta bayt oldinda".
Kadrni ochish #
Yozish qanchalik oson bo'lsa, o'qish ham shunchalik:
import struct
TURLAR = {0x0800: "IPv4", 0x0806: "ARP", 0x86DD: "IPv6"}
def mac(bayt):
return ":".join(f"{b:02x}" for b in bayt)
def kadrni_och(kadr):
manzil, jonatuvchi, tur = struct.unpack("!6s6sH", kadr[:14])
return {
"kimga": mac(manzil),
"kimdan": mac(jonatuvchi),
"tur": TURLAR.get(tur, f"0x{tur:04x}"),
"yuk": kadr[14:],
}
kadr = bytes.fromhex("aabbccddeeff001a2b3c4d5e0800") + b"...IP paketi..."
q = kadrni_och(kadr)
print("kimdan:", q["kimdan"])
print("kimga :", q["kimga"])
print("ichida:", q["tur"])
print("yuk :", q["yuk"].decode())
kimdan: 00:1a:2b:3c:4d:5e
kimga : aa:bb:cc:dd:ee:ff
ichida: IPv4
yuk : ...IP paketi...
Mana shu - tarmoq kartasi har kadr uchun bajaradigan ishning soddalashtirilgan modeli.
MAC manzil ichida nima bor? #
MAC manzil 6 bayt, ya'ni 48 bit. U shunchaki tasodifiy son emas - birinchi baytning ikki eng past biti maxsus ma'noga ega:
def mac_tahlil(matn):
bayt = bytes.fromhex(matn.replace(":", ""))
birinchi = bayt[0]
return {
"manzil": matn,
# eng past bit: 0 = bitta qurilmaga, 1 = guruhga
"yuborish": "guruhga" if birinchi & 1 else "bitta qurilmaga",
# ikkinchi bit: 0 = ishlab chiqaruvchi bergan, 1 = mahalliy
"kim bergan": "mahalliy" if birinchi & 2 else "ishlab chiqaruvchi",
"ishlab chiqaruvchi qismi": matn[:8],
"qurilma qismi": matn[9:],
}
for m in ["00:1a:2b:3c:4d:5e", "ff:ff:ff:ff:ff:ff", "02:42:ac:11:00:02"]:
q = mac_tahlil(m)
print(q["manzil"])
print(" yuborish :", q["yuborish"])
print(" kim bergan:", q["kim bergan"])
print(" OUI / qurilma:", q["ishlab chiqaruvchi qismi"],
"/", q["qurilma qismi"])
00:1a:2b:3c:4d:5e
yuborish : bitta qurilmaga
kim bergan: ishlab chiqaruvchi
OUI / qurilma: 00:1a:2b / 3c:4d:5e
ff:ff:ff:ff:ff:ff
yuborish : guruhga
kim bergan: mahalliy
OUI / qurilma: ff:ff:ff / ff:ff:ff
02:42:ac:11:00:02
yuborish : bitta qurilmaga
kim bergan: mahalliy
OUI / qurilma: 02:42:ac / 11:00:02
Uchta manzil, uchta hikoya:
| Manzil | Nima ekani |
|---|---|
00:1a:2b:... | Oddiy tarmoq kartasi |
ff:ff:ff:ff:ff:ff | Tarqatish (broadcast) - hammaga |
02:42:ac:... | Dasturiy qurilma - masalan konteyner |
ff:ff:... bo'yicha natijani to'g'ri o'qingDastur ff:ff:ff:ff:ff:ff uchun "mahalliy" deb yozdi, chunki
ikkinchi bit haqiqatan yoqilgan.
Lekin bu manzil alohida ajratib qo'yilgan: u "hamma eshitsin" degani. Uni hech kim "o'ziniki" qilib qo'ymaydi.
Bit tahlili qoidani to'g'ri qo'lladi - shunchaki bu manzil qoidadan tashqarida turadi. Protokollarni o'qiyotganda bunday istisnolarni alohida eslab qolish kerak.
02: bilan boshlanadigan manzillar ham qiziq: ikkinchi bit
yoqilgan, ya'ni uni ishlab chiqaruvchi emas, dastur bergan.
Docker konteynerlari va virtual mashinalar aynan shunday
manzillar ishlatadi.
Kalit (switch) qanday ishlaydi? #
Eski tarmoqlarda hab (hub) ishlatilardi: u kelgan kadrni hamma portga takrorlardi. Natijada tarmoqning butun tezligi hammaga bo'linardi.
Kalit boshqacha ish tutadi - u o'rganadi:
- Kadr keldi - kalit uning jo'natuvchi MAC ini va qaysi portdan kelganini yozib qo'yadi.
- Kadrni kimga uzatishni jadvaldan qaraydi.
- Jadvalda yo'q bo'lsa - hamma portga yuboradi (bir marta).
- Javob kelganda ikkinchi manzilni ham o'rganadi.
Bir necha kadrdan keyin kalit butun tarmoq xaritasini biladi va har kadrni faqat kerakli portga yuboradi.
ARP - IP dan MAC ni topish #
Endi eng muhim savol. Siz 192.168.1.20 ga murojaat qilasiz,
lekin kadr yuborish uchun MAC manzil kerak. Uni qayerdan
olasiz?
Javob: so'raysiz. Bu ARP protokoli.
class Tarmoq:
"""Bitta LAN - qurilmalar bir-birini eshitadi."""
def __init__(self):
self.qurilmalar = {} # IP -> MAC
self.efir = [] # tarqatilgan so'rovlar jurnali
def qosh(self, ip, mac):
self.qurilmalar[ip] = mac
def arp_sorov(self, kim_soradi, qidirilayotgan_ip):
self.efir.append(f"{kim_soradi} tarqatdi: {qidirilayotgan_ip} kimda?")
return self.qurilmalar.get(qidirilayotgan_ip)
class Kompyuter:
def __init__(self, nom, ip, mac, tarmoq):
self.nom, self.ip, self.mac = nom, ip, mac
self.tarmoq = tarmoq
self.arp_jadval = {}
tarmoq.qosh(ip, mac)
def mac_topish(self, ip):
if ip in self.arp_jadval:
print(f" {self.nom}: {ip} keshda bor - so'rov kerak emas")
return self.arp_jadval[ip]
print(f" {self.nom}: {ip} keshda yo'q - ARP so'rovi tarqatiladi")
mac = self.tarmoq.arp_sorov(self.nom, ip)
if mac:
self.arp_jadval[ip] = mac
return mac
lan = Tarmoq()
husanboy = Kompyuter("husanboy-pc", "192.168.1.10", "00:1a:2b:3c:4d:5e", lan)
Kompyuter("malika-pc", "192.168.1.20", "00:1a:2b:99:88:77", lan)
print("1-urinish:")
print(" natija:", husanboy.mac_topish("192.168.1.20"))
print("2-urinish:")
print(" natija:", husanboy.mac_topish("192.168.1.20"))
print("yo'q qurilma:")
print(" natija:", husanboy.mac_topish("192.168.1.99"))
print()
print("efirga chiqqan so'rovlar:", len(lan.efir))
for q in lan.efir:
print(" ", q)
1-urinish:
husanboy-pc: 192.168.1.20 keshda yo'q - ARP so'rovi tarqatiladi
natija: 00:1a:2b:99:88:77
2-urinish:
husanboy-pc: 192.168.1.20 keshda bor - so'rov kerak emas
natija: 00:1a:2b:99:88:77
yo'q qurilma:
husanboy-pc: 192.168.1.99 keshda yo'q - ARP so'rovi tarqatiladi
natija: None
efirga chiqqan so'rovlar: 2
husanboy-pc tarqatdi: 192.168.1.20 kimda?
husanboy-pc tarqatdi: 192.168.1.99 kimda?
Uch marta murojaat qilindi, lekin efirga faqat ikki so'rov chiqdi - ikkinchisida javob keshdan olindi. Haqiqiy ARP keshi ham xuddi shunday ishlaydi.
Linux va macOS da:
ip neigh
Windows da:
arp -a
Ro'yxatdagi har qator - yaqinda gaplashgan qo'shningiz. Odatda u yerda marshrutizator (router) ham bo'ladi - chunki tashqi dunyoga chiqadigan har paket avval unga boradi.
ARP 1982-yilda yozilgan va u davrda tarmoqdagi hamma bir-biriga ishonardi.
Natijada: javobni kim bergani tekshirilmaydi. Bir tarmoqdagi hujumchi "192.168.1.1 mening MAC imda" deb yolg'on javob yuborishi mumkin - va butun trafik undan o'tadi.
Bu ARP spoofing deb ataladi. Himoya kanal qatlamida emas, yuqorida quriladi: TLS ishlatilsa, hujumchi trafikni ko'radi, lekin o'qiy olmaydi. Buni 15-bo'limda ko'ramiz.
- Kadr yig'ish misolini ishga tushiring.
turni0x86DDga o'zgartiring va kadrni qayta oching.- Noma'lum tur raqami bering - dastur nima chiqaradi?
- MAC tahlilini
01:00:5e:00:00:01uchun ishga tushiring. - O'z kompyuteringizdagi MAC manzilni toping va uni tahlil qiling.
- ARP misolida uchinchi kompyuter qo'shing.
- ARP keshini tozalaydigan metod yozing va so'rovlar sonini qaytadan sanang.
ip neighyokiarp -ani ishga tushiring va natijani o'qing.- Hab va kalit farqini uch qatorda yozing.
- Nima uchun kanal qatlami uzoq tarmoqqa yo'l topa olmasligini tushuntiring.
Xulosa #
- Kanal qatlami faqat bitta tarmoq ichida, qo'shnidan qo'shniga yetkazadi.
- Bu qatlamdagi ma'lumot bo'lagi - kadr.
- Ethernet sarlavhasi 14 bayt: kimga (6), kimdan (6), turi (2).
- "Turi" maydoni ichkarida nima borligini aytadi: IPv4, ARP yoki IPv6.
- Tarmoqda sonlar katta bayt oldinda tartibida yoziladi (
!formati). - MAC 48 bit; birinchi baytning ikki biti yuborish turini va manba'ni bildiradi.
ff:ff:ff:ff:ff:ff- tarqatish manzili, uni hamma eshitadi.- Kalit jo'natuvchi manzillarni eslab, kadrni faqat kerakli portga yuboradi.
- ARP IP manzildan MAC manzilni topadi va natijani keshlaydi.
- ARP javobni tekshirmaydi - shuning uchun himoya yuqori qatlamlarda quriladi.
Keyingi bo'limda bir tarmoqdan chiqamiz va IP manzil bilan tarmoq maskasini o'rganamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
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.