Saltar al contenido principal
Jordi Izquierdo Montalbán
Lo que practico

Fundamentos

Redes

Entiendo el camino de cada petición: DNS, TLS, CORS y proxy inverso.

Seguir el recorrido de una petición

Cuando una aplicación «va lenta» o «no conecta», la causa casi siempre está en una capa concreta de un recorrido que tiene un orden fijo. El oficio de redes consiste en conocer ese recorrido lo bastante bien como para señalar en qué paso se rompe. Este es el camino de una petición web:

El camino completo desde que se escribe una dirección hasta que llega la respuesta.
  1. El nombre se traduce a una dirección IP (DNS).
  2. Se abre una conexión de transporte hacia esa IP y ese puerto (TCP o QUIC).
  3. Se negocia el cifrado (TLS) y se verifica la identidad del servidor.
  4. Se envía la petición de aplicación (HTTP) y llega a un punto de entrada: balanceador, proxy o CDN.
  5. Hasta el servidor final cruza cortafuegos, segmentos de red y, quizá, redes de contenedores.
  6. La respuesta recorre el camino inverso, a menudo con cachés intermedias.

El resto de la página recorre ese camino capa por capa y termina con las herramientas para diagnosticarlo.

Modelos de capas

El modelo OSI (siete capas) es una referencia conceptual; el modelo TCP/IP (cuatro) es el que describe lo que se usa en realidad. Cada capa resuelve un problema y confía en la de abajo.

Cada capa resuelve un problema y confía en la de abajo.
OSITCP/IPFunciónEjemplos
7 Aplicación, 6 Presentación, 5 SesiónAplicaciónProtocolos que ve el programaHTTP, DNS, SMTP, SSH
4 TransporteTransporteEntrega entre procesos, puertosTCP, UDP, QUIC
3 RedInternetDireccionamiento y encaminamiento entre redesIP, ICMP
2 Enlace, 1 FísicaAcceso a la redEntrega dentro de un mismo segmentoEthernet, Wi-Fi, ARP

Al enviar, cada capa encapsula el mensaje de la superior con su propia cabecera:

Cada capa añade su cabecera al bajar y la retira al subir.

Por eso se habla de mensaje en aplicación, segmento en TCP, paquete en IP y trama en enlace.

Direccionamiento IP, CIDR y NAT

Una dirección IPv4 son 32 bits (cuatro bytes en decimal); IPv6, 128 bits en hexadecimal. La notación CIDR indica cuántos bits identifican la red: 192.168.10.0/24 significa que los 24 primeros bits son la red y quedan 8 para equipos (256 direcciones, de las que dos se reservan: la de red y la de difusión).

CIDRMáscaraDireccionesUso típico
/32255.255.255.2551Un único equipo
/30255.255.255.2524Enlace punto a punto
/24255.255.255.0256Una subred pequeña
/16255.255.0.065 536Una red mediana dividida en subredes
/8255.0.0.016 777 216Bloque muy grande

Rangos privados de IPv4 (no enrutables en Internet): 10.0.0.0/8, 172.16.0.0/12 y 192.168.0.0/16. 127.0.0.0/8 es el bucle local (loopback) y 169.254.0.0/16 el de autoconfiguración local, que en entornos de nube suele alojar el servicio de metadatos.

Subredes: dividir una red mayor en bloques menores permite separar funciones y aplicar reglas distintas a cada una. Un plan de direccionamiento deja huecos para crecer y evita solapar rangos con otras redes a las que se conectará (por ejemplo, una VPN con la oficina).

NAT (traducción de direcciones) permite que muchos equipos con direcciones privadas salgan a Internet compartiendo una dirección pública: el router reescribe origen y puerto y recuerda la correspondencia para devolver las respuestas. Consecuencias prácticas: desde fuera no se puede iniciar una conexión hacia un equipo detrás de NAT sin una regla de reenvío de puertos, y por eso existen técnicas para atravesarlo en comunicaciones directas.

Puertos y sockets

Un puerto (16 bits, de 0 a 65 535) identifica un servicio dentro de un equipo. Una conexión queda definida por la cuarteta: IP origen, puerto origen, IP destino, puerto destino. Puertos habituales:

