0%
Conversión entre enteros de 32 bits y direcciones IPv4 con Python

Conversión entre enteros de 32 bits y direcciones IPv4 con Python

Aprende a implementar funciones para convertir enteros de 32 bits en direcciones IPv4 y viceversa, útiles para el procesamiento de red y la seguridad.

I

InSkillCoach

· min

Introducción

En el ámbito de las redes informáticas, las direcciones IPv4 se representan generalmente como una cadena de caracteres comprensible para las personas (p. ej., 192.168.1.1). Sin embargo, a nivel de máquina, estas direcciones se almacenan y manipulan como enteros de 32 bits. La conversión entre estas dos representaciones es una operación fundamental para numerosas aplicaciones de red, de seguridad y de administración de sistemas.

En este tutorial vamos a explorar cómo:

  • Convertir una dirección IPv4 en un entero de 32 bits
  • Convertir un entero de 32 bits en una dirección IPv4
  • Aplicar estas conversiones en casos prácticos

Bases teóricas

Una dirección IPv4 se compone de 4 octetos (32 bits en total). Cada octeto puede tomar un valor entre 0 y 255. Cuando visualizamos una dirección como 192.168.1.1, en realidad estamos viendo la representación decimal con puntos del valor binario 11000000.10101000.00000001.00000001.

Para convertir esta dirección en un único entero, podemos utilizar la siguiente fórmula:

entier = (octet1 * 256³) + (octet2 * 256²) + (octet3 * 256¹) + (octet4 * 256⁰)

Lo que equivale a:

entier = (octet1 << 24) | (octet2 << 16) | (octet3 << 8) | octet4

Implementación en Python

Convertir una dirección IPv4 en entero

def ip_to_int(ip_address):
    """
    Convierte una dirección IPv4 en un entero de 32 bits.
    
    Args:
        ip_address (str): Dirección IPv4 en formato '192.168.1.1'
        
    Returns:
        int: Representación entera de la dirección IPv4
    """
    octets = ip_address.split('.')
    
    # Verificación de la validez de la dirección IP
    if len(octets) != 4:
        raise ValueError("Format d'adresse IPv4 invalide")
    
    # Conversión de los octetos a enteros y verificación de los rangos
    octets_int = []
    for octet in octets:
        o = int(octet)
        if o < 0 or o > 255:
            raise ValueError(f"Valeur d'octet invalide: {o}")
        octets_int.append(o)
    
    # Cálculo del entero final
    return (octets_int[0] << 24) | (octets_int[1] << 16) | (octets_int[2] << 8) | octets_int[3]

Convertir un entero en dirección IPv4

def int_to_ip(ip_int):
    """
    Convierte un entero de 32 bits en una dirección IPv4.
    
    Args:
        ip_int (int): Entero de 32 bits que representa una dirección IPv4
        
    Returns:
        str: Dirección IPv4 en formato '192.168.1.1'
    """
    # Verificación del rango válido para una dirección IPv4
    if ip_int < 0 or ip_int > 4294967295:  # 2^32 - 1
        raise ValueError("L'entier doit être compris entre 0 et 2^32 - 1")
    
    # Extracción de los octetos
    octet1 = (ip_int >> 24) & 255
    octet2 = (ip_int >> 16) & 255
    octet3 = (ip_int >> 8) & 255
    octet4 = ip_int & 255
    
    # Construcción de la dirección IP
    return f"{octet1}.{octet2}.{octet3}.{octet4}"

Ejemplos de uso

Estos son algunos ejemplos para demostrar el uso de estas funciones:

# Conversión de IP a entero
print(ip_to_int("192.168.1.1"))  # Output: 3232235777
print(ip_to_int("127.0.0.1"))    # Output: 2130706433
print(ip_to_int("10.0.0.1"))     # Output: 167772161

# Conversión de entero a IP
print(int_to_ip(3232235777))     # Output: 192.168.1.1
print(int_to_ip(2130706433))     # Output: 127.0.0.1
print(int_to_ip(167772161))      # Output: 10.0.0.1

Uso de la biblioteca estándar

Python también ofrece una solución mediante el módulo socket de la biblioteca estándar para realizar estas conversiones:

import socket
import struct

