[Anterior: Filtrado de paquetes] [Contenido] [Siguiente: Redireccionamiento de tráfico (reenvío de puertos)]
La Traducción de Direcciones de Red, o NAT (Network Address Translation), es un sistema que se utiliza para asignar una red completa (o varias redes) a una sola dirección IP. NAT es necesario cuando la cantidad de direcciones IP que nos haya asignado nuestro proveedor de Internet sea inferior a la cantidad de ordenadores que queramos que accedan a Internet. NAT se describe en el RFC 1631, "The IP Network Address Translator (NAT)".
NAT nos permite aprovechar los bloques de direcciones reservadas que se describen en el RFC 1918, "Address Allocation for Private Internets". Generalmente, una red interna se suele configurar para que use uno o más de estos bloques de red. Estos bloques son:
10.0.0.0/8 (10.0.0.0 - 10.255.255.255) 172.16.0.0/12 (172.16.0.0 - 172.31.255.255) 192.168.0.0/16 (192.168.0.0 - 192.168.255.255)
Un sistema OpenBSD configurado para NAT tendrá como mínimo dos adaptadoras de red, una para Internet y la otra para la red interna. NAT se encargará de traducir los requerimientos desde la red interna, de modo que parezca que todos provienen del sistema OpenBSD en el que se encuentra configurado NAT.
Cuando un cliente en la red interna contacta con un máquina en Internet, envía paquetes IP destinados a esa máquina. Estos paquetes contienen toda la información de direccionamiento necesaria para que puedan ser llevados a su destino. NAT se encarga de estas piezas de información:
Cuando los paquetes pasan a través de la pasarela de NAT, son modificados para que parezca que se han originado y provienen de la misma pasarela de NAT. La pasarela de NAT registra los cambios que realiza en su tabla de estado, para así poder: a) invertir los cambios en los paquetes devueltos, y b) asegurarse de que los paquetes devueltos pasen a través del cortafuegos y no sean bloqueados. Por ejemplo, podrían ocurrir los siguientes cambios:
Ni la máquina interna ni el anfitrión de Internet se dan cuenta de estos pasos de traducción. Para la máquina interna, el sistema NAT es simplemente una pasarela a Internet. Para el anfitrión de Internet, los paquetes parecen venir directamente del sistema NAT; ni siquiera se da cuenta de que existe la estación interna.
Cuando el anfitrión de Internet responde a los paquetes internos de la máquina, los direcciona a la IP externa de la pasarela de NAT (24.5.0.5) y a su puerto de traducción (53136). La pasarela de NAT busca entonces en la tabla de estado para determinar si los paquetes de respuesta concuerdan con alguna conexión establecida. Entonces encontrará una única concordancia basada en la combinación de la dirección IP y el puerto, y esto indica a PF que los paquetes pertenecen a una conexión iniciada por la máquina interna 192.168.1.35. Acto seguido PF realiza los cambios opuestos a los que realizó para los paquetes salientes, y reenvía los paquetes de respuesta a la máquina interna.
La traducción de paquetes ICMP ocurre de forma parecida, pero sin la modificación del puerto de origen.
Dado que NAT se utiliza casi siempre en los enrutadores y pasarelas de red, probablemente será necesario habilitar el reenvío de IP (IP Forwarding) para que los paquetes puedan viajar entre las interfaces de red de la máquina OpenBSD. El reenvío de IP se habilita mediante el mecanismo sysctl(3):
# sysctl net.inet.ip.forwarding=1
# sysctl net.inet6.ip6.forwarding=1 (if using IPv6)
Para que este cambio sea permanente, hay que añadir las siguientes líneas al fichero /etc/sysctl.conf:
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1
Estas líneas ya existen en la instalación determinada, pero como comentarios (prefijadas con #). Hay que quitar el signo # y guardar el fichero. El reenvío de IP se activará cuando se reinicie la máquina.
NAT se especifica como un parámetro opcional nat-to por una regla de salida pass. A menudo, en lugar de establecer directamente la regla pass, se usa una regla match. Cuando un paquete es seleccionado por una regla match, los parámetros de dicha regla (por ejemplo, nat-to) se recuerdan y se aplican al paquete cuando se ve afectado por la regla match coincidente. Esto permite que toda una clase de paquetes sea manipulada por una sola regla match y a continuación las decisiones específicas sobre la conveniencia de autorizar el tráfico se puede hacer con las reglas block y pass.
El formato general para las reglas de NAT en /etc/pf.conf es parecido al siguiente:
match out on interface [af] \
from src_addr to dst_addr \
nat-to ext_addr [pool_type] [static-port]
...
pass out [log] on interface [af] [proto protocol] \
from ext_addr [port src_port] \
to dst_addr [port dst_port]
Esto nos llevaría a una forma muy básica de estas líneas, que quedaría parecida a la siguiente:
match out on tl0 from 192.168.1.0/24 to any nat-to 24.5.0.5O se puede usar simplemente
pass on tl0 from 192.168.1.0/24 to any
pass out on tl0 from 192.168.1.0/24 to any nat-to 24.5.0.5
Esta regla indica que hay que realizar NAT en la interfaz tl0 para cualquier paquete que venga de 192.168.1.0/24, y sustituir la dirección IP de origen con 24.5.0.5.
Aunque la regla anterior es correcta, la forma no es la recomendable. El mantenimiento podría resultar difícil ya que cualquier cambio de los números de la red externa o interna requeriría que se cambiara la línea. Cómparese con la siguiente regla (tl0 es externa y dc0 interna), que es más fácil de mantener:
pass out on tl0 from dc0:network to any nat-to tl0
La ventaja debería ser obvia: podemos cambiar la dirección IP de cualquiera de las interfaces sin cambiar esta regla.
Cuando se especifica un nombre de interfaz para la dirección de traducción, como en el ejemplo anterior, la dirección IP se determina en el momento de carga de pf.conf, no sobre la marcha. Si se está usando DHCP para configurar la interfaz externa, esto puede representar un problema, ya que si la dirección IP asignada cambiara, entonces NAT seguiría traduciendo los paquetes salientes usando la dirección IP antigua. Como resultado, las conexiones salientes dejarían de funcionar. Para evitarlo, se puede indicar a PF que actualice automáticamente la dirección de traducción poniendo entre paréntesis el nombre de la interfaz:
pass out on tl0 from dc0:network to any nat-to (tl0)
Este método funciona para traducir tanto direcciones IPv4 como IPv6.
Se puede establecer una asignación de tipo bidireccional usando la regla binat-to. Una regla binat-to establece una asignación de uno a uno entre la dirección IP interna y la dirección externa. Esto puede ser útil, por ejemplo, para colocar un servidor web en la red interna con su propia dirección IP externa. Las conexiones desde Internet hacia la dirección externa se traducirán a la dirección interna, y las conexiones desde el servidor web (como las peticiones DNS) se traducirán a la dirección externa. Los puertos TCP y UDP nunca se modifican con las reglas binat-to como se modifican con las reglas nat.
Ejemplo:
web_serv_int = "192.168.1.100"
web_serv_ext = "24.5.0.6"
pass on tl0 from $web_serv_int to any binat-to $web_serv_ext
Si se necesita traducir la mayoría del tráfico, pero incluyendo excepciones en algunos casos, asegúrese de que las excepciones son manejadas por una regla de filtrado que no incluya el parámetro nat-to. Así, el ejemplo de NAT anterior se modificaría del siguiente modo:
pass out on tl0 from 192.168.1.0/24 to any nat-to 24.2.74.79
pass out on tl0 from 192.168.1.208 to any
Y entonces los paquetes de toda la red 192.168.1.0/24 se traducirían a la dirección externa 24.2.74.79, a excepción de 192.168.1.208.
Para ver las traducciones de NAT activas se usa pfctl(8) con la opción y el argumento -s state. Esta opción muestra un listado de todas las sesiones de NAT actuales:
# pfctl -s state fxp0 TCP 192.168.1.35:2132 -> 24.5.0.5:53136 -> 65.42.33.245:22 TIME_WAIT:TIME_WAIT fxp0 UDP 192.168.1.35:2491 -> 24.5.0.5:60527 -> 24.2.68.33:53 MULTIPLE:SINGLE
La explicación de esto (solo de la primera línea) es:
[Anterior: Filtrado de paquetes] [Contenido] [Siguiente: Redireccionamiento de tráfico (reenvío de puertos)]