Ebben a számban egy rövid betekintést nyújtanék a sinffing-be illetve evesdropping-ba. Magyarul abba a módszerbe, aminek a segítségével meg tudjuk, hogy mi megy a "dróton". Pontosabban, hogy mi megy a helyi ethernet hálózaton. Sokféle ilyen un. "sniffer" program létezik, nem célom egy komplett program megírása. Az elvet szeretném bemutatni, aminek segítségével talán közelebb kerülünk a témához.

Az alapok
Az internet helyi hálózatok összekapcsolásából áll. Ezek a helyi hálózatok az esetek nagyon nagy részében ethernet hálózatok. Ez gyakorlatilag azt jelenti, hogy egy kábelre (BNC/UTP) van kötve az összes gép. Tehát, amit az egyik gép küld a másiknak, azt az összes többi is látja a helyi hálózaton, és persze tudja, hogy nem neki szól, így alapesetben meg sem nézi. Egy kis ráfordítással bármelyik gépen nyomon követhető az egész hálózati kommunikáció azon a kábelen (szegmensen). Természetesen nem csak azt fogjuk látni, amit az egyik helyi hálózatban lévő gép küld a másiknak, hanem azt is, amikor hálózaton kívülre küld valaki, vagy ha kívülről kap valamit.

Bármely két gép közti kommunikáció lefigyelhető, ha van egy gépünk az egyiknek a helyi hálózatán. Illetve, ha az útvonalban rendelkezünk egy géppel. Ez utóbbi jóval bonyolultabb, hiszen az interneten keresztüli útvonalat a két gép között nem tudhatjuk biztosan előre (kivételes esetekben befolyásolható).

Tehát nem kell megijedni, nem létezik olyan pont az interneten, ahonnan minden lefigyelhető. Két gép közti adatcsere is csak abban az esetben megy, ha vagy az egyik, vagy a másik gép helyi hálózatán vagyunk, illetve ha van olyan szerencsénk, hogy eltaláltuk az útvonalat.

Hogy mikor kell ez?

Minden olyan esetben, amikor kíváncsiak vagyunk a hálózati forgalomra. Ez lehet azért, mert kíváncsiak vagyunk a kódolatlanul küldött jelszavakra, vagy a hálózati forgalom elemzésével próbálunk rájönni, mi nem működik, esetleg próbáljuk kiszűrni a külső támadásokat.
A hálózati háttér.
Amint az eddigiekben kiderült, a "sniffing" csak akkor megy, ha a hálózat kiépítése olyan, hogy mindenki lát mindent. Ez az egyszerű egy kábeles, illetve HUB-os hálózatokra igaz. Ha a gépek SWITCH-en keresztül kapcsolódnak, akkor már nem jó a dolog. (Ld. Hálózatok rovat)

Az adatok az ethernet hálózatban fizikailag un. Ethernet frame-ekben közlekednek. Ez a frame tartalmazza a forrás kártya hardver címét, a cél kártya hardver címét, és magát az IP csomagot.
 

+--+--+--+--+--+--+ | destination MAC | +--+--+--+--+--+--+ |   source MAC    | +--+--+--+--+--+--+ |08 00            | +--+--+-----------+ |                 | . IP              . . packet          . .                 . |                 | +--+--+--+--+-----+ | CRC       | +--+--+--+--+

Hogy mi az a hardvercím? Minden kártyának van egy azonosítója, amit használ. Elvileg a világon két azonos hardvercímű kártya nem létezik.

Az eszköz, amin keresztül látjuk a forgalmat
Az eszköz egy mezei ethernet kártya, ugyanolyan, mint bármelyik másik gépben. PROMISCUOUS módba kell kapcsolni. Alapesetben a kártya drivere látja, hogy nem neki érkezett az ethernet keret (nem az ő hardvercíme szerepel a cél hardvercím helyén), így egyszerűen eldobja. Ha PROMISCUOUS módba kapcsoltuk, akkor viszont megtartja, és be tudjuk olvasni.

A kártya PROMISCUOUS módba kapcsolása:

> ifconfig eth0 promisc

Értelemszerűen az eth0 helyére a hálózati interface nevét kell írni. A művelethez root-nak kell lenni az adott gépen.

Vajon PROMISCUOUS módban van a kártya?
 
 

> ifconfig -a eth0

eth0 Link encap:Ethernet HWaddr 00:00:E8:73:27:8C 
inet addr:192.168.0.2 Bcast:192.168.0.255 Mask:255.255.255.0
UP BROADCAST RUNNING PROMISC MULTICAST MTU:1500 Metric:1
 

