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 real | En Linux | Comando |
|---|---|---|
| Un ordenador | namespace | ip netns add pc1 |
| Un cable | par veth (dos tarjetas unidas) | ip link add eth0 netns pc1 type veth peer name p-pc1 netns sw1 |
| Un switch | bridge | ip link add br0 type bridge |
| Un router | namespace que reenvía | sysctl 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.
Paso a paso: ¿qué pasa cuando pc1 hace ping 10.0.2.10?
- 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. - El switch sw1 solo mueve la trama de un cable a otro dentro de la LAN. No mira IPs.
- 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. - r2 hace lo mismo:
10.0.2.0/24 via 10.1.24.4→ a r4. - r4 tiene la LAN2 conectada directamente, así que lo entrega a pc2 a través de sw2.
- 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.
Los dos trucos del router de casa (NAT)
| Truco | Qué hace | Regla 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):
| Tramo | Origen | Destino | Quién lo cambia |
|---|---|---|---|
| 1. pc1 → casa1 | 192.168.1.10:51000 | 198.51.100.20:8002 | — |
| 2. casa1 → internet | 203.0.113.10:51000 | 198.51.100.20:8002 | casa1 (MASQUERADE) |
| 3. isp1 → isp2 | 203.0.113.10:51000 | 198.51.100.20:8002 | nadie, solo enrutan |
| 4. casa2 → pc2 | 203.0.113.10:51000 | 192.168.1.10:80 | casa2 (DNAT puerto 8002) |
- pc1 no conoce 198.51.100.20, así que lo manda a su puerta de enlace, casa1.
- casa1 lo manda a internet por su cable
wany, 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. - isp1 e isp2 solo ven IPs públicas y saben llegar a ellas: lo llevan hasta casa2.
- casa2 ve que va a su puerto 8002 y, según su regla, cambia el destino a 192.168.1.10:80: pc2.
- 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