jueves, diciembre 18, 2008

Notas sobre NAT en MacOS X (I)

Esta tarde he tenido que usar el NAT en MacOS X, y me he entretenido redactando algunas notas de como funciona. La pila TCP/IP y las utilidades de red que utiliza MacOS X derivan directamente de FreeBSD. El sistema de firewall es ipfw, y viene incluido y activado por defecto en MacOS X. El comando para controlar el firewall es ipfw. A diferencia de Linux, el proceso de NAT de los paquetes no se realiza en el kernel del sistema, sino en un proceso aparte denominado natd. A este proceso llegan los paquetes que se seleccionen a través de las reglas de ipfw y del mecanismo divert.

Activando la conexión a Internet compartida

La manera más sencilla de activar el NAT en MacOS X es usar la conexión compartida. Se ejecuta las preferencias del sistema, elegimos la opción de Compartir y se despliega el siguiente cuadro de diálogo:

compartir internet

En este cuadro de diálogo seleccionamos la interfaz que consideramos pública (en este caso será el Airport) y las interfaces de red que se van a compartir, cosa que se hace en el cuadro de diálogo de abajo. Una vez que se ha activado, pulsamos iniciar y se comienza a compartir las interfaces de red.

Veamos los cambios de configuración que ha realizado la GUI. En primer lugar, las reglas de firewall. Para ello desde una ventana de Terminal, ejecutamos la orden ipfw show.

00010  26221  16201955 divert 8668 ip from any to any via en1 02000 264607  23464758 allow ip from any to any via lo* 02010      0         0 deny ip from 127.0.0.0/8 to any in 02020      0         0 deny ip from any to 127.0.0.0/8 in 02030      0         0 deny ip from 224.0.0.0/3 to any in 02040      0         0 deny tcp from any to 224.0.0.0/3 in 02050 209103  38244907 allow tcp from any to any out 02060 333894 376385236 allow tcp from any to any established 02065      0         0 allow tcp from any to any frag 12190      3       192 deny tcp from any to any 65535   7662    912661 allow ip from any to any
Aparte, se habrá ejecutado un proceso, natd que será el encargado de traducir las direcciones. Podemos verlo ejecutando el comando:
ibookdrizzt:~ terron$ ps aux|grep natd root       372   0.0  0.0    27332    580  ??  Ss   12:14AM   0:00.43 /usr/sbin/natd -alias_address 192.168.1.33 -interface en1 ibookdrizzt:~ terron$ 

Lo que hace la primera regla del firewall, es dirigir todos los paquetes que lleguen a la interfaz en1 - el Airport - hacia el proceso natd, que será el encargado de traducir las direcciones, cambiando la origen con la que tenga la interfaz en1. Como puede verse el NAT se realiza en el momento de salida de los paquetes, tras decidir por cual interfaz va a salir.

Configurando el NAT de manera manual

La situación en la que quería usar el NAT es la que está representada en el siguiente esquema:

Tenemos un PowerMac G5 conectado a una red wireless cuyo punto de acceso es un router WIFI que me conecta a Internet. La red que se forma es una 192.168.1.0/24 y el Mac tiene asignado la dirección IP 192.168.1.100 (interfaz en1) . A la interfaz ethernet del Mac se crea una red ethernet con dirección IP asignada 192.168.2.1 (interfaz en0). Lo que quiero es que el Mac me haga NAT de las IP de la red 192.168.2.x y me las traduzca a una dirección IP en la red 192.168.1.x, a ser posible la misma que tiene asignada la interfaz wireless. Una implementación de un masquerading clásico.

El NAT se realiza en MacOS X justo antes de que el paquete abandone la interfaz de red. En el esquema anterior, los paquetes salen hacía Internet a través de la interfaz en1. Por tanto, se deberá configurar natd para que intercete los paquetes antes de salir y modifique la dirección origen del paquete y llegado el caso, el puerto origen. Hay que indicarle al kernel que pase los paquetes que coinciden. En nuestro caso, cualquier paquete que tenga dirección origen 192.168.2.0/24 hacia cualquier dirección. Usaremos ipfw para que el kernel nos pase los paquetes a través del mecanismo divert:

ipfw -f flush
ipfw add divert natd all from 192.168.2.0/24 to any via en1
Ojo, en caso de que ya existan reglas en el firewall, comentar que ipfw -f flush borraría todas las existentes. En este caso habría que ver donde insertarlas. Se puede consultar las reglas que ya están instaladas ejecutando la orden ipfw show.

Ahora habrá que ejecutar natd, el programa que se va a encargar de traducir las direcciones. La dirección IP a la cual se va a traducir recibe el nombre de alias. Este programa cuando se ejecuta, automáticamente pasa a background, con lo cual si se quiere depurar el tráfico de paquetes, se debe ejecutar con la opción -v. Puesto que queremos que se le traduzca todo lo que nos mande la regla de divert configurada anteriormente, teóricamente debería valer con:

/usr/sbin/natd -v -interface en1
Sin embargo, veremos que esto no funciona. ¿Por qué?. Porque aunque nos traduzca correctamente la dirección origen de cualquier paquete que salga con la dirección en el rango 192,.168.2.0/24, los que recibe el firewall no sabe que debe enviarlos de nuevo al proceso natd. Esto ocurre por la particular implementación que usa MacOS X y que deriva de FreeBSD, frente a la implementación de Linux toda realizada en el núcleo, y que tiene la correspondiente tabla de estados que permita saber que paquetes están nateados o qué paquetes tienen como origen la propia máquina que hace NAT.

La solución para mi situación es muy sencilla,puesto que tengo dos redes privadas que controlo y puedo usar direcciones en ellas sin problemas: Lo que hago es añadir una IP alias a la interfaz en1 que va a ser la que usen los paquetes nateados. Una regla de nuevo en el ipfw que haga que todo lo que llegue hasta esa IP sea dirigido hacia el natd y ya está. La configuración sería de la siguiente manera:

ifconfig en1 192.168.1.101 alias ipfw -f flush
ipfw add divert natd all from 192.168.2.0/24 to any via en1
ipfw add divert natd all from any to 192.168.1.101 via en1
natd -a 192.168.1.101

Problemas

La implementación de NAT que utiliza MacOS X no es lo que se puede decir muy eficiente. La necesidad de mover los paquetes desde el kernel a programas de modo usuario y posteriormente volverlos a pasar al kernel para su transmisión hace que sea más lento que implementaciones completas en kernel como la de Linux y su NetFilter.

El soporte de inspección de protocolos es muy limitado, sólo tiene soporte para FTP e IRC, estando el resto de protocolos que mandan información de direcciones dentro de los mismos no soportados - los famosos módulos de masquerading de Linux -.

Referencias

I have translate to english the post: Some notes about using de MacOS X NAT (Network address traslation), first part

Technorati Tags: , ,

No hay comentarios: