Esta pagina se ve mejor con JavaScript habilitado

PF básico

 ·  🎃 kr0m

Packet Filer o PF es un sistema de filtrado de tráfico TCP/IP y NAT, PF también es capaz de normalizar y condicionar tráfico TCP/IP además de proveer mecanismos de control de ancho de banda y priorización de paquetes. PF forma parte de FreeBSD desde la versión 5.3, a lo largo de los años las versiones de OpenBSD y FreeBSD han divergido de forma considerable por lo que algunas funcionalidades funcionarán de forma distinta según el sistema subyacente.


Instalación

Para poder arrancar PF debemos crear un fichero de reglas, inicialmente puede estar vacío ya que solo lo generamos para comprobar que PF arranque:

touch /etc/pf.conf
chmod 600 /etc/pf.conf

Habilitamos PF en el arranque:

sysrc pf_enable=YES
sysrc pf_rules="/etc/pf.conf"

PF nos permite logear tráfico para ser visualizado en tiempo real mediante un analizador de tráfico en la interfaz pflog0 o tener un registro en un fichero de texto.

 The pflog interface is a device which makes visible all packets logged by the packet filter, pf(4).
 Logged packets can easily be monitored in realtime by invoking tcpdump(1) on the pflog interface, or stored to disk using pflogd(8).

Habilitamos PF-LOG en el arranque y configuramos el fichero de logs:

sysrc pflog_enable=YES
sysrc pflog_logfile="/var/log/pflog"

Si el equipo va a actuar como router o NATear tráfico, debemos habilitar el forwarding a nivel de sysctl:

sysctl net.inet.ip.forwarding=1
sysctl net.inet6.ip6.forwarding=1

Para que la configuración persista debemos modificar los siguientes parámetros RC:

sysrc gateway_enable=YES
sysrc ipv6_gateway_enable=YES

Arrancamos los dos servicios:

service pf start
service pflog start

Al arrancar el servicio pflog veremos como se ha generado una interfaz de red adicional:

ifconfig pflog0

pflog0: flags=141<UP,RUNNING,PROMISC> metric 0 mtu 33160
	groups: pflog

PF viene con bastantes ejemplos de configuración:

ls -la /usr/share/examples/pf/

total 62
drwxr-xr-x   2 root  wheel    12 May 12  2022 .
drwxr-xr-x  41 root  wheel    41 May 12  2022 ..
-r--r--r--   1 root  wheel  1245 May 12  2022 ackpri
-r--r--r--   1 root  wheel   937 May 12  2022 faq-example1
-r--r--r--   1 root  wheel  3141 May 12  2022 faq-example2
-r--r--r--   1 root  wheel  4723 May 12  2022 faq-example3
-r--r--r--   1 root  wheel  1074 May 12  2022 pf.conf
-r--r--r--   1 root  wheel   860 May 12  2022 queue1
-r--r--r--   1 root  wheel  1122 May 12  2022 queue2
-r--r--r--   1 root  wheel   492 May 12  2022 queue3
-r--r--r--   1 root  wheel   912 May 12  2022 queue4
-r--r--r--   1 root  wheel   268 May 12  2022 spamd

Comandos útiles

Una vez arrancado PF este puede ser administrado mediante el comando pfctl, los comandos mas utilizados son:

Comando Descripción
pfctl -e Habilita PF
pfctl -d Deshabilita PF
pfctl -f /etc/pf.conf Recarga configuración
pfctl -nf /etc/pf.conf Comprueba configuración sin cargarla
pfctl -nvf /etc/pf.conf Comprueba configuración sin cargarla, además muestra el parseo de las reglas
pfctl -F all -f /etc/pf.conf Flushea todas las reglas de NAT, filter, state, table y recarga la configuración
pfctl -s rules/nat/states Muestra las reglas de las tablas filtrado/NAT/estado
pfctl -sa Muestra toda la información posible

Aspectos importantes

