ipaddress en Python: redes IPv4 e IPv6

Publicado el: 18/08/2026
Tempo de leitura: 5 minutos
Close-up view of a computer screen displaying code in a software development environment.

El módulo ipaddress en Python crea, valida y manipula direcciones IPv4, IPv6, redes CIDR e interfaces. Permite comprobar pertenencia, calcular red y broadcast, dividir bloques, resumir rangos, clasificar direcciones especiales y convertir entre texto, enteros y bytes.

La biblioteca no abre sockets, no resuelve DNS y no modifica la configuración del sistema. Trabaja con valores y reglas de direccionamiento. Esta separación es útil en firewalls, listas permitidas, inventarios, logs, APIs y validadores de configuración.

Crea una dirección automáticamente

from ipaddress import ip_address

ipv4 = ip_address("192.0.2.10")
ipv6 = ip_address("2001:db8::10")

print(ipv4.version)
print(ipv6.compressed)

ip_address() elige IPv4 o IPv6 y lanza ValueError si la entrada no es válida. Cuando conoces la versión esperada y necesitas errores más específicos, utiliza IPv4Address o IPv6Address.

Valida datos del usuario

import ipaddress

def validar_ip(texto: str):
    try:
        return ipaddress.ip_address(texto.strip())
    except ValueError as error:
        raise ValueError("dirección IP inválida") from error

Las direcciones IPv4 con ceros iniciales, como 010.0.0.1, se rechazan para evitar ambigüedad con notación octal. No corrijas automáticamente entradas sospechosas porque una cadena inválida podría convertirse silenciosamente en otra dirección.

Dirección, red e interfaz

  • ip_address("10.0.0.5") representa una dirección.
  • ip_network("10.0.0.0/24") representa un rango.
  • ip_interface("10.0.0.5/24") conserva el host y muestra la red asociada.
from ipaddress import ip_interface

interfaz = ip_interface("10.0.0.5/24")
print(interfaz.ip)
print(interfaz.network)
print(interfaz.with_netmask)

Modo strict en redes

Por defecto, ip_network() exige que los bits de host estén a cero:

from ipaddress import ip_network

red = ip_network("192.168.1.0/24")
normalizada = ip_network("192.168.1.42/24", strict=False)
print(normalizada)

Usa strict=False solo cuando la normalización sea intencional y esté documentada. En reglas de seguridad, ocultar bits de host puede esconder un error de configuración.

Comprueba pertenencia

from ipaddress import ip_address, ip_network

red = ip_network("10.20.0.0/16")
cliente = ip_address("10.20.8.15")

if cliente in red:
    print("dirección permitida")

Los objetos IPv4 deben compararse con redes IPv4 y los IPv6 con redes IPv6. Mezclar versiones normalmente produce TypeError.

Propiedades importantes

from ipaddress import ip_address

ip = ip_address("127.0.0.1")
print(ip.is_loopback)
print(ip.is_private)
print(ip.is_global)
print(ip.is_multicast)
print(ip.is_link_local)
print(ip.reverse_pointer)

reverse_pointer devuelve el nombre utilizado en una consulta PTR; no realiza la consulta DNS. Las clasificaciones is_private e is_global siguen los registros especiales de IANA y pueden corregirse entre versiones. Python 3.13 corrigió varias clasificaciones, por lo que no conviene reemplazar la biblioteca con listas antiguas.

Privado no significa confiable

Una dirección privada, loopback o link-local no demuestra identidad. En aplicaciones web, X-Forwarded-For puede falsificarse si la cadena de proxies no está controlada. Obtén la dirección efectiva desde una fuente confiable.

is_global describe alcance de direccionamiento, no reputación, propiedad, autenticación ni autorización.

Detalles de una red

from ipaddress import ip_network

red = ip_network("192.0.2.0/29")
print(red.network_address)
print(red.broadcast_address)
print(red.netmask)
print(red.hostmask)
print(red.num_addresses)
print(list(red.hosts()))

En IPv4, hosts() suele excluir red y broadcast. En /31 incluye ambos extremos para enlaces punto a punto y en /32 devuelve un host. IPv6 tiene reglas distintas; no traslades suposiciones de broadcast de IPv4.

No materialices redes enormes

Una red IPv6 /64 contiene una cantidad impracticable de direcciones. Usa pertenencia, índices, propiedades y operaciones de subred en lugar de convertirla en lista.

from ipaddress import ip_network

red = ip_network("2001:db8::/64")
print(red.num_addresses)
print(red[0])
print(red[-1])

Divide una red

from ipaddress import ip_network

red = ip_network("10.0.0.0/24")
for subred in red.subnets(new_prefix=26):
    print(subred)

superred = red.supernet(new_prefix=22)

El prefijo de una subred debe ser mayor y el de una superred debe ser menor.

Compara redes

from ipaddress import ip_network

principal = ip_network("10.0.0.0/8")
filial = ip_network("10.20.0.0/16")
segmento = ip_network("10.20.128.0/17")

print(filial.subnet_of(principal))
print(principal.supernet_of(segmento))
print(filial.overlaps(segmento))

Estas operaciones ayudan a detectar reglas redundantes, conflictos de rutas y rangos superpuestos.

Excluye un rango

from ipaddress import ip_network

bloque = ip_network("192.0.2.0/28")
reservado = ip_network("192.0.2.4/30")

for restante in bloque.address_exclude(reservado):
    print(restante)

La red excluida debe estar totalmente contenida. El resultado cubre las direcciones restantes con redes CIDR.

Resume y colapsa