PuertoServicio
22SSH
53DNS
80 / 443HTTP / HTTPS
5432PostgreSQL
3306MySQL
6379Redis

Un servicio que escucha en 127.0.0.1 solo acepta conexiones locales; en 0.0.0.0 acepta de todas las interfaces. Escuchar solo donde hace falta es la primera defensa de red.

Transporte: TCP, UDP y QUIC

Tres mensajes confirman que ambos extremos pueden enviar y recibir.
TCPUDP
ConexiónSí, con saludo en tres pasosNo
EntregaFiable: confirma, reenvía, ordenaSin garantías
Control de flujo y congestiónSíNo (lo resuelve quien lo use)
LatenciaMayor (saludo, esperas por reenvíos)Menor
Uso típicoWeb, correo, bases de datosDNS, voz y vídeo, juegos, QUIC

Ideas clave de TCP, a nivel conceptual:

  • Números de secuencia y confirmaciones: el receptor confirma lo recibido y el emisor reenvía lo que no se confirma.
  • Control de flujo: el receptor anuncia cuánto puede recibir (ventana) para no ser desbordado.
  • Control de congestión: el emisor empieza despacio, aumenta su ritmo mientras todo va bien y lo reduce al detectar pérdidas, para no saturar la red.
  • Cierre ordenado con intercambio de mensajes FIN y un estado de espera (TIME_WAIT) en el extremo que cierra; muchos de estos estados son normales en servidores muy activos.

UDP deja la fiabilidad a la aplicación. QUIC (base de HTTP/3) construye sobre UDP una conexión fiable, cifrada y multiplexada, con migración de conexión cuando cambia la red del cliente.

DNS: el sistema de nombres

DNS traduce nombres a datos. Es jerárquico y se apoya en caché en todos los niveles.

El resolvedor pregunta de arriba abajo y guarda la respuesta durante su TTL.
RegistroContenidoEjemplo de uso
ANombre a dirección IPv4app.ejemplo.org apunta a un servidor
AAAANombre a dirección IPv6Lo mismo en IPv6
CNAMEAlias de otro nombrewww apunta a otro nombre; no puede convivir con otros registros en el mismo nombre
MXServidores de correo del dominio, con prioridadEntrega de email
TXTTexto libreVerificación de dominio, SPF, DKIM y DMARC
NSServidores autoritativos de la zonaDelegación
CAAQué autoridades pueden emitir certificadosRestringir emisión de certificados

El TTL es el tiempo (en segundos) que una respuesta puede conservarse en caché. Con un TTL alto, los cambios tardan en propagarse; antes de una migración se baja el TTL con antelación y se vuelve a subir después. La «propagación» de DNS es en realidad la caducidad de cachés en cadena.

# Registro A de un nombre, mostrando solo la respuesta
dig +short A app.ejemplo.org
 
# Seguir toda la cadena de delegación desde la raíz
dig +trace app.ejemplo.org
 
# Preguntar a un resolvedor concreto para descartar cachés locales
dig @1.1.1.1 MX ejemplo.org

HTTP: tres versiones, tres formas de transportar

Cada versión reduce esperas cambiando cómo se transportan las peticiones.
HTTP/1.1HTTP/2HTTP/3
FormatoTextoBinarioBinario
TransporteTCPTCPQUIC sobre UDP
Peticiones en paraleloVarias conexionesMultiplexado en unaMultiplexado en una
Bloqueo de cabecera de líneaEn la conexiónEn TCP si se pierde un paquetePor flujo, sin bloqueo cruzado
Compresión de cabecerasNoHPACKQPACK
CifradoOpcionalDe hecho, con TLSObligatorio (TLS 1.3 integrado)

Más allá de la versión, lo que gobierna el comportamiento es la semántica: métodos (GET, POST, PUT, DELETE), códigos de estado (2xx éxito, 3xx redirección, 4xx error del cliente, 5xx error del servidor), cabeceras de caché (Cache-Control, ETag) y conexiones persistentes (keep-alive) que evitan repetir el saludo.

TLS 1.3: cifrado e identidad

TLS aporta tres cosas: confidencialidad (nadie lee el tráfico), integridad (nadie lo modifica) y autenticación del servidor mediante certificados.