Algunos aspectos importantes a tener en cuenta cuando utilizamos PF son:

  • Cuando una regla machea NO se para el procesamiento de reglas a no ser que se utilice quick .
  • La regla que se aplicará siempre será la última en machear.
  • Esto equivale a leer las reglas de abajo hacia arriba.
  • Todas las reglas son statefull.

Reglas básicas

La sintaxis de las reglas es la siguiente:

action [direction] [log] [quick] [on interface] [af] [proto protocol]
       [from src_addr [port src_port]] [to dst_addr [port dst_port]]
       [flags tcp_flags] [state]

Como ejemplo básico vamos a configurar unas reglas que denieguen el tráfico entrante a excepción del puerto 22 y que permitan conexiones salientes.

vi /etc/pf.conf

block in all
pass in proto tcp to any port 22
pass out all

Recargamos la configuración:

pfctl -f /etc/pf.conf


Listas

PF soporta el uso de listas lo que nos facilitará mucho la escritura de reglas:

block all
pass out proto tcp to any port { 80, 443 }
pass in proto tcp to any port 22

Macros

PF también soporta el uso de macros, realmente útiles:

ext_if = "em0"
tcp_services = "{ ssh, smtp, domain, http, pop3, auth, pop3s }"
udp_services = "{ domain }"
block all
pass out proto tcp to any port $tcp_services
pass proto udp to any port $udp_services
pass in proto tcp to any port 22

Podemos ver como se permite el tráfico HTTP:

HTTP/1.1 302 Found
content-length: 0
location: https://alfaexploit.com/
cache-control: no-cache

Pero no el HTTPS:

curl: (7) Couldn't connect to server

Quick

Como ya hemos comentado, por defecto la regla que se aplica siempre es la última en machear, para evitar este comportamiento y hacer que se interrumpa el procesamiento de las reglas al hacer match, debemos utilizar la función quick.
Pongamos este ejemplo de reglas con una conexión ssh saliente desde el equipo en cuestión:

ext_if = "em0"
tcp_services = "{ ssh, smtp, domain, http, pop3, auth, pop3s }"
udp_services = "{ domain }"
block all
pass out proto tcp to any port $tcp_services
pass out proto tcp to any
pass proto udp to any port $udp_services
pass in proto tcp to any port 22

Las reglas que machean el tráfico son:

block all
pass out proto tcp to any port $tcp_services
pass out proto tcp to any

Pero solo se aplicará la tercera ya que es la última en machear:

pass out proto tcp to any

Este comportamiento puede ser evitado si añadimos la función quick, de este modo cuando una regla machee se parará el procesamiento de reglas y el tráfico será tratado acorde a dicha regla.

Pongamos el mismo ejemplo anterior pero esta vez utilizando quick:

vi /etc/pf.conf

ext_if = "em0"
tcp_services = "{ ssh, smtp, domain, http, pop3, auth, pop3s }"
udp_services = "{ domain }"
block all
pass out quick proto tcp to any port $tcp_services
pass out proto tcp to any
pass proto udp to any port $udp_services
pass in proto tcp to any port 22

Siguen macheando tres reglas:

block all
pass out quick proto tcp to any port $tcp_services
pass out proto tcp to any

Pero al llegar a la segunda se parará el procesamiento de reglas y se aplicará dicha regla:

pass out quick proto tcp to any port $tcp_services

Respuesta tráfico descartado

Se puede definir como responder ante el tráfico descartado, hay dos opciones:

  • Drop(default): Se descarta el tráfico sin mas.
  • Return: Se descarta y además se le envía al origen un mensaje de status code.
set block-policy return

Scrub

Existen ciertos ataques que aprovechan la fragmentación de paquetes para evadir reglas de filtrado o sistemas de detección de ataques, mediante PF podremos bloquear dichos ataques utilizando la función scrub.
Scrub reensamblará los fragmentos asegurándose así de que toda la información del paquete TCP sea correcta.
La manera mas sencilla de utilizar scrub es esta:

