“10.68” no es magia: así funcionan las direcciones IPv4 abreviadas (y por qué un sysadmin debería tratarlas con respeto)

Quien administre Linux desde hace tiempo se ha topado con el truco: escribir 10.68 y llegar a 10.0.0.68, o teclear 10.20.2 y alcanzar 10.20.0.2. En un laboratorio ahorra pulsaciones; en producción puede convertirse en un dolor de cabeza. Este medio explica por qué funciona, dónde funciona, dónde dejará de funcionar y cómo gestionarlo de forma responsable en entornos Linux modernos.

No es brujería, es “parsing” heredado

El comportamiento nace de las APIs históricas de sockets IPv4 (familia inet_), que aceptaban formatos abreviados además del clásico “dotted quad” (a.b.c.d). Muchas herramientas Unix (y derivados) se construyeron sobre esas APIs, y de ahí la compatibilidad:

  • a.b.c → el último campo c ocupa 16 bits (dos octetos).
    10.20.210.20.0.2.
  • a.b → el último campo b ocupa 24 bits (tres octetos).
    10.6810.0.0.68.
  • a (un entero) → 32 bits completos.
    16777216110.0.0.1.

Cuando faltan octetos, se rellenan por la izquierda con ceros dentro del bloque de 16/24/32 bits. De ahí que ping 10.68 funcione y termine en 10.0.0.68, como muestra la captura de muchos laboratorios.

¿Dónde sigue funcionando en Linux?

Depende del binario y de qué API usa:

  • Herramientas clásicas (ping, telnet, ssh, algunos curl compilados con resolutores tolerantes) suelen aceptar abreviados gracias a funciones como inet_aton() / inet_addr().
  • Utilidades y librerías más modernas que usan getaddrinfo()+inet_pton() suelen exigir el formato a.b.c.d o un FQDN. Muchos SDKs y runtimes (Go, Rust, Python ipaddress, Java moderno) son estrictos.
  • Navegadores y clientes HTTP endurecieron parsing en los últimos años; algunos rechazan abreviados por motivos de seguridad.

Consecuencia: lo que funciona en una TTY puede fallar en otra herramienta, contenedor o pipeline. Para un sysadmin, esa inconsistencia es el problema.

“10.68” no es magia: así funcionan las direcciones IPv4 abreviadas (y por qué un sysadmin debería tratarlas con respeto) | ipv4 resume
“10.68” no es magia: así funcionan las direcciones IPv4 abreviadas (y por qué un sysadmin debería tratarlas con respeto)

Los “peros” que conviene conocer (y documentar)

1) Ceros a la izquierda, octal y hexadecimal: campo minado

Muchos parsers legacy interpretan:

  • 010 como octal8.
  • 0x10 como hex16.

Eso ha originado bypass reales en WAF/SSRF y confusiones en ACLs. Ejemplo: 010.000.000.001 puede acabar resolviendo a 8.0.0.1. Regla de oro: evitar ceros a la izquierda y bases no decimales.

2) No vale para todo

  • CIDR, rutas y máscaras no aceptan abreviados: 10.0.0.0/24 debe escribirse completo.
  • Documentación, tickets, inventario, ACLs, firewalls: mezclar abreviados genera ambigüedad y deuda técnica.
  • Logs y auditoría: normalizar siempre a cuatro octetos.

3) Seguridad operativa

Un atacante puede aprovechar divergencias de parsing entre componentes (proxy estricto vs. backend permisivo) para escapar validaciones. Evitar la superficie de ataque pasa por unificar representaciones.

Guía de buenas prácticas para equipos Linux

Producción: formato canónico o nada

  • Siempre a.b.c.d en configuración (systemd-networkd, NetworkManager, iproute2, nftables, keepalived, bird, FRR…).
  • Sin ceros a la izquierda (10.0.0.1, no 010.000.000.001).
  • Evitar abreviados en scripts, playbooks y plantillas (Ansible, Terraform, Helm).

Normalización automática (pre-commit / CI)

Integra un chequeo sencillo que rechace direcciones no canónicas en cambios de red:

# detecta IPs no canónicas (aprox.)
grep -RhoE '\b([0-9]+(\.[0-9]+){0,3})\b' ./configs \
| awk '
  function valid(o){return (o>=0 && o<=255)}
  {
    n=split($0,a,".");
    if (n!=4) { print "Non-canonical:", $0; next }
    for (i=1;i<=4;i++) if (!valid(a[i])) bad=1;
    if (bad) print "Out of range:", $0
  }'
Lenguaje del código: PHP (php)

O utiliza parsers robustos:

# Canonicalizador simple (Python 3)
import ipaddress, sys
for line in sys.stdin:
    for tok in line.split():
        try:
            ip = ipaddress.IPv4Address(tok)
            print(str(ip))
        except:
            pass
Lenguaje del código: PHP (php)

Comprobación y “linter” en vivo

  • getent ahosts 10.68 te mostrará a qué IP resuelve tu glibc.
  • python - <<'PY'\nimport ipaddress; print(ipaddress.ip_address("10.68"))\nPY fallará (estricto), útil para detectar abreviados que se cuelan.
  • ipcalc 10.68 te obliga a escribir completo; buena prueba para pipelines.

Documenta el comportamiento en tus “Runbooks”

