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

    A developer typing code on a laptop with a Python book beside in an office.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    queue en Python: coordina hilos

    Aprende queue en Python para coordinar hilos con FIFO, prioridad, backpressure, tracking, reintentos y shutdown seguro.

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026
    Chic portrait of a woman wearing trendy sunglasses reflecting numbers, captured in a modern setting.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    struct en Python: datos binarios

    Aprende struct en Python para empaquetar datos binarios, controlar endianness, reutilizar buffers y validar protocolos externos.

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026
    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    tarfile en Python: crea TAR seguro

    Aprende tarfile en Python para crear TAR comprimido, inspeccionar miembros y extraer con filtros, límites y protección de rutas.

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026
    Row of colorful office binders neatly arranged on a shelf, ideal for organization concepts.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    gzip en Python: comprime archivos .gz

    Aprende gzip en Python para leer y escribir .gz, crear streams reproducibles, procesar datos grandes y limitar la expansión externa.

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026
    Neatly arranged blue office binders labeled with dates and names for organized storage.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    lzma en Python: comprime archivos XZ

    Aprende lzma en Python para crear archivos XZ, procesar streams, elegir checks y filtros y limitar memoria con datos externos.

    Ler mais

    Tempo de leitura: 4 minutos
    17/08/2026
    A close-up shot showcasing the intricate scales of a snake, highlighting texture and color.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    bz2 en Python: comprime con bzip2

    Aprende bz2 en Python para comprimir archivos y bytes, procesar streams por bloques y limitar la expansión de datos externos.

    Ler mais

    Tempo de leitura: 4 minutos
    16/08/2026