Firewall básico en OpenBSD (.SIC)


Ahora toca el turno a la configuración de un firewall en OpenBSD. Para esto usaremos Packet Filter – por comodidad llamado PF -. Debo decir que este artículo puede verse como un resumen de la documentación oficial que esta disponible en la página de OpenBSD.

Lo primero a hacer es activar PF, esto podemos hacerlo con el siguiente comando:

#pfctl -e

Para desactivarlo usamos la opción “-d” y para activarlo por defecto en el sistema tenemos que tener modificar la línea de PF en el archivo /etc/rc.conf, quedará así:

pf=YES

También debes editar /etc/sysctl.conf para habilitar “IP forwarding”:

net.inet.ip.forwarding=1

Ahora reiniciamos el sistema, es recomendable debido a que a veces no funciona muy bien si reiniciamos solamente los servicios de red.

Una vez hecho esto, debemos configurar las tarjetas de red, esto se hace en el archivo /etc/hostname.XXX donde XXX es el nombre de tu tarjeta de red, con un ifconfig -a puedes ver como identifica tu tarjeta OpenBSD. La configuración típica del archivo hostname.XXX es la siguiente:

inet <DirecciónIP> <MáscaraRed> <DirecciónBroadcast> media autoselect up

Observación: Comunmente la dirección de Broadcast se queda indicado solamente con la palabra NONE.

Una vez hecho esto podemos empezar a entendernos con PF, aquí algunas ordenes importantes:

# pfctl -f /etc/pf.conf -> Carga el archivo pf.conf
# pfctl -nf /etc/pf.conf -> Verifica el archivo pero no carga las reglas del mismo
# pfctl -Nf /etc/pf.conf -> Carga solo las reglas de NAT
# pfctl -Rf /etc/pf.conf -> Carga solo las reglas de Filtrado
# pfctl -sn -> Muestra las reglas de NAT que estan vigentes
# pfctl -sr -> Muestra las reglas de filtrado que estan vigentes
# pfctl -ss -> Muestra tabla de estado
# pfctl -sa -> Muestra TODO lo que es posible

Sabiendo esto, pasamos al archivo de configuración. Esta dividido en siete partes, no todas las abordaremos en este artículo, pero aquí las nombro:

Macros
Tablas
Opciones
Scrub
Prioridad
Reglas de NAT
Reglas de filtrado

Ahora iremos armando un archivo pf.conf de ejemplo. Lo primero que verás será algo como esto:

ext_if=”pcn1″
int_if=”pcn0″

Son macros, es decir, una especie de variables y como todas las variables sirven para identificar y abreviar. En nuestro ejemplo, representan las tarjetas de red, cuestro firewall tendrá dos tarjetas de red, una de ‘entrada’ y otra de ‘salida’.Cuando llamemos los macros para su uso, debemos antemoner un signo $ antes del nombre del macro.
También podemos hacer listas y prepresentarlas como macros, y es válido hacer listas de macros.:

port1=”25″
port2=”22″
ports=”{“$port1, $port2″} ”

Las listan se marcan entre llaves o en inglés “brackets”, la coma es opcional, el espacio es obligatorio. Podemos usar listas con elementos negados de la siguiente forma:

seg_val=”{192.168.0.1/24, !192.168.0.2}”

En este ejemplo todo el segmento de red 192.168.0.1/24 es válido en la lista exceptuando 192.168.0.2.

Pasemos al siguiente punto, tablas que son muy similares a las listas, con algunas ventajas. Hay dos tipos de tablas:

const: Este tipo de tablas son fijas, una vez creadas no es posible modificarlas.
persist: Este tipo de tablas son dinámicas, se encuentran en memoria.

Las tablas pueden crearse por línea de comandos con el comando table, la sintaxis es al siguiente:

#table <nombre_tabla> [tipo tabla] {lista de elementos}

luego podemos manupularlas dinámicamente con el comando pfctl:

#pfctl -t [nombre_tabla] -T add [elemento]
#pfclt -t [nombre_tabla] -T show
#pfclt -t [nombre_tabla] -T delete [elemento]

Es importante decir que podemos hacer un archivo con el nombre de la tabla, donde especifiquemos sus elementos así si reiniciamos la máquina no es necesario crear la tabla de nuevo. El comando pfclt no afectará el archivo en el que se tenga la tabla, solo afectará la tabla en memoria. en pf.conf la parte de tablas queda así:

table <friends> persist file “/etc/friends”
table <priv> const

Pasemos a la parte más fácil, para normalización de paquetes y permitir su fragmentación esta el scrub solo nos interesan los que vienen del exterior, hay que escribir:

scrub in all

Que rápido ¿no?, ahora pasamos a las reglas, en forma general la sintaxis es esta:

acción [dirección] [log] [quick] [on interfaz] [af] [proto protocolo] \
[from dir_fuente [port puerto_fuente]] [to dir_destino [port puerto_destino]] \
[flags tcp_flags] [state]

La \ que ves al final de los primeros dos renglones indica que la regla continua en el siguiente renglón.

Las reglas NAT son sencillas lo explicaremos con un ejemplo:

Declaramos 2 macros.

lidsol_ip=”132.248.59.73/32″
debian_services=”192.168.1.2/32″

Declaramos reglas NAT y de redireccionamiento.

nat on $red_ext from $red_int:network to any -> $lidsol_ip
rdr on $red_ext proto tcp from any to $lidsol_ip port http -> $debian_services port http

El macro lidsol_ip se refiere a una dirección IP que nos ha sido asignada por nuestro ISP, empresa o lo que corresponda. El macro debian_services se refiere a una dirección de nuestra LAN, que corresponde a la máquina que tiene los servicios que estamos ofreciendo.

La regla nat se lee “realizar NAT en la interfaz red_ext para cualquier paquete que venga de red_int, la dirección destino será lidsol_ip”. La regla contiene una acción un origen y un destino y algunas especificaciones, y todo concuerda con la forma general que describimos arriba. Como verás no maneje números de direcciones IP porque eso dificulta la administración del firewall en caso de hacer un cambio en nuestra red.

La segunda regla es de redireccionamiento ‘rdr’ que sigue la misma estructura “redirecciona en la interfaz red_ext cualquier paquete TCP que venga a lidsol_ip en el puerto HTTP hacia debian_services en el puerto HTTP”. El redireccionamiento solo es necesario si nuestro servidor esta en una máquina diferente de nuestro firewall.

Las reglas de filtrado son similares debido a que la estructura general es la misma. Lo primero que recomiendo hacer es poner la regla más básica:

block in all
block out all

Con esto bloqueamos toda comunicación en ambos sentidos, ahora podemos empezar a hacer reglas para permitir el paso únicamente de las cosas que nos interesan. Un ejemplo es el siguiente:

pass in log on $ext_if proto tcp from any to <friends> port http keep state

Esta regla se lee “Permite el paso y guarda en un log en la interfaz ext_if cualquier paquete TCP que venga a las máquinas que pertenezcan a la tabla friends en el puerto HTTP y recuerda el estado de conexión”. Debemos poner atención con los logs debido a que estos archivos ocupan espacio en el HDD y puede traer problemas si saturamos nuestro firewall con estos archivos, así que manda a un log solo lo indispensable. La parte de “keep state” nos permite recordar el estado de conexión, así no tendremos que hacer una regla adicional que permita la salida de una posible respuesta a la petición hecha a nuestro servidor.

Depurando un poco esta regla podemos escribir lo siguiente:

pass in on $ext_if proto tcp from any to <friends> port http keep state (max 20,source-track rule,max-src-nodes 5,max-src-states 2)

Ahora tenemos la misma regla, hemos quitado la instrución log pero lo interesante son los parámetros que aparecen entre paréntesis, expliquemos uno a uno:

– max # : representa el número máximo de conexiones simultaneas permitidas, esto afecta ya sea a todo nuestro firewall o solo a la instrucción donde se declara dependiendo del siguiente parámetro.

– source-track [rule || global] : si es global afectará a todas las reglas del archivo pf.conf y es rule afectará solo a la instrucción donde se declaró.

– max-src-nodes # : define el número máximo de direcciones IP que pueden conectarse simultaneamente, solo se usa junto con la instrucción source-track rule, por lo que solo afecta a una regla de PF.

– max-src-states # : indica el máximo de conexiones simultaneas que puede tener una dirección IP en nuestra red.

Además de esas opciones existen otras importantes, te recomiendo leer el manual de PF, aquí enlisto algunas más:

– max-src-conn # : indica el número máximo de peticiones TCP que podrán completar el 3-way handshake al mismo tiempo. Solo válida usando source-track rule

– max-src-conn-rate conexiones/tiempo : especifica el numero de nuevas conexiones que pueden realizarse por una IP en un intervalo de tiempo definido en segundos. Solo válida usando source-track rule

– overload <table> : ingresa a la tabla especificada las direcciones IP que superen los límites especificados en la regla.

– flush [global] : Elimina cualquier conexión realizada por una IP por medio de la regla donde esta declarado el flush. Si se anexa el parámetro global elimina todas la conexiones realizadas por la IP sin importar que regla creo la conexión.

Para terminar debo decir que si deseas un filtrado por MAC, PF no es capaz de hacerlo directamente, tendrás que crear un bridge:

# vi /etc/bridgename.bridge0

El archivo será algo así:

