Combo PSAD + fwsnort para iptables

por | noviembre 25, 2017

Habiendo visto ya la manera de bloquear una IP o grupos de IPs, vamos a revisar dos herramientas que son de gran utilidad como complemento a iptables:

  • Utilizaremos PSAD (Port Scan Attack Detector) para parsear logs de iptables, detectar y opcionalmente bloquear IPs infractoras. Si conocéis fail2ban el mecanismo es prácticamente el mismo, pero esta vez aplicado al servicio de iptables.

  • Por otro lado, fwsnort podemos considerarlo un complemento a nuestra configuración de iptables. Su función es generar reglas para bloquear tráfico traduciendo reglas del conocido IDS Snort.

Para el artículo me baso en Debian Stretch, por lo que también aplica a cualquier derivada.

PSAD: Instalación y configuración

PSAD se encuentra en repositorios por lo que instalaremos con apt-get o apt:

[root@jota-pc ~]# apt-get install psad
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  libnotmuch4
Use 'apt autoremove' to remove it.
The following additional packages will be installed:
  libbit-vector-perl libcarp-clan-perl libdate-calc-perl libdate-calc-xs-perl libiptables-chainmgr-perl libiptables-parse-perl libnetaddr-ip-perl libunix-syslog-perl
Suggested packages:
  fwsnort
The following NEW packages will be installed:
  libbit-vector-perl libcarp-clan-perl libdate-calc-perl libdate-calc-xs-perl libiptables-chainmgr-perl libiptables-parse-perl libnetaddr-ip-perl libunix-syslog-perl psad
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 754 kB of archives.
After this operation, 2,584 kB of additional disk space will be used.
Do you want to continue? [Y/n]

Una vez instalado, el servicio podemos gestionarlo con systemctl, por ejemplo para reiniciar:

systemctl restart psad.service

El fichero de configuración es /etc/psad/psad.conf.

PSAD parsea por defecto /var/log/messages o journalct en caso de utilizar systemd. Precisamente para que PSAD pueda parsear los mensajes de log, primero hay que activar el logging en iptables. Una de las múltiples maneras es añadir la cadena LOGGING al final del resto de reglas que tengamos, tal y como está en el siguiente script.

# Logging
iptables -N LOGGING
iptables -A INPUT -j LOGGING
iptables -A OUTPUT -j LOGGING
iptables -A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
iptables -A LOGGING -j DROP

Unas de las primeras variables a cambiar son EMAIL_ADDRESSES y HOSTNAME. Los avisos de PSAD se envian a la dirección de mail especificada.

### Supports multiple email addresses (as a comma separated
### list).
EMAIL_ADDRESSES             root@localhost;                        

### Machine hostname
HOSTNAME                    _CHANGEME_;

Por defecto PSAD mandará un correo siempre que detecte un bloqueo del firewall, pero podemos modificarlo para que o bien no los mande o sólo a partir de un determinado threshold para no recibir demasiados avisos.

### Allow reporting methods to be enabled/restricted.  This keyword can
### accept values of "nosyslog" (don't write any messages to syslog),
### "noemail" (don't send any email messages), or "ALL" (to generate both       
### syslog and email messages).  "ALL" is the default.  Both "nosyslog"
### and "noemail" can be combined with a comma to disable all logging
### and alerting.
#ALERTING_METHODS            ALL;
ALERTING_METHODS             noemail;

...

### Minimum danger level a scan must reach before any logging or
### alerting is done.  The EMAIL_ALERT_DANGER_LEVEL variable below              
### only refers to email alerts; the MIN_DANGER_LEVEL variable
### applies to everything from email alerts to whether or not the
### IP directory is created within /var/log/psad/.  Hence
### MIN_DANGER_LEVEL should be set less than or equal to the value
### assigned to the EMAIL_ALERT_DANGER_LEVEL variable.
MIN_DANGER_LEVEL            1;

### Only send email alert if danger level >= to this value.
EMAIL_ALERT_DANGER_LEVEL    1;

Si todo funciona bien, podemos ver entradas en /var/log/messages tipo «psad: scan detected». Como prueba de concepto:

...
Nov 25 13:53:33 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 13:55:41 jota-pc psad: scan detected ( -sU scan): 0.0.0.0 -> 255.255.255.255 udp: [67] udp pkts: 1 DL: 2
Nov 25 13:55:41 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 13:57:47 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 13:59:49 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 14:01:56 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 14:03:42 jota-pc psad: scan detected 192.168.1.39 -> 224.0.0.22 DL: 1
Nov 25 14:03:48 jota-pc psad: scan detected 192.168.1.39 -> 224.0.0.22 DL: 1
Nov 25 14:04:59 jota-pc psad: scan detected ( -sU scan): 0.0.0.0 -> 255.255.255.255 udp: [67] udp pkts: 3 DL: 2
Nov 25 14:06:06 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 14:06:11 jota-pc psad: scan detected ( -sU scan): 192.168.1.39 -> 255.255.255.255 udp: [27036] udp pkts: 1 DL: 1
Nov 25 14:06:17 jota-pc psad: scan detected ( -sU scan): 192.168.1.39 -> 255.255.255.255 udp: [27036] udp pkts: 1 DL: 1
Nov 25 14:08:12 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
Nov 25 14:10:19 jota-pc psad: scan detected 0.0.0.0 -> 224.0.0.1 DL: 2
...

Con psad -S podemos comprobar las estadísticas:

[root@jota-pc ~]# psad -S
[-] psad: pid file /var/run/psad/psadwatchd.pid does not exist for psadwatchd on jota-pc
[+] psad_fw_read (pid: 1029)  %CPU: 0.0  %MEM: 0.1
    Running since: Sat Nov 25 09:53:47 2017

[+] psad (pid: 1028)  %CPU: 0.0  %MEM: 0.2
    Running since: Sat Nov 25 09:53:47 2017
    Command line arguments: [none specified]
    Alert email address(es): root@localhost

[+] Version: psad v2.4.3

[+] Top 50 signature matches:
        [NONE]

[+] Top 25 attackers:
      0.0.0.0         DL: 3, Packets: 259, Sig count: 0
      192.168.1.39    DL: 1, Packets: 36, Sig count: 0

[+] Top 20 scanned ports:
      tcp 8443  11 packets
      tcp 993   7 packets

      udp 67    34 packets
      udp 1124  4 packets
      udp 3289  4 packets
      udp 5353  3 packets
      udp 27036 3 packets

[+] iptables log prefix counters:
      "IPTables-Dropped:": 364

    Total protocol packet counters:
         tcp: 18 pkts
         udp: 48 pkts
...

¿Bloquear IPs infractoras?

PSAD puede generar dinámicamente reglas de bloqueo en nuestro firewall. Sin embargo, esta opción está desactivada por defecto para evitar bloqueos (incluso autobloqueos) inesperados si no se ha configurado cuidadosamente el comportamiento de la herramienta. Por ello siempre es recomendable tenerla corriendo un tiempo, observar patrones, qué IPs detecta, etc… y si estamos seguros de que no vamos a generar un problema adicional entonces activar esta opción.

Debemos tener tres variables en cuenta:

  • ENABLE_AUTO_IDS controla si PSAD puede generar dinámicamente reglas iptables de bloqueo en nuestro firewall.
  • AUTO_IDS_DANGER_LEVEL controla a partir de qué nivel de peligro se genera una regla de bloqueo.
  • AUTO_BLOCK_TIMEOUT especifica el tiempo de bloqueo en segundos.

De esta manera, para activar el bloqueo:

  1. Ponemos ENABLE_AUTO_IDS en Y.
  2. Ajustamos AUTO_IDS_DANGER_LEVEL al valor deseado.
  3. Ajustamos AUTO_BLOCK_TIMEOUT también al tiempo deseado.

Ejemplo:

### If "Y", enable automated IDS response (auto manages
### firewall rulesets).
ENABLE_AUTO_IDS             Y;                                                                                                                                                                                     

### Block all traffic from offending IP if danger
### level >= to this value
AUTO_IDS_DANGER_LEVEL       5;

### Set the auto-blocked timeout in seconds (the default is one hour).
### A value of 0 means block forever.
AUTO_BLOCK_TIMEOUT          3600;

¿Cómo se determina un nivel de peligro (Danger Level)? Básicamente según el nº de paquetes infractores detectados:

### Danger levels.  These represent the total number of
### packets required for a scan to reach each danger level.
### A scan may also reach a danger level if the scan trips                                                                                                                                                         
### a signature or if the scanning ip is listed in
### auto_ips so a danger level is automatically
### assigned.
DANGER_LEVEL1               5;    ### Number of packets.
DANGER_LEVEL2               15;
DANGER_LEVEL3               150;
DANGER_LEVEL4               1500;
DANGER_LEVEL5               10000;

A más nivel de peligro (Danger Level) se pueden aplicar distintos tiempos de bloqueo. Por defecto para los niveles inferiores a 5 se aplica AUTO_BLOCK_TIMEOUT y sólo se bloquea permanentemente el nivel más alto de ataque que podemos recibir (DANGER_LEVEL5):

