lunes 7 de julio de 2008

PPTP, GRE y VPN múltiples con firewalls Stonegate (2 de 2)

Sigo con lo de antes.

Me logo al appliance con SSH y analizo con tcpdump un intento de abrir túneles como el explicado en el artículo de antes. Y veo algo así:

...
00:04:41.953787 IP 192.168.192.100 > 80.58.117.49: GREv1, call 19314, seq 0, length 37: LCP, Conf-Request (0x01), id 0, length 23

00:04:42.042053 IP 80.58.117.49 > 192.168.192.100: GREv1, call 49152, seq 0, ack 0, length 76: LCP, Conf-Request (0x01), id 0, length 58
00:04:42.044755 IP 192.168.192.100 > 80.58.117.49: GREv1, call 19314, seq 1, ack 0, length 55: LCP, Conf-Reject (0x04), id 0, length 37
00:04:42.045949 IP 80.58.117.49 > 192.168.192.100: GREv1, call 49152, seq 1, length 37: LCP, Conf-Ack (0x02), id 0, length 23
00:04:42.109984 IP 80.58.117.49 > 192.168.192.100: GREv1, call 49152, seq 2, ack 1, length 45: LCP, Conf-Request (0x01), id 1, length 27
00:04:42.110487 IP 192.168.192.100 > 80.58.117.49: GREv1, call 19314, seq 2, ack 2, length 29: LCP, Conf-Nack (0x03), id 1, length 11
...


Se comprueba lo que explicaba la nota de Stonesoft: GRE no utiliza el concepto de puerto que sí utilizan TCP o UDP. Nos dicen que esto impide que el firewall sea capaz de mapear/mantener el estado de más de una conexion con origen LAN al mismo destino WAN, que para el mundo exterior tendrán IPs públicas iguales. En cualquier cortafuego, mantener un estado para cada conexión es imprescindible, por ejemplo para permitir el paso de los paquetes de respuesta (acceso implícito, sin regla de acceso asociada) a las peticiones que haya enviado el originador de una conexión (para las que sí que hay reglas de acceso explicitas que permiten el paso).

De acuerdo, no hay src-port ni dst-port en los paquetes GRE. Pero, aún sin haberme leído los RFC correspondientes, veo lo que parece un id. de llamada (call) y otro de secuencia (seq) que, desde la ignorancia, parecen suficientes para mantener los estados de los que hablábamos antes.

Así que me da por intercalar un GNU/Linux con iptables (una Debian) entre la LAN y el Stonegate. El Linux actúa de dispositivo nateador, de forma que cualquier paquete que pase a través de él, sale con idéntica IP de origen (la del propio Linux, o sea 192.168.192.2). Establezco este equipo como puerta de enlace de los equipos desde los que intento abrir los túneles PPTP. Este es el nuevo dibujo:



La prueba también falla en el segundo túnel, pero al menos en el Stonegate ya no veo las denegaciones "Requested NAT cannot be done" (Esto es debido al NAT previo que está haciendo el Linux, que provoca que el Stonegate reciba un único origen y no se queje de nada).

Sniffo el Linux con un tcpdump y veo que el NAT sólo lo está haciendo para los paquetes de aquella máquina que ha sido la primera en abrir la conexión PPTP. Hasta aquí, más o menos, mismo comportamiento que el visto en el Stonegate.

Pero sigo sin creerme que el router de mi casa sea capaz de hacer más cosas que una distro Debian. Me doy un paseo por netfilter.org, me voy a Google y al final aterrizo en éste link.

Aquí me dicen que iptables dispone de dos helpers (ip_nat_pptp y ip_conntrack_pptp) que cargados en el kernel en forma de módulos permiten mantener los estados necesarios en las conexiones PPTP.

Aplico lo que proponen y pruebo de nuevo. Y todo empieza a funcionar. Mi GNU/Linux maneja correctamente los estados de las conexiones basadas en paquetes GRE, que de salida tienen la misma tupla origen-destino.

Este es el script iptables definitivo que he utilizado en el GNU/Linux (único propósito: natear la IP de origen, no actúa como cortafuegos):

#/bin/bash
export MYSELF="192.168.192.2"
export ANY="0.0.0.0/0"
iptables -F
iptables -X
iptables -Z
iptables -t nat -F
iptables -P INPUT ACCEPT
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
modprobe ip_nat_pptp || exit -1
modprobe ip_conntrack_pptp || exit -2
iptables -t nat -A POSTROUTING -s $ANY -d $ANY -j SNAT --to-source $MYSELF
echo 1 > /proc/sys/net/ipv4/ip_forward