scrub in all

Pero scrub permite hacer mas ajustes como por ejemplo cambiar flags TCP, en este caso elimina el bit “do not fragment” e impone un tamaño máximo de segmente de 1440 bytes:

scrub in all fragment reassemble no-df max-mss 1440

Antispoof

Una buena práctica es denegar el tráfico cuyo origen no coincida con la interfaz de red conectada a dicha red:

martians = "{ 127.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8, 169.254.0.0/16, 192.0.2.0/24, 0.0.0.0/8, 240.0.0.0/4 }"
block drop in quick on $ext_if from $martians to any
block drop out quick on $ext_if from any to $martians

Una manera de hacer esto automáticamente es mediante la función antispoof, pero antes debemos skipear el tráfico loopback ya que se ve afectado por antispoof:

set skip on lo
antispoof for $ext_if inet

Tablas

Las tablas son listas que pueden ser modificadas sin necesidad de recargar el set de reglas, además estas pueden ser consultadas de forma muy rápida.

Tablas dinámicas:
Su contenido puede ser modificado.

table <spammers> { 192.168.2.0/24, !192.168.2.5 }

block all
pass in proto tcp to any port 25
block in proto tcp from <spammers> to any port 25
pass in proto tcp to any port 22

Podemos consultar la tabla:

pfctl -t spammers -T show

   192.168.2.0/24
  !192.168.2.5

Una peculiaridad de las tablas es que si no son referenciadas por alguna regla, no se crean:

table <spammers> { 192.168.2.0/24, !192.168.2.5 }

block all
pass in proto tcp to any port 25
#block in proto tcp from <spammers> to any port 25
pass in proto tcp to any port 22

Borramos las tablas y recargamos la configuración:

pfctl -F Tables && pfctl -f /etc/pf.conf

Intentamos consultar la tabla:

pfctl -t spammers -T show

pfctl: Table does not exist.

Si queremos que la tabla se cree incluso sin existir referencias a ella debemos indicarlo:

table <spammers> persist { 192.168.2.0/24, !192.168.2.5 }

block all
pass in proto tcp to any port 25
#block in proto tcp from <spammers> to any port 25
pass in proto tcp to any port 22

Borramos las tablas y recargamos la configuración:

pfctl -F Tables && pfctl -f /etc/pf.conf

Podemos consultar la tabla:

pfctl -t spammers -T show

   192.168.2.0/24
  !192.168.2.5

Una tabla dinámica puede ser manipulada en real-time mediante pfctl:

pfctl -t spammers -T add 192.168.3.4

1/1 addresses added.
pfctl -t spammers -T show
   192.168.2.0/24
  !192.168.2.5
   192.168.3.4

Las modificaciones realizadas sobre una tabla no persisten al reinicio del equipo, una manera de hacer que persistan es cargándolas desde un fichero de texto y crontabeando un volcado regular de estas al fichero en cuestión.

vi /etc/spammers

192.168.2.0/24
!192.168.2.5

Modificamos el script de reglas del siguiente modo:

table <spammers> file "/etc/spammers"

block all
pass in proto tcp to any port 25
block in proto tcp from <spammers> to any port 25
pass in proto tcp to any port 22

Borramos las tablas y recargamos la configuración:

pfctl -F Tables && pfctl -f /etc/pf.conf

Añadimos una entrada a la tabla:

pfctl -t spammers -T add 192.168.3.4

Volcamos manualmente el contenido de la tabla al fichero, este comando es el que deberíamos de crontabear:

pfctl -t spammers -T show >/etc/spammers

Finalmente recargamos la configuración:

pfctl -F Tables && pfctl -f /etc/pf.conf

Y efectivamente el contenido de la tabla es correcto tras el reinicio:

pfctl -t spammers -T show

   192.168.2.0/24
  !192.168.2.5
   192.168.3.4

Tablas estáticas:
Su contenido no puede ser modificado.