### Set the auto-blocked timeout in seconds for each danger
### level - zero means to block permanently.  Each of these
### can be set independently
AUTO_BLOCK_DL1_TIMEOUT      $AUTO_BLOCK_TIMEOUT;
AUTO_BLOCK_DL2_TIMEOUT      $AUTO_BLOCK_TIMEOUT;
AUTO_BLOCK_DL3_TIMEOUT      $AUTO_BLOCK_TIMEOUT;
AUTO_BLOCK_DL4_TIMEOUT      $AUTO_BLOCK_TIMEOUT;
AUTO_BLOCK_DL5_TIMEOUT      0;   ### permanent

Fwsnort: de snort a iptables

Por otro lado fwsnort se encarga de generar reglas de iptables a partir de las de Snort.

Instalamos con:

[root@jota-pc sysstat]# apt install fwsnort
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following package was automatically installed and is no longer required:
  libnotmuch4
Use 'apt autoremove' to remove it.
The following additional packages will be installed:
  libnet-rawip-perl oinkmaster snort-rules-default
Suggested packages:
  snort | snort-pgsql | snort-mysql
The following NEW packages will be installed:
  fwsnort libnet-rawip-perl oinkmaster snort-rules-default
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 551 kB of archives.
After this operation, 2,574 kB of additional disk space will be used.
Do you want to continue? [Y/n] 

Te habrás dado cuenta de que se ha instalado el paquete snort-rules-default, que contiene las reglas de Snort que vamos a utilizar con fwsnort.

Copiamos las reglas de snort que se han instalado en /etc/snort/rules/ al directorio /etc/fwsnort/snort_rules/

[root@jota-pc iptables]# cp /etc/snort/rules/* /etc/fwsnort/snort_rules/

Después ejecutamos fwsnort para parsear las reglas (es normal que no llegue a parsear el 100% de reglas):

[root@jota-pc ~]# fwsnort 
[+] Testing /sbin/iptables for supported capabilities...
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
    Snort Rules File          Success   Fail      Total     

[+] attack-responses.rules    16        1         17        
[+] backdoor.rules            65        11        76        
[+] bad-traffic.rules         9         3         12        
[+] chat.rules                28        2         30        
[+] community-bot.rules       1         44        45        
[+] community-dos.rules       5         1         6         
[+] community-exploit.rules   4         1         5         
[+] community-ftp.rules       0         0         0         
[+] community-game.rules      4         1         5         
[+] community-icmp.rules      1         1         2         
[+] community-imap.rules      1         7         8         
[+] community-inappropriate.rules2         1         3         
[+] community-mail-client.rules0         0         0         
[+] community-misc.rules      20        4         24        
[+] community-nntp.rules      0         1         1         
[+] community-oracle.rules    0         1         1         
[+] community-policy.rules    3         1         4         
[+] community-sip.rules       0         0         0         
[+] community-smtp.rules      2         4         6         
[+] community-sql-injection.rules4         5         9         
[+] community-virus.rules     1         9         10        
[+] community-web-attacks.rules1         4         5         
[+] community-web-cgi.rules   5         8         13        
[+] community-web-client.rules3         5         8         
[+] community-web-dos.rules   0         0         0         
[+] community-web-iis.rules   1         3         4         
...
                              =============================
                              1791      1886      3677      

[+] Generated iptables rules for 1791 out of 3677 signatures: 48.71%

[+] Logfile: /var/log/fwsnort/fwsnort.log
[+] iptables script (individual commands): /var/lib/fwsnort/fwsnort_iptcmds.sh


    Main fwsnort iptables-save file: /var/lib/fwsnort/fwsnort.save

    You can instantiate the fwsnort policy with the following command:

    /sbin/iptables-restore < /var/lib/fwsnort/fwsnort.save

    Or just execute: /var/lib/fwsnort/fwsnort.sh

Las reglas generadas se guardan en /var/lib/fwsnort/fwsnort.save. Como vemos, podemos cargarlas bien con iptables-restore o lanzando el script fwsnort.sh

La combinación PSAD + fwsnort está más clara ahora: cargando las reglas generadas por fwsnort en iptables, el tráfico bloqueado dejará su correspondiente marca en los logs. PSAD posteriormente parseará dichos logs, detectando (y bloqueando si lo hemos configurado) las IPs infractoras.

Tenéis en GitHub los respositorios del proyecto fwsnort y PSAD.