Como ya he explicado en otras ocasiones, Stonesoft basa el SO de sus firewalls en la distribución Debian. ¡Vaya! La misma que he utilizado yo en mi prueba.

También veo que la versión de kernel que incorpora es suficiente para cargar los dos helpers iptables necesarios, según el link de wlug.org.nz

Conclusión: No estoy seguro de si Stonegate utiliza iptables, pero queda claro que manejar el contexto descrito aquí es perfectamente viable. Mientras Stonesoft no me lo aclare mejor, su firewall no soporta múltiples PPTP (misma combinación origen-destino en el lado público) porque a ellos no les da la real gana.

8 Comentarios:

Anónimo dijo...

Hola, tengo una duda sobre todo esto.
Como logro saber qué interface es la que tengo que usar para poner el tcpdump?
Gracias

Pere Moltó Agut dijo...

Supón que tienes tres interfaces:

eth0: 192.168.0.1 / 255.255.255.0
eth1: 10.0.0.1 / 255.255.255.0
eth2: otra IP en en otra red distinta

Ahora un host en 192.168.0.111 hace un ping a 10.0.0.222.

Secuencialmente ocurre lo siguiente (asumiendo que el 10.0.0.222 responde y el firewall no corta el ping):

1 - el host 192.168.0.111 lanza un "ICMP request" (entra por eth0)
2 - el firewall enruta ese paquete "ICMP request" (sale por eth1)
3 - el host 10.0.0.222 reponde con un "ICMP reply" (entra por eth1)
4 - el firewall enruta ese paquete "ICMP reply" (sale por eth0) y finalmente llega a la máquina que lanzó el ping.

En este caso, con un tcpdump verías pasar el tráfico tanto en eth0 como en eth1, que corresponden a los interfaces que el firewall decide utilizar en las decisiones de ruteo respectivas. Así pués, si conoces el origen del paquete, debes lanzar el tcpdump en el interface que sepas seguro va a recibir ese paquete. En el ejemplo, yo empezaría sniffando en eth0, pero como te decía en eth1 también verías el mismo tráfico.

Espero haber aclarado tu duda.

Anónimo dijo...

Pere,

Ante todo muchas gracias por tu ayuda y disculpa la tardanza en contestar.

Sí tengo más o menos claro en qué interfaces tengo que poner el tcpdump. El problema es que hay muchas rutas configuradas en los interfaces y no se cual es la forma de saber por cual interfaz es por la que entraría y por cual saldría la comunicación.

Mi pregunta es, hay alguna instrucción (tipo show ip route IP) que me indique por cual interfaz sale ese esa comunicación?

Gracias de nuevo y un saludo.

Pere Moltó Agut dijo...

Creo que lo que me quieres saber lo puedes obtener con "ip route get IP".

P. ej.:

nofw:~# ip route get 217.12.3.11
217.12.3.11 via 10.0.192.1 dev eth0 src 10.0.192.49
cache mtu 1500 advmss 1460 hoplimit 64

nofw:~# ip route get 10.0.193.24
10.0.193.24 dev eth1 src 10.0.193.2
cache mtu 1500 advmss 1460 hoplimit 64

Con esto sabrías que un ping desde 10.0.193.24 hacia 217.12.3.11, entra por eth1 y sale por eth0 (y viceversa para las respuestas).
Si en lugar de puertas de enlace "normales" tienes netlinks, no estoy seguro de que este método sirva (de hecho creo que no sirve).

Ya me dirás si es lo que necesitabas o no.

Saludos

Anónimo dijo...

Muchas gracias, de momento esto es exáctamente lo que necesito.

Un saludo.

Pere Moltó Agut dijo...

Gracias a ti por animar el "foro" de comentarios.

Saludos.

Anónimo dijo...

Hola Pere,

Te escribo para realizarte una pregunta sobre el entorno gráfico de stonegate (no sé si este es el lugar apropiado.)

Yo tengo una política con varias subpolíticas. Me gustaría saber donde está situada una ip exactamente (ahora, busco por la ip y me dice la subpolítica pero yo quiero saber la línea).

Se puede hacer esto?

Muchas gracias de nuevo por tu ayuda y un saludo.

Pere Moltó Agut dijo...

Sí, se puede. Aprovecho la temática de la pregunta para abrir una nueva entrada acerca de esto. Espero que te sea de ayuda.

Saludos.