table <spammers> const { 192.168.2.0/24, !192.168.2.5 }

block all
pass in proto tcp to any port 25
block in proto tcp from <spammers> to any port 25
pass in proto tcp to any port 22

Si intentamos añadir una entrada mostrará el siguiente error:

pfctl -t spammers -T add 192.168.3.4

pfctl: Operation not permitted.

Manipulación de tablas
Añadir entradas:

pfctl -t spammers -T add 192.168.1.0/16

Mostrar contenido de la tabla:

pfctl -t spammers -T show

Eliminar contenido de la tabla:

pfctl -t spammers -T delete 192.168.0.0/16

Eliminar todas las entradas de una tabla:

pfctl -t spammers -T flush

Eliminar la tabla en si misma:

pfctl -t spammers -T kill

Recargar el contenido al vuelo:

pfctl -t spammers -T replace -f /etc/spammers

Se puede hacer limpieza de las tablas eliminando las entradas que no han sido referenciadas en los últimos X segundos.

pfctl -t spammers -T expire 86400


Anchors

Los anchors son un conjunto de reglas, tablas u otros anchors a los que se les ha asignado un nombre, se podría decir que son el equivalente a un include de código, la ventaja de los anchors es que pueden ser manipuladas en tiempo real mediante pfctl, además pueden ser anidados lo que proporciona una gran flexibilidad.

Los anchors pueden incluirse de manera que solo incluyan cierto tipo de reglas:

  • anchor name: Incluye las reglas del anchor.
  • binat-anchor name: Incluye solo las reglas bitnat del anchor.
  • nat-anchor name: Incluye solo las reglas nat del anchor.
  • rdr-anchor name: Incluye solo las reglas rdr del anchor.

Los anchors pueden ser poblados de distintas maneras.

Desde un fichero de texto

vi /etc/anchor-goodguys

pass in proto tcp from 192.168.69.0/24 to any port 25

En este script se bloquea todo el tráfico por defecto pero se permite el tráfico al puerto 25 a través de un anchor:

block all
anchor goodguys
load anchor goodguys from "/etc/anchor-goodguys"
pass in proto tcp to any port 22

Podemos ver el contenido de los anchors:

pfctl -a goodguys -s rules

pass in inet proto tcp from 192.168.69.0/24 to any port = smtp flags S/SA keep state

Es posible editar el fichero y recargar el contenido de nuevo:

vi /etc/anchor-goodguys

pass in proto tcp from 192.168.69.0/24 to any port 25
pass in proto tcp from 192.168.2.0/24 to any port 25

Recargamos el contenido:

pfctl -a goodguys -f /etc/anchor-goodguys

Podemos ver el contenido de los anchors:

pfctl -a goodguys -s rules

pass in inet proto tcp from 192.168.69.0/24 to any port = smtp flags S/SA keep state
pass in inet proto tcp from 192.168.2.0/24 to any port = smtp flags S/SA keep state

Mediante pfctl
Simplemente definimos el anchor en el script de filtrado:

block all
anchor goodguys
pass in proto tcp to any port 22

Borramos las reglas anteriores:

pfctl -a goodguys -F rules

Lo poblamos con el siguiente comando:

echo "pass in proto tcp from 192.168.69.0/24 to any port 25" | pfctl -a goodguys -f -

Podemos ver el contenido de los anchors:

pfctl -a goodguys -s rules

pass in inet proto tcp from 192.168.69.0/24 to any port = smtp flags S/SA keep state

Inline dentro del script de reglas
Tan solo debemos escribir las reglas dentro de {}, el nombre del anchor es opcional:

block all
anchor "goodguys" {
        pass in proto tcp from 192.168.69.0/24 to port 25
}
pass in proto tcp to any port 22

Podemos ver el contenido de los anchors:

pfctl -a goodguys -s rules

pass in inet proto tcp from 192.168.69.0/24 to any port = smtp flags S/SA keep state

Los anchors pueden ser anidados:

vi /etc/anchor-goodguys

anchor "goodguys" {
    anchor "client1" {
        pass in proto tcp from 192.168.69.4 to port 25
    }
    anchor "client2" {
        pass in proto tcp from 192.168.69.5 to port 25
    }
}

Cargamos el contenido del anchor:

pfctl -a goodguys -f /etc/anchor-goodguys

Podemos ver el contenido de los anchors:

pfctl -a "goodguys/*" -s rules

anchor "goodguys" all {
  anchor "client1" all {
    pass in inet proto tcp from 192.168.69.4 to any port = smtp flags S/SA keep state
  }
  anchor "client2" all {
    pass in inet proto tcp from 192.168.69.5 to any port = smtp flags S/SA keep state
  }
}

Ahora incluimos todos los anchors de segundo nivel de goodguys, estos serán evaluados en orden alfabético:

block all
anchor "goodguys/*"
pass in proto tcp to any port 22

NOTA: Hay que tener en cuenta que no se descenderá recursivamente, solo se evaluarán los anchors de segundo de nivel, si hubiese anchors de tercer nivel estos serían ignorados.

Mostrar las reglas de un anchor:

pfctl -a goodguys -s rules

Borrar las reglas de un anchor:

pfctl -a goodguys -F rules


LOG

Mediante la opción log podremos generar entradas en el fichero de log o verlas en tiempo real en la interfaz log0.
El script de reglas será este, generamos logs del tráfico rechazado y del destinado al puerto 25:

block log all
pass in log proto tcp to any port 25
pass in proto tcp to any port 22

Podemos consultar los logs accediendo al fichero, pero debemos de tener en cuenta que el volcado no es real time, si queremos verlo en tiempo real tendremos que consultar directamente la interfaz log0:

tcpdump -n -e -ttt -r /var/log/pflog

 00:00:00.000000 rule 1/0(match): pass in on em0: 192.168.69.4.64484 > 192.168.69.55.25: Flags [S], seq 4073334594, win 65535, options [mss 1460,[|tcp]>

O directamente en la interfaz de red:

tcpdump -n -e -ttt -i pflog0

 00:00:00.000000 rule 1/0(match): pass in on em0: 192.168.69.4.19198 > 192.168.69.55.25: Flags [S], seq 494470215, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 4053058779 ecr 0], length 0

Log soporta varios opciones interesantes:

  • all: Por defecto solo se logea el primer paquete, con all logearemos los paquetes subsecuentes de dicha conexión.
  • to pflogN: Cambia la interfaz en la que logear las entradas.
  • user: También se logea el UID/GID del socket que generó o recibió la conexión.

En este caso vamos a guardar el tráfico bloqueado y los paquetes relacionados con la conexión al puerto 25 y el UID/GID del socket:

block log all
pass in log (all, user) proto tcp to any port 25
pass in proto tcp to any port 22
tcpdump -n -e -ttt -i pflog0
 00:00:00.000000 rule 1/0(match): pass in on em0: 192.168.69.4.35085 > 192.168.69.55.25: Flags [S], seq 702812990, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 1667456513 ecr 0], length 0
 00:00:02.057478 rule 1/0(match): pass in on em0: 192.168.69.4.35096 > 192.168.69.55.25: Flags [P.], seq 1:5, ack 1, win 1027, options [nop,nop,TS val 1978886000 ecr 1634216891], length 4: SMTP: asd

También podemos filtrar las entradas del fichero de log:

tcpdump -n -e -ttt -r /var/log/pflog port 25

Tcpdump soporta la salida de pflogd por lo que podremos realizar filtrados mas avanzados:

ip - address family is IPv4.
ip6 - address family is IPv6.
on int - packet passed through the interface int.
ifname int - same as on int.
ruleset name - the ruleset/anchor that the packet was matched in.
rulenum num - the filter rule that the packet matched was rule number num.
action act - the action taken on the packet. Possible actions are pass and block.
reason res - the reason that action was taken. Possible reasons are match, bad-offset, fragment, short, normalize, memory, bad-timestamp, congestion, ip-option, proto-cksum, state-mismatch, state-insert, state-limit, src-limit and synproxy.
inbound - packet was inbound.
outbound - packet was outbound.