Un viaje de ida y vuelta basta para acordar claves y verificar al servidor.
  1. El cliente propone algoritmos y envía su parte del intercambio de claves.
  2. El servidor responde con la suya y su certificado.
  3. Ambos derivan las mismas claves de sesión sin enviarlas por la red. La confidencialidad hacia adelante garantiza que, aunque se robe más tarde la clave del servidor, las sesiones pasadas siguen siendo ilegibles.
  4. El cliente verifica el certificado y el tráfico pasa a ir cifrado.

Cadena de confianza: el certificado del servidor está firmado por una autoridad intermedia, que a su vez está firmada por una raíz que el sistema o el navegador ya traen instalada. Se valida que la cadena llegue a una raíz confiable, que no haya caducado ni esté revocado, y que el nombre del certificado coincida con el del sitio.

Errores típicos de despliegue:

  • Certificado caducado por renovación manual olvidada: se automatiza la renovación y se vigila la caducidad.
  • Cadena incompleta (falta el certificado intermedio).
  • Nombre que no coincide con el dominio usado.
  • Aceptar certificados inválidos «solo en pruebas» y dejarlo así en producción.

HSTS indica al navegador que use siempre HTTPS con ese dominio, y mTLS hace que el cliente también presente certificado, útil entre servicios internos.

# Ver la cadena de certificados y el protocolo negociado
openssl s_client -connect app.ejemplo.org:443 -servername app.ejemplo.org
 
# Fechas de validez del certificado
echo | openssl s_client -connect app.ejemplo.org:443 -servername app.ejemplo.org 2>/dev/null \
  | openssl x509 -noout -dates -subject

Proxy inverso, balanceo y CDN

Un proxy inverso recibe el tráfico en nombre de los servidores: termina TLS, enruta por ruta o dominio, aplica límites y oculta la topología interna. Un balanceador reparte la carga entre varias instancias y retira las que fallan.

Un único punto de entrada reparte el tráfico y oculta los servidores.
Capa 4 (transporte)Capa 7 (aplicación)
Decide porIP y puertoRuta, dominio, cabeceras, cookies
CosteMuy bajoMayor (interpreta HTTP)
PuedeRepartir conexiones TCPEnrutar por URL, reescribir, cachear, limitar
CuándoTráfico no HTTP o máximo rendimientoAPIs y webs con reglas de enrutado

Algoritmos de reparto:

AlgoritmoIdeaCuándo
Round robinPor turnosInstancias iguales y peticiones parecidas
Menos conexionesAl que tiene menos activasPeticiones de duración muy desigual
Hash de IP o de cabeceraEl mismo cliente al mismo servidorAfinidad sin cookies
PonderadoMás carga a los más potentesInstancias heterogéneas

Puntos de diseño: comprobaciones de salud (health checks) que decidan quién recibe tráfico, sesiones pegajosas solo si la aplicación guarda estado local (lo mejor es no guardarlo), y propagar la IP real del cliente en cabeceras como X-Forwarded-For, confiando solo en las cabeceras puestas por los proxies propios, nunca en las que envíe el cliente.

Una CDN es una red de servidores de caché repartidos geográficamente. Acerca el contenido al usuario, absorbe picos y protege el origen. Se controla con Cache-Control (max-age, s-maxage, no-store, stale-while-revalidate) y con nombres de fichero que cambian con el contenido para poder cachear de forma agresiva. El contenido personalizado o autenticado no debe cachearse en una caché compartida.

Política del mismo origen, CORS y WebSocket

El navegador aplica la política del mismo origen: una página solo puede leer respuestas de su propio origen (esquema, dominio y puerto). CORS es el mecanismo por el que un servidor autoriza explícitamente a otros orígenes.

El navegador pregunta al servidor si otra web puede llamarlo, antes de enviar la petición real.
GET /api/perfil HTTP/1.1
Origin: https://app.ejemplo.org
 
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.ejemplo.org
Access-Control-Allow-Credentials: true
Vary: Origin
  • Las peticiones «no simples» (por ejemplo, con Content-Type: application/json o métodos distintos de GET y POST) van precedidas de una comprobación previa (OPTIONS) que el servidor debe responder.
  • Con credenciales (cookies) no vale el comodín: hay que devolver el origen concreto y, por eso, Vary: Origin.
  • Una lista de orígenes permitidos explícita es lo correcto; reflejar sin más el Origin recibido equivale a no tener política.
  • CORS protege al usuario en el navegador; no es un control de acceso del servidor. Un cliente que no sea un navegador lo ignora.