import ipaddress

inicio = ipaddress.ip_address("192.0.2.0")
fin = ipaddress.ip_address("192.0.2.130")
print(list(ipaddress.summarize_address_range(inicio, fin)))

redes = [
    ipaddress.ip_network("10.0.0.0/25"),
    ipaddress.ip_network("10.0.0.128/25"),
]
print(list(ipaddress.collapse_addresses(redes)))

collapse_addresses() combina bloques adyacentes o redundantes. No mezcles IPv4 e IPv6.

Conversión a entero y bytes

from ipaddress import ip_address

ip = ip_address("192.0.2.1")
print(int(ip))
print(ip.packed)
print(str(ip))

packed devuelve cuatro bytes para IPv4 y dieciséis para IPv6 en orden de red. Combínalo con struct en Python para cabeceras binarias, documentando versión y longitud.

IPv6 compacto, expandido y con scope

from ipaddress import IPv6Address

ip = IPv6Address("2001:db8::1")
print(ip.compressed)
print(ip.exploded)

local = IPv6Address("fe80::1234%eth0")
print(local.scope_id)

Las direcciones link-local pueden incluir zone ID. La misma dirección numérica con ámbitos distintos no es igual. Convertir a entero elimina el ámbito, así que no lo hagas cuando la interfaz forme parte de la identidad.

IPv4 mapeado en IPv6

ipv4_mapped extrae el IPv4 contenido en direcciones como ::ffff:192.0.2.1. Las versiones recientes hacen que is_private e is_global sigan la semántica del IPv4 subyacente. Normaliza representaciones equivalentes para evitar bypass de políticas.

Construye una lista permitida

from ipaddress import ip_address, ip_network

PERMITIDAS = tuple(map(ip_network, [
    "192.0.2.0/24",
    "2001:db8:abcd::/48",
]))

def permitido(texto: str) -> bool:
    direccion = ip_address(texto)
    return any(
        direccion.version == red.version and direccion in red
        for red in PERMITIDAS
    )

Analiza las redes al iniciar, no en cada petición. configparser en Python puede leer configuración, pero las reglas críticas necesitan validación y revisión.

SSRF requiere varias defensas

ipaddress ayuda a bloquear loopback, privados y link-local, pero no resuelve SSRF por sí solo. Un hostname puede devolver varios IPs, cambiar entre validación y conexión o redirigir. Resuelve y valida todos los resultados, conecta a la dirección validada, restringe protocolos y puertos y vuelve a validar redirecciones. Analiza URLs con urllib.parse, no con concatenación.

Hash y ordenación

Direcciones y redes son inmutables y hashable, por lo que sirven como claves y elementos de sets. Las direcciones de la misma versión pueden ordenarse. Para mezclar direcciones y redes deliberadamente, usa get_mixed_type_key().

Observabilidad

Devuelve mensajes simples al usuario y registra un valor sanitizado, la regla coincidente y la versión IP. Para seguir validaciones complejas, usa trace en Python. Los lotes grandes pueden distribuirse con queue en Python, manteniendo las redes preanalizadas.

Pruebas recomendadas

Incluye IPv4 e IPv6 válidos, ceros iniciales, prefijos inválidos, bits de host en modo estricto, /31, /32, /127, /128, direcciones mapeadas, zone IDs, redes superpuestas, rangos enormes, espacios, Unicode confusable y cadenas demasiado largas.

Buenas prácticas

  • Convierte cadenas en objetos una sola vez.
  • Usa modo estricto en reglas críticas.
  • No materialices redes enormes.
  • No trates una IP privada como identidad.
  • Soporta IPv4 e IPv6 deliberadamente.
  • Normaliza representaciones equivalentes.
  • Limita listas e intervalos.
  • Combina validación IP con DNS, proxies y política de aplicación.

Conclusión

ipaddress en Python proporciona una base sólida para validar direcciones, calcular CIDR e implementar políticas consistentes en IPv4 e IPv6. Los objetos inmutables sustituyen manipulaciones frágiles de cadenas.

Consulta la documentación oficial de ipaddress y el registro especial de IANA. La clasificación de alcance ayuda, pero la autorización necesita contexto adicional.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python para representar fracciones exactas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: convierte números en fracciones

    Aprende fractions.from_number en Python para convertir números en fracciones exactas, controlar precisión, validar entradas y evitar redondeos inesperados.

    Ler mais

    Tempo de leitura: 4 minutos
    09/10/2026
    Desarrollador configurando un servidor HTTPS y certificado TLS con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crea un servidor HTTPS local en Python

    Aprende HTTPSServer en Python para crear servicios HTTPS locales, configurar certificados, usar hilos y comprender sus límites.

    Ler mais

    Tempo de leitura: 4 minutos
    08/10/2026
    Archivos protegidos que representan extracción segura de TAR con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extrae TAR con seguridad

    Aprende tarfile extraction_filter en Python para extraer archivos TAR con validación, seguridad y control de rutas.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python mostrando avisos controlados con catch_warnings
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: captura warnings en pruebas Python

    Aprende catch_warnings en Python para capturar, probar y controlar avisos con filtros específicos y alcance seguro.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python que representa referencias persistentes de pickle
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serializa referencias externas

    Aprende pickle persistent_id en Python para referencias externas estables, validación, seguridad, rendimiento y compatibilidad.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binario que representa buffers y vistas de memoria en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: cuenta valores sin copiar buffers

    Aprende memoryview.count en Python para contar bytes y valores en buffers sin copias, con formatos, límites y buenas prácticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026