En este ejemplo veremos el tráfico denegado de salida:

tcpdump -n -e -ttt -i pflog0 outbound and action block

 00:00:00.000000 rule 0/0(match) [uid 0]: block out on em0: 192.168.69.55.33512 > 192.168.69.4.443: Flags [S], seq 26421961, win 65535, options [mss 1460,nop,wscale 6,sackOK,TS val 1046077323 ecr 0], length 0

PFTop

Una herramienta muy útil para ver las conexiones y el ancho de banda consumido por cada una de ellas es pftop.

pkg install pftop

pfTop: Up State 1-33/33, View: default, Order: none, Cache: 10000                                                                                                                                                                                                                  10:40:51

PR        DIR SRC                                           DEST                                                   STATE                AGE       EXP     PKTS    BYTES
udp       Out 192.168.69.4:29155                            142.250.200.138:443                              MULTIPLE:MULTIPLE     00:52:04  00:00:59     1078   108109
tcp       Out 192.168.69.4:37191                            192.168.69.2:22                               ESTABLISHED:ESTABLISHED  00:52:07  23:59:56       67    11968
tcp       Out 192.168.69.4:41701                            192.168.69.203:8009                           ESTABLISHED:ESTABLISHED  00:52:05  23:59:55     1888   242722
tcp       Out 192.168.69.4:60886                            192.168.69.198:8009                           ESTABLISHED:ESTABLISHED  00:52:07  23:59:59     1892   244049
tcp       Out 192.168.69.4:55729                            149.154.167.92:443                            ESTABLISHED:ESTABLISHED  00:51:34  23:59:25      307    52375
tcp       Out 192.168.69.4:19092                            157.90.179.245:443                            ESTABLISHED:ESTABLISHED  00:44:00  23:59:31      183    29954
tcp       Out 192.168.69.4:32448                            198.252.206.25:443                            ESTABLISHED:ESTABLISHED  00:41:37  23:59:15      146    15433
tcp       Out 192.168.69.4:31612                            140.82.114.26:443                             ESTABLISHED:ESTABLISHED  00:11:28  23:59:32       71    10235
tcp       Out 192.168.69.4:30968                            140.82.114.26:443                             ESTABLISHED:ESTABLISHED  00:10:32  23:59:29       68    13000
tcp       Out 192.168.69.4:48598                            192.168.69.19:443                              FIN_WAIT_2:FIN_WAIT_2   00:01:16  00:00:50       15     4171
udp       Out 192.168.69.4:65471                            142.250.184.4:443                                MULTIPLE:MULTIPLE     00:00:43  00:00:19      115    56281
tcp       Out 192.168.69.4:48582                            216.58.209.74:443                             ESTABLISHED:ESTABLISHED  00:02:42  23:59:33       26     5924
tcp       Out 192.168.69.4:65216                            199.71.0.46:43                                 FIN_WAIT_2:FIN_WAIT_2   00:00:54  00:00:36       12     2893
tcp       Out 192.168.69.4:65226                            88.26.176.27:443                               FIN_WAIT_2:FIN_WAIT_2   00:00:11  00:01:24       22     9094
tcp       Out 192.168.69.4:65225                            192.168.69.19:443                             ESTABLISHED:ESTABLISHED  00:00:16  23:59:44       16     9265
tcp       Out 192.168.69.4:65220                            88.26.176.27:443                               FIN_WAIT_2:FIN_WAIT_2   00:00:41  00:00:54       22     9094
tcp       Out 192.168.69.4:48586                            192.168.69.19:443                              FIN_WAIT_2:FIN_WAIT_2   00:02:16  00:00:14       15     3788
tcp       Out 192.168.69.4:48587                            192.168.69.19:443                              FIN_WAIT_2:FIN_WAIT_2   00:02:16  00:00:14       17     5757
udp       Out 192.168.69.4:54755                            142.250.201.78:443                               MULTIPLE:MULTIPLE     00:00:54  00:00:06       18     6855
tcp       Out 192.168.69.4:65221                            142.250.200.138:443                             TIME_WAIT:TIME_WAIT    00:00:40  00:00:51       11     1038
tcp       Out 192.168.69.4:41841                            162.159.138.60:443                            ESTABLISHED:ESTABLISHED  00:01:02  23:59:43       17     6580
tcp       Out 192.168.69.4:65222                            142.250.200.138:443                             TIME_WAIT:TIME_WAIT    00:00:40  00:00:50        9      920
tcp       Out 192.168.69.4:48599                            88.26.176.27:443                               FIN_WAIT_2:FIN_WAIT_2   00:01:11  00:00:24       22     9094
tcp       Out 192.168.69.4:65224                            142.250.200.138:443                             TIME_WAIT:TIME_WAIT    00:00:39  00:00:51        9      946
tcp       Out 192.168.69.4:65218                            88.26.176.27:443                               FIN_WAIT_2:FIN_WAIT_2   00:00:41  00:00:54       24     8964
tcp       Out 192.168.69.4:65219                            88.26.176.27:443                               FIN_WAIT_2:FIN_WAIT_2   00:00:41  00:00:54       21     8156
tcp       Out 192.168.69.4:65511                            192.0.47.59:43                                 FIN_WAIT_2:FIN_WAIT_2   00:00:55  00:00:36       10      864
tcp       Out 192.168.69.4:65223                            142.250.200.138:443                             TIME_WAIT:TIME_WAIT    00:00:39  00:00:51        9      946
udp       Out 192.168.69.4:36386                            8.8.8.8:53                                       MULTIPLE:SINGLE       00:00:01  00:00:29        2      170
tcp       Out 192.168.69.4:65217                            172.217.168.170:443                            FIN_WAIT_2:FIN_WAIT_2   00:00:52  00:00:39       28    15504
udp       Out 192.168.69.4:61727                            142.250.200.74:443                               MULTIPLE:MULTIPLE     00:00:01  00:00:59       18     5518
tcp       Out 192.168.69.4:48589                            162.159.130.234:443                           ESTABLISHED:ESTABLISHED  00:01:56  23:59:56       46    31599
udp       Out 192.168.69.4:64629                            142.250.200.74:443                               MULTIPLE:MULTIPLE     00:00:01  00:01:00       17     6942

Mi script servidor Bastille

Como nota final dejo mi script de filtrado en un servidor Bastille:

ext_if = "nfe0"

set block-policy return
scrub in on $ext_if all fragment reassemble
set skip on lo

table <badguys> persist
table <jails> persist

nat on $ext_if from <jails> to any -> ($ext_if:0)
rdr-anchor "rdr/*"

antispoof for $ext_if inet

block log all
pass out quick
block in quick from <badguys>

pass in proto tcp to 192.168.69.2 port 7777

# SMTP -> HellStorm
pass in proto tcp to 192.168.69.17 port 25

# HTTP/HTTPS -> Atlas
pass in proto tcp to 192.168.69.19 port 80
pass in proto tcp to 192.168.69.19 port 443

# Xbox -> Paradox
pass in proto tcp from 192.168.69.196 to 192.168.69.18 port 80
# TARS -> Paradox
pass in proto tcp from 192.168.69.198 to 192.168.69.18 port 80

pass in proto tcp to any port 22

Crontabeado tengo el comando de limpieza que elimina las entradas que no han sido referenciadas en las últimas 24h:

# 24h or reboot: Banned ips
00 11 * * * pfctl -t badguys -T expire 86400
Si te ha gustado el artículo puedes invitarme a un RedBull aquí