Redes con ip netns

Dos laboratorios hechos solo con Linux y bash. Cada PC, switch y router es un network namespace: una copia aislada de la red del sistema, como si fuera un aparato distinto.

0 · Las piezas del lego

Con cuatro comandos se simula cualquier red:

Aparato realEn LinuxComando
Un ordenadornamespaceip netns add pc1
Un cablepar veth (dos tarjetas unidas)ip link add eth0 netns pc1 type veth peer name p-pc1 netns sw1
Un switchbridgeip link add br0 type bridge
Un routernamespace que reenvíasysctl net.ipv4.ip_forward=1

Luego a cada tarjeta se le pone una IP (ip addr add) y a cada aparato se le dice por dónde mandar lo que no es suyo (ip route add). Nada más.

1 · Red de redes sin internet

Cuatro LANs (cada una con su switch y su PC) unidas por cuatro routers. Todas las IPs son privadas (10.x.x.x) y no pasa nada: todos los routers conocen todas las redes, así que no hace falta traducir direcciones. Entre pc1 y pc2 hay varios caminos: pulsa para verlos.

10.1.12.0/24 10.1.13.0/24 10.1.24.0/24 10.1.34.0/24 10.1.23.0/24 pc1 10.0.1.10 LAN1 10.0.1.0/24 sw1 r1 r2 r3 r4 sw2 pc2 10.0.2.10 LAN2 10.0.2.0/24 sw3 pc3 10.0.3.10LAN3 10.0.3.0/24 sw4 pc4 10.0.4.10LAN4 10.0.4.0/24
PC (namespace) switch (bridge) router (ip_forward=1) camino actual pc1 ⇄ pc2

Paso a paso: ¿qué pasa cuando pc1 hace ping 10.0.2.10?

  1. pc1 mira su tabla de rutas. 10.0.2.10 no está en su LAN (10.0.1.0/24), así que usa su única regla: default via 10.0.1.1 → se lo manda a r1.
  2. El switch sw1 solo mueve la trama de un cable a otro dentro de la LAN. No mira IPs.
  3. r1 busca en su tabla quién lleva a 10.0.2.0/24. En el camino “arriba” la regla es 10.0.2.0/24 via 10.1.12.2 → se lo pasa a r2.
  4. r2 hace lo mismo: 10.0.2.0/24 via 10.1.24.4 → a r4.
  5. r4 tiene la LAN2 conectada directamente, así que lo entrega a pc2 a través de sw2.
  6. pc2 responde y la respuesta hace el viaje al revés: r4 sabe que 10.0.1.0/24 va por r2, r2 que va por r1…

Cambiar de camino es solo cambiar el “siguiente salto” en algunos routers. Por ejemplo, para ir “abajo”:

ip netns exec r1 ip route replace 10.0.2.0/24 via 10.1.13.3   # ida: r1 -> r3
ip netns exec r4 ip route replace 10.0.1.0/24 via 10.1.34.3   # vuelta: r4 -> r3

Eso es lo que hace cambiar_ruta.sh. Con tracepath ves los routers por los que pasa:

$ sudo ip netns exec pc1 tracepath -n 10.0.2.10     # camino zigzag
 1:  10.0.1.1      <- r1
 2:  10.1.12.2     <- r2
 3:  10.1.23.3     <- r3
 4:  10.1.34.4     <- r4
 5:  10.0.2.10     alcanzado (pc2)

En la vida real las rutas no se escriben a mano: protocolos como OSPF o BGP las calculan solos y cambian de camino si un cable se rompe. Aquí se ponen a mano para ver claramente cómo funciona.

2 · Dos casas comunicadas por internet

Ahora las LANs de los extremos son dos casas normales. Las dos usan la misma red privada 192.168.1.0/24 (como casi todos los routers domésticos), así que pc1 y pc2 tienen incluso la misma IP 192.168.1.10. Los routers de internet (isp1, isp2) no conocen las redes privadas: solo saben llegar a IPs públicas. Cada casa tiene una sola IP pública, la de su router, y usa puertos para decidir a qué PC va cada conexión.