add pn0
up
rule pass out on pn0 src 00:00:00:00:00:00

Donde pn0 es tu tarjeta de red, puedes agregar todas las tarjetas de red que quieras y tengas en tu computadora. La regla del bridge es similar a las reglas de PF siguen la misma lógica, considera 00:00:00:00:00:00 como una dirección MAC. El uso de un bridge es obligatorio en un firewall transparente y cuando tienes un firewall dedicado. Si tu sistema es de uso personal seguramente no lo necesitarás.

Espero que este artículo les sirva para configurar sus firewalls, dejo estos ejemplos de archivos pf.conf y recomiendo lectura de las páginas de manual de PF, brconfig y bridgename.if

3 Respuestas a “Firewall básico en OpenBSD (.SIC)

  1. 🙂
    ]
    Buena revision! por lo menos evita entrar al FAQ de OpenBSD.org🙂

    Algo que yo utilizo mucho y no esta en este post es el “Flush por partes”

    pfctl -F regla_caracteristica,

    p ej

    pfctl -F nat

    reiniciaria unicamente la reglas de nat , digamos si cambie un rdr, sin tocar todo lo demas.

    Saludos!

    RESPUESTA

    Cierto, esa parte se me ha pasado mencionarlo y es muy útil para reiniciar solo las partes necesarias, sobre todo si la red es concurrida, le evita problemas a los usuarios.

  2. amigo, tengo armado mi pf, pero quiero aprender hacer las queue para mi red local ya que se estan llevando todo el canal que tengo asignado y no quiero esto, podrias ayudarme con tal eventualidad?

    de antemano mis agradecimientos

    RESPUESTA

    Primeramente, gracias por preguntar algo que no tiene que ver con wireless jajaja. Te contesto:

    Para priorizar con PF tenemos 2 reglas:

    altq : Esta crea la cola general sobre la interfaz de red. (en inglés les dicen root queue)
    queue: Crea criterios específicos aplicables a lo señalado en altq. (en inglés les dicen child queue)

    Ejemplo:

    altq on pcn0 priq bandwidth 1Mb queue { highpri_q, default_q, ssh_q }
    queue ftp priority 3
    queue ssh priority 2
    queue default_q priority 1 priq(default)

    Bien, lo que hicimos con esa cola fue:

    1.- Se aplicara en la tarjeta de red pcn0 una cola de prioridad de paquetes (la otra opción es cbq, puedes asignarle porcentajes de ancho de banda específicos, como 50% ó 250kb son valores válidos en esa modalidad) el ancho de banda de la red es de 1Mbps y se aplicarán las especificaciones de las “colas hijas” llamadas default ftp y ssh.

    2.- Los paquetes de ftp tendrán una prioridad mayor por lo que serán procesados con una latencia menor, después con una prioridad menor a los del ftp estarán los de ssh que serán preferentes ante todos los demás paquetes.

    Este es un ejemplo sencillo puedes hacer otros más complejos con más opciones, como por ejemplo el tamaño máximo de una cola. Así mismo debo decirte que la cola ftp puede tener otras subcolas o colas hijas, como quieras llamarlas, para hacer aun más precisa la prioridad. Después de eso solo tienes que usar la cola en tus reglas de pf:

    pass in quick on pcn0 from any to any port 22 queue ssh

    Como puedes ver, los nombres de las colas son solo para descripción “ssh” pudo llamarse “acc_rem” o de otra forma. También decir que en la regla del firewall puedes aplicar la cola a otras tarjetas de red como pcn1, pcn2.

    Espero te sirva. Saludos y visita el FAQ de OpenBSD que menciona Rommel.

  3. Excelente guia para PF., sabes necesito si me puedes ayudar con un problemita, tengo un firewall / vpn openbsd, mantiene un enlace satelital, pero necesito saber como puedo mejorar el rendimiento de filtrado, algo como lo que comentas de la prioridad de paquetes, lamentablemente no lo entendí mucho como aplicarlo, me gustaria si me puedes explicar nuevamente como hacerlo. mi idea es crear calidad de servicios objeto no se vea mermada la conectividad con la seguridad que aplico en mi red.
    Muchas gracias y felicitaciones denuevo por tu excelente artículo-

    RESPUESTA

    Bueno, para la ayuda que te puedo dar es que revises la FAQ de PF ahí puedes entender mejor los conceptos que he tratado de explicar, pues no se me ocurrió como hacerlo de nuevo, para mi esta claro, pero seguro leyendo la FAQ y haciendo algunas pruebas sobre su funcionamiento te queda claro😛.

    Por otro lado, dependiendo de los servicios que manejes, podrías usar Squid para acelerar algunas cosas, es un software libre muy poderoso y podrías encontrarle alguna utilidad.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s