Packet sniffing in Java

L'astrazione della java virtual machine pone il limite alla realizzazione di programmi Java in grado di interagire a basso livello con l'hardware della macchina. Tuttavia ricorrendo ai metodi nativi (JNI) e utilizzando degli espedienti opportuni, è stato possibile realizzare una libreria Java, Jpcap per l’appunto, in grado di gestire la scheda di rete in modalità promiscua ed utilizzare il sistema molto veloce di filtraggio dei pacchetti del BPF.

Jpcap

Jpcap è un progetto nato nel giugno del 2000 da un'idea di Keita Fujii e distribuito con licenza GNU , GENERAL PUBLIC LICENSE, durante gli ultimi anni la libreria non ha subito sostanziali cambiamenti, un suo ultimo aggiornamento risale al settembre del 2003. Esiste un altro progetto simile iniziato nel maggio del 2001 completamente Open Source sviluppato dalla NetSourceForge ed in continua evoluzione, tale progetto può vantare in più un Tool per la visualizzazione del traffico di rete e funzioni aggiuntive per la gestione del traffico catturato. Entrambe utilizzano la Libpcap. Tra le due si è deciso di utilizzare quella sviluppata da Keita Fujii che non si discosta molto dalla interfaccia delle funzioni della libreria Libpcap risultando più semplice da utilizzare, mentre nella Jpcap sviluppata dalla NetSourceForge le interfacce delle funzioni sono state completamente ridisegnate.

Il package Jpcap si avvale di una interfaccia e di una serie di classi per la cattura, l’analisi e la manipolazione di pacchetti di rete.

La classe principale è Jpcap che permette di accedere alla libreria di sistema utilizzata per catturare i pacchetti, ecco la gerarchia di ereditarietà relativa alla classe in questione:

Class Jpcap
java.lang.Object
|
+--
jpcap.Jpcap

tra i metodi più importanti che mette a disposizione abbiamo:

static java.lang.String[]

getDeviceDescription ()
Ritorna la descrizione dell’interfacce di rete.(Utilizzabile solo in ambiente Windows)

static java.lang.String[]

getDeviceList ()
Ritorna gli identificativi delle interfacce di rete che possono essere usate per la cattura dei pacchetti.

static java.lang.String

lookupDevice ()
Ritorna il nome dell’interfaccia principale.

static

openDevice (java.lang.String device, int snaplen, boolean promisc, int to_ms)
Inizializza l’interfaccia e ritorna l’istanza di questa classe.

static Jpcap

openFile (java.lang.String filename)
Apre un dump file creato con un tcpdump or Ethereal, e ritorna un’istanza della classe.

Packet

getPacket ()
Ritorna un pacchetto catturato.

int

loopPacket (int count, JpcapHandler handler)
Cattura un numero specifico (count) di pacchetti.

int

processPacket (int count, JpcapHandler handler)
Cattura un numero specifico (count) di pacchetti.

void

setFilter (java.lang.String condition, boolean optimize)
Setta un filtro.

void

close ()
Chiude l’interfaccia aperta.

java.lang.String

getErrorMessage()
Ritorna un messaggio di errore.

Un’altra classe importante legata strettamente a quella precedentemente descritta è la classe Packet tale classe contiene i campi relativi ai pacchetti catturati mediante la classe Jpcap. Ecco la gerarchia di ereditarietà relativa alla classe in questione:

Class Packet
java.lang.Object
|
+--jpcap.Packet

I campi che è possibile prendere in considerazione sono:
byte[] data
Rappresenta il campo dati del pacchetto
DatalinkPacket datalink
E’ il Datalink Layer
byte[] header
Rappresenta il campo Header
int len
E’ la lunghezza del pacchetto catturato

Nella realizzazione dello Sniffer Talk gli unici pacchetti che andremo ad analizzare che non filtreremo saranno quelli provenienti dai protocolli TCP e UDP.
Il package Jpcap mette a disposizione due classi che sono ad hoc per il nostro scopo. Le classi sono:

La prima rappresenta i pacchetti TCP mentre la seconda rappresenta i pacchetti UDP. Ecco la gerarchia di ereditarietà relativa alla prima classe:

Class TCPPacket
java.lang.Object
|
+--jpcap.Packet
|
+--jpcap.IPPacket
|
+--
jpcap.TCPPacket

Ed ecco alcuni dei campi che mette a disposizione la seguente classe per rappresentare i pacchetti di tipo TCP:
long ack_num
Numero dell’ACK
long sequence
Numero della sequenza
int dst_port
Numero della porta di destinazione
int src_port
Numero della porta sorgente

Ecco la gerarchia di ereditarietà relativa alla seconda classe:

Class UDPPacket
java.lang.Object
|
+--jpcap.Packet
|
+--jpcap.IPPacket
|
+--
jpcap.UDPPacket

Ed ecco alcuni dei campi che mette a disposizione la seguente classe per rappresentare i pacchetti di tipo UDP:
int dst_port
Numero della porta di destinazione
int src_port
Numero della porta sorgente
int length
Lunghezza del pacchetto

L’unica interfaccia utilizzata nel package è la :

Inferface JpcapHandler

Questa interfaccia è utilizzata per definire un metodo per analizzare i pacchetti catturati, questa interfaccia è utilizzata in Jpcap.processPacket() e Jpcap.loopPacket(), e rappresenta l'handle per la procedura che riceve il pacchetto catturato. L’unico metodo disponibile è:

void handlePacket (Packet p)
Analizza un pacchetto.
Questo metodo è chiamato ogni volta che un pacchetto è catturato.

(top)


Vantaggi Jpcap

Il wrapper Jpcap mette a nostra disposizione le funzionalità della libreria libpcap, ma in Java, così da utilizzare questo linguaggio come base per catturare ed analizzare i pacchetti di rete. Il ponte creato da Jpcap rappresenta una soluzione interessante perché, se da un lato fornisce un accesso alla libreria originale sotto una piattaforma di sviluppo nota e diffusa, dall’altro si interfaccia ad essa in una maniera che non ne altera la sostanza. Jpcap è una astrazione di libpcap che ci risparmia la necessità di lavorare con complesse strutture dati, puntatori, handler di funzioni, e via dicendo.

Note:

Oltre all'implementazione della libreria Jpcap da noi utilizzata, esiste un'ulteriore implementazione sviluppata come progetto open source disponibile sul sito sourceforge.net.
Sebbene le due implementazioni assolvono i medesimi compiti, risultano molto differenti per le API messe a disposizione. La nostra decisione nella scelta dell'implementazione della libreria da utilizzare è dovuta alla maggiore similarità col la libreria originale libpcap, sebbene il progetto della sourceforge.net risulti più completo e in continua evoluzione.

(top)

Vantaggi Java

Nel nostro caso il multi-threading è risultato utile in quanto ha reso possibile la suddivisione logica del processo di sniffing del nostro programma. Infatti si è deciso di utilizzare due tipi di thread, un primo responsabile dello sniffing dei messaggi di controllo sul canale UDP e un secondo tipo di thread responsabile dello sniffing dei messaggi relativi ad ogni singola sessione Talk tra ogni coppia di utenti.

(top)