Este artículo explica el funcionamiento de PF, junto con una configuración de filtrado básica a modo de ejemplo. PF (Packet Filter) es el mecanismo que utiliza por defecto OpenBSD para implementar el filtrado de tráfico TCP/IP y realizar NAT (Network Address Translation). PF también es capaz de normalizar y condicionar tráfico TCP/IP, al igual que proveer packet shaping y priorización de tráfico.



En OpenBSD, el filtrado de paquetes se realiza en el kernel y el pseudo-dispositivo /dev/pf permite que procesos en espacio usuario puedan controlar el comportamiento del firewall. PF es un firewall que trabaja en las capas 3 (IPv4, IPv6) y 4 (TCP, UDP, ICMP, ICMPv6). Los criterios más utilizados a la hora de clasificar tráfico son las direcciones fuente y destino, los puertos involucrados (fuente y destino), y el protocolo, similar a iptables.

Cada regla especifica el criterio para seleccionar paquetes (criterio con el cual un paquete debe coincidir) y la acción a tomar, ya sea bloquear o permitir, cuando hay una coincidencia. Las reglas se evalúan en orden secuencial de principio a fin. Cada paquete es evaluado contra todas las reglas, excepto cuando una regla incluye la palabra clave quick, la cual fuerza a que dicha regla sea la última. La última regla en coincidir es la "ganadora" y es la que dicta la acción a tomar sobre el paquete.

PF se encuentra activado por defecto y levanta las reglas desde el archivo /etc/pf.conf.

Configuración de un firewall básico

La política recomendada en todo firewall es bloquear todo por defecto, luego permitir tráfico de forma selectiva. Esta política debe valer para cualquier tipo de firewall, independientemente de su implementación (iptables, pf ,ipf, ipfw, etc.)

De acuerdo a lo mencionado anteriormente, para configurar el firewall se debe editar el archivo de configuración de reglas de PF: /etc/pf.conf. Suponiendo que se trata de un servidor Web

#       $OpenBSD: pf.conf,v 1.54 2014/08/23 05:49:42 deraadt Exp $
#
# See pf.conf(5) and /etc/examples/pf.conf

# Por defecto, boquear todo 
block in all
block out all

# Permitir todo en la interfaz loopback
set skip on lo

# Permitir trafico entrante hacia el puerto 22 (SSH)
pass in proto tcp from 192.168.1.0/24 to port 22

# Permitir trafico entrante hacia los puertos 80 y 443 (HTTP/HTTPS)
pass in proto tcp from any to port 80
pass in proto tcp from any to port 443

# Permitir todo el trafico saliente
pass out proto { tcp, udp, icmp } from any to any modulate state

Permitir todo el tráfico saliente es una falencia, pues en caso de intrusión o compromiso, se le permite al atacante el acceso irrestricto hacia la red interna. Lo más adecuado es permitir sólo cierto tipo de tráfico. Por ejemplo sólo hacia los puertos 80 y 443 (HTTP/HTTPS), 123 (NTP), 22 (pero sólo hacia el exterior, si se van a actualizar fuentes con CVS) y cualquier otro puerto que sea estrictamente necesario (3306 si tuviese que conectarse a un servidor de bases de datos MySQL). Pero, claro está, esta configuración corresponde a un firewall básico, a modo de ejemplo.

La última línea de configuración determina que se trata de un firewall stateful, es decir un firewall que guarda el estado de las conexiones. Al igual que iptables, ipfw y otros, pf es capaz de realizar un seguimiento de las conexiones, inspeccionando cada conexión y guardando el estado en una tabla interna (keep state). De esta forma es posible determinar rápidamente si un paquete pasando a través del firewall pertenece a una conexión ya establecida. Si es así, pasa a través del mismo sin necesidad de evaluar todas las reglas.

Para guardar el estado, generalmente se utiliza la directiva keep state. Las reglas pass guardan el estado por defecto. La opción modulate state funciona igual a keep state pero además genera ISN (initial sequence number) aleatorios para las conexiones TCP. Esto es recomendable para protegerse contra IP spoofing.

La regla skip en la interfaz loopback evita que se evalúen reglas para el tráfico interno.

Gestión de pf mediante pfctl

Luego de configurar el firewall es necesario recargar la configuración de pf. Para ello se debe recurrir al comando pfctl, el cual controla el pseudo-dispositivo /dev/pf:

# pfctl -f /etc/pf.conf

Finalmente es posible listar las reglas ejecutando:

# pfctl -sr
block drop in all
block drop out all
pass in inet proto tcp from 192.168.1.0/20 to any port = 22 flags S/SA
pass in inet proto tcp from any to any port = 80 flags S/SA
pass in inet proto tcp from any to any port = 443 flags S/SA
pass out proto tcp all flags S/SA modulate state
pass out proto udp all
pass out proto icmp all

Para más información:

man pf.conf
man pfctl

Referencias

OpenBSD PF - User's Guide

OpenBSD PF - Getting Started

OpenBSD PF - Packet Filtering


Tal vez pueda interesarte


Compartí este artículo