Instalar JNetPcap en Linux

26/Apr/2014 | Eder

Inicio » Tutoriales » Instalar JNetPcap en Linux

Hace poco tuve que realizar una práctica para el análisis de las tramas de una red utilizando una herramienta conocida como JNetPcap, la cual hace uso de una librería llamada Libpcap y que nos permite, entre otras cosas, capturar las tramas que alguna de nuestras interfaces de red envían o reciben.

Sin embargo tuve algunos problemas para correr el código de ejemplo que la profesora nos brindó, por ejemplo acceder a las interfaces de red y correr el programa en ArchLinux.

Compilar código con JNetpcap

El primer problema que tuve fue compilar el código fuera de un IDE como Eclipse o Netbeans, ya que con ellos no hallé la manera de ejecutar mi código con privilegios de root; la solución es tremendamente sencilla: basta con descomprimir la carpeta org del archivo jnetpcap.jar

Captura de pantalla de 2014-04-22 22:39:15

 

Acceder a las interfaces de red

En Linux, para acceder a ciertos dispositivos y ficheros se necesitan privilegios especiales que generalmente solo el superusuario tiene, por lo que la solución de nueva cuenta es muy sencilla: compilar y correr el programa como root.

Corregir excepción lanzada al ejecutar el programa

Eventualmente puede que ocurra una excepción exactamente del tipo Exception in thread "main" java.lang.UnsatisfiedLinkError: no jnetpcap in java.library.path al ejecutar la aplicación, por lo que tendremos qué hacer lo siguiente:

  1. Instalar el paquete libpcap: pacman -S libpcap (en Arch)
  2. Para la versión de las clases compiladas en el JAR que podrás descargar más abajo, se necesita la librería libpcap versión 0.9 y lo más seguro es que instales una versión más reciente; para hacer que el programa corra con la librería instalada únicamente creamos un enlace simbólico al archivo libpcap.so.X.X.X (‘X’ son números cualesquiera) y lo nombramos libpcap.so.0.9; todo se hace en la carpeta /usr/lib
  3. Correr el programa como root

Captura de pantalla de 2014-04-22 23:01:17

Código fuente y descarga del JAR

Este es el código de ejemplo (no es mi práctica).

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.io.*;

// Tutorial hecho por Eder Or - blog.nativehex.com
// Sourcecode extraído del curso de Redes: http://148.204.58.221/cvirtual24

import org.jnetpcap.Pcap;
import org.jnetpcap.PcapIf;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import org.jnetpcap.PcapBpfProgram;
import org.jnetpcap.protocol.lan.Ethernet;
import org.jnetpcap.protocol.tcpip.*;
import org.jnetpcap.protocol.network.*;
import org.jnetpcap.nio.JBuffer;
import org.jnetpcap.packet.Payload;
import org.jnetpcap.protocol.network.Arp;
import org.jnetpcap.protocol.lan.IEEE802dot2;
import org.jnetpcap.protocol.lan.IEEE802dot3;


public class Captura {

	/**
	 * Main startup method
	 *
	 * @param args
	 *          ignored
	 */
   private static String asString(final byte[] mac) {
    final StringBuilder buf = new StringBuilder();
    for (byte b : mac) {
      if (buf.length() != 0) {
        buf.append(':');
      }
      if (b >= 0 && b < 16) {
        buf.append('0');
      }
      buf.append(Integer.toHexString((b < 0) ? b + 256 : b).toUpperCase());
    }

    return buf.toString();
  }