INTERNET (solo IPs públicas) CASA 1 · 192.168.1.0/24 (privada) CASA 2 · 192.168.1.0/24 (privada) pc1 .10 · puerto 8001 pc3 .11 · puerto 8003 sw1 casa1 LAN .1 203.0.113.10 isp1 isp2 192.0.2.0/24 casa2 LAN .1 198.51.100.20 sw2 pc2 .10 · puerto 8002 pc4 .11 · puerto 8004
router de casa (hace NAT) router de internet (ISP) IP pública

Los dos trucos del router de casa (NAT)

TrucoQué haceRegla en el script
NAT de salida
(MASQUERADE)
Al salir a internet, cambia la IP privada
de origen por la IP pública de la casa.
iptables -t nat -A POSTROUTING -o wan -j MASQUERADE
Reenvío de puertos
(DNAT)
Lo que llega a un puerto de la IP pública
lo manda a un PC concreto de dentro.
iptables -t nat -A PREROUTING -i wan -p tcp --dport 8002 -j DNAT --to-destination 192.168.1.10:80
Dirección pública→PC de dentro
203.0.113.10:8001→pc1 · 192.168.1.10:80 (casa 1)
203.0.113.10:8003→pc3 · 192.168.1.11:80 (casa 1)
198.51.100.20:8002→pc2 · 192.168.1.10:80 (casa 2)
198.51.100.20:8004→pc4 · 192.168.1.11:80 (casa 2)

Paso a paso: pc1 ejecuta curl http://198.51.100.20:8002

Mira cómo cambian las direcciones del paquete en cada tramo (en rojo, lo que se ha cambiado):

TramoOrigenDestinoQuién lo cambia
1. pc1 → casa1192.168.1.10:51000198.51.100.20:8002—
2. casa1 → internet203.0.113.10:51000198.51.100.20:8002casa1 (MASQUERADE)
3. isp1 → isp2203.0.113.10:51000198.51.100.20:8002nadie, solo enrutan
4. casa2 → pc2203.0.113.10:51000192.168.1.10:80casa2 (DNAT puerto 8002)
  1. pc1 no conoce 198.51.100.20, así que lo manda a su puerta de enlace, casa1.
  2. casa1 lo manda a internet por su cable wan y, al salir, cambia el origen 192.168.1.10 por su IP pública 203.0.113.10. Apunta el cambio en una tabla (conntrack) para deshacerlo en la respuesta.
  3. isp1 e isp2 solo ven IPs públicas y saben llegar a ellas: lo llevan hasta casa2.
  4. casa2 ve que va a su puerto 8002 y, según su regla, cambia el destino a 192.168.1.10:80: pc2.
  5. pc2 contesta “Hola, soy pc2” a 203.0.113.10. Los routers deshacen los cambios en la vuelta y la respuesta llega a pc1. pc2 nunca ve la IP privada de pc1: en su log aparece 203.0.113.10.

¿Y si pc1 intentara usar la IP privada de pc2? 192.168.1.10 es… ¡la propia pc1! Y aunque no lo fuera, isp1 no tiene ninguna ruta hacia 192.168.x.x (Network is unreachable). Por eso, para salir de casa, hacen falta IPs públicas y puertos.

Cómo ejecutarlo

Necesitas Linux con iproute2, iptables, python3 y curl. Todo se crea dentro de namespaces: tu red real no se toca.

Proyecto 1

cd proyecto1_sin_internet
sudo ./crear_red.sh              # monta la red
sudo ./probar.sh                 # pings + tracepath + tabla de rutas de r1
sudo ./cambiar_ruta.sh abajo     # arriba | abajo | zigzag
sudo ip netns exec pc1 tracepath -n 10.0.2.10
sudo ./borrar_red.sh             # lo quita todo

Proyecto 2

cd proyecto2_con_internet
sudo ./crear_red.sh              # monta la red, el NAT y los servidores web
sudo ip netns exec pc1 curl http://198.51.100.20:8002   # -> Hola, soy pc2
sudo ./probar.sh                 # todas las pruebas
sudo ./borrar_red.sh

Trucos para curiosear

sudo ip netns list                       # ver todos los aparatos
sudo ip netns exec r2 ip route           # tabla de rutas de un router
sudo ip netns exec pc1 bash              # abrir una terminal "dentro" de pc1
sudo ip netns exec casa1 iptables -t nat -L -n -v   # reglas NAT

Código: github.com/melvinfranco99/redes-con-y-sin-internet