# Conversión de IP a entero
def ip_to_int_socket(ip_address):
    return struct.unpack('!I', socket.inet_aton(ip_address))[0]

# Conversión de entero a IP
def int_to_ip_socket(ip_int):
    return socket.inet_ntoa(struct.pack('!I', ip_int))

# Ejemplos
print(ip_to_int_socket("192.168.1.1"))  # Output: 3232235777
print(int_to_ip_socket(3232235777))     # Output: 192.168.1.1

Este enfoque es más conciso y gestiona automáticamente la validación de las direcciones IP.

Aplicaciones prácticas

1. Verificación de pertenencia a una subred

def is_in_subnet(ip, subnet, mask):
    """
    Verifica si una dirección IP pertenece a una subred.
    
    Args:
        ip (str): Dirección IP que se va a verificar
        subnet (str): Dirección de la subred
        mask (int): Máscara de subred en notación CIDR (p. ej.: 24 para /24)
    
    Returns:
        bool: True si la IP pertenece a la subred, False en caso contrario
    """
    ip_int = ip_to_int(ip)
    subnet_int = ip_to_int(subnet)
    
    # Creación de la máscara binaria
    cidr_mask = (0xFFFFFFFF << (32 - mask)) & 0xFFFFFFFF
    
    # Comparación de las redes
    return (ip_int & cidr_mask) == (subnet_int & cidr_mask)

# Ejemplo
print(is_in_subnet("192.168.1.5", "192.168.1.0", 24))  # Output: True
print(is_in_subnet("192.168.2.1", "192.168.1.0", 24))  # Output: False

2. Iteración sobre un bloque de direcciones IP

def ip_range(start_ip, end_ip):
    """
    Genera todas las direcciones IP de un rango dado.
    
    Args:
        start_ip (str): Dirección IP inicial
        end_ip (str): Dirección IP final
    
    Yields:
        str: Direcciones IP del rango
    """
    start_int = ip_to_int(start_ip)
    end_int = ip_to_int(end_ip)
    
    if start_int > end_int:
        raise ValueError("L'adresse IP de début doit être inférieure à l'adresse IP de fin")
    
    for ip_int in range(start_int, end_int + 1):
        yield int_to_ip(ip_int)

# Ejemplo
for ip in ip_range("192.168.1.1", "192.168.1.5"):
    print(ip)
# Output:
# 192.168.1.1
# 192.168.1.2
# 192.168.1.3
# 192.168.1.4
# 192.168.1.5

Rendimiento y optimizaciones

Para las aplicaciones que requieren numerosas conversiones, las funciones pueden optimizarse:

# Versión optimizada sin validación
def ip_to_int_fast(ip_address):
    a, b, c, d = map(int, ip_address.split('.'))
    return (a << 24) | (b << 16) | (c << 8) | d

def int_to_ip_fast(ip_int):
    return f"{(ip_int >> 24) & 255}.{(ip_int >> 16) & 255}.{(ip_int >> 8) & 255}.{ip_int & 255}"

Estas versiones sacrifican la validación en favor del rendimiento, por lo que solo deben utilizarse en contextos en los que las entradas ya estén validadas.

Conclusión

La conversión entre direcciones IPv4 y enteros de 32 bits es una operación fundamental en numerosos ámbitos relacionados con las redes informáticas. Python ofrece varios enfoques para realizar estas conversiones, desde la implementación manual hasta el uso de la biblioteca estándar.

Estas funciones pueden integrarse en diversas herramientas de red como:

  • Escáneres de red
  • Herramientas de análisis de logs
  • Sistemas de detección de intrusiones
  • Aplicaciones de monitorización de red

Al dominar estas conversiones, dispones de una competencia esencial para el desarrollo de aplicaciones de red en Python.

InSkillCoach

Acerca de InSkillCoach

Experto en formación y tecnologías

Coach especializado en tecnologías avanzadas e IA, impulsado por GNeurone Inc.

Certificaciones:

  • AWS Certified Solutions Architect – Professional
  • Certificaciones de Google Cloud
  • Microsoft Certified: DevOps Engineer Expert
  • Certified Kubernetes Administrator (CKA)
  • CompTIA Security+
1.9k
80

Comentarios

Los comentarios funcionan con GitHub Discussions

Inicia sesión con GitHub para participar en la discusión

¡Enlace copiado!