WebSocket abre un canal bidireccional persistente a partir de una petición HTTP con upgrade. Hay que dimensionar conexiones abiertas, validar el origen en el saludo, autenticar y limitar mensajes, y configurar tiempos de inactividad en proxies y balanceadores, que suelen cortar conexiones silenciosas.

Cortafuegos, segmentación y VPN

Un cortafuegos permite o bloquea tráfico según origen, destino, puerto y protocolo. Puede ser con estado (recuerda las conexiones iniciadas y deja pasar sus respuestas) o sin estado. La base es denegar por defecto y abrir solo lo necesario.

Cada zona solo puede hablar con la siguiente, por los puertos imprescindibles.

Principios de la segmentación:

  • Solo el punto de entrada tiene IP pública; el resto vive en redes privadas.
  • La base de datos solo acepta conexiones de la capa de aplicación, no de Internet ni de los equipos de los usuarios.
  • Separar entornos (producción, pruebas) para que un incidente en uno no alcance al otro.
  • Controlar también el tráfico de salida: limita la exfiltración y reduce el alcance del SSRF.

Una VPN crea un túnel cifrado entre dos redes o entre un equipo y una red, para acceder a recursos internos como si se estuviera dentro. Variantes: acceso remoto de usuarios, conexión entre sedes (sitio a sitio) y mallas modernas entre equipos. Una VPN no sustituye a la autenticación de cada servicio: estar «dentro» no debería conceder acceso a todo (modelo de confianza cero).

Ejemplo de reglas con un cortafuegos de host:

# Política por defecto: denegar la entrada
ufw default deny incoming
ufw default allow outgoing
 
# Permitir solo lo imprescindible
ufw allow 443/tcp
ufw allow from 10.0.1.0/24 to any port 5432 proto tcp   # base de datos solo desde la red de aplicación
ufw enable

Redes de contenedores

Los contenedores reciben su propia red virtual, normalmente con direcciones privadas y NAT hacia el exterior.

  • Red puente (bridge): contenedores del mismo equipo comunicados entre sí; hacia fuera, mediante NAT y publicación de puertos.
  • Red del host: el contenedor comparte la red del equipo; mayor rendimiento y menor aislamiento.
  • Redes definidas por el usuario: añaden resolución de nombres entre contenedores por su nombre de servicio.
  • Orquestadores (como Kubernetes): cada grupo de contenedores recibe una dirección y los servicios dan un nombre estable con balanceo interno; las políticas de red limitan qué grupos pueden hablar entre sí.

Buenas prácticas: no publicar puertos innecesarios (publicar un puerto lo expone a la red del equipo), usar redes separadas por función, y aplicar políticas de red que deniegan por defecto el tráfico entre servicios.

# Docker Compose: la base de datos no publica puerto y solo está en la red interna
services:
  web:
    ports: ["443:443"]
    networks: [publica, interna]
  db:
    networks: [interna]
networks:
  publica: {}
  interna:
    internal: true

SSRF: cuando el servidor hace de intermediario

En una vulnerabilidad SSRF (falsificación de peticiones del lado del servidor), una funcionalidad que descarga una URL aportada por el usuario puede usarse para hacer que el servidor consulte destinos que el usuario no alcanzaría: servicios internos, paneles de administración o el servicio de metadatos de la nube, que puede entregar credenciales.

El servidor no debe hacer peticiones a destinos que elija un atacante sin validarlos.
// Vulnerable: descarga lo que diga el usuario
const resp = await fetch(req.query.url);
 
// Más seguro: esquema, lista de destinos permitidos y comprobación de la IP resuelta
const url = new URL(req.query.url);
if (url.protocol !== "https:" || !DESTINOS_PERMITIDOS.has(url.hostname)) {
  return res.status(400).end();
}
const resp = await fetch(url, { redirect: "error", signal: AbortSignal.timeout(5000) });

