Tarmoqdagi kompyuter MAC manzilini olish. Ethernet va ARP.
Salom. Anchadan beri maqola ham yoza olmadim. Shu aybimni yuvish uchun tarmoqlar bilan ishlaydigan kichkina (balki kattadir) dastur tuzdim. Bu dasturning asosiy maqsadi ikkita bir tarmoqdagi kompyuterlardan MAC manzil olishdir. Bu dasturni yozishda www.winpcap.org/ kutubxonalaridan (LIB, *.h) foydalandim.
Oddiy foydalanuvchi uchun tarmoq, internet oddiygina ishlaydi. Login/parol ni teradi va browserni ochib hohlagan saytiga kira (agar dostup yopilmagan bo’lsa 🙂 ). Lekin biz dasturchi sifatida hamma narsani tushunishimiz kerak.
Keling Ethernet haqida. Bundan ancha oldin (3-kursligimda, TATU da) Ethernet 10 Base, 100 Base lar haqida kurs ishi topshirganman. Yodlab topshirganman, nima gapirganimni o’zim tushunmaganman, domlani bilmadim. Tushunmagan odam qanday qilib tushuntiradi :). Lekin baho olganman. Hozirga kelib ozgina bo’lsada tasavvurga ega bo’ldim desam ham bo’ladi.
Ethernet o’zi nima? OSI modeli bo’yicha 2-daraja (kanal darajasida) ishlaydigan protokol. Manimcha bu gapni hamma joylarda o’qigansiz a? Oddiyroq qilib tushuntirsam.
Siz pizzaplanet.uz/ saytiga kirib pizza zakaz qilsangiz, sizning zakazingiz aytgan manzilingizga ma’lum bir muddat ichida yetib keladi. Shu pizzani sizga kim olib keladi? Kuryer. Shu pizzani tayyorlanganidan to sizning uyingizgacha ko’tarib keladigan kuryerni — Ethernet desa bo’ladi. Pizza — bu ethernet protokolning ustiga qurilgan ma’lumot.
Demak ethernet — tarmoqdagi ikkita kompyuter orasidagi aloqani ta’minlovchi protokol. Ya’ni birinchi kompyuterdagi pizzani ikkinchi kompyuterga yetkazishga xizmat qiladiga kuryer.
MAC manzil nima?. Bu tarmoq platasining manzili. Bu gapni ham deyali barcha kitoblarda o’qisiz. Aslida ham shunday. Bizani pizza misolida ko’rsak MAC manzil pizzani tayyorlangan joy va sizning uyingizning manzili bo’ladi.
Endi keling ethernet protokolini tuzilishini ko’rsak: Siz zakaz berishingizdan oldin manzilingizni shunga qo’shimcha ma’lumotlaringizni ham kiritasiz. Tarmoqda ham xuddi shunday. Agar bitta kompyuter ikkinchisiga ma’lumot yubormoqchi bo’lsa quyidagicha ma’lumotlarni paketga yozadi.
commons.wikimedia.org/wiki/File:Ethernet_Type_II_Frame_format.svg?uselang=ru
Destination MAC address — jo’natilayotgan qurilmaning MAC manzili. Ya’ni sizning uyingizning manzili.
Source MAC address — jo’natuvchining MAC manzili. pizzaplanet ning manzili.
EtherType — paket turi. To’liq ro’yxatini en.wikipedia.org/wiki/EtherType dan ko’rishingiz mumkin. Bizni holatda qanaqa pizza zakaz qilganingiz.
Payload — qo’shimcha ma’lumotlar. Kamida 46 baytdan 1500 baytgacha bo’lishi mumkin. Bizni misolda pizzani kattaligi, yoniga qo’shimcha masalliqlari haqidagi ma’lumotlar shu yerda bo’ladi.
CRC checksum — bu yerda oldidagi ma’lumotlardan kelib chiqib 4 baytli sonni xosil qiladi va shu yerga yoziladi. Yetib borgan kompyuter ham qabul qilgan ma’lumotlaridan kelib chiqib CRC ni hosil qiladi va solishtiradi. Agar to’g’ri kelsa paketni qabul qiladi, agar noto’g’ri bo’lsa paket o’ldiriladi. Bizni misolda, siz zakaz qilgan narsalarning birontasi qolib ketgan bo’lsa, zakazni qabul qilmagan bo’lasiz.
Keling endi quyidagicha holatni ko’rsak, demak ikkita kompyuter bir biri bilan bog’lanishi uchun ikkichi kompyuterning MAC manzilini bilishi kerak ekan. Lekin tarmoqqa yangi kompyuter kelsayu unga tarmoq IP si berilsa qolgan kompyuterlar o’z-o’zidan yangi kelgan kompyuterni ham ko’ra boshlaydi. Biz hech qayerga yangi kompyuterning MAC manzilini yomadikku? Demak bu yerda yana nimadir bor.
IP manzil — har bir kompyuterga berilgan manzil (nom). Bitta tarmoq platasi bor kompyuterda bir nechta IP bo’lishi mumkin. Demak IP dasturiy yo’l bilan aniqlanarkan. Ya’ni Operatsion Sistema tomonidan hal qilinadi. IP haqida keyingi maqolalarda to’liqroq ma’lumot beraman. Bizning misolda sizning uyingizdagi har bir odamning ismi IP vasifasini bajarishi mumkin.
Ya’na savolga qaytsak. Yangi kompyuter kelgan MAC manzili bizar yozmasakda ishlab ketdi. Aslida u o’z o’zidan ishlamaydi. Buning uchun ARP (Address Resolution Protocol) protokoli ishlab chiqilgan. Bu protokol IP manzildan kelib chiqib, shu IP turgan kompyuterdagi tarmoq platasining MAC manzilini olishga xizmat qiladi. To’liq: ru.wikipedia.org/wiki/ARP
ARP ning tuzilishi
Hardware type (2 byte) — kanal darajasida ishlatilaniyotgan protokol raqami. Ethernet uchun bu qiymat — 0x0001
Protocol type (2 byte) — bu tarmoq protokoli. IPv4 uchun 0x0800.
Hardware length (1 byte) — kanal darajasidagi protokolidagi manzil uzunligi. Ethernet uzhun 6 qiymati bo’ladi. Chunki MAC manzilning uchunligi 6 bayt
Protocol length (1 byte) — tarmoq protokoli qiymati uzunligi. IPv4 uchun 4.
Operation (2 byte) — Qiymati 1 — so’rov, 2 — javob.
Sender hardware address — Operation=1 bo’lsa: sizning tarmoq platangizning MAC manzili. Operation=2 bo’lsa: sizga javob qaytargan kompyuterning MAC manzili
Sender protocol address — Operation = 1 bo’lsa: sizning IP manzilingiz. Operation=2 bo’sla: sizga javob qaytargan kompyuterning IP manzili
Target hardware address — Operation = 1 bo’lganda ishlatilmaydi (0 bo’ladi). Operation=2 bo’lgandan bu yerda sizning MAC manzilingiz bo’ladi.
Target protocol address — Operation = 1 bo’lsa: Sizga MAC manzili kerak bo’lgan kompyuterning IP manzili. Operation = 2 bo’lsa: Sizning IP manzilingiz.
IPv6 uchun bu protokol ishlatilmaydi. Buning o’rniga ICMPv6 (http://ru.wikipedia.org/wiki/ICMPv6) ishlatiladi. Vaqti kelib bularni ham ko’ramiz.
ARP ni pizza holatida tushuntirsam, sizning mahallangiz bu BROADCAST deyiladi tarmoqda. Sizning uyingiz bu kompyuter. Sizning uyingizning manzili MAC, sizning ismingiz esa etganimdek IP ga mos keladi. Kuryer mahalangizga keldiyu manzilingizni esidan chiqaridi. U mahallangizning boshiga keladi va sizning ismingizni etib uyingizni so’raydi. Ya’ni palonchining uyi qayerda. Bilgan odam sizning uyingizni ko’rsatadi. ARP ham xuddi shu usulda ishlaydi. IP li kompyuter qayerda ya’ni MAC manzili qaysi degab so’rovni beradi. Ethernetda BROADCAST ga paket jo’natish uchun Destination Address ga FF:FF:FF:FF:FF:FF ko’rsatiladi. Keyin Ethernetda EtherType bor edi, agar ro’yxatni ko’rgan bo’lsangiz APR protokoli uchun 0x0806.
Checksum (FCS) haqida — bu HASH funksiya. Ethernetda umuman tarmoqda jo’natilgan packet to’g’ri yetib borganligini tekshirishga kerak. Ya’ni jo’natuvchi jo’natilayotgan ma’lumotlardan kelib chiqib hesh qiymatni oladi fa Ethernet framening FCS ga yozib jo’natadi. Qabul qilgan kompyuter (qurilma) ham kelgan ma’lumotlarni heshlab jo’natilgan qiymat bilan solishtiriladi. Agar to’g’ri kelmasa paket «o’ldiriladi», agar to’g’ri kelsa paketni qayta ishlashni boshlaydi. Dastur kodida crc32 degan funksiya bajaradi bu vazifani. Kimdakim PHP da ishlagan bo’lsa unda ham CRC32.
Shu yerga kelguncha Ethernet, IP, ARP larni ko’rdik. Endi keling shulardan foydalanib tarmoqdagi biror IP li kompyuterning MAC manzilini olib ko’raylik. Tepada yozganimdek bizga WinPCap kerak bo’ladi. Bu tarmoq platasidan to’g’ridan to’g’ri eng pastki darajada ishlash imkoniyatini beradi. Aslida ko’pchilik tarmoq dasturchilari SOCKET dan darajasidan pastga tushishmaydi. Chunki qolgan pastdagi darajalarni OS ning o’zi hal qiladi.
Dasturni kompilyatsiya qilishdan oldin www.winpcap.org/devel.htm dan developer paketlarini ko’chirib olish zarur. Bundan tashqari www.winpcap.org/install/default.htm dan installerini olib o’rnatish kerak.
Dastur kodi. Izohlar kodning ichida berilgan.
#include
#include
#define HAVE_REMOTE
//Project > Properties (Alt + F7) > C++ > Additional Include Directories = c:/WpdPack/Include/
#include
#pragma comment(lib, "c:/WpdPack/Lib/wpcap.lib")
#pragma comment(lib, "c:/WpdPack/Lib/Packet.lib")
//pcap interface lar haqida ma'lumot saqlavchi o'zgaruvchilar
pcap_if_t *alldevs;
pcap_if_t *d = NULL;
//xatoliklar uchun
char errbuf[PCAP_ERRBUF_SIZE];
//IPv4 ni kiritib saqlash uchun
u_char ip[4];
//pcap handle (pointeri)
pcap_t *adhandle;
//CRC32 ni CHECKSUM ni hisoblash uchun zarur bo'lgan qiymatlar
const unsigned int Crc32Table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
void select_device();
unsigned int crc32(const unsigned char * buf, size_t len);
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
void main()
{
u_char packet[64];
//IP ni kiritish, ya'ni MAC manzili zarur bo'lgan IP
printf("IP ni kiriting: (a.b.c.d): ");
scanf("%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]);
//Qaysi qurilmadan jo'natish
select_device();
if (d == NULL)
{
return;
}
/* Qurilmani ochish */
if ( (adhandle= pcap_open(d->name, // name of the device
65536, // portion of the packet to capture
// 65536 guarantees that the whole packet will be captured on all the link layers
PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
1000, // read timeout
NULL, // authentication on the remote machine
errbuf // error buffer
) ) == NULL)
{
fprintf(stderr,"nQurilmani ochishda xatolik yuz berdi.n");
pcap_freealldevs(alldevs);
return;
}
printf("Tanlangan qurilma %s...n", d->description);
pcap_freealldevs(alldevs);
/*
Broadcastga ya'ni tarmoqdagi barcha kompyuterlarga
Qabul qiluvchiniki FF:FF:FF:FF:FF:FF */
packet[0]=0xFF;
packet[1]=0xFF;
packet[2]=0xFF;
packet[3]=0xFF;
packet[4]=0xFF;
packet[5]=0xFF;
/* Jo'natuvchiniki (ya'ni sizning kompingizniki). Manda MAC: 00-1E-8C-07-70-AC */
packet[6]=0x00;
packet[7]=0x1E;
packet[8]=0x8C;
packet[9]=0x07;
packet[10]=0x70;
packet[11]=0xAC;
//protocol type: ARP (2 byte) = 0x0806
packet[12] = 0x08;
packet[13] = 0x06;
//------------------------------
//Hardware type: Ethernet (2 byte) = 0x0001
packet[14] = 0x00;
packet[15] = 0x01;
//Protol type: IPv4 (2 byte) = 0x0800
packet[16] = 0x08;
packet[17] = 0x00;
//Hardware length: Ethernet uchun 6 (1 byte)
packet[18] = 0x06;
//Protocol length: IPv4 uchun 4 byte (1 byte)
packet[19] = 0x04;
//Operation: 1 - request, 2 - response (2 byte) = 0x0001
packet[20] = 0x00;
packet[21] = 0x01;
//Sender hardware address: Sizning MAC adresingiz
packet[22] = packet[6];
packet[23] = packet[7];
packet[24] = packet[8];
packet[25] = packet[9];
packet[26] = packet[10];
packet[27] = packet[11];
//Sender protocol address: Sizning IP manzilingiz. Manda 172.17.2.208
packet[28] = 172;
packet[29] = 17;
packet[30] = 2;
packet[31] = 208;
//Target hardware address. Qabul qiluvchining MAC manzili. Shartmas
packet[32] = 0;
packet[33] = 0;
packet[34] = 0;
packet[35] = 0;
packet[36] = 0;
packet[37] = 0;
//Target protocol address. MAC manzili zarur bo'lgan IP
packet[38] = ip[0];
packet[39] = ip[1];
packet[40] = ip[2];
packet[41] = ip[3];
//Ethernetda Payload kamida 46 bayt bo'lganligi uchun qolganini 0 bilan to'ldiramiz
for(int i = 42; i > 8;
}
/* Paketni jo'natish */
if (pcap_sendpacket(adhandle, // Adapter
packet, // buffer with the packet
64 // size
) != 0)
{
fprintf(stderr,"nPaketni jo'natishda xatolik: %sn", pcap_geterr(adhandle));
return;
}
//javobni kutish
pcap_loop(adhandle, 0, packet_handler, NULL);
pcap_close(adhandle);
}
/* Callback function invoked by libpcap for every incoming packet */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
//Kelgan paketlarni filtr qilamiz
//Uzunligi 32 dan katta bo'lgan
if (header->len >= 31)
{
//ARP paketga to'g'ri kelgan (EtherType) va ARP respose bo'lganlardan
if (pkt_data[12] == 0x08 && pkt_data[13] == 0x06 &&
pkt_data[20] == 0x00 && pkt_data[21] == 0x02) //response
{
//Bizar kiritgan IP ga mosini
int c = 0;
for(int i = 28; i > 8) ^ Crc32Table[(crc ^ *buf++) & 0xFF];
return crc ^ 0xFFFFFFFF;
}
//Qaysi tarmoq platasidan jo'natishni tanlash
void select_device()
{
int i=0;
int inum;
/* Kompyuterdagi interface larning ro'yxatini olish */
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %sn", errbuf);
exit(1);
}
/* Ro'yxatni chiqarish */
for(d=alldevs; d; d=d->next)
{
printf("%d. ", ++i);
if (d->description)
printf(" (%s)n", d->description);
else
printf(" (No description available)n");
}
if(i==0)
{
printf("nBironta ham interface topilmadi.n");
return;
}
printf("Qaysi interfacedan jo'natish kerak (1-%d):",i);
scanf_s("%d", &inum);
if(inum i)
{
printf("nSiz noto'g'ri tanladingiz.n");
/* Barcha interfacelarni o'chirish */
pcap_freealldevs(alldevs);
return;
}
/* Tanlangan qurilmani tanlash */
for(d=alldevs, i=0; inext, i++);
}
Natija:
Oddiyroq degandim, hali ham oddiy bu, TCP ni qiziqib ko’rsangiz….
Agar savollar bo’lsa kutaman.
Texnologiyalar
Tarmoqdagi kompyuter MAC manzilini olish. Ethernet va ARP.