Ha ez megvan, akkor minden adatot megkapunk, ami csak átfolyik a dróton. Csak be kell olvasnunk.
Erre több féle mód létezik, nézzünk kettőt.

Az adatok beolvasása a protokoll socketen keresztül
Az első feladat, annak a meghatározása, hogy milyen protokollra vagyunk kíváncsiak. Ha például az ICMP forgalmat akarjuk monitorozni, elég egy ICMP socketet létrehozni, és várni rajta az adatot. Ha a TCP, vagy az UDP is érdekes, akkor azokra is külön socketet kell létrehozni. Ezzel a módszerrel a gép minden hálózati eszközéről olvasunk, nem tudjuk, melyikről jött a csomag.

pl.:
 
 

#define MAXPACKET 65535 char packet[MAXPACKET]; int rawtcp, rawudp, rawicmp,r,s; fd_set readset,temp; /*A socketek létrehozása, ahonnan majd olvasunk*/
/*sock_raw tipusu socket csak root jogokkal hozhato letre*/
rawicmp=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); rawtcp=socket(AF_INET, SOCK_RAW, IPPROTO_TCP); rawudp=socket(AF_INET, SOCK_RAW, IPPROTO_UDP); FD_ZERO(&readset); FD_SET(rawicmp,&readset); FD_SET(rawtcp,&readset); FD_SET(rawudp,&readset); while(1) {   temp=readset;   r=select(FD_SETSIZE, &temp, NULL, NULL, NULL);   if (r>0)   {     if (FD_ISSET(rawicmp, &temp))     {       s=read(rawicmp, packet, MAXPACKET);       icmp_print(packet,s);     }     if (FD_ISSET(rawtcp, &temp))     {       s=read(rawtcp, packet, MAXPACKET);       tcp_print(packet,s);     }     if (FD_ISSET(rawudp, &temp))     {       s=read(rawudp, packet, MAXPACKET);       udp_print(packet,s);     }   } }

A program minden megkapott ICMP, UDP, és TCP csomagot kiírat. Persze a kiírató függvényeket (tcp_print, udp_print, icmp_print) nekünk kell megírni.
ld. snifsock.c

Természetesen lefordítás után root suidossá kell tenni, vagy csak rootként megy.
 

Az ethernet keret olvasása közvetlenül a kártya driverétől
Ez egy másik fajta megoldás, ami a drivertől olvas. Meg kell határoznunk egy hálózati interfészt, amelyről olvasni fogunk. A különbség az az előzőhez képest, hogy nem kell megadni a monitorozott protokollokat, mindegyikhez socketet nyitni, mindent megkapunk, de csak arról az egy kártyáról. Sőt nem is az IP csomagot kapjuk meg, hanem az egész ethernet frame-et. Így ez a megoldás nem annyira portolható, mint az első, de mélyebben nyúlunk bele a dolgokba.
 
 
int s,size;char buf[MAXPACKET]; struct sockaddr_ll ll; struct packet_mreq mreq;
/*Ethernet socketet nyitunk. ROOT jog kell*/
s=socket(PF_PACKET, SOCK_RAW, ETH_P_IP); bzero(&ll, sizeof(ll)); ll.sll_family=AF_PACKET; ll.sll_protocol=htons(ETH_P_IP); ll.sll_ifindex=if_nametoindex("eth0"); /*interface megadása*/
/*Hozzá kell kötni az intefészhez*/
if (bind(s, (struct sockaddr *)&ll, sizeof(ll))) {   printf("bind hiba");   exit(1); } while(1) {   printf(".\n");   size=recvfrom(s, buf, MAXPACKET, 0,0,0);   pr_iph((struct ip*)&buf[ETH_HLEN]); }

Az eljárás lényege, hogy létrehozunk egy socketet, majd ezt a bind függvénnyel hozzákötjük a hálózati interface-hez, amin átmenő adatokra kíváncsiak vagyunk.
ld. snifeth.c

Lefordítás után rootként megy.


Pár igazi sniffer program:

tcpdump
A legrégibb unixos hálózatfigyelő.
TCPDUMP/LIBPCAP public repository.

Ethereal
Egy szép grafikus sniffer.
http://ethereal.zing.org

exdump
Egy nagyon egyszerű program. Ennek a forrását ajánlom először elolvasni, ugyanis ebben legalább nem veszik el az ember.
NetPedia.net -