NAT bidireccional con iptables

NAT bidireccional con iptables

En resumen, tengo un sistema de clúster en mis manos, para el cual tengo que enrutar el tráfico a través de su maestro. El enrutamiento del tráfico desde los nodos al mundo exterior funciona, pero el enrutamiento del tráfico desde la subred de nuestro departamento a los nodos falla. Desafortunadamente, agregar los nodos a nuestra subred está fuera de discusión.

La puesta en marcha

Configuración de clúster, sin interruptores tontos para simplificar

El clúster consta de un maestro y varios nodos, junto con algo de periferia. Los nodos están en una red interna, ocultos de nuestra intranet o internet. Ya existe una NAT en el maestro, por lo que los nodos tienen acceso a servidores internos y externos. Esta parte funciona.

La interfaz externa del maestro está en la misma subred que nuestras estaciones de trabajo, que comparten una puerta de enlace fuera de nuestro control.

Editar: el clúster ejecuta CentOS 7, las PC ejecutan una distribución basada en Ubuntu xenial.

La tarea

Algunos de nuestros paquetes de software necesitan acceso directo a los nodos. Para esto, queríamos configurar una segunda NAT en el maestro usando iptables y agregar una ruta IP en las PC para enviar tráfico a 10.10.1.0/24 a través del maestro.

La configuración

maestro: ruta ip

default via 123.45.67.254 dev eth0 proto static metric 100
10.10.0.0/16 dev eth1 proto kernel scope link src 10.10.0.1
123.45.67.0/23 dev eth0 proto kernel scope link src 123.45.67.204 metric 100

maestro: iptables -vnL -t nat

Chain PREROUTING (policy ACCEPT 7356 packets, 880K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain INPUT (policy ACCEPT 4884 packets, 687K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 3445 packets, 225K bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 3445 packets, 225K bytes)
 pkts bytes target     prot opt in     out     source               destination
  439 33324 MASQUERADE  all  --  *     eth0    10.10.1.0/24         0.0.0.0/0
61828 3710K MASQUERADE  all  --  *     eth1    123.45.67.0/23       10.10.1.0/24

Usar SNAT en lugar de MASQUERADE no hace ninguna diferencia.

nodo: ruta ip

default via 10.10.0.1 dev eth1
10.10.0.0/16 dev eth1 proto kernel scope link src 10.10.1.1

ordenador personal: ruta ip

default via 123.45.67.254 dev eth0  proto static  metric 100
10.10.0.0/16 via 123.45.67.204 dev eth0
123.45.67.0/23 dev eth0  proto kernel  scope link  src 123.45.67.191  metric 100

Diagnóstico hasta el momento

  • NAT desde node01 a internet/intranet/pcs funciona perfectamente.
  • NAT de pc1 a node01 falla durante el protocolo de enlace TCP:
    • SYN se pasa a través del maestro al nodo01 y está marcado como SYN_RECV en tcpdump
    • SYN+ACK se envía desde el nodo01 al maestro
    • SYN+ACK aparece en tcpdump en el maestro, se pasa al filtro
    • tcpdump muestra el SYN+ACK pasando al filtro
    • iptables muestra los paquetes SYN+ACK que pasan por el filtro FORWARD, mangle FORWARD + POSTROUTING
    • Los paquetes SYN+ACK nunca pasan por nat POSTROUTING (¿deberían hacerlo?)
    • Los paquetes SYN+ACK nunca llegan a la pc1
  • Por supuesto, el apretón de manos falla.
    • pc1 está atascado en SYN_SENT
    • nodo01 está atascado en SYN_RECV
    • eventualmente, la conexión se agota
  • No tengo forma de monitorear paquetes en la puerta de enlace.

Mi mejor suposición es que un enrutador con estado en camino descarta el paquete SYN+ACK debido a que su dirección de origen se reescribe en el maestro, por lo que se pierde su relación con el paquete SYN original.

¿Cómo podemos hacer que esto funcione?

Avíseme si se necesitan configuraciones/registros adicionales.

información relacionada