One place for hosting & domains

      Filter

      How To Use the Python Filter Function


      Introduction

      The Python built-in filter() function can be used to create a new iterator from an existing iterable (like a list or dictionary) that will efficiently filter out elements using a function that we provide. An iterable is a Python object that can be “iterated over”, that is, it will return items in a sequence such that we can use it in a for loop.

      The basic syntax for the filter() function is:

      filter(function, iterable)
      

      This will return a filter object, which is an iterable. We can use a function like list() to make a list of all the items returned in a filter object.

      The filter() function provides a way of filtering values that can often be more efficient than a list comprehension, especially when we’re starting to work with larger data sets. For example, a list comprehension will make a new list, which will increase the run time for that processing. This means that after our list comprehension has completed its expression, we’ll have two lists in memory. However, filter() will make a simple object that holds a reference to the original list, the provided function, and an index of where to go in the original list, which will take up less memory.

      In this tutorial, we’ll review four different ways of using filter(): with two different iterable structures, with a lambda function, and with no defined function.

      Using filter() with a Function

      The first argument to filter() is a function, which we use to decide whether to include or filter out each item. The function is called once for every item in the iterable passed as the second argument and each time it returns False, the value is dropped. As this argument is a function, we can either pass a normal function or we can make use of lambda functions, particularly when the expression is less complex.

      Following is the syntax of a lambda with filter():

      filter(lambda item: item[] expression, iterable)
      

      With a list, like the following, we can incorporate a lambda function with an expression against which we want to evaluate each item from the list:

      creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']
      

      To filter this list to find the names of our aquarium creatures that start with a vowel, we can run the following lambda function:

      print(list(filter(lambda x: x[0].lower() in 'aeiou', creature_names)))
      

      Here we declare an item in our list as x. Then we set our expression to access the first character of each string (or character “zero”), so x[0]. Lowering the case of each of the names ensures this will match letters to the string in our expression, 'aeiou'.

      Finally we pass the iterable creature_names. Like in the previous section we apply list() to the result in order to create a list from the iterator filter() returns.

      The output will be the following:

      Output

      ['Ashley', 'Olly']

      This same result can be achieved using a function we define:

      creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']
      
      def names_vowels(x):
        return x[0].lower() in 'aeiou'
      
      filtered_names = filter(names_vowels, creature_names)
      
      print(list(filtered_names))
      

      Our function names_vowels defines the expression that we will implement to filter creature_names.

      Again, the output would be as follows:

      Output

      ['Ashley', 'Olly']

      Overall, lambda functions achieve the same result with filter() as when we use a regular function. The necessity to define a regular function grows as the complexity of expressions for filtering our data increases, which is likely to promote better readability in our code.

      Using None with filter()

      We can pass None as the first argument to filter() to have the returned iterator filter out any value that Python considers “falsy”. Generally, Python considers anything with a length of 0 (such as an empty list or empty string) or numerically equivalent to 0 as false, thus the use of the term “falsy.”

      In the following case we want to filter our list to only show the tank numbers at our aquarium:

      aquarium_tanks = [11, False, 18, 21, "", 12, 34, 0, [], {}]
      

      In this code we have a list containing integers, empty sequences, and a boolean value.

      filtered_tanks = filter(None, aquarium_tanks)
      

      We use the filter() function with None and pass in the aquarium_tanks list as our iterable. Since we have passed None as the first argument, we will check if the items in our list are considered false.

      print(list(filtered_tanks))
      

      Then we wrap filtered_tanks in a list() function so that it returns a list for filtered_tanks when we print.

      Here we see the output shows only the integers. All the items that evaluated to False, that are equivalent to 0 in length, were removed by filter():

      Output

      [11, 25, 18, 21, 12, 34]

      Note: If we don’t use list() and print filtered_tanks we would receive a filter object something like this: <filter object at 0x7fafd5903240>. The filter object is an iterable, so we could loop over it with for or we can use list() to turn it into a list, which we’re doing here because it’s a good way to review the results.

      With None we have used filter() to quickly remove items from our list that were considered false.

      Using filter() with a List of Dictionaries

      When we have a more complex data structure, we can still use filter() to evaluate each of the items. For example, if we have a list of dictionaries, not only do we want to iterate over each item in the list — one of the dictionaries — but we may also want to iterate over each key:value pair in a dictionary in order to evaluate all the data.

      As an example, let’s say we have a list of each creature in our aquarium along with different details about each of them:

      aquarium_creatures = [
        {"name": "sammy", "species": "shark", "tank number": "11", "type": "fish"},
        {"name": "ashley", "species": "crab", "tank number": "25", "type": "shellfish"},
        {"name": "jo", "species": "guppy", "tank number": "18", "type": "fish"},
        {"name": "jackie", "species": "lobster", "tank number": "21", "type": "shellfish"},
        {"name": "charlie", "species": "clownfish", "tank number": "12", "type": "fish"},
        {"name": "olly", "species": "green turtle", "tank number": "34", "type": "turtle"}
      ]
      

      We want to filter this data by a search string we give to the function. To have filter() access each dictionary and each item in the dictionaries, we construct a nested function, like the following:

      def filter_set(aquarium_creatures, search_string):
          def iterator_func(x):
              for v in x.values():
                  if search_string in v:
                      return True
              return False
          return filter(iterator_func, aquarium_creatures)
      

      We define a filter_set() function that takes aquarium_creatures and search_string as parameters. In filter_set() we pass our iterator_func() as the function to filter(). The filter_set() function will return the iterator resulting from filter().

      The iterator_func() takes x as an argument, which represents an item in our list (that is, a single dictionary).

      Next the for loop accesses the values in each key:value pair in our dictionaries and then uses a conditional statement to check whether the search_string is in v, representing a value.

      Like in our previous examples, if the expression evaluates to True the function adds the item to the filter object. This will return once the filter_set() function has completed. We position return False outside of our loop so that it checks every item in each dictionary, instead of returning after checking the first dictionary alone.

      We call filter_set() with our list of dictionaries and the search string we want to find matches for:

      filtered_records = filter_set(aquarium_creatures, "2")    
      

      Once the function completes we have our filter object stored in the filtered_records variable, which we turn into a list and print:

      print(list(filtered_records))      
      

      We’ll see the following output from this program:

      Output

      [{'name': 'ashley', 'species': 'crab', 'tank number': '25', 'type': 'shellfish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': '21', 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': '12', 'type': 'fish'}]

      We’ve filtered the list of dictionaries with the search string 2. We can see that the three dictionaries that included a tank number with 2 have been returned. Using our own nested function allowed us to access every item and efficiently check each against the search string.

      Conclusion

      In this tutorial, we’ve learned the different ways of using the filter() function in Python. Now you can use filter() with your own function, a lambda function, or with None to filter for items in varying complexities of data structures.

      Although in this tutorial we printed the results from filter() immediately in list format, it is likely in our programs we would use the returned filter() object and further manipulate the data.

      If you would like to learn more Python, check out our How To Code in Python 3 series and our Python topic page.



      Source link

      Cómo configurar Packet Filter (PF) en FreeBSD 12.1


      El autor seleccionó el COVID-19 Relief Fund para que reciba una donación como parte del programa Write for DOnations.

      Introducción

      El firewall posiblemente sea una de las líneas de defensa más importantes contra los ataques cibernéticos. La capacidad de configurar un firewall desde cero es una habilidad increíble que permite al administrador tomar el control de sus redes.

      Packet Filter (PF) es una renombrada aplicación de firewall que se mantiene upstream por el proyecto orientado a la seguridad OpenBSD. Se expresa de forma más expresiva como una herramienta de filtrado de paquetes, de ahí su nombre, y es conocida por su sintaxis sencilla, facilidad de uso y gran cantidad de funciones. PF es un firewall con estados por defecto, que almacena información sobre las conexiones en una tabla de estados a la que puede accederse con fines analíticos. PF es parte del sistema básico de FreeBSD y cuenta con el apoyo de una fuerte comunidad de desarrolladores. Aunque existen diferencias entre las versiones FreeBSD y OpenBSD de PF en relación con las arquitecturas del kernel, en general su sintaxis es similar. Dependiendo de su complejidad, los conjuntos de reglas comunes pueden modificarse para que funcionen en cualquier distribución con un esfuerzo relativamente pequeño.

      A través de este tutorial, creará un firewall desde cero en un servidor FreeBSD 12.1 con PF. Diseñará un conjunto de reglas básico que puede usarse como plantilla para futuros proyectos. También explorará algunas de las funciones avanzadas de PF, como la limpieza de paquetes, la prevención de ataques por fuerza bruta, la monitorización y el registro, y otras herramientas de terceros.

      Requisitos previos

      Antes de iniciar este tutorial, necesitará lo siguiente:

      • Un servidor FreeBSD 12.1 (ZFS o UFS). Puede usar nuestro tutorial Cómo comenzar con FreeBSD para configurar su servidor con su configuración deseada.
      • FreeBSD no tiene un firewall habilitado por defecto; la personalización es una característica propia de la filosofía de FreeBSD. Por tanto, cuando inicie su servidor por primera vez, necesitará protección temporal mientras que se configura PF. Si usa DigitalOcean, puede habilitar su firewall en la nube de inmediato tras iniciar el servidor. Consulte Inicio rápido del firewall de DigitalOcean para obtener instrucciones sobre cómo configurar un firewall en la nube. Si está usando otro proveedor en la nube, determine la ruta más rápida para la protección inmediata antes de comenzar. Sea cual sea el método que elija, su firewall temporal debe permitir solo el tráfico SSH entrante y puede permitir todos los tipos de tráfico saliente.

      Paso 1: Crear su conjunto de reglas preliminares

      Comenzará este tutorial esbozando un conjunto de reglas prelimnares que proporcionan protección básica y acceso a los servicios críticos de Internet. En este momento, tendrá un servidor FreeBSD 12.1 en ejecución con un firewall en la nube activo.

      Existen dos enfoques a la hora de crear un firewall: denegación por defecto y permiso por defecto. El enfoque denegación por defecto bloquea todo el tráfico, y solo permite lo que se especifica en una regla. El enfoque permiso por defecto, hace justo lo contrario: pasa todo el tráfico y solo bloquea lo que se especifica en una regla. Utilizará el enfoque denegación por defecto.

      Los conjuntos de reglas PF se escriben en un archivo de configuración llamado /etc/pf.conf, que también es su ubicación predeterminada. Está bien guardar este archivo en otro lugar siempre que se especifique en el archivo de configuración de /etc/rc.conf. Para este tutorial, usará la ubicación predeterminada.

      Inicie sesión en su servidor con su usuario no root:

      • ssh freebsd@your_server_ip

      A continuación, cree su archivo /etc/pf.conf:

      Nota: Si desea ver el conjunto de reglas básico completo en cualquier punto de este tutorial, puede consultar los ejemplos del paso 4 o del paso 8.

      PF filtra los paquetes según tres acciones principales: block, pass y match. Cuando se combinan con otras opciones, forman reglas. Se realiza una acción cuando un paquete cumple con el criterio especificado en una regla. Como puede esperar, las reglas pass y block aplicarán pass y block al tráfico, respectivamente. Una regla match realiza una acción sobre un paquete cuando encuentra un criterio de coincidencia, pero no lo pasa o bloquea. Por ejemplo, puede realizar la traducción de dirección de red (NAT) sobre un paquete que coincida sin pasarlo o bloquearlo, y permanecerá allí hasta que le diga que haga algo en otra regla, como dirigirlo a otro equipo o puerta de enlace.

      A continuación, añada la primera regla a su archivo /etc/pf.conf:

      /etc/pf.conf

      block all
      

      Esta regla bloquea todas las formas de tráfico en cada dirección. Ya que no especifica una dirección, los valores por defecto son in y out. Esta regla es legítima para una estación de trabajo local que deba estar aislada del mundo, pero es muy poco práctica y no funcionará en un servidor remoto porque no permite tráfico SSH. De hecho, si tuviese PF habilitado habría bloqueado usted mismo su acceso al servidor.

      Revise su archivo /etc/pf.conf para permitir el tráfico SSH con la siguiente línea resaltada:

      /etc/pf.conf

      block all
      pass in proto tcp to port 22
      

      Nota: De forma alternativa, puede usar el nombre del protocolo:

      /etc/pf.conf

      block all
      pass in proto tcp to port ssh
      

      Para mantener la consistencia, usaremos los números de puerto, a menos que exista una razón válida para no hacerlo. Hay una lista detallada de protocolos y sus números de puertos respectivos en el archivo /etc/services, que le aconsejamos que vea.

      PF procesa las reglas de forma secuencial de arriba a abajo, por tanto, su conjunto de reglas inicialmente bloquea todo el tráfico, pero luego lo pasa si el criterio de la siguiente línea se cumple, como en el caso del tráfico SSH.

      Ahora podrá permitir tráfico SSH en su servidor. No obstante, bloqueará toda forma de tráfico saliente. Esto es problemático por que no puede acceder a los servicios críticos desde Internet para instalar paquetes, actualizar sus ajustes de fecha y hora, etc.

      Para corregir esto, añada la siguiente regla resaltada al final de su archivo /etc/pf.conf:

      /etc/pf.conf

      block all
      pass in proto tcp to port { 22 }
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      

      Su conjunto de reglas ahora permite tráfico SSH, DNS, HTTP, NTP y HTTPS saliente, y bloquea todo el tráfico entrante (con la excepción de SSH). Coloca los números de puerto y protocolos entre corchetes, lo que forma una lista en la sinaxis de PF, permitiéndole añadir más números de puertos si es necesario. También añada una regla de paso para el protocolo UDP en los puertos 53 y 123 porque DNS y NTP a menudo alternan entre los protocolos TCP y UDP. Casi completó el conjunto de reglas preliminares. Solo debe agregar algunas reglas para lograr una funcionalidad básica.

      Complete el conjunto de reglas preliminares con las reglas resaltadas:

      Preliminary Ruleset /etc/pf.conf

      set skip on lo0
      block all
      pass in proto tcp to port { 22 }
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass out inet proto icmp icmp-type { echoreq }
      

      Guarde el archivo y ciérrelo.

      Creará la regla set skip para el dispositivo loopback porque no necesita filtrar tráfico y probablemente haga que se aplique rastreo en su servidor. Añada una regla pass out inet para el protocolo ICMP, que le permite usar la utilidad ping(8) para resolver problemas. La opción inet representa la familia de direcciones IPv4.

      ICMP es un protocolo de mensajería polivalente usado por los dispositivos de red para varios tipos de comunicaciones. La utilidad ping, por ejemplo, utiliza un tipo de mensaje conocido como echo request, que ha añadido a su lista icmp_type. Como precaución, solo permite los tipos de mensaje que necesita para evitar que dispositivos no permitidos se pongan en contacto con su servidor. A medida que sus necesidades aumentan, puede añadir más tipos de mensajes a su lista.

      Ahora tiene un conjunto de reglas en funcionamiento que proporciona funcionalidad básica para la mayoría de las máquinas. En la siguiente sección, vamos a confirmar que todo funcione correctamente habilitando PF y probando su conjunto de reglas preliminares.

      Paso 2: Probar su conjunto de reglas preliminares

      En este paso, probará su conjunto de reglas preliminares, realizará la transición de su firewall en la nube a su firewall de PF y permitirá que PF tenga todo el control. Activará su conjunto de reglas con la utilidad pfctl, que es la herramienta de línea de comandos integrada de PF, y el método principal para interactuar con PF.

      Los conjuntos de reglas PF no son otra cosa que archivos de texto, lo cual significa que no hay procedimientos delicados implicados en la carga de nuevos conjuntos de reglas. Puede cargar un nuevo conjunto de reglas y el anterior desaparecerá. En escasas ocasiones, si es necesario, existe la necesidad de eliminar un conjunto de reglas existente.

      FreeBSD utiliza una web de secuencias de comandos shell conocida como el sistema rc para administrar cómo se inician los servicios en el momento del arranque; especificamos esos servicios en varios archivos de configuración rc. Para los servicios globales como PF, utiliza el archivo /etc/rc.conf. Debido a que los archivos rc son críticos para el bienestar de un sistema de FreeBSD, no deberían editarse directamente. En su lugar, FreeBSD ofrece una utilidad de línea de comandos conocida como sysrc diseñada para ayudarle a editar estos archivo de forma segura.

      Habilitaremos PF usando la utilidad de línea de comandos sysrc:

      • sudo sysrc pf_enable="YES"
      • sudo sysrc pflog_enable="YES"

      Verifique estos cambios imprimiendo el contenido de su archivo /etc/rc.conf:

      Verá lo siguiente:

      Output

      pf_enable="YES" pflog_enable="YES"

      También habilitará el servicio pflog que, a su vez, permite que el demonio pflogd inicie sesión en PF. Trabajará con el inicio de sesión en un paso posterior.

      Se especifican dos servicios globales en su archivo /etc/rc.conf, pero estos no se inicializarán hasta que reinicie el servidor o los ponga en marcha manualmente. Reinicie el servidor de forma que pueda probar también su acceso SSH.

      Inicie PF reiniciando el servidor:

      La conexión se caerá. Dele unos minutos para actualizarse.

      Ahora, realice SSH de nuevo en el servidor:

      • ssh freebsd@your_server_ip

      Aunque inicializó sus servicios de PF, en realidad no cargó su conjunto de reglas /etc/pf.conf, lo cual significa que su firewall no está aún activo.

      Cargue el conjunto de reglas con pfctl:

      • sudo pfctl -f /etc/pf.conf

      Si no hay errores o mensajes, significa que su conjunto de reglas no tiene errores y el firewall está activo.

      Ahora que PF está en ejecución, puede desconectar su servidor de su firewall en la nube. Esto puede conseguirse en el panel de control de su cuenta de DigitalOcean eliminando su Droplet de su portal de firewall en la nube. Si está usando otro proveedor en la nube, asegúrese que lo que esté usando para la protección temporal esté desactivado. Es casi seguro que ejecutar dos firewalls en un servidor causará problemas.

      Por seguridad, reinicie su servidor de nuevo:

      Tras unos minutos, vuelva a hacer SSH en su servidor:

      • ssh freebsd@your_server_ip

      PF es ahora su firewall activo. Puede asegurarse de que esté ejecutándose accediendo a algunos datos con la utilidad pfctl.

      Vamos a ver algunas estadísticas y contadores con pfctl -si:

      Pasará los indicadores -si, que significa mostrar info. Esta es una de las muchas combinaciones de parámetros de filtros que puede usar con pfctl para analizar datos sobre la actividad de su firewall.

      Verá los siguientes datos tabulares (los valores variarán según el equipo):

      Output

      Status: Enabled for 0 days 00:01:53 Debug: Urgent State Table Total Rate current entries 5 searches 144 1.3/s inserts 11 0.1/s removals 6 0.1/s Counters match 23 0.2/s bad-offset 0 0.0/s fragment 0 0.0/s short 0 0.0/s normalize 0 0.0/s memory 0 0.0/s bad-timestamp 0 0.0/s congestion 0 0.0/s ip-option 0 0.0/s proto-cksum 0 0.0/s state-insert 0 0.0/s state-limit 0 0.0/s src-limit 0 0.0/s synproxy 0 0.0/s map-failed 0 0.0/s

      Debido a que acaba de activar su conjunto de reglas, no verá aún mucha información. Sin embargo, este resultado muestra que PF ya registró 23 reglas que coinciden, lo cual significa que se hallaron 23 coincidencias para los criterios de su conjunto de reglas. El resultado también confirma que su firewall está funcionando.

      Su conjunto de reglas también permite que el tráfico saliente acceda a algunos servicios críticos de Internet, incluyendo la utilidad ping.

      Vamos a comprobar la conectividad a Internet y el servicio DNS con ping contra google.com:

      Ya que ejecutó el indicador de recuento -c 3, verá tres respuestas de conexión correcta:

      Output

      PING google.com (172.217.0.46): 56 data bytes 64 bytes from 172.217.0.46: icmp_seq=0 ttl=56 time=2.088 ms 64 bytes from 172.217.0.46: icmp_seq=1 ttl=56 time=1.469 ms 64 bytes from 172.217.0.46: icmp_seq=2 ttl=56 time=1.466 ms --- google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.466/1.674/2.088/0.293 ms

      Asegúrese de que puede acceder al repositorio pkgs con el siguiente comando:

      Si hay paquetes para actualizar, hágalo ahora.

      Si ambos servicios están funcionando, significa que su firewall está activo y puede continuar. Aunque su conjunto de reglas preliminares ofrece protección y funcionalidad, sigue siendo un conjunto de reglas elemental y podría tener algunas mejoras. En las secciones restantes, completará su conjunto de reglas básico y usará algunas de las funciones avanzadas de PF.

      Paso 3: Completar su conjunto de reglas básico

      En este paso, creará a partir del conjunto de reglas preliminares para completar su conjunto de reglas básico. Reorganizará algunas de sus reglas y trabajará con conceptos más avanzados.

      Incorporar macros y tablas

      En su conjunto de reglas preliminares, ha predefinido el código de todos sus parámetros en cada regla, es decir, los números de los puertos que forman las listas. Esto puede ser muy difícil de administrar en el futuro, dependiendo de la naturaleza de sus redes. Con fines organizativos, PF incluye macros, listas y tablas. Ya incluyó las listas directamente en sus reglas, pero también puede separarlas de ellas y asignarlas a una variable usando macros.

      Abra su archivo para transfefrir algunos de sus parámetros a macros:

      Ahora, añada el siguiente contenido a la parte superior del conjunto de reglas:

      /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq }"
      . . .
      

      Modifique sus reglas SSH y ICMP anteriores con sus nuevas variables:

      /etc/pf.conf

      . . .
      pass in on $vtnet0 proto tcp to port { 22 }
      . . .
      pass inet proto icmp icmp-type $icmp_types
      . . .
      

      Sus reglas SSH y ICMP anteriores ahora usan macros. Los nombres de variables se indican mediante la sintaxis del símbolo de dólar en PF. Asigna su interfaz vtnet0 a una variable con el mismo nombre solo como formalidad, lo que le ofrece la opción de cambiarle el nombre en el futuro si es necesario. Otros nombres comunes de variables para las interfaces de cara al público son $pub_if o $ext_if.

      A continuación, implementará una tabla, que es similar a un macro, pero diseñada para albergar grupos de direcciones IP. Crearemos una tabla para las direcciones IP no enrutables, que a menudo juegan un papel en los ataques de denegación de servicio (DOS). Puede usar las direcciones IP especificadas en RFC6890, que define registros de direcciones IP con fines especiales. Su servidor no debería enviar o recibir paquetes a o desde estas direcciones a través de la interfaz de cara al público.

      Cree esta tabla añadiendo el siguiente contenido directamente bajo el macro icmp_types:

      /etc/pf.conf

      . . .
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      . . .
      

      Ahora, añada sus reglas para la tabla <rfc6890> debajo de la regla set skip on lo0:

      /etc/pf.conf

      . . .
      set skip on lo0
      block in quick on egress from <rfc6890>
      block return out quick on egress to <rfc6890>
      . . .
      

      Aquí introduce la opción return, que complementa su regla block out. Esto soltará los paquetes y enviará un mensaje RST al host que intentó realizar esas conexiones, lo que es útil para analizar la actividad del host. Luego, se añade la palabra clave egress, que automáticamente encuentra las rutas predeterminadas de cualquier interfaz concreta. Este es normalmente un método más limpio de encontrar rutas predeterminadas, especialmente con redes complejas. La palabra clave quick ejecuta las reglas de inmediato sin considerar el resto del conjunto de reglas. Por ejemplo, si un paquete con una dirección IP ilógica intenta establecer conexión con el servidor, le convendrá cortar la conexión de inmediato y no tendrá motivos para ejecutar ese paquete a través del conjunto de reglas restante.

      Proteger sus puertos SSH

      Ya que su puerto SSH está abierto al público, está sujeto a ataques. Una de las señales de aviso más obvias de un atacante es las cantidades masivas de intentos de inicio de sesión. Por ejemplo, si la misma dirección IP intenta iniciar sesión en su servidor 10 veces en un segundo, puede asumir que no se hizo con manos humanas, sino con un software informático que está intentando averiguar su contraseña de inicio de sesión. Estos tipos de vulneraciones de seguridad sistemáticas a menudo se denominan ataques por fuerza bruta y normalmente tienen éxito si las contraseñas del servidor son inseguras.

      Advertencia: Recomendamos encarecidamente usar autenticación con clave pública en todos los servidores. Consulte el tutorial de DigitalOcean sobre la autenticación basada en claves.

      PF tiene funciones integradas para lidiar con ataques por fuerza bruta o de tipo similar. Con PF puede limitar el número de intentos de conexión simultáneos permitidos por un único host. Si un host supera esos límites, la conexión se detendrá y se le prohibirá el acceso al servidor. Para conseguir esto, usará el mecanismo de sobrecarga de PF, que mantiene una tabla de direcciones IP baneadas.

      Modifique su regla SSH anterior para limitar el número de conexiones simultáneas desde un host único como sigue:

      /etc/pf.conf

      . . .
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      . . .
      

      Añade la opción keep state que le permite definir el criterio de estado para la tabla de sobrecarga. Se pasa el parámetro max-src-conn para especificar el número de conexiones simultáneas permitidas desde un único host por segundo y el parámetro max-src-conn-rate para especificar el número de nuevas conexiones permitidas desde un único host por segundo. Especifica 15 conexiones para max-src-conn y 3 conexiones para max-src-conn-rate. Si un host supera estos límites, el mecanismo overload añade el IP de origen a la tabla <bruteforce>, que prohíbe las conexiones desde el servidor. Finalmente, la opción flush global cierra la conexión.

      Ha definido una tabla de sobrecarga en su regla SSH, pero no ha declarado esa tabla en su conjunto de reglas.

      Añada la tabla <bruteforce> debajo de la macro icmp_types:

      /etc/pf.conf

      . . .
      icmp_types = "{ echoreq }"
      table <bruteforce> persist
      . . .
      

      La palabra clave persist permite que exista una tabla vacía en el conjunto de reglas. Sin ella, PF indicará que no hay direcciones IP en la tabla.

      Estas medidas garantizan que su puerto SSH está protegido por un potente mecanismo de seguridad. PF le permite configurar soluciones rápidas para protegerse de formas de vulneraciones de seguridad catastróficas. En las siguientes secciones, dará los pasos para limpiar los paquetes a medida que llegan a su servidor.

      Limpiar su tráfico

      Nota: En las siguientes secciones se describen los fundamentos básicos de la suite de protocolos TCP/IP. Si planea crear aplicaciones web o redes, le convendrá dominar estos conceptos. Eche un vistazo al tutorial Introducción a la terminología, interfaces y protocolos de red de DigitalOcean.

      Debido a la complejidad de la suite de protocolos TCP/IP, y a la perseverancia de actores maliciosos, los paquetes a menudo llegan con discrepancias y ambigüedades como fragmentos de IP que se solapan, direcciones IP fraudulentas, y mucho más. Es imperativo que limpie su tráfico antes de que entre en el sistema. El término técnico para este proceso es normalización.

      Cuando los datos viajan por Internet, normalmente se desglosan en fragmentos más pequeños en el origen para acomodarse a los parámetros de transmisión del host de destino, donde se vuelven a montar en paquetes completos. Desafortunadamente, un intruso puede secuestrar este proceso de varias formas que van más allá del alcance de este tutorial. Sin embargo, con PF puede gestionar la fragmentación a través de una regla. PF incluye una palabra clave scrub que normaliza los paquetes.

      Añada la palabra clave scrub directamente antes de su regla block all:

      /etc/pf.conf

      . . .
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      block all
      . . .
      

      Esta regla realiza una limpieza de todo el tráfico entrante. Incluye la opción fragment reassemble para evitar el ingreso de fragmentos en el sistema. En vez de eso, se almacenan en la memoria caché hasta que se vuelvan a ensamblar en paquetes completos, lo cual significa que sus reglas de filtro solo tendrán que tratar con paquetes uniformes. También incluye la opción max-mss 1440 que representa el tamaño máximo del segmento de los paquetes TCP reesamblados, también conocida como carga útil. Especifica un valor de 1440 bytes, que consigue un equilibrio entre tamaño y rendimiento, dejando suficiente espacio para los encabezados.

      Otro aspecto importante de la fragmentación es un término conocido como la unidad de transmisión máxima (MTU). Los protocolos TCP/IP permiten a los dispositivos negociar tamaños de paquetes para realizar conexiones. El host de destino utiliza mensajes ICMP para informar a la IP de origen de su MTU, un proceso conocido como descubrimiento de ruta MTU. El tipo de mensaje ICMP específico es el destination unreachable (destino inalcanzable). Habilitará el descubrimiento de la ruta MTU añadiendo el tipo de mensaje unreach a su lista icmp_types.

      Usará la MTU predeterminada de su servidor de 1500 bytes, que puede determinarse con el comando ifconfig:

      Verá el siguiente resultado que incluye su MTU actual:

      Output

      vtnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=6c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6> . . .

      Actualice la lista icmp_types para incluir el tipo de mensaje destination unreachable:

      /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach}"
      . . .
      

      Ahora que tiene las políticas implementadas para gestionar la fragmentación, los paquetes que entren en su sistema serán uniformes y consistentes. Esto es deseable porque hay muchos dispositivos intercambiando datos en Internet.

      Ahora trabajará para evitar otro problema de seguridad conocido como spoofing de IP. Los atacantes a menudo cambian sus IP de origen para que parezca que residen en un nodo confiable en una organización. PF incluye una directiva antispoofing para gestionar las IP de origen falsificadas. Cuando se aplica a una interfaz específica, el antispoofing bloquea todo el tráfico de la red de esa interfaz (a menos que se origine desde esa interfaz). Por ejemplo, si aplica antispoofing a una interfaz que reside en 5.5.5.1/24, el tráfico desde la red de 5.5.5.0/24 no puede comunicarse con el sistema a menos que se origine desde esas interfaces.

      Añada el siguiente contenido resaltado para aplicar antispoofing a su interfaz vtnet0:

      /etc/pf.conf

      . . .
      set skip on lo0
      scrub in
      antispoof quick for $vtnet0
      block all
      . . .
      

      Guarde el archivo y ciérrelo.

      Esta regla de antispoofing establece que el tráfico de las redes vtnet0 solo puede pasar a través de la interfaz de vtnet0 o se desconectará rápidamente con la palabra clave quick. Los agentes maliciosos no podrán ocultarse en la red de vtnet0 y comunicarse con otros nodos.

      Para demostrar su regla de antispoofing, imprimirá su conjunto de reglas en la pantalla en su formato detallado. Las reglas en PF se escriben normalmente en formato acortado, pero la escritura de estas también es posible en formato detallado. Normalmente es poco práctico escribir las reglas de ese modo, pero para realizar pruebas puede ser útil.

      Imprima el contenido de /etc/pf.conf usando pfctl con el siguiente comando:

      • sudo pfctl -nvf /etc/pf.conf

      Este comando pfctl toma los indicadores -nvf, que imprimen el conjunto de reglas y lo prueba sin cargar nada; se conoce también como simulacro. Verá todo el contenido de /etc/pf.conf en su formato detallado.

      Verá algo similar al siguiente resultado en la parte antispoofing:

      Output

      . . . block drop in quick on ! vtnet0 inet from your_server_ip/20 to any block drop in quick on ! vtnet0 inet from network_address/16 to any block drop in quick inet from your_server_ip to any block drop in quick inet from network_address to any block drop in quick on vtnet0 inet6 from your_IPv6_address to any . . .

      Su regla antispoofing descubrió que es parte de la red your_server_ip/20. También detectó que (para el ejemplo de este tutorial) el servidor es parte de una red network_address/16, y tiene direcciones IPv6 adicionales. Antispoofing bloquea todas estas redes para que no se comuniquen con el sistema, a menos que su tráfico pase a través de la interfaz vtnet0.

      Su regla de antispoofing es la última adición a su conjunto de reglas básico. En el siguiente paso, iniciará estos cambios y realizará algunas pruebas.

      Paso 4: Probar su conjunto de reglas básico

      En este paso revisará y probará su conjunto de reglas básico para garantizar que todo funciona adecuadamente. Es mejor evitar implementar demasiadas reglas a la vez sin probarlas. Una buena práctica es empezar con las esenciales, aumentar de forma incremental y realizar una copia de seguridad del trabajo cuando se realizan cambios en la configuración.

      Este es su conjunto de reglas básico completo:

      Base Ruleset /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach }"
      table <bruteforce> persist
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      antispoof quick for $vtnet0
      block in quick on $vtnet0 from <rfc6890>
      block return out quick on egress to <rfc6890>
      block all
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass inet proto icmp icmp-type $icmp_types
      

      Asegúrese que su archivo /etc/pf.conf es idéntico al del conjunto de reglas básico completo aquí antes de continuar. Guarde el archivo y ciérrelo.

      Su conjunto de reglas básico completo le ofrece:

      • Una colección de macros que pueden definir servicios y dispositivos clave.
      • Políticas de higiene de la red para abordar la fragmentación de paquetes y las direcciones IP ilógicas.
      • Una estructura de filtrado de default deny que bloquea todo y permite solo lo que usted especifique.
      • Acceso SSH entrante con límites sobre el número de conexiones simultáneas que puede realizar un host.
      • Políticas de tráfico saliente que le proporciona acceso a algunos servicios críticos de Internet.
      • Las políticas ICMP que proporciona acceso a la utilidad ping y el descubrimiento de ruta MTU.

      Ejecute el siguiente comando pfctl para realizar un simulacro:

      • sudo pfctl -nf /etc/pf.conf

      Se pasan los indicadores -nf que le solicitan a pfctl ejecutar el conjunto de reglas sin cargarlo, lo que generará errores si algo incorrecto.

      Ahora, una vez que no se encuentren errores, cargue el conjunto de reglas:

      • sudo pfctl -f /etc/pf.conf

      Si no hay errores, significa que su conjunto de reglas básico está activo y funciona correctamente. Como antes en el tutorial, realizará algunas pruebas en su conjunto de reglas.

      Primero pruebe la conectividad a Internet y su servicio DNS:

      Verá lo siguiente:

      Output

      PING google.com (172.217.0.46): 56 data bytes 64 bytes from 172.217.0.46: icmp_seq=0 ttl=56 time=2.088 ms 64 bytes from 172.217.0.46: icmp_seq=1 ttl=56 time=1.469 ms 64 bytes from 172.217.0.46: icmp_seq=2 ttl=56 time=1.466 ms --- google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.466/1.674/2.088/0.293 ms

      A continuación, compruebe que puede llegar al repositorio pkgs:

      Una vez más, actualice los paquetes si es necesario.

      Finalmente, reinicie su servidor:

      Dé unos minutos a su servidor para que se reinicie. Completó e implementó su conjunto de reglas básico, lo cual es un paso significativo en términos de su progreso. Ahora estará listo para explorar algunas de las funciones avanzadas de PF. En el siguiente paso impedirá ataques de fuerza bruta.

      Paso 5: Gestionar su tabla de sobrecarga

      Con el tiempo, la tabla de sobrecarga <bruteforce> se llenará de direcciones IP maliciosas deberá limpiarse periódicamente. Es improbable que un atacante siga usando la misma dirección IP, de forma que no merece la pena almacenarlas en la tabla de sobrecarga durante largos periodos de tiempo.

      Usará pfctl para borrar manualmente todas las direcciones IP que hayan sido almacenadas en la tabla de sobrecarga durante 48 horas o más con el siguiente comando:

      • sudo pfctl -t bruteforce -T expire 172800

      Verá un resultado similar a este:

      Output

      0/0 addresses expired.

      Se pasan el indicador -t bruteforce, que significa fuerza bruta para tabla, y el indicador -T, que le permite ejecutar varios comandos integrados. En este caso, ejecuta el comando expire para borrar todas las entradas de -t bruteforce, con un valor de tiempo representado en segundos. Ya que está trabajando en un nuevo servidor, probablemente no haya direcciones IP en la tabla de sobrecarga aún.

      Esta regla funciona para correcciones rápidas, pero una solución más robusta sería automatizar el proceso con el programador de trabajo cron, de FreeBSD. Vamos a crear una secuencia de comandos shell que ejecute esta secuencia de comandos.

      Cree un archivo de secuencia de comandos shell en el directorio /usr/local/bin:

      • sudo vi /usr/local/bin/clear_overload.sh

      Añada el siguiente contenido a su secuencia de comandos shel:

      /usr/local/bin/clear_overload.sh

      #!/bin/sh
      
      pfctl -t bruteforce -T expire 172800
      

      Haga que el archivo sea ejecutable con el siguiente comando:

      • sudo chmod 755 /usr/local/bin/clear_overload.sh

      A continuación, creará un trabajo cron. Hay trabajos que se ejecutarán repetitivamente según el momento que especifique. Se utilizan comúnmente para las copias de seguridad o para cualquier proceso que deba ejecutarse al mismo tiempo cada día. Crea trabajos cron con los archivos crontab. Consulte las páginas principales para obtener más información sobre cron(8) y crontab(5).

      Cree un archivo crontab con usuario root con el siguiente comando:

      Ahora añada el siguiente contenido al archivo crontab:

      crontab

      # minute    hour    mday    month   wday    command
      
        *             0     *       *     *     /usr/local/bin/clear_overload.sh
      

      Guarde el archivo y ciérrelo.

      Nota: Alinee todos los valores con su tabla correspondiente para mayor legibilidad si no se alinean adecuadamente cuando añada contenido.

      Este trabajo cron ejecuta la secuencia de comandos clear_overload.sh cada día a medianoche, eliminando las direcciones UP que tienen una antigüedad de 48 horas de la tabla de sobrecarga <bruteforce>. A continuación, añadirá anclajes a su conjunto de reglas.

      Paso 6: Introducir anclajes a sus conjuntos de reglas

      En este paso, introducirá anclajes, que se usan para aprovisionar reglas al conjunto de reglas principal, ya sea manualmente o desde un archivo de texto externo. Los anclajes pueden contener fragmentos de reglas, tablas e incluso otros anclajes, conocidos como anclajes anidados. Demostraremos la forma en que funcionan los anclajes añadiendo una tabla a un archivo externo y proporcionándolo a su conjunto de reglas. Su tabla incluirá un grupo de hosts internos cuya conexión con el mundo exterior desee impedir.

      Cree un archivo llamado /etc/blocked-hosts-anchor:

      • sudo vi /etc/blocked-hosts-anchor

      Añada el siguiente contenido al archivo:

      /etc/blocked-hosts-anchor

      table <blocked-hosts> { 192.168.47.1 192.168.47.2 192.168.47.3 }
      
      block return out quick on egress from <blocked-hosts>
      

      Guarde el archivo y ciérrelo.

      Estas reglas declaran y definen la tabla <blocked-hosts>, y luego impiden que todas las direcciones IP de la tabla <blocked-hosts> accedan a los servicios del mundo exterior. Utiliza la palabra egress como método preferido para encontrar la ruta predeterminada, o salida a Internet.

      Aún deberá declarar el anclaje en su archivo /etc/pf.conf:

      Ahora, añada las siguientes reglas de anclajes después de la regla block all:

      /etc/pf.conf

      . . .
      block all
      anchor blocked_hosts
      load anchor blocked_hosts from "/etc/blocked-hosts-anchor"
      . . .
      

      Guarde el archivo y ciérrelo.

      Estas reglas declaran los blocked_hosts y cargan las reglas de anclajes en su conjunto de reglas principal desde el archivo /etc/blocked-hosts-anchor.

      Ahora, inicie estos cambios volviendo a cargar su conjunto de reglas con pfctl:

      • sudo pfctl -f /etc/pf.conf

      Si no hay errores, significa que no hay errores en su conjunto de reglas y sus cambios está activos.

      Utilice pfctl para verificar que su anclaje se está ejecutando:

      El indicador -s Anchors significa “mostrar anclajes ”. Verá el siguiente resultado:

      Output

      blocked_hosts

      La utilidad pfctl puede también analizar las reglas específicas de su anclaje con los indicadores -a y -s:

      • sudo pfctl -a blocked_hosts -s rules

      Verá lo siguiente:

      Output

      block return out quick on egress from <blocked-hosts> to any

      Otra función de los anclajes es que permiten añadir reglas bajo demanda sin tener que volver a carga el conjunto de reglas. Esto puede ser útil para realizar pruebas, reparaciones rápidas, emergencias, etc. Por ejemplo, si un host interno está actuando de forma peculiar y desea impedir que realice conexiones salientes, tiene un anclaje puesto que le permite intervenir rápidamente desde la línea de comandos.

      Vamos a abrir /etc/pf.conf y añadir otro anclaje:

      Llamará al delmitador rogue_hosts y lo dispondrá en la regla block all:

      /etc/pf.conf

      . . .
      block all
      anchor rogue_hosts
      . . .
      

      Guarde el archivo y ciérrelo.

      Para iniciar estos cambios, vuelva a cargar el conjunto de reglas con pfctl:

      • sudo pfctl -f /etc/pf.conf

      De nuevo, utilice pfctl para verificar que el anclaje se esté ejecutando:

      Esto generará el siguiente resultado:

      Output

      blocked_hosts rogue_hosts

      Ahora que el anclaje se está ejecutando, podrá añadirle reglas en cualquier momento. Pruebe esto añadiendo la siguiente regla:

      • sudo sh -c 'echo "block return out quick on egress from 192.168.47.4" | pfctl -a rogue_hosts -f -'

      Esto invoca el comando echo y el contenido de su cadena, que luego se canaliza a la utilidad pfctl con el símbolo |, donde se procesa en otra regla de anclaje. Puede abrir otra sesión shell con el comando sh-c. Esto es porque establece un canal entre dos procesos, pero necesita privilegios sudo para que persistan en toda la secuencia de comandos. Existen varias formas de resolver esto; aquí abre un proceso shell adicional con privilegios sudo usando sudo sh -c.

      Ahora, utilice pfctl de nuevo para verificar que estas reglas está activas:

      • sudo pfctl -a rogue_hosts -s rules

      Esto generará el siguiente resultado:

      Output

      block return out quick on egress inet from 192.168.47.4 to any

      El uso de anclajes es completamente circunstancial y a menudo subjetivo. Igual que cualquier otra función, existen pros y contras a la hora de usar los anclajes. Algunas aplicaciones, como blacklistd interactúan con anclajes debido a su diseño. A continuación, centrará la atención en el registro con PF, que es un aspecto crítico de seguridad de la red. Su firewall no es útil si no puede ver lo que hace.

      Paso 7: Registro de la actividad de su firewall

      En este paso, trabajará con el registro de PF, que se gestiona mediante una pseudo interfaz llamada pflog. El registro se habilita en el momento del inicio añadiendo pflog_enabled=YES al archivo /etc/rc.conf, procedimiento que completó en el paso 2. Esto habilita el demonio pflogd que abre una interfaz llamada pflog0 y escribe registros en formato binario en un archivo llamado /var/log/pflog. Los registros pueden analizarse en tiempo real desde la interfaz, o ser leídos desde el archivo /var/log/pflog con la utilidad tcpdump(8).

      Primero acceda a algunos registros desde el archivo /var/log/pflog:

      • sudo tcpdump -ner /var/log/pflog

      Pasa los indicadores -ner que formatean el resultado para mejorar la legibilidad, y también especifica un archivo desde el que leer, que en su caso es /var/log/pflog.

      Verá lo siguiente:

      Output

      reading from file /var/log/pflog, link-type PFLOG (OpenBSD pflog file)

      En estas etapas tempranas es posible que no haya datos en el archivo /var/log/pflog. En poco tiempo, el archivo de registro comenzará a ampliarse.

      También puede ver los registros en tiempo real desde la interfaz pflog0 usando el siguiente comando:

      Pasa los indicadores -nei, que también formatean el resultado para mejorar la legibilidad, pero esta vez especifica una interfaz, que en su caso es pflog0.

      Verá lo siguiente:

      Output

      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on pflog0, link-type PFLOG (OpenBSD pflog file), capture size 262144 bytes

      Ahora verá las conexiones en tiempo real. Si es posible, haga ping a su servidor desde un equipo remoto y verá cómo se producen las conexiones. El servidor permanecerá en este estado hasta que salga de él.

      Para salir de este estado y volver a la línea de comandos, pulse CTRL + Z.

      Hay mucha información en Internet sobre tcpdump(8). También se puede acceder al sitio web oficial.

      Acceder a los archivos de registro desde pftop

      La utilidad pftop es una herramienta que permite ver rápidamente la actividad del firewall en tiempo real. Su nombre se ve influenciado por la conocida utilidad top de Unix.

      Para usarlo, deberá instalar el paquete pftop:

      Ahora ejecute el binario pftop:

      Esto generará el siguiente resultado (sus IP serán diferentes):

      Output

      PR DIR SRC DEST STATE AGE EXP PKTS BYTES tcp In 251.155.237.90:27537 157.225.173.58:22 ESTABLISHED:ESTABLISHED 00:12:35 23:59:55 1890 265K tcp In 222.186.42.15:25884 157.225.173.58:22 TIME_WAIT:TIME_WAIT 00:01:25 00:00:06 22 3801 udp Out 157.245.171.59:4699 67.203.62.5:53 MULTIPLE:SINGLE 00:00:14 00:00:16 2 227

      Crear interfaces de registro adicionales

      Como cualquier otra interfaz, pueden crearse múltiples interfaces de registro y nombrarse con un archivo /etc/hostname. Es posible que encuentre esto útil con fines organizativos, por ejemplo, si desea registrar ciertos tipos de actividad por separado.

      Cree una interfaz de registro adicional llamada pflog1:

      • sudo vi /etc/hostname.pflog1

      Añada el siguiente contenido al archivo /etc/hostname.pflog1:

      /etc/hostname.pflog1

      up
      

      Ahora, habilite el dispositivo en el momento del inicio en su archivo /etc/rc.conf:

      • sudo sysrc pflog1_enable="YES"

      Puede monitorizar y registrar la actividad de su firewall. Esto le permite ver quién establece conexiones con su servidor y los tipos de conexiones establecidas.

      A lo largo de este tutorial, ha incorporado algunos conceptos avanzados a su conjunto de reglas de PF. Solo es necesario implementar las funciones avanzadas a medida que las necesite. Dicho esto, en el siguiente paso volverá al conjunto de reglas básico.

      Paso 8: Restablecer el conjunto de reglas básico

      En esta sección final, restablecerá su conjunto de reglas básico. Este es un paso rápido que le llevará de nuevo a un estado minimalista de la funcionalidad.

      Abra el conjunto de reglas básico con el siguiente comando:

      Elimine el conjunto de reglas actual en su archivo y sustitúyalo con el siguiente conjunto de reglas básico.

      /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach }"
      table <bruteforce> persist
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      antispoof quick for $vtnet0
      block in quick on $vtnet0 from <rfc6890>
      block return out quick on egress to <rfc6890>
      block all
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass inet proto icmp icmp-type $icmp_types
      

      Guarde el archivo y ciérrelo.

      Vuelva a cargar el conjunto de reglas:

      • sudo pfctl -f /etc/pf.conf

      Si no hay errores en el comando, significa que no hay errores en su conjunto de reglas y su firewall está funcionando correctamente.

      También deberá desactivar la interfaz pflog1 que ha creado. Ya que es posible que no sepa si lo necesita aún, puede deshabilitar pflog1 con la utilidad sysrc:

      • sudo sysrc pflog1_enable="NO"

      Ahora, elimine el archivo /etc/hostname.pflog1 del directorio /etc:

      • sudo rm /etc/hostname.pflog1

      Antes de salir, reinicie el servidor una vez más para garantizar que todos sus cambios estén activos y sean persistentes:

      Espere unos minutos antes de iniciar sesión en su servidor.

      Opcionalmente, si desea implementar PF con un servidor web, el siguiente es un conjunto de reglas para este escenario. Este conjunto de reglas es un punto de inicio suficiente para la mayoría de las aplicaciones web.

      Simple Web Server Ruleset

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach }"
      table <bruteforce> persist
      table <webcrawlers> persist
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      antispoof quick for $vtnet0
      block in quick on $vtnet0 from <rfc6890>
      block return out quick on egress to <rfc6890>
      block all
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      pass in on $vtnet0 proto tcp to port { 80 443 } 
          keep state (max-src-conn 45, max-src-conn-rate 9/1, 
              overload <webcrawlers> flush global)
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass inet proto icmp icmp-type $icmp_types
      

      Esto crea una tabla de sobrecarga llamada <webcrawlers>, que tiene una política de sobrecarga más liberal que su puerto SSH según los valores de max-src-conn 45 y max-src-conn-rate. Esto es porque no todas las sobrecargas corresponden a agentes maliciosos. También pueden originarse de netbots no maliciosos, de forma que evite medidas de seguridad excesivas en los puertos 80 y 443. Si decide implementar el conjunto de reglas del servidor web, deberá añadir la tabla <webcrawlers> a /etc/pf.conf y borrar las IP de la tabla periódicamente. Consulte el Paso 5 para hacer esto.

      Conclusión

      A través de este tutorial, configuró PF en FreeBSD 12.1. Ahora dispondrá de un conjunto de reglas básico que puede servir como punto de inicio para todos sus proyectos de FreeBSD. Para obtener más información sobre PF, eche un vistazo a las páginas man de pf.conf(5).

      Visite nuestra página sobre el tema FreeBSD para ver más tutoriales y Preguntas y respuestas.



      Source link

      Настройка Packet Filter (PF) в FreeBSD 12.1


      Автор выбрал COVID-19 Relief Fund для получения пожертвования в рамках программы Write for DOnations.

      Введение

      Брандмауэр, вероятно, является одной из наиболее важных линий защиты от кибератак. Способность настроить брандмауэр с нуля — это очень важный навык, который позволяет администратору получить контроль над своими сетями.

      Packet Filter (PF) — это известный брандмауэр, поддерживаемый в рамках проекта OpenBSD для обеспечения безопасности. Если быть более точным, это инструмент фильтрации пакетов, как видно из названия, который известен простым синтаксисом, удобством для пользователей и обширным функционалом. PF — это по умолчанию хранящий состояние брандмауэр, помещающий информацию о подключениях в таблице состояния, которую можно использовать в аналитических целях. PF — это часть базовой системы FreeBSD, которая поддерживается активным сообществом разработчиков. Хотя между версиями PF во FreeBSD и OpenBSD существуют различия, связанные с разной архитектурой ядра, в целом они используют один синтаксис. В зависимости от сложности общий набор правил можно изменить, чтобы работать с любым дистрибутивом с минимальными усилиями.

      В этом обучающем руководстве мы выполним сборку брандмауэра с нуля на сервере FreeBSD 12.1 с помощью PF. Вы создадите базовый набор правил, который можно использовать в качестве шаблона для будущих проектов. Также вы познакомитесь с рядом продвинутых функций PF, таких как гигиена пакетов, предотвращение атак brute force, мониторинг и логирование, а также рядом сторонних инструментов.

      Предварительные требования

      Перед началом выполнения этого обучающего руководства вам потребуется следующее:

      • Сервер FreeBSD 12.1 с 1 ГБ памяти (ZFS или UFS). Вы можете воспользоваться нашим руководством по началу работы с FreeBSD для настройки вашего сервера согласно предпочитаемой конфигурации.
      • FreeBSD не имеет активированного по умолчанию брандмауэра, кастомизация — это один из важнейших принципов FreeBSD. Таким образом, при первом запуске вашего сервера вам потребуется временная защита, пока будет выполняться настройка PF. Если вы используете DigitalOcean, вы можете активировать облачный брандмауэр сразу после запуска сервера. Инструкции по настройке облачного брандмауэра см. в кратком руководстве по брандмауэру DigitalOcean. Если вы используете услуги другого поставщика облачных решений, воспользуйтесь самым быстрым способом для немедленной защиты перед началом работы. Какой бы метод вы ни выбрали, ваш временный брандмауэр должен разрешать только входящий трафик SSH и может разрешать любой исходящий трафик.

      Шаг 1 — Создание предварительного набора правил

      Начните выполнение данного руководства, создав черновик предварительного набора правил, который обеспечивает базовую защиту и доступ к важнейшим услугам через Интернет. В настоящий момент у вас есть работающий сервер FreeBSD 12.1 с активным облачным брандмауэром.

      Существует два подхода к созданию брандмауэра: отказ по умолчанию и разрешение по умолчанию. При использовании отказа по умолчанию блокируется весь трафик, а пропускается только трафик, указанный в правиле. Подход с разрешением по умолчанию делает противоположное: он пропускает весь трафик, блокируя только то, что указано в правиле. Вы будете использовать подход с отказом по умолчанию.

      Набор правил PF записывается в файл конфигурации /etc/pf.conf, который также является местом его расположения по умолчанию. Вы можете хранить этот файл в другом месте, если это указано в файле конфигурации /etc/rc.conf. В этом руководстве вы будете использовать местоположение по умолчанию.

      Войдите на сервер с пользователем non-root user:

      • ssh freebsd@your_server_ip

      Далее создайте ваш файл /etc/pf.conf:

      Примечание. Если вы захотите посмотреть полный базовый набор правил в любой момент при выполнении руководства, см. примеры в шаге 4 и шаге 8.

      PF фильтрует пакеты в соответствии с тремя основными действиями: block, pass и match. В сочетании с другими опциями они образуют правила. Действие выполняется, когда пакет соответствует критериям, указанным в правиле. Как вы можете ожидать, правила pass и block будут пропускать и блокировать трафик. Правило match выполняет действие с пакетом при обнаружении соответствующих критериев, но не пропускает или блокирует его. Например, оно может выполнять преобразование сетевых адресов (NAT) для соответствующего пакета, не блокируя или пропуская его, пакет останется на месте, пока вы не скажете ему сделать что-то в другом правиле, например, направите его на другой сервер или шлюз.

      Далее добавьте первое правило в ваш файл /etc/pf.conf:

      /etc/pf.conf

      block all
      

      Это правило блокирует все формы трафика в каждом направлении. Поскольку направление на указано, по умолчанию блокируется входящий и исходящий трафик. Данное правило является законным для локальных рабочих станций, которые необходимо изолировать от мира, однако оно во многом не пригодно к использованию на практике и не будет работать на удаленном сервере, поскольку оно запрещает трафик SSH. На деле, если бы вы активировали PF, то могли бы заблокировать для себя доступ к серверу.

      Измените ваш файл /etc/pf.conf, чтобы разрешить трафик SSH в следующих выделенных строках:

      /etc/pf.conf

      block all
      pass in proto tcp to port 22
      

      Примечание. В качестве альтернативы вы можете использовать имя протокола:

      /etc/pf.conf

      block all
      pass in proto tcp to port ssh
      

      Для единообразия мы будем использовать номера портов, если нет веских причин не делать этого. Существует подробный список протоколов и соответствующих номеров портов в файле /etc/services, который мы рекомендуем просмотреть.

      PF выполняет правила последовательно сверху вниз, поэтому ваш текущий набор правил на начальном этапе блокирует весь трафик, но затем пропускает его, если он отвечает критериям на следующей линии, что в данном случае соответствует трафику SSH.

      Теперь вы можете подключиться к серверу через SSH, но вы все равно можете блокировать все формы исходящего трафика. Это проблема, поскольку вы не можете получить доступ к критическим сервисам из Интернета для установки пакетов, обновления настроек времени и т. д.

      Для устранения этой проблемы добавьте следующее выделенное правило в конце файла /etc/pf.conf:

      /etc/pf.conf

      block all
      pass in proto tcp to port { 22 }
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      

      Теперь ваш набор правил разрешает исходящий трафик SSH, DNS, HTTP, NTP и HTTPS, а также блокирует весь входящий трафик (за исключением SSH). Вы размещаете номера портов и протоколы в фигурные скобки, которые образуют список в синтаксисе PF, что позволяет добавлять дополнительные номера портов, если это потребуется. Также вы добавляете разрешающее правило для протокола UDP на портах 53 и 123, поскольку DNS и NTP часто переключаются между протоколами TCP и UDP. Вы почти закончили работу с предварительным набором правил, осталось только добавить несколько правил для получения базового функционала.

      Добавьте в предварительный набор правил следующие выделенные правила:

      Preliminary Ruleset /etc/pf.conf

      set skip on lo0
      block all
      pass in proto tcp to port { 22 }
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass out inet proto icmp icmp-type { echoreq }
      

      Сохраните и закройте файл.

      Вы создали правило set skip для устройства закольцовывания, поскольку ему не требуется фильтр трафика, а такая фильтрация может вызывать заметное замедление работы сервера. Вы добавили правило pass out inet​​​ для протокола ICMP, которое позволяет использовать утилиту ping(8) для поиска и устранения проблем. Опция inet представляет семейство адресов IPv4.

      ICMP — это многоцелевой протокол обмена сообщениями, используемый сетевыми устройствами для различных видов коммуникации. Например, утилита ping использует сообщения, известные как echo request, которые вы добавили в список icmp_type. В качестве меры предосторожности вы разрешаете только типы сообщений, которые вам нужны для предотвращения контакта нежелательных устройств с вашим сервером. По мере роста ваших потребностей вы можете добавить в список новые типы сообщений.

      Теперь у вас есть рабочий набор правил, который обеспечивает базовый функционал для большинства серверов. В следующем разделе мы убедимся, что все работает корректно, активировав PF и протестировав ваш предварительный набор правил.

      Шаг 2 — Тестирование вашего предварительного набора правил

      На этом шаге мы протестируем ваш предварительный набор правил и выполним переход с облачного брандмауэра на ваш брандмауэр PF, позволив PF взять полный контроль над ситуацией. Вы активируете ваш набор правил с помощью утилиты pfctl, которая представляет собой встроенный инструмент командной строки PF и основной метод взаимодействия с PF.

      Наборы правил PF являются простым текстовым файлом, что означает, что при загрузке новых наборов правил не потребуются сложные процедуры. После загрузки нового набора правил старый исчезает. Очень редко, если это вообще возможно, требуется удалить существующий набор правил.

      FreeBSD использует сеть shell-скриптов, известную как система rc, чтобы управлять запуском служб во время загрузки, а мы укажем эти службы в разных файлах конфигурации rc. Для таких глобальных служб, как PF, вы будете использовать файл /etc/rc.conf. Поскольку файлы rc имеют критическое значение для нормальной работы системы FreeBSD, они не должны редактироваться напрямую. Вместо этого FreeBSD предоставляет утилиту командной строки sysrc, которая предназначена для безопасного редактирования этих файлов.

      Давайте активируем PF, используя утилиту командной строки sysrc:

      • sudo sysrc pf_enable="YES"
      • sudo sysrc pflog_enable="YES"

      Проверьте внесение изменений, отобразив содержимое вашего файла /etc/rc.conf:

      Результат будет выглядеть следующим образом:

      Output

      pf_enable="YES" pflog_enable="YES"

      Также вы активируете службу pflog, которая, в свою очередь, активирует демон pflogd для ведения журнала PF. Вы поработаете с журналами позже.

      Вы должны указать две глобальные службы в вашем файле /etc/rc.conf, но они не инициализируются, пока вы не перезагрузите сервер или не запустите их вручную. Перезапустите сервер, чтобы протестировать ваш доступ через SSH.

      Запустите PF, перезапустив сервер:

      Подключение будет сброшено. Подождите несколько минут, пока не закончится процесс обновления.

      Теперь снова подключитесь по SSH к серверу:

      • ssh freebsd@your_server_ip

      Хотя ваши службы PF уже проинициализированы, вы еще не загрузили ваш набор правил /etc/pf.conf, что означает, что ваш брандмауэр еще не активен.

      Загрузите набор правил с помощью pfctl:

      • sudo pfctl -f /etc/pf.conf

      Если ошибки или сообщения отсутствуют, это означает, что ваш набор правил не имеет ошибок, а брандмауэр активен.

      Теперь, когда PF запущен, вы можете отключить ваш сервер от облачного брандмауэра. Это можно сделать в панели управления вашей учетной записи DigitalOcean, удалив дроплет из портала облачного брандмауэра. Если вы используете другого поставщика облачных услуг, убедитесь, что все, что вы использовали для временной защиты, отключено. Запуск двух разных брандмауэров на сервере практически точно вызовет проблемы.

      В дополнение к этому перезагрузите ваш сервер еще раз:

      Через несколько минут подключитесь через SSH к вашему серверу:

      • ssh freebsd@your_server_ip

      Теперь PF — ваш действующий брандмауэр. Чтобы проверить, что он запущен, вы можете попробовать получить доступ к данным с помощью утилиты pfctl.

      Давайте рассмотрим некоторые статистические данные и счетчики с помощью pfctl -si​​​:

      Вы передаете флаги -si, которые означают show info, т. е. показать информацию. Это одна из многочисленных комбинаций параметров фильтра, которую вы можете использовать с pfctl для парсинга данных об активности брандмауэра.

      Вы увидите следующие данные в таблице (значения будут варьироваться в зависимости от сервера):

      Output

      Status: Enabled for 0 days 00:01:53 Debug: Urgent State Table Total Rate current entries 5 searches 144 1.3/s inserts 11 0.1/s removals 6 0.1/s Counters match 23 0.2/s bad-offset 0 0.0/s fragment 0 0.0/s short 0 0.0/s normalize 0 0.0/s memory 0 0.0/s bad-timestamp 0 0.0/s congestion 0 0.0/s ip-option 0 0.0/s proto-cksum 0 0.0/s state-insert 0 0.0/s state-limit 0 0.0/s src-limit 0 0.0/s synproxy 0 0.0/s map-failed 0 0.0/s

      Поскольку вы только что активировали набор правил, вы не увидите большое количество информации. Однако этот вывод показывает, что PF уже записал 23 совпавших правила. Это означает, что критерии набора правил были использованы 23 раза. Вывод также подтверждает, что ваш брандмауэр работает.

      Ваш набор правил также разрешает исходящий трафик для доступа к ряду критически важных сервисов в Интернете, включая утилиту ping.

      Давайте проверим подключение через Интернет и службу DNS с помощью ping для google.com:

      Поскольку вы использовали флаг -c 3 при запуске, вы увидите три успешные попытки подключения:

      Output

      PING google.com (172.217.0.46): 56 data bytes 64 bytes from 172.217.0.46: icmp_seq=0 ttl=56 time=2.088 ms 64 bytes from 172.217.0.46: icmp_seq=1 ttl=56 time=1.469 ms 64 bytes from 172.217.0.46: icmp_seq=2 ttl=56 time=1.466 ms --- google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.466/1.674/2.088/0.293 ms

      Убедитесь, что у вас есть доступ к репозиторию pkgs с помощью следующей команды:

      Если имеются какие-либо обновления для пакетов, выполните обновление.

      Если обе службы работают, это означает, что ваш брандмауэр работает, и вы можете двигаться дальше. Хотя ваш предварительный набор правил обеспечивает защиту и необходимый функционал, это по-прежнему очень простой набор, который может быть улучшен. В остальных разделах мы будем дополнять базовый набор правил и используем некоторые продвинутые функции PF.

      Шаг 3 — Дополнение базового набора правил

      На этом шаге мы разберем наш предварительный набор правил, чтобы дополнить базовый набор правил. Вы измените некоторые правила и поработаете с более продвинутыми понятиями.

      Включение макросов и таблиц

      В предварительном наборе правил вы жестко задали все параметры для каждого правила, в нашем случае это номера портов, которые составляют список. В будущем такая конфигурация может стать неуправляемой, в зависимости от природы ваших сетей. Для большей организованности PF включает макросы, списки и таблицы. Вы уже включили списки прямо в ваши правила, но вы также можете отделить их от правил и назначить переменную с помощью макросов.

      Откройте ваш файл, чтобы передать некоторые параметры в макрос:

      Теперь добавьте в самый верх набора правил следующее содержание:

      /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq }"
      . . .
      

      Измените ваши предыдущие правила SSH и ICMP, указав новые переменные:

      /etc/pf.conf

      . . .
      pass in on $vtnet0 proto tcp to port { 22 }
      . . .
      pass inet proto icmp icmp-type $icmp_types
      . . .
      

      Ваши предыдущие правила SSH и ICMP теперь используют макросы. Имена переменных отображаются с помощью принятого в PF синтаксиса со знаком доллара. Вы назначаете интерфейс vtnet0 для переменной с тем же именем только в качестве формальности, что позволяет переименовать ее в будущем, если возникнет такая потребность. Другие распространенные имена переменных для общедоступных интерфейсов включают $pub_if​​​ или $ext_if.

      Далее вы должны имплементировать таблицу, которая похожа на макрос, но предназначена для хранения групп IP-адресов. Давайте создадим таблицу для немаршрутизуемых IP-адресов, которые часто используются в DoS-атаках. Вы можете использовать IP-адреса, указанные в RFC6890, где определяются реестры IP-адресов особенного назначения. Ваш сервер не должен посылать пакеты на эти адреса или получать пакеты от этих адресов через общедоступные интерфейсы.

      Создайте эту таблицу, добавив следующее содержание сразу после макроса icmp_types:

      /etc/pf.conf

      . . .
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      . . .
      

      Теперь добавьте ваши правила для таблицы <rfc6890> под правилом set skip on lo0:

      /etc/pf.conf

      . . .
      set skip on lo0
      block in quick on egress from <rfc6890>
      block return out quick on egress to <rfc6890>
      . . .
      

      Здесь вы добавляете опцию return, которая дополняет ваше правило block out​​​. Эта команда отклоняет пакеты и отправляет сообщение RST на хост, который попытался установить эти подключения, что полезно для анализа активности хоста. Затем добавьте ключевое слово egress, которое автоматически находит маршруты по умолчанию для любых заданных интерфейсов. Обычно это более простой метод поиска маршрутов по умолчанию, особенно для сложных сетей. Ключевое слово quick выполняет правила немедленно без учета остальной части набора правил. Например, если пакет с нелогичными IP-адресами попытается подключиться к серверу, вы можете захотеть немедленно сбросить соединение, и у вас не будет причин пропускать этот пакет через остальную часть набора правил.

      Защита портов SSH

      Поскольку ваш порт SSH общедоступен, он может стать объектом атаки. Один из самых очевидных признаков нападения — это массовые попытки входа в систему. Например, если один IP-адрес пытается выполнить вход на ваш сервер 10 раз за секунду, вы можете предположить, что это дело рук не человека, а компьютерного программного обеспечения, которое пытается взломать ваш пароль входа в систему. Такие виды систематических эксплойтов часто называют атаками brute force​​​, и обычно они являются успешными, если у сервера слабый пароль.

      Предупреждение. Мы настоятельно рекомендуем использовать аутентификацию по открытому ключу на всех ваших серверах. Ознакомьтесь с руководством DigitalOcean по аутентификации на базе ключей.

      PF имеет встроенные функции для противодействия атакам brute force и другим похожим атакам. С помощью PF вы можете ограничить количество попыток одновременного подключения с одного хоста. Если хост превышает эти ограничения, соединение будет сброшено, а сам хост будет запрещен на сервере. Для этого вы можете использовать механизм устранения перегрузки PF, который поддерживает таблицу запрещенных IP-адресов.

      Измените предыдущее правило SSH, чтобы ограничить количество одновременных подключений с одного хоста, следующим образом:

      /etc/pf.conf

      . . .
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      . . .
      

      Вы добавили опцию keep state, которая позволяет определить критерии состояния для таблицы устранения перегрузки: Вы передаете параметр max-src-conn, чтобы указать разрешенное количество одновременных подключений с одного хоста в секунду, а также параметр max-src-conn-rate, чтобы указать разрешенное количество новых подключений с одного хоста в секунду. Вы указали 15 подключений для max-src-conn и 3 подключения для max-src-conn-rate. Если хост превышает эти ограничения, механизм устранения перегрузки добавляет IP-адрес источника в таблицу <bruteforce>, которая запрещает его использование на сервере. Наконец, опция flush global немедленно сбрасывает подключение.

      Вы определили таблицу устранения перегрузки в вашем правиле SSH, но не объявили саму таблицу в вашем наборе правил.

      Добавьте таблицу <bruteforce> под макросом icmp_types:

      /etc/pf.conf

      . . .
      icmp_types = "{ echoreq }"
      table <bruteforce> persist
      . . .
      

      Ключевое слово persist позволяет создавать пустую таблицу в наборе правил. Без него PF будет жаловаться, что в таблице нет IP-адресов.

      Эти меры гарантируют защиту вашего порта SSH с помощью мощного механизма безопасности. PF позволяет настраивать быстрые решения для защиты от катастрофических форм атак. В следующих разделах мы выполним действия для очистки пакетов, которые поступают на сервер.

      Очистка вашего трафика

      Примечание. В следующих разделах описываются базовые принципы работы протокола TCP/IP. Если вы планируете создавать веб-приложения или работать с сетью, вам будет полезно знать эти вещи. Ознакомьтесь с руководством DigitalOcean Знакомство с сетевой терминологией, интерфейсами и протоколами.

      Из-за сложности протокола TCP/IP, а также действий злоумышленников пакеты часто поступают с отклонениями и неопределенностями, например с наложением фрагментов IP-адресов, поддельными IP-адресами и многим другим. Поэтому необходимо очищать трафик, прежде чем он поступит в систему. Технический термин, используемый для обозначения этого процесса, — нормализация.

      Когда данные передаются через Интернет, они обычно разбиваются на небольшие фрагменты в источнике, чтобы отвечать параметрам передачи целевого хоста, где эти фрагменты пересобираются в полные пакеты. К сожалению, злоумышленники могут взламывать этот процесс большим количеством способов, описание которых выходит за пределы данного руководства. Кроме того, с PF вы можете управлять фрагментацией с помощью одного правила. PF имеет ключевое слово scrub, с помощью которого производится нормализация пакетов.

      Добавьте ключевое слово scrub непосредственно перед правилом block all​​​:

      /etc/pf.conf

      . . .
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      block all
      . . .
      

      Это правило применяется для очищения входящего трафика. Вы добавили опцию fragment reassemble, которая предотвращает попадание фрагментов в систему. Вместо этого они кэшируются в памяти, пока не будут пересобраны в полные пакеты, что означает, что правилам фильтра придется работать только с единообразными пакетами. Также вы должны включить опцию max-mss 1440, которая представляет максимальный размер сегмента пересобираемых пакетов TCP, также известный как полезная нагрузка. Вы указываете значение 1440 байт, которое отражает баланс между размером и производительностью, оставляя достаточное пространство для заголовков.

      Еще один важный аспект фрагментации — это термин, известный как максимальный передаваемый модуль данных (MTU). Протоколы TCP/IP позволяют устройствам обсуждать размеры пакетов для установления подключений. Целевой хост использует сообщения ICMP для информирования IP-адреса источника о своем MTU. Данный процесс известен как открытие пути MTU. Конкретный тип сообщения ICMP — destination unreachable. Вы должны активировать открытие пути MTU, добавив тип сообщения unreach в ваш список icmp_types.

      Вы будете использовать стандартное значение MTU в 1500 байт, которое можно определить с помощью команды ifconfig:

      Вы увидите следующий вывод, который включает ваше текущее значение MTU:

      Output

      vtnet0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=6c07bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,VLAN_HWTSO,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6> . . .

      Обновите список icmp_types, чтобы добавить тип сообщения destination unreachable​​​:

      /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach}"
      . . .
      

      Теперь, когда у вас есть политики для обработки фрагментации, пакеты, которые попадают в вашу систему, будут единообразными и согласованными. Это желательно, поскольку огромное количество устройств обмениваются данными через Интернет.

      Теперь вы можете заняться предотвращением другой опасности, известной как подмена IP (спуфинг). Злоумышленники часто изменяют IP-адрес источника, чтобы могло показаться, что он находится на доверенном узле внутри организации. PF включает директиву antispoofing для обработки подмененных IP-адресов источника. При применении для конкретного интерфейса (интерфейсов) эта директива блокирует весь трафик из сети данного интерфейса (если его источником не является сам интерфейс). Например, если вы примените директиву antispoofing для интерфейса (интерфейсов) с адресом 5.5.5.1/24, весь трафик из сети 5.5.5.0/24 не будет приниматься системой, если только его источником не является этот интерфейс (интерфейсы).

      Добавьте следующее выделенное содержание, чтобы применить antispoofing для интерфейса vtnet0:

      /etc/pf.conf

      . . .
      set skip on lo0
      scrub in
      antispoof quick for $vtnet0
      block all
      . . .
      

      Сохраните и закройте файл.

      Это правило для борьбы с подменой указывает, что весь трафик из сети (сетей) vtnet0 может передаваться только через интерфейс vtnet0, либо он будет немедленно отклонен с помощью ключевого слова quick. Злоумышленники не смогут скрыться в сети vtnet0 и взаимодействовать с другими узлами.

      Для демонстрации вашего правила для борьбы с подменой IP-адресов вы можете вывести ваш набор правил на экран в подробном виде. Правила в PF обычно написаны в сокращенной форме, но также они могут быть написаны в подробной форме. Как правило, не очень удобно писать правила таким образом, но для целей тестирования это может быть полезно.

      Выведите на экран содержимое /etc/pf.conf, используя pfctl со следующей командой:

      • sudo pfctl -nvf /etc/pf.conf

      Эта команда pfctl получает флаги -nvf, выводит набор правил и тестирует его без фактической загрузки данных, что известно как пробный прогон. Теперь вы увидите полное содержимое /etc/pf.conf в подробной форме.

      Вы увидите примерно следующий вывод внутри части для борьбы с подменой IP-адресов:

      Output

      . . . block drop in quick on ! vtnet0 inet from your_server_ip/20 to any block drop in quick on ! vtnet0 inet from network_address/16 to any block drop in quick inet from your_server_ip to any block drop in quick inet from network_address to any block drop in quick on vtnet0 inet6 from your_IPv6_address to any . . .

      Ваше правило показало, что это часть сети your_server_ip/20. Также оно обнаружило, что (в примере для данного обучающего руководства) сервер является частью сети network_address/16 и имеет дополнительный IPv6-адрес. Правило блокирует коммуникации системы со всеми этими сетями, если их трафик не проходит через интерфейс vtnet0.

      Ваше правило для борьбы с подменой IP-адреса является последним добавлением в базовый набор правил. На следующем шаге вы примените эти изменения и выполните ряд тестов.

      Шаг 4 — Тестирование базового набора правил

      На этом шаге вы просмотрите и протестируете базовый набор правил, чтобы убедиться, что все работает корректно. Рекомендуется избегать применения слишком большого количества правил одновременно без тестирования. Рекомендуется начать с основ, постепенно расширяя функционал и выполнять резервное копирование при внесении изменений в конфигурацию.

      Вот как выглядит ваш полный базовый набор правил:

      Base Ruleset /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach }"
      table <bruteforce> persist
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      antispoof quick for $vtnet0
      block in quick on $vtnet0 from <rfc6890>
      block return out quick on egress to <rfc6890>
      block all
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass inet proto icmp icmp-type $icmp_types
      

      Убедитесь, что ваш файл /etc/pf.conf идентичен полному базовому набор правил, прежде чем продолжить. Сохраните и закройте файл.

      Ваш полный базовый набор правил предоставляет вам следующее:

      • Набор макросов, который может определять ключевые службы и устройства.
      • Политика гигиены сети для решения проблем с фрагментацией пакетов и нелогичными IP-адресами.
      • Структура фильтрации default deny​​​, которая блокирует весь трафик и разрешает только то, что вы указываете.
      • Входящий доступ через SSH с ограничением количества одновременных подключений с одного хоста.
      • Политики для исходящего трафика, которые позволяют получить доступ к критически важным сервисам в Интернете.
      • Политики ICMP, которые обеспечивают доступ к утилите ping и открытию пути MTU.

      Запустите следующую команду pfctl для выполнения пробного прогона:

      • sudo pfctl -nf /etc/pf.conf

      Вы передаете флаги -nf, которые указывают pfctl запускать набор правил без загрузки, в результате чего будут брошены ошибки, если что-то пойдет не так.

      Теперь, если ошибки отсутствуют, загрузите набор правил:

      • sudo pfctl -f /etc/pf.conf

      Если ошибок нет, это означает, что ваш базовый набор правил активен и работает корректно. Как и ранее в этом руководстве, вы выполните несколько тестов для вашего набора правил.

      Первый тест — подключение к Интернету и службе DNS:

      Результат будет выглядеть следующим образом:

      Output

      PING google.com (172.217.0.46): 56 data bytes 64 bytes from 172.217.0.46: icmp_seq=0 ttl=56 time=2.088 ms 64 bytes from 172.217.0.46: icmp_seq=1 ttl=56 time=1.469 ms 64 bytes from 172.217.0.46: icmp_seq=2 ttl=56 time=1.466 ms --- google.com ping statistics --- 3 packets transmitted, 3 packets received, 0.0% packet loss round-trip min/avg/max/stddev = 1.466/1.674/2.088/0.293 ms

      Затем проверьте, что вы можете получить доступ к репозиторию pkgs:

      Еще раз обновите пакеты, если это необходимо.

      В заключение перезапустите ваш сервер:

      Подождите несколько минут, пока сервер не перезагрузится. Вы выполнили и имплементировали базовый набор правил, что является важным шагом с точки зрения вашего прогресса. Теперь вы готовы к изучению некоторых продвинутых функций PF. На следующем шаге вы сможете продолжить работу по предотвращению атак brute force.

      Шаг 5 — Управление таблицей устранения перегрузки

      Со временем таблица устранения перегрузки <bruteforce> будет заполнена IP-адресами злоумышленников, и вам придется выполнять ее периодическую очистку. Маловероятно, что злоумышленник будет использовать один и тот же IP-адрес, поэтому нет необходимости хранить эти адреса в таблице в течение длительного времени.

      Вы можете использовать pfctl для ручной очистки IP-адресов, которые хранятся в таблице устранения перегрузки в течение 48 часов и более с помощью следующей команды:

      • sudo pfctl -t bruteforce -T expire 172800

      Вы увидите примерно следующий результат:

      Output

      0/0 addresses expired.

      Вы передаете флаг -t bruteforce, что означает table bruteforce, и флаг -T, который позволяет запускать целый ряд встроенных команд. В этом случае вы должны запустить команду expire, чтобы очистить все записи из -t bruteforce со значением времени, указанным в секундах. Поскольку вы работаете на новом сервере, в таблице, вероятно, не будет IP-адресов.

      Это правило работает для быстрого исправления ситуации, но более надежным решением будет автоматизация процесса с помощью cron, планировщика заданий FreeBSD. Давайте создадим скрипт оболочки, который запускает эту последовательность выполнения команды.

      Создайте файл скрипта оболочки в директории /usr/local/bin:

      • sudo vi /usr/local/bin/clear_overload.sh

      Добавьте в скрипт оболочки следующие строки:

      /usr/local/bin/clear_overload.sh

      #!/bin/sh
      
      pfctl -t bruteforce -T expire 172800
      

      Сделайте файл исполняемым с помощью следующей команды:

      • sudo chmod 755 /usr/local/bin/clear_overload.sh

      Далее вам необходимо создать задание cron. Это задания, которые будут запускаться периодически в соответствии с указанным вами временем. Часто они используются для резервного копирования или любого процесса, который необходимо запускать в одно и то же время каждый день. Создавать задания cron можно с помощью файлов crontab. Дополнительную информацию о cron(8) и crontab(5) см. в Man Pages.

      Создайте файл crontab пользователя root с помощью следующей команды:

      Теперь добавьте в файл crontab следующее содержимое:

      crontab

      # minute    hour    mday    month   wday    command
      
        *             0     *       *     *     /usr/local/bin/clear_overload.sh
      

      Сохраните и закройте файл.

      Примечание. Пожалуйста, сопоставьте каждое значение с соответствующим элементом в таблице для удобства чтения, если содержимое размещается некорректно при добавлении контента.

      Это задание cron запускает скрипт clear_overload.sh каждый день в полночь, удаляя IP-адреса, которые находятся в таблице перегрузки <bruteforce> более 48 часов. Далее вам необходимо добавить якоря в ваш набор правил.

      Шаг 6 — Добавление якорей в ваши наборы правил

      На этом шаге вы должны ввести якоря, которые используются для поиска правил в основном наборе правил, либо вручную, либо из внешнего текстового файла. Якоря могут содержать элементы правил, таблицы и даже другие якоря, которые называются вложенными якорями. Давайте продемонстрируем, как работают якоря, добавив таблицу во внешний файл, а затем выполним ее извлечение в ваш базовый набор правил. Ваша таблица будет включать группу внутренних хостов, для которой вы хотите ограничить подключение к внешнему миру.

      Создайте файл под именем /etc/blocked-hosts-anchor:

      • sudo vi /etc/blocked-hosts-anchor

      Добавьте в файл следующие строчки:

      /etc/blocked-hosts-anchor

      table <blocked-hosts> { 192.168.47.1 192.168.47.2 192.168.47.3 }
      
      block return out quick on egress from <blocked-hosts>
      

      Сохраните и закройте файл.

      Эти правила объявляются и определяются в таблице <blocked-hosts>​​​ и запрещают доступ с любого IP-адреса в таблице <blocked-hosts> к любым сервисам внешнего мира. Вы используете ключевое слово egress в качестве предпочитаемого метода поиска маршрута по умолчанию или выхода наружу, в Интернет.

      Вам все еще необходимо объявить якорь в вашем файле /etc/pf.conf​​​:

      Теперь добавьте следующие правила якоря после правила block all​​:

      /etc/pf.conf

      . . .
      block all
      anchor blocked_hosts
      load anchor blocked_hosts from "/etc/blocked-hosts-anchor"
      . . .
      

      Сохраните и закройте файл.

      Эти правила декларируют blocked_hosts и загружают правила якоря в ваш главный набор правил из файла /etc/blocked-hosts-anchor.

      Теперь примените эти изменения, перезагрузив ваш набор правил с помощью pfctl:

      • sudo pfctl -f /etc/pf.conf

      Если ошибок нет, это означает, что в вашем наборе правил нет ошибок, а изменения активны.

      Используйте pfctl для проверки запуска якоря:

      Флаг -s Anchors означает show anchors. Вывод должен выглядеть так:

      Output

      blocked_hosts

      Утилита pfctl также может парсить конкретные правила вашего якоря с помощью флагов -a и -s:

      • sudo pfctl -a blocked_hosts -s rules

      Результат будет выглядеть следующим образом:

      Output

      block return out quick on egress from <blocked-hosts> to any

      Еще одна функция якорей состоит в том, что они позволяют вам добавить правила по запросу без необходимости перезагрузки набора правил. Это может быть полезно при тестировании, быстрых исправлениях, авариях и т. д. Например, если внутренний хост действует странно, и вы хотите заблокировать для него исходящие подключения, вы можете использовать якорь, который позволяет вам быстро исправить ситуацию из командной строки.

      Давайте откроем /etc/pf.conf и добавим еще один якорь:

      Вы можете назвать якорь rogue_hosts и поместить его в правило block all​​​:

      /etc/pf.conf

      . . .
      block all
      anchor rogue_hosts
      . . .
      

      Сохраните и закройте файл.

      Чтобы применить изменения, перезагрузите набор правил с помощью pfctl:

      • sudo pfctl -f /etc/pf.conf

      Еще раз используйте pfctl для подтверждения запуска якоря:

      Результат будет выглядеть следующим образом:

      Output

      blocked_hosts rogue_hosts

      Теперь, когда якорь запущен, вы можете добавить к нему правила в любое время. Проверьте это, добавив следующее правило:

      • sudo sh -c 'echo "block return out quick on egress from 192.168.47.4" | pfctl -a rogue_hosts -f -'

      Здесь вызывается команда echo и строковое содержимое, которое затем передается в утилиту pfctl с символом |, где оно обрабатывается в правило якоря. Откройте новый сеанс оболочки с помощью команды sh -c. Это связано с тем, что вы создаете связь между двумя процессами, но вам необходимо использовать права sudo для прохождения всей последовательности команд. Существует несколько способов решения этой проблемы, в нашем случае вы откроете дополнительный процесс оболочки с привилегиями sudo, используя для этого команду sudo sh -c.

      Теперь воспользуйтесь pfctl еще раз, чтобы убедиться, что правила активны:

      • sudo pfctl -a rogue_hosts -s rules

      Результат будет выглядеть следующим образом:

      Output

      block return out quick on egress inet from 192.168.47.4 to any

      Использование якорей является ситуационным и субъективным решением. Как и для любых других функций, существуют плюсы и минусы использования якорей. Некоторые приложения, такие как интерфейс blacklistd, изначально имеют якоря. Далее мы рассмотрим подробнее процесс записи журналов в PF, что является критически важным аспектом сетевой безопасности. Ваш брандмауэр будет бесполезен, если вы не можете посмотреть, что он делает.

      Шаг 7 — Запись журнала активности вашего брандмауэра

      На этом шаге мы будем работать с журналом PF, который управляется с помощью псевдоинтерфейса pflog. Функция ведения журнала активируется при загрузке с помощью добавления pflog_enabled=YES в файл /etc/rc.conf, что вы уже сделали на шаге 2. Это позволяет активировать демон pflogd, который генерирует интерфейс под именем pflog0 и записывает журналы в бинарном формате в файл /var/log/pflog. Журналы можно парсить в режиме реального времени из интерфейса или читать из файла /var/log/pflog с помощью утилиты tcpdump(8)​​.

      Вначале получите доступ к журналам из файла /var/log/pflog:

      • sudo tcpdump -ner /var/log/pflog

      Вы передаете флаги -ner, которые форматируют вывод в удобочитаемый вид, а также указываете файл для чтения, в нашем случае это /var/log/pflog.

      Результат будет выглядеть следующим образом:

      Output

      reading from file /var/log/pflog, link-type PFLOG (OpenBSD pflog file)

      На этих ранних этапах в файле /var/log/pflog может не быть данных. В очень короткий срок файл журнала начнет расти в размере.

      Также вы можете просмотреть журналы в реальном времени с помощью интерфейса pflog0, используя следующую команду:

      Вы передаете флаги -nei, которые также форматируют вывод для удобства чтения, но в этот раз указываете интерфейс, в нашем случае это pflog0.

      Результат будет выглядеть следующим образом:

      Output

      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on pflog0, link-type PFLOG (OpenBSD pflog file), capture size 262144 bytes

      Теперь вы увидите подключения в реальном времени. Если это возможно, проверьте пинг сервера с удаленного компьютера, в результате чего вы увидите подключения. Сервер будет находиться в этом состоянии, пока вы не выйдете.

      Чтобы выйти из этого состояния и вернуться в командную строку, нажмите CTRL + Z.

      В Интернете есть огромное количество информации о tcpdump(8), включая официальный сайт.

      Доступ к файлам журнала с помощью pftop

      Утилита pftop — это инструмент для быстрого просмотра активности брандмауэра в реальном времени. Ее имя отсылает к хорошо известной утилите Unix top.

      Для ее использования вам необходимо установить пакет pftop:

      Теперь запустите бинарный файл pftop:

      В результате будет получен следующий вывод (ваши IP-адреса будут отличаться):

      Output

      PR DIR SRC DEST STATE AGE EXP PKTS BYTES tcp In 251.155.237.90:27537 157.225.173.58:22 ESTABLISHED:ESTABLISHED 00:12:35 23:59:55 1890 265K tcp In 222.186.42.15:25884 157.225.173.58:22 TIME_WAIT:TIME_WAIT 00:01:25 00:00:06 22 3801 udp Out 157.245.171.59:4699 67.203.62.5:53 MULTIPLE:SINGLE 00:00:14 00:00:16 2 227

      Создание дополнительных интерфейсов журнала

      Как и для любого другого интерфейса, можно создавать несколько интерфейсов журнала, которые могут перечисляться в файле /etc/hostname. Это может оказаться полезным в целях организации, например, если вы хотите создавать журнал для отдельных типов деятельности.

      Создайте дополнительный интерфейс журнала с именем pflog1:

      • sudo vi /etc/hostname.pflog1

      Добавьте в файл /etc/hostname.pflog1 следующие строки:

      /etc/hostname.pflog1

      up
      

      Теперь активируйте устройство при загрузке в вашем файле /etc/rc.conf​​​:

      • sudo sysrc pflog1_enable="YES"

      Теперь вы можете контролировать и регистрировать активность брандмауэра. Это позволяет посматривать данные о том, кто подключается к серверу и какие типы подключений используются.

      В этом обучающем руководстве вы включили несколько продвинутых понятий в ваш набор правил PF. Это необходимо для включения продвинутых функций, если они вам потребуются. На следующем шаге вы вернетесь к базовому набору правил.

      Шаг 8 — Возврат к вашему базовому набору правил

      В этом последнем разделе вы вернетесь к базовому набору правил. Это быстрый шаг, который позволит вернуться к минимальному набору функций.

      Откройте базовый набор правил с помощью следующей команды:

      Удалите текущий набор правил в вашем файле и замените его на следующий базовый набор правил:

      /etc/pf.conf

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach }"
      table <bruteforce> persist
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      antispoof quick for $vtnet0
      block in quick on $vtnet0 from <rfc6890>
      block return out quick on egress to <rfc6890>
      block all
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass inet proto icmp icmp-type $icmp_types
      

      Сохраните и закройте файл.

      Перезагрузите набор правил:

      • sudo pfctl -f /etc/pf.conf

      Если ошибки при выполнении команды отсутствуют, это значит, что в вашем наборе правил нет ошибок, а ваш брандмауэр работает корректно.

      Также вам необходимо отключить созданный вами интерфейс pflog1. Поскольку вы не знаете, понадобится ли он вам еще, вы можете отключить pflog1 с помощью утилиты sysrc:

      • sudo sysrc pflog1_enable="NO"

      Теперь удалите файл /etc/hostname.pflog1 из директории /etc:

      • sudo rm /etc/hostname.pflog1

      Прежде чем выходить, перезагрузите сервер еще раз, чтобы гарантировать, что все изменения активны и сохраняются:

      Подождите несколько минут, прежде чем выполнять вход на сервер.

      В качестве опции, если вы хотите использовать PF с веб-сервером, ниже представлен следующий набор правил для этого сценария. Этот набор правил является достаточной отправной точкой для большинства веб-приложений.

      Simple Web Server Ruleset

      vtnet0 = "vtnet0"
      icmp_types = "{ echoreq unreach }"
      table <bruteforce> persist
      table <webcrawlers> persist
      table <rfc6890> { 0.0.0.0/8 10.0.0.0/8 100.64.0.0/10 127.0.0.0/8 169.254.0.0/16          
                        172.16.0.0/12 192.0.0.0/24 192.0.0.0/29 192.0.2.0/24 192.88.99.0/24    
                        192.168.0.0/16 198.18.0.0/15 198.51.100.0/24 203.0.113.0/24            
                        240.0.0.0/4 255.255.255.255/32 }
      
      set skip on lo0
      scrub in all fragment reassemble max-mss 1440
      antispoof quick for $vtnet0
      block in quick on $vtnet0 from <rfc6890>
      block return out quick on egress to <rfc6890>
      block all
      pass in on $vtnet0 proto tcp to port { 22 } 
          keep state (max-src-conn 15, max-src-conn-rate 3/1, 
              overload <bruteforce> flush global)
      pass in on $vtnet0 proto tcp to port { 80 443 } 
          keep state (max-src-conn 45, max-src-conn-rate 9/1, 
              overload <webcrawlers> flush global)
      pass out proto { tcp udp } to port { 22 53 80 123 443 }
      pass inet proto icmp icmp-type $icmp_types
      

      В результате создается таблица с именем <webcrawlers>, которая имеет более гибкую политику в отношении перегрузки, чем ваш порт SSH, согласно значениям max-src-conn 45 и max-src-conn-rate. Это связано с тем, что не все перегрузки связаны с действиями злоумышленников. Они также могут быть связаны с активностью незлонамеренных сетевых ботов, поэтому вы можете избежать чрезмерных мер безопасности на портах 80 и 443. Если вы решите использовать набор правил для веб-сервера, вам необходимо добавить таблицу <webcrawlers> в /etc/pf.conf и периодически очищать IP-адреса в таблице. Подробнее см. в шаге 5.

      Заключение

      В этом обучающем руководстве вы настроили PF в FreeBSD 12.1. Теперь у вас есть базовый набор правил, который может служить в качестве отправной точки для всех ваших проектов FreeBSD. Дополнительную информацию о PF можно найти на странице pf.conf(5)​​​ в Man Pages.

      Посетите нашу страницу FreeBSD, чтобы найти дополнительные обучающие руководства и ответы на частые вопросы.



      Source link