Defensa en profundidad: lista de destinos permitidos (mejor que lista de bloqueo), resolver el nombre y rechazar IP privadas, de loopback y de enlace local, desactivar o revalidar redirecciones, evitar que la respuesta se devuelva en bruto al usuario, aislar la función en una red sin acceso a lo interno, y exigir la versión del servicio de metadatos que requiere un token en la nube.

Diagnóstico: de abajo arriba

Cuando algo falla, se comprueba capa por capa. Una pregunta por herramienta.

Se avanza de abajo arriba hasta encontrar la capa que falla.
HerramientaPregunta que responde
ping¿Hay camino de red hasta el destino? (puede estar bloqueado ICMP)
traceroute¿Por qué saltos pasa y dónde se pierde o se retrasa?
dig¿Qué devuelve el DNS y desde qué servidor?
curl -v¿Qué ocurre en TLS y HTTP, paso a paso?
ss -tulpn¿Qué procesos escuchan, en qué dirección y puerto?
nc -vz host puerto¿Se puede abrir la conexión TCP a ese puerto?
tcpdump¿Qué paquetes viajan realmente?
# Latencia y pérdida hacia un destino
ping -c 4 10.0.2.15
 
# Ruta seguida por los paquetes
traceroute app.ejemplo.org
 
# Detalle de la conexión: resolución, TLS, cabeceras y tiempos
curl -v https://app.ejemplo.org/salud
curl -s -o /dev/null -w "dns=%{time_namelookup} conexion=%{time_connect} tls=%{time_appconnect} total=%{time_total}\n" https://app.ejemplo.org
 
# Qué escucha en el servidor
ss -tulpn
 
# Capturar tráfico DNS en una interfaz (requiere permisos)
tcpdump -i eth0 -n port 53

El script de curl con tiempos separa en qué fase se va la latencia: si crece dns, es resolución; si crece conexion, es la red o el filtrado; si crece tls, es el saludo o el certificado; si solo crece total, es la aplicación.

Síntomas y causas probables

SíntomaCausa probableDónde mirar
Un nombre no resuelveRegistro ausente, TTL con valor antiguo, resolvedor distintodig contra distintos servidores
Conexión rechazada de inmediatoNada escucha en ese puerto o escucha solo en loopbackss -tulpn en el servidor
Conexión que se queda colgadaCortafuegos que descarta paquetes sin responderReglas del cortafuegos y grupos de seguridad
Error de certificadoCaducado, cadena incompleta o nombre incorrectoopenssl s_client
Funciona por IP y no por nombreDNS o cabecera de dominio en el proxydig, configuración del host virtual
Error 502 o 504 del proxyServidor de origen caído o lentoComprobaciones de salud y tiempos máximos
Funciona en curl y falla en el navegadorCORS o contenido mixtoConsola del navegador, cabeceras de respuesta
Lentitud intermitentePérdida de paquetes, saturación o cola en el balanceadorTiempos por fase, métricas del balanceador

Lista de comprobación

  • Plan de direccionamiento documentado, sin solapes y con espacio para crecer.
  • Solo el punto de entrada es accesible desde Internet; todo lo demás, en redes privadas.
  • Cortafuegos con denegación por defecto, en entrada y en salida.
  • TLS en todo el tráfico, renovación automática de certificados y HSTS.
  • Servicios escuchando únicamente en las interfaces necesarias.
  • Comprobaciones de salud y tiempos máximos en proxies y balanceadores.
  • CORS con lista explícita de orígenes y sin comodín cuando hay credenciales.
  • Descargas de URL del usuario protegidas contra SSRF.
  • TTL de DNS bajado antes de una migración.
  • Procedimiento de diagnóstico por capas, escrito y conocido.

Antipatrones

  • Dejar la base de datos con IP pública «para poder conectar desde casa».
  • Desactivar la verificación de certificados para que «funcione».
  • Abrir un rango entero de puertos o 0.0.0.0/0 en un cortafuegos por comodidad.
  • Confiar en X-Forwarded-For tal como llega del cliente.
  • Responder a CORS con * o reflejando el origen recibido, junto con credenciales.
  • Depender de la IP del cliente como único control de acceso.
  • Cambiar registros DNS sin haber bajado el TTL antes y sin plan de vuelta atrás.
  • Diagnosticar «a ciegas» cambiando configuración en lugar de medir por capas.