Raw Sockets

 1. Introducción

En el ámbito de las redes informáticas, los Raw Sockets permiten la manipulación directa de paquetes sin la intervención del sistema operativo en los niveles superiores del modelo OSI. Su uso es fundamental para la captura de tráfico, el análisis de protocolos y la implementación de protocolos personalizados.


2. Protocolo ICMP (Internet Control Message Protocol)

ICMP es un protocolo de Capa 3 (Red) utilizado para el diagnóstico y la notificación de errores en redes IP. Su función principal es proporcionar información sobre problemas en la comunicación de paquetes, tales como un host inalcanzable o la expiración del TTL (Time To Live). ICMP no está diseñado para el intercambio de datos entre aplicaciones.

Una aplicación comúnmente utilizada que emplea ICMP es la herramienta ping, la cual funciona enviando mensajes de tipo "Echo Request" y esperando respuestas "Echo Reply" para medir la conectividad y latencia entre dispositivos en una red.


3. Raw Sockets (Sockets sin Formato)

Un Raw Socket es un tipo especial de socket que permite enviar y recibir paquetes de red sin que el sistema operativo los procese en los niveles de Transporte (Capa 4) o superiores. Esto proporciona un control total sobre el contenido de los paquetes, lo que resulta útil en diversas aplicaciones, tales como:

  • Monitoreo de tráfico de red (sniffing).

  • Implementación de protocolos personalizados.

  • Envío de paquetes con cabeceras modificadas o forjadas.

Dado su potencial impacto en la seguridad, la creación de Raw Sockets está restringida a usuarios con privilegios de superusuario en la mayoría de los sistemas operativos.


4. Inclusión de Bibliotecas Necesarias

Para trabajar con Raw Sockets en C, es necesario incluir las siguientes bibliotecas:

#include <stdio.h>

#include <stdlib.h>

#include <sys/socket.h>            // Para socket(), bind(), recv()     

#include <unistd.h>               // Para close()

#include <netinet/in.h>            // Para estructuras de red 

#include <netinet/if_ether.h>        // Para encabezados Ethernet como ETH_P_ALL

#include <netpacket/packet.h>       // Para la estructura sockaddr_ll

#include <arpa/inet.h>              // Para ntohs(). En la red se usa big endian (byte mas significativo primero).


El uso de estas bibliotecas dependerá de si se trabaja en Capa 3 (AF_INET) o en Capa 2 (AF_PACKET).

Protocolo

Capa OSI

Tipo de comunicación

Ejemplo de uso

Bibliotecas

AF_INET

Capa 3 (Red)

Basado en direcciones IP

TCP, UDP

<sys/socket.h>, <netinet/in.h>

AF_PACKET

Capa 2 (Enlace)

Basado en direcciones MAC

RAW sockets, captura de paquetes

<sys/socket.h>, <netpacket/packet.h>, <net/if.h>


5. Flujo General de un Raw Socket

El uso de un Raw Socket sigue un flujo de trabajo estándar:

  1. Creación del socket mediante la función socket().

  2. Configuración de la interfaz de red si es necesario.

  3. Envío o recepción de paquetes mediante sendto() o recvfrom().

  4. Procesamiento de los datos recibidos, como extracción de cabeceras y análisis de payload.

  5. Cierre del socket una vez finalizado el uso.


6. Tipos de Raw Sockets y Protocolos Soportados


6.1 Raw Sockets en Capa 3 (AF_INET)

Los Raw Sockets en Capa 3 trabajan con paquetes IP directamente, sin capturar la cabecera Ethernet. Son útiles para analizar paquetes ICMP, UDP o TCP antes de que sean entregados a la capa de transporte.

int sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

AF_INET → Captura paquetes a nivel de Capa 3 (Red).

SOCK_RAW → Permite recibir paquetes sin procesar.

IPPROTO_ICMP → Captura solo paquetes ICMP.


6.2 Raw Sockets en Capa 2 (AF_PACKET)

Para capturar tráfico Ethernet completo, incluyendo direcciones MAC de origen y destino, se utiliza AF_PACKET.

int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

AF_PACKET → Captura paquetes Ethernet completos (Capa 2).

SOCK_RAW → Permite recibir tramas sin procesar.

htons(ETH_P_ALL) → Captura todo el tráfico Ethernet.

7. Configuración de la Interfaz de Red (bind())

Dado que Raw Sockets no utilizan puertos, la función bind() solo se usa para fijar una dirección IP de origen específica.

struct sockaddr_in addr;

memset(&addr, 0, sizeof(addr));

addr.sin_family = AF_INET;

addr.sin_addr.s_addr = inet_addr("192.168.1.100"); // IP de origen


if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {

    perror("Error en bind");

}


8. Enviar y Recibir Datos (sendto(), recvfrom())

8.1 Comparación entre recv() y recvfrom()

En Raw Sockets, recvfrom() es preferible a recv() porque permite obtener la dirección de origen del paquete recibido.

Función

¿Qué hace?



¿Cuándo usarla?


recv()

Recibe datos sin información del remitente.

Cuando no necesitas la IP de origen.

recvfrom()

Recibe datos y almacena la IP del remitente.

Cuando usas Raw Sockets o UDP.


9. Conclusión

Los Raw Sockets permiten el acceso directo a paquetes de red, lo que los hace esenciales para la captura de tráfico, la seguridad informática y la implementación de protocolos personalizados. Dependiendo del nivel de análisis requerido, se puede trabajar en Capa 3 (AF_INET) para capturar paquetes IP o en Capa 2 (AF_PACKET) para capturar tramas Ethernet completas.

El uso de Raw Sockets requiere permisos de superusuario y un entendimiento detallado de las estructuras de red para su correcta implementación.