Firewall Dinámico en FreeBSD

author
By admin
17 de abril de 2026
image

Sistema de firewall dinámico basado en el principio de Privilegio Mínimo, hemos logrado que un usuario sin privilegios modifique el comportamiento del firewall (PF) sin usar sudo ni SUID bits.
Los dispositivos (devfs rules + BPF) + tcpdump. una combinación limpia, nativa y eficiente.


Optimización de Sistemas Unix: Configuración avanzada de políticas de dispositivos mediante devfs.rules y automatización de servicios mediante scripts RC personalizados y gestión de daemons.

La IP autorizada se inyecta en el firewall (Packet Filter) cuando se establece la conexión SSH.


Fichero: /etc/pf.conf

# Interfaces
ext_if="vtnet0"

# Definir la tabla (persist permite que exista aunque esté vacía)
table <mi_ip> persist

# Block abusive hosts
block quick from <abusive_hosts>

# Incoming traffic, denegación total
block all
pass out quick keep state

# Filtering
pass in quick on $ext_if reply-to ($ext_if ip-gateway) proto tcp from <mi_ip> to ip-sistema port 22 keep state (max-src-conn 5, max-src-conn-rate 15/7, overload <abusive_hosts> flush global)



Crea un pipe: mkfifo /var/run/pf_helper.pipe y dale permisos chown root:admin y chmod 620.


Fichero: /etc/ssh/sshrc

Este archivo se ejecuta automáticamente cada vez que alguien se loguea por SSH.


# Capturamos la IP, limpiamos posibles puntos finales o puertos y nos aseguramos 
# de que sea solo texto IP_PUBLICA=$(tcpdump -ni vtnet0 -c 1 port XXXXX 2>/dev/null | awk '{print $3}' | cut -d. -f1-4) if [ ! -z "$IP_PUBLICA" ]; then # Enviamos al pipe en segundo plano para no bloquear el login echo "$IP_PUBLICA" > /var/run/pf_helper.pipe & fi

El Script "Daemon" (PF-Injector): Un script corriendo en segundo plano:


Fichero: /usr/local/bin/pf_injector.sh

#!/bin/sh

PIPE="/var/run/pf_helper.pipe"

while true; do
    ip=$(cat "$PIPE")
    
    if [ ! -z "$ip" ]; then
        if echo "$ip" | grep -E '^([0-9]{1,3}\.){3}[0-9]{1,3}$' > /dev/null; then
            /sbin/pfctl -t mi_ip -T flush >/dev/null 2>&1
            /sbin/pfctl -t mi_ip -T add "$ip"
            logger -t pf_injector "Tabla flusheada y nueva IP añadida: $ip"
        fi
    fi
done

permisos de ejecución: chmod +x /usr/local/bin/pf_injector.sh


El Script de Servicio (RC.d)


Fichero: /usr/local/etc/rc.d/pf_injector

#!/bin/sh
#
# PROVIDE: pf_injector
# REQUIRE: LOGIN pf
# KEYWORD: shutdown

. /etc/rc.subr

name="pf_injector"
rcvar="pf_injector_enable"
command="/usr/sbin/daemon"
# Parámetros para daemon: 
# -f (corre en segundo plano)
# -p (crea el archivo PID)
# -u (podría ser root, pero daemon lo gestiona)
command_args="-f -p /var/run/${name}.pid /usr/local/bin/pf_injector.sh"
pidfile="/var/run/${name}.pid"

load_rc_config $name
run_rc_command "$1"

permisos :chmod +x /usr/local/etc/rc.d/pf_injector

sysrc pf_injector_enable="YES"

service pf_injector start


El escenario Final:

Conectas VPN.

Haces SSH (entras por el túnel de la VPN)

SSH lanza el script(/etc/ssh/sshrc): detecta tu IP (tcpdump) y se la pasa al PIPE (pf_helper.pipe), el script RC deja como demonio a pf_injector.sh, que limpia la tabla mi_ip, e inyecta la IP autorizada en Packet Filter .

La IP pública ya esta en la tabla mi_ip de PF

Ahora conectas desde otra consola: ssh -i id_key -p XXXXX user@ip-sistema

Puedes desconectar si quieres la primera conexión SSH, y después si quieres también la VPN

El Sistema debería limpiar la tabla mi_ip , cuando te desconectes de SSH


 
Share this post :

Subscribe to receive future updates

Lorem ipsum dolor sited Sed ullam corper consectur adipiscing Mae ornare massa quis lectus.

No spam guaranteed, So please don’t send any spam mail.