	public static void main(String[] args) {
		List<PcapIf> alldevs = new ArrayList<PcapIf>(); // Will be filled with NICs
		StringBuilder errbuf = new StringBuilder(); // For any error msgs

		/***************************************************************************
		 * First get a list of devices on this system
		 **************************************************************************/
		int r = Pcap.findAllDevs(alldevs, errbuf);
		if (r == Pcap.NOT_OK || alldevs.isEmpty()) {
			System.err.printf("Can't read list of devices, error is %s", errbuf
			    .toString());
			return;
		}

		System.out.println("Network devices found:");

		int i = 0;
                try{
		for (PcapIf device : alldevs) {
			String description =
			    (device.getDescription() != null) ? device.getDescription()
			        : "No description available";
                        final byte[] mac = device.getHardwareAddress();
			String dir_mac = (mac==null)?"No tiene direccion MAC":asString(mac);
                        System.out.printf("#%d: %s [%s] MAC:[%s]\n", i++, device.getName(), description, dir_mac);

		}//for

		PcapIf device = alldevs.get(0); // We know we have atleast 1 device
		System.out
		    .printf("\nChoosing '%s' on your behalf:\n",
		        (device.getDescription() != null) ? device.getDescription()
		            : device.getName());

		/***************************************************************************
		 * Second we open up the selected device
		 **************************************************************************/
                /*"snaplen" is short for 'snapshot length', as it refers to the amount of actual data captured from each packet passing through the specified network interface.
                64*1024 = 65536 bytes; campo len en Ethernet(16 bits) tam máx de trama */

		int snaplen = 64 * 1024;           // Capture all packets, no trucation
		int flags = Pcap.MODE_PROMISCUOUS; // capture all packets
		int timeout = 10 * 1000;           // 10 seconds in millis
                Pcap pcap =
		    Pcap.openLive(device.getName(), snaplen, flags, timeout, errbuf);

		if (pcap == null) {
			System.err.printf("Error while opening device for capture: "
			    + errbuf.toString());
			return;
		}//if

                       /********F I L T R O********/
            PcapBpfProgram filter = new PcapBpfProgram();
            String expression =""; // "port 80";
            int optimize = 0; // 1 means true, 0 means false
            int netmask = 0;
            int r2 = pcap.compile(filter, expression, optimize, netmask);
            if (r2 != Pcap.OK) {
                System.out.println("Filter error: " + pcap.getErr());
            }//if
            pcap.setFilter(filter);
                /****************/


		/***************************************************************************
		 * Third we create a packet handler which will receive packets from the
		 * libpcap loop.
		 **********************************************************************/
		PcapPacketHandler<String> jpacketHandler = new PcapPacketHandler<String>() {

			public void nextPacket(PcapPacket packet, String user) {

				System.out.printf("Received packet at %s caplen=%-4d len=%-4d %s\n",
				    new Date(packet.getCaptureHeader().timestampInMillis()),
				    packet.getCaptureHeader().caplen(),  // Length actually captured
				    packet.getCaptureHeader().wirelen(), // Original length
				    user                                 // User supplied object
				    );
                                /******Desencapsulado********/
                                for(int i=0;i<packet.size();i++){
                                System.out.printf("%02X ",packet.getUByte(i));
                                if(i%16==15)
                                    System.out.println("");
                                }
                                System.out.println("\n\nEncabezado: "+ packet.toHexdump());
      

			}
		};


		/***************************************************************************
		 * Fourth we enter the loop and tell it to capture 10 packets. The loop
		 * method does a mapping of pcap.datalink() DLT value to JProtocol ID, which
		 * is needed by JScanner. The scanner scans the packet buffer and decodes
		 * the headers. The mapping is done automatically, although a variation on
		 * the loop method exists that allows the programmer to sepecify exactly
		 * which protocol ID to use as the data link type for this pcap interface.
		 **************************************************************************/
		pcap.loop(10, jpacketHandler, "jNetPcap rocks!");

		/***************************************************************************
		 * Last thing to do is close the pcap handle
		 **************************************************************************/
		pcap.close();
                }catch(IOException e){e.printStackTrace();}
	}
}

Descargar JNetpcap

Contraseña del archivo


Acerca de Eder
Software Engineer, estudiante politécnico del CECyT No. 3 y ESCOM-IPN.

Comentarios