Incluye una nota operativa: “En CLI se permiten abreviados por compatibilidad; la forma válida en este entorno es a.b.c.d. Evita que un miembro nuevo del equipo “optimice” con abreviados en un playbook.

“Cheat sheet” didáctico (por si necesitas explicarlo al equipo)

  • a.b.c
    c ocupa 16 bits:
    10.20.210.20.(2>>8).(2&255)10.20.0.2
  • a.b
    b ocupa 24 bits:
    10.6810.(68>>16).((68>>8)&255).(68&255)10.0.0.68
  • a (entero de 32 bits)
    (a>>24).((a>>16)&255).((a>>8)&255).(a&255)

Úsalo para didáctica interna, no para justificar su uso en producción.

Herramientas Linux: quién es estricto y quién no (panorama típico)

  • Tolerantes (depende build): ping/ping6 (iputils), ssh (OpenSSH), nc tradicional, algunos curl/wget según resolutor.
  • Estrictos: parsers de Go (net.ParseIP), Rust (std::net/ipnet), Python (ipaddress), systemd en varias unidades, muchos SDK cloud y APIs web modernas, iptables/nftables (en reglas esperan a.b.c.d), navegadores.

Este listado puede variar por distro, versión y flags de compilación. Lo importante es no asumir homogeneidad.

Ejemplos útiles para formación interna

Mostrar el “engaño” de ceros a la izquierda (octal)

# En sistemas con inet_legacy:
ping -c1 010.000.000.001   # puede ir a 8.0.0.1 (¡peligro!)
# En herramientas estrictas:
python3 - <<'PY'
import ipaddress
try: print(ipaddress.ip_address('010.000.000.001'))
except Exception as e: print("Error:", e)
PY
Lenguaje del código: PHP (php)

Normalizar listas de hosts heredadas

# hosts.txt con IPs mezcladas
awk '{for(i=1;i<=NF;i++) if ($i ~ /^[0-9.]+$/) print $i}' hosts.txt \
| while read ip; do
  python3 - "$ip" <<'PY'
import sys, ipaddress
try:
  print(ipaddress.ip_address(sys.argv[1]))
except:
  print("INVALID:", sys.argv[1])
PY
done | sort -u
Lenguaje del código: PHP (php)

Política recomendada del equipo de redes/SRE

  1. Formato canónico obligatorio en repos de config, CMDB e infraestructura como código.
  2. Bloqueo CI ante direcciones no canónicas o con ceros a la izquierda.
  3. Conversión automática de inventarios heredados con herramientas de normalización.
  4. Runbooks actualizados: cuándo un abreviado puede aparecer (CLI puntual en laboratorio) y por qué no se acepta en PRs.
  5. Pruebas de seguridad: añade casos de IP abreviadas/octales/hex a test de WAF/SSRF y validadores de entradas.

¿Y en IPv6?

Otra historia. IPv6 sí admite compresión, pero con reglas distintas (::, supresión de ceros a la izquierda en cada hexteto, una sola :: por dirección, etc.). No mezclar compresión IPv6 con abreviados “legacy” de IPv4: son mundos separados.

Conclusión

La compatibilidad con direcciones IPv4 abreviadas es un artefacto histórico útil en laboratorio que puede romper supuestos en producción. Un equipo Linux profesional debería:

  • Conocer por qué 10.68 llega a 10.0.0.68.
  • Evitarlo en todo lo que toque configuración, automatización, documentación y seguridad.
  • Normalizar y validar de forma sistemática en CI/CD.
  • Formar al equipo sobre ceros a la izquierda, octal y hexadecimal.

Ahorra pulsaciones donde no importe; evita sorpresas donde sí.


Preguntas frecuentes (FAQ)

¿Cómo convertir direcciones IPv4 abreviadas a formato canónico en un script?
Usa parsers estrictos. En Python: ipaddress.IPv4Address('10.68') falla (útil para detectar), pero puedes escribir una pequeña función que expanda a.ba.0.0.b y a.b.ca.b.(c>>8).(c&255) antes de validar y emitir a.b.c.d.

¿Puedo usar IP abreviadas en reglas de iptables/nftables o en ip route?
No es recomendable (y a menudo no funciona). Los motores esperan el dotted quad canónico. Mantén 10.0.0.68/32, no 10.68/32.

¿Por qué curl acepta 10.68 en un servidor y lo rechaza en otro?
Probablemente porque está compilado con diferentes resolutores o versiones de glibc/libcURL. No confíes en que el comportamiento sea igual entre distros, contenedores o imágenes base.

¿Cómo detectar en mis repos si alguien coló una IP no canónica?
Añade un pre-commit o un job de CI que busque tokens ^[0-9.]+$, descarte verdaderos a.b.c.d y marque el resto como no canónico. Complementa con una pasada de ipaddress en Python para validar rango (0–255) y rechazar ceros a la izquierda.

Suscríbete al boletín SysAdmin

Este es tu recurso para las últimas noticias y consejos sobre administración de sistemas, Linux, Windows, cloud computing, seguridad de la nube, etc. Lo enviamos 2 días a la semana.

¡Apúntate a nuestro newsletter!


– patrocinadores –

Noticias destacadas

– patrocinadores –

¡SUSCRÍBETE AL BOLETÍN
DE LOS SYSADMINS!

Scroll al inicio
×