[Anterior: Authpf: Shell de Usuario para la Autenticación de Pasarelas] [Contenido]
En este ejemplo, PF es parte de un sistema OpenBSD que actúa como cortafuegos y pasarela de NAT para una pequeña red en casa o en la oficina. El objetivo final es el de dar acceso hacia Internet desde la red, y permitir un acceso limitado a la máquina cortafuegos desde Internet. En este documento se repasa un grupo de reglas completo con este fin.
La configuración de la red es como sigue:
[ COMP1 ] [ COMP3 ]
| | ADSL
---+------+-----+------- fxp0 [ OpenBSD ] ep0 -------- ( Internet )
|
[ COMP2 ]
En la red interna hay varios ordenadores; el diagrama muestra sólo tres (COMP1, ... COMP3), aunque el número real no es relevante. Estos ordenadores son estaciones de trabajo normales que se usan para navegar por la web, correo electrónico, charlas interactivas (chats), etc., excepto COMP3 que además corre un pequeño servidor web. La red interna usa el bloque de red 192.168.0.0 / 255.255.255.0.
El enrutador con OpenBSD es un Pentium 100 con dos tarjetas de red: una 3com 3c509B (ep0) y una Intel EtherExpress Pro/100 (fxp0). El enrutador tiene una conexión de ADSL a Internet, y está usando NAT para compartir esta conexión con la red interna. La dirección IP en la interfaz externa la asigna de forma dinámica el Proveedor de Internet.
Los objetivos son:
En este documento se asume que se ha configurado correctamente el anfitrión con OpenBSD para que funcione como un enrutador, incluida la verificación de la configuración de redes IP, la conexión a Internet, y haber configurado net.inet.ip.forwarding con el valor "1".
A continuación construiremos un grupo de reglas que conseguirá los objetivos anteriores.
Las siguientes macros se han definido para facilitar el mantenimiento y la lectura del grupo de reglas:
int_if = "fxp0"
ext_if = "ep0"
tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"
priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
comp3 = "192.168.0.3"
Las primeras dos líneas definen las interfaces de red en las que tendrá lugar el filtrado. La tercera y cuarta líneas son una lista de los números de puertos TCP de los servicios que se abrirán a Internet (SSH y ident/auth) y de los tipos de paquetes ICMP a los se que les permitirá llegar a la máquina cortafuegos. La quinta línea define la dirección de loopback y los bloques de direcciones RFC 1918. Finalmente, la última línea define la dirección IP de COMP3.
Nota: Si la conexión de Internet ADSL requiere PPPoE, entonces el filtrado y NAT tendrán que realizarse en la interfaz tun0, y no en la ep0.
Con las siguientes dos opciones se configura la respuesta predeterminada para las reglas de filtrado block, y se activa el registro de estadísticas para la interfaz externa:
set block-policy return
set loginterface $ext_if
No hay motivo para no usar la normalización recomendada en todo el tráfico entrante, así que aquí va una simple línea:
scrub in all
Para llevar a cabo el servicio de NAT en toda la red interna, se usa la siguiente regla de nat:
nat on $ext_if from $int_if:network to any -> ($ext_if)
Como la dirección IP en la interfaz interna se asigna de forma dinámica, se usan paréntesis alrededor de la interfaz de traducción para que PF sepa cuándo cambia la dirección.
La primera regla de redireccionamiento se necesita para ftp-proxy(8), de modo que los clientes de FTP en la red local puedan conectarse a servidores de FTP en Internet.
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 port 8021
Nótese que esta regla sólo servirá para conexiones de FTP al puerto 21. Si los usuarios se conectan a servidores de FTP por otros puertos, entonces se debe usar una lista que especifique el puerto de destino; por ejemplo: from any to any port { 21, 2121 }.
la segunda recla de redireccionamiento atrapa cualquier intento de conexión desde Internet hacia el puerto TCP 80 en el corta fuegos. Intentos legítimos de acceso a este puerto serán realizados por usuarios que intentan acceder al servidor web de la red. Estos intentos de conexión necesitan ser redirigidos a COMP3:
rdr on $ext_if proto tcp from any to any port 80 -> $comp3
Ahora vienen las reglas de filtrado. Empezaremos con la denegación predeterminada:
block all
En este punto nada pasará por el cortafuegos, ni siquiera desde la red interna. Las siguientes reglas irán abriendo el cortafuegos paso a paso para que se puedan alcanzar los objetivos que se han propuesto, y además abrirán cualquier interfaz virtual que sea necesaria.
Todo sistema Unix tiene una interfaz de loopback. Ésta es una interfaz virtual de red que usan las aplicaciones para comunicarse entre sí mismas dentro del sistema. Todo el tráfico debería pasar por la interfaz de loopback. En OpenBSD, la interfaz de loopback es lo(4).
pass quick on lo0 all
A continuación se bloquearán las direcciones RFC 1918 para evitar que entren a, o salgan desde, la interfaz externa. Estas direcciones nunca deben aparecer en público en Internet, y filtrándolas nos aseguraremos de que el enrutador no «muestra» estas direcciones fuera de la red interna, y también bloquearemos cualquier paquete entrante que tenga como dirección de origen una de esas redes.
block drop in quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets
Nótese que se usa block drop para indicar a PF que no responda con un paquete TCP RST o ICMP Unreachable. Como las direcciones RFC 1918 no existen en Internet, cualquier paquete que se envíe a esas direcciones nunca llegará. La opción quick se usa para indicar a PF que no evalúe el resto de las reglas de filtrado si concuerda alguna de las reglas anteriores; los paquetes hacia o desde las redes $priv_nets se bloquearán inmediatamente.
Ahora abriremos los puertos usados por aquellos servicios de red que estarán disponibles por Internet:
pass in on $ext_if inet proto tcp from any to ($ext_if) \
port $tcp_services flags S/SA keep state
Especificar los puertos de red en la macro $tcp_services hace que sea más simple abrir servicios adicionales a Internet, simplemente editando la macro y recargando el grupo de reglas. Los servicios de UDP también se pueden abrir mediante la creación de una macro $udp_services y añadiendo una regla de filtrado parecida a la anterior que especifique proto udp.
Además de tener una regla rdr que redirija el tráfico del servidor web a COMP3, también DEBEMOS dejar pasar este tráfico a través del corta fuegos:
pass in on $ext_if proto tcp from any to $comp3 port 80 \
flags S/SA synproxy state
Como una medida de seguridad adicional, usaremos TCP SYN Proxy para proteger aún más el servidor web.
Ahora debemos dejar pasar el tráfico ICMP:
pass in inet proto icmp all icmp-type $icmp_types keep state
De forma parecida a la macro $tcp_services, la macro $icmp_types se puede editar fácilmente para cambiar los tipos de paquetes ICMP a los que se permitirá alcanzar el cortafuegos. Nótese que esta regla es aplicable a todas la interfaces de red.
Ahora debemos permitir el paso del tráfico hacia y desde la red interna. Asumiremos que los usuarios en la red interna saben lo que están haciendo y que no van a causar problemas. Esto no es algo que deba ser asumido necesariamente, y en algunos entornos sería apropiado usar un grupo de reglas mucho más restrictivo.
pass in on $int_if from $int_if:network to any keep state
La regla anterior permitirá que cualquier máquina interna pueda enviar paquetes a través del cortafuegos; sin embargo, no permitirá que el cortafuegos inicie una conexión con una máquina interna. ¿Es esto una buena idea? Depende de algunos detalles de la configuración de la red. Si el cortafuegos también es un servidor de DHCP, puede que sea necesario enviar señales de ping a alguna dirección para verificar su disponibilidad antes de darle una asignación. Permitir que el cortafuegos se conecte a la red interna también permite que alguien que se haya conectado mediante ssh al cortafuegos desde Internet pueda entonces acceder a la máquinas de la red. Hay que tener en cuenta que no permitir que el cortafuegos se comunique directamente con la red no representa un gran beneficio de seguridad; si alguien logra acceder al cortafuegos en primera instancia, es probable que pueda alterar las reglas de filtrado. Añadiendo la siguiente regla, el cortafuegos podrá iniciar conexiones con la red interna:
pass out on $int_if from any to $int_if:network keep state
Nótese que si ambas líneas están en uso, no se necesita la opción keep state; todos los paquetes podrán pasar a través de la interfaz interna porque hay una regla para permitir el paso de paquetes en ambas direcciones. Sin embargo, si la línea pass out no va incluida, la línea pass in debe incluir keep state. El mantenimiento de estado también ofrece algún beneficio en el rendimiento: Las tablas de estado se comprueban antes de evaluar las reglas, y si se encuentra un estado que concuerda, se permite pasar al paquete a través del cortafuegos sin que pase a través de la evaluación del grupo de reglas. Esto puede ofrecer un beneficio en el rendimiento de un cortafuegos con mucha carga, aunque no es probable que un sistema tan simple como el de este ejemplo genere la carga suficiente como para que esto sea importante.
Finalmente, dejaremos salir el tráfico en la interfaz externa:
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state
Se permite que el tráfico TCP, UDP, y ICMP salga del cortafuegos hacia Internet. La información sobre el estado se guarda para que los paquetes de vuelta pasen a través del cortafuegos.
# macros
int_if = "fxp0"
ext_if = "ep0"
tcp_services = "{ 22, 113 }"
icmp_types = "echoreq"
priv_nets = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"
comp3 = "192.168.0.3"
# opciones
set block-policy return
set loginterface $ext_if
# normalización
scrub in all
# nat/rdr
nat on $ext_if from $int_if:network to any -> ($ext_if)
rdr on $int_if proto tcp from any to any port 21 -> 127.0.0.1 \
port 8021
rdr on $ext_if proto tcp from any to any port 80 -> $comp3
# reglas de filtrado
block all
pass quick on lo0 all
block drop in quick on $ext_if from $priv_nets to any
block drop out quick on $ext_if from any to $priv_nets
pass in on $ext_if inet proto tcp from any to ($ext_if) \
port $tcp_services flags S/SA keep state
pass in on $ext_if proto tcp from any to $comp3 port 80 \
flags S/SA synproxy state
pass in inet proto icmp all icmp-type $icmp_types keep state
pass in on $int_if from $int_if:network to any keep state
pass out on $int_if from any to $int_if:network keep state
pass out on $ext_if proto tcp all modulate state flags S/SA
pass out on $ext_if proto { udp, icmp } all keep state
|
[Anterior: Authpf: Shell de Usuario para la Autenticación de Pasarelas] [Contenido]