domingo, 16 de diciembre de 2007

PF Firewalls con Open BSD



El concepto de firewall (cortafuegos) es sencillo: Internet es una red sucia, donde existe una mezcla de tráfico que nos interesa recibir (por ej las páginas que queremos accesar, nuestra administración remota, etc.) junto con otro tráfico que no querremos recibir ](hackers, virus, spam, etc.). Queremos que nuestra red interna sea limpia, es decir que reciba solamente lo que nos interesa y sobre todo que no entregue otrra información que la que específicamente le permitamos. El cortafuegos es una máquina con un programa que hace esa tarea de filtrar desde y hacia nuestra red limpia a la red sucia. Puede ser solo un programa corriendo en nuestra máquina, pero cuando la seguridad es importante se usa una máquina aparte, dedicada exclusivamente a correr un programa con nuestras pol{iticas de filtrado.

Uno de los usos principales del Open BSD es para implementar máquinas cortafuego en sistemas de servidores conectados a Internet. El Open BSD es Unix, es seguro y funciona en muchas plataformas especialmente i386 (o sea los PC). Su uso entonces es conectar Internet (la red externa o sucia) con un equipo corriendo Open BSD que actúa como cortafuegos, es decir filtra los paquetes que entran y salen de nuestra red interna (limpia) adonde se conectan los servidores. O sea tenemos Internet - Cortafuegos - Router y finalmente nuestra red interna limpia.

Open BSD usa un sistema llamado PF (por packets filter) que nos permitirá controlar todo lo que entra y sale a nuestra red. En la práctica el cortafuegos se define en un archivo de texto simple (en formato Unix, sin CR+LF) llamado pf.conf y ubicado en /etc/ o sea el archivo es /etc/pf.conf

Sin embargo no basta con crear o editar el archivo, para que las reglas sean leídas por el kernel se deben cargar con el comando pfctl. El prompt del Open BSD es #, así es que desde la línea de comandos podríamos cargar el archivo /etc/pf.conf usando

# pfctl -o none -R -f /etc/pf.conf

en este ejemplo se usaron varias opciones como:
-o none significa optimizaciones: none (no optimizar) la razón es que las optimizaciones no funcionan con la opción -R en openbsd 4.2

-R para cargar solo las reglas de filtro presentes en /etc/pf.conf ignorando las demás reglas

- f espera the que la opción siguiente sea el archivo a cargar

Las reglas básicas son block (para bloquear) y pass (para dejar pasar)

Las reglas de un archivo /etc/pf.conf se ejecutan consecutivamente y si se contradicen la que queda al final es la que vale, por ejemplo

block in all
pass in all

la primera regla bloquea todo el tráfico de entrada y la segunda deja pasar todo el tráfico de entrada, si están escritas en ese orden, al ejecutarse el archivo prevalecería pass in all porque es la última en ejecutarse

Aunque lo anterior no tiene sentido algo similar se usa en script reales, por ejemplo primero se bloquea todo lo que ingrese y después se permite pasar los paquetes de una dirección determinada:

block in all
pass in from maquina.amiga.org to any

Si una regla tiene un "quick" entonces la ejecución secuencial se detiene en esa regla y no se chequean las otras reglas

En un script real las reglas serían más o menos así:

################################################################################
# Define Interface Shortcuts
################################################################################
IntIF="em0" # Internal (clean) Interface
ExtIF="em2" # External (dirty) Interface
FWAdminIF="em2" # Remote Admin Firewall (SSH only) Interface

Esas reglas por ejemplo definen variables dándoles un valor, en este caso em2 es el nombre de la interfase ethernet que está conectada a Internet y em0 as la interface conectada a los servers detrás del firewall

Otra regla muy común es bloquear las direcciones RFC1918, que son de redes privadas y a veces salen para Internet causando mucho estropicio en las redes internas. El punto aquí es que se pueden usar estas direcciones detrás del firewall, pero este tráfico nunca se debe filtrar para afuera, y si alguien fuera del firewall las está usando ese tráfico no se debe filtrar ahacia adentro.

NoRouteIPs="{ 0.0.0.0/32, 127.0.0.1/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }"

Con eso la red interna queda limpia de los paquetes de esos rangos que se pueden confundir con los que usamos en los mismos rangos para nuestras redes. También se usa scrub, para normalizar los paquetes defectuosos o fragmentados que llegan, por ejemplo con

scrub in all

Y por defecto, al principio del script se bloquea todo el tráfico tanto de entrada como de salida, las reglas más adelante irán permitiendo selectivamente que es lo que puede pasar por el cortafuegos, este bloqueo general se hace con:

block in log all
block out log all

Por ejemplo podríamos permitir que el Administrador tenga acceso a nuestra red interna via SSH (putty o similar) con

# ---
# --- Admin Interface for firewall itself
# ---
# --- Block all except SSH
# ---
block in log on $FWAdminIF all
block out log on $FWAdminIF all
pass in log quick on $FWAdminIF \
inet proto tcp from $RemoteAdmins to $FWAdminIP \
port 84 \
flags S/SA keep state

las líneas con # son comentarios y no tienenefecto, ahora veamos este conjunto de reglas por partes:

block in log on $FWAdminIF all
block out log on $FWAdminIF all

Bloquea por defecto todo tráfico de entrada y salida de $FWAdminIF dejándo los intentos de acceso registrados en un archivo log

pass in log quick on $FWAdminIF \

Deja pasar el tráfico de entrada de $FWAdminIF registrándolo en un archivo log, la regla quick hace que esto se ejecute de inmediato, sin necesidad de buscar otras órdenes posteriores que pudieran contradecir esta. Para que pasen todos los paquetes en protocolo tcp de Internet se usa:

inet proto tcp from $RemoteAdmins to $FWAdminIP \

Donde $RemoteAdmins son las redes externas de administrador remoto y $FWAdminIP es el número IP de firewall del administrador (son variables definidas antes en el mismo script). Finalmente veamos:

flags S/SA keep state

flags se usa para filtrar los paquetes TCP según sus indicadores, flags S/SA permite el paso de tráfico TCP con el indicador SYN activo, y sólo mira a los indicadores SYN y ACK. Un paquete con los indicadores SYN y ECE concordaría con la regla anterior, mientras que un paquete con SYN y ACK, o sólo con ACK, no concordaría.

keep state es para que recuerde la conexión anterior en la memoria del equipo.

Esos son algunos ejemplos de reglas PF, a medida que vaya viendo más las colocaré acá mismo.