Fiesta de procesos zombies en el sistema

por | noviembre 2, 2017

Revisando mi dashboard de sistema de Grafana me llevé recientemente una sorpresa:

Parece que alguien organizó una fiesta de Halloween estos días y empezó a dejar procesos zombies por todo mi sistema. Procedo a buscarlos con ps aux | grep 'Z'

[root@jota-pc ~]# ps aux | grep 'Z'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      2741  0.0  0.0      0     0 ?        Z    07:00   0:00 [sh] <defunct>
root      3778  0.0  0.0      0     0 ?        Z    07:01   0:00 [sh] <defunct>
root      3801  0.0  0.0      0     0 ?        Z    07:02   0:00 [sh] <defunct>
root      3822  0.0  0.0      0     0 ?        Z    07:03   0:00 [sh] <defunct>
root      3841  0.0  0.0      0     0 ?        Z    07:05   0:00 [sh] <defunct>
root      3850  0.0  0.0      0     0 ?        Z    07:06   0:00 [sh] <defunct>
root      3868  0.0  0.0      0     0 ?        Z    07:07   0:00 [sh] <defunct>
root      3880  0.0  0.0      0     0 ?        Z    07:08   0:00 [sh] <defunct>
root      3890  0.0  0.0      0     0 ?        Z    07:09   0:00 [sh] <defunct>
root      3982  0.0  0.0      0     0 ?        Z    07:10   0:00 [sh] <defunct>
root      3988  0.0  0.0      0     0 ?        Z    07:11   0:00 [sh] <defunct>
root      4014  0.0  0.0      0     0 ?        Z    07:12   0:00 [sh] <defunct>
root      4031  0.0  0.0      0     0 ?        Z    07:13   0:00 [sh] <defunct>
root      4040  0.0  0.0      0     0 ?        Z    07:14   0:00 [sh] <defunct>
root      4409  0.0  0.0      0     0 ?        Z    07:15   0:00 [sh] <defunct>
root      4546  0.0  0.0      0     0 ?        Z    07:16   0:00 [sh] <defunct>
root      4600  0.0  0.0      0     0 ?        Z    07:17   0:00 [sh] <defunct>
root      4641  0.0  0.0      0     0 ?        Z    07:18   0:00 [sh] <defunct>
root      4720  0.0  0.0      0     0 ?        Z    07:19   0:00 [sh] <defunct>
root      4862  0.0  0.0      0     0 ?        Z    07:20   0:00 [sh] <defunct>
root      4990  0.0  0.0      0     0 ?        Z    07:21   0:00 [sh] <defunct>
root      5051  0.0  0.0      0     0 ?        Z    07:22   0:00 [sh] <defunct>
...
root     22716  0.0  0.0      0     0 ?        Z    16:43   0:00 [sh] <defunct>
root     22748  0.0  0.0      0     0 ?        Z    16:44   0:00 [sh] <defunct>
root     22771  0.0  0.0      0     0 ?        Z    16:45   0:00 [sh] <defunct>
root     22790  0.0  0.0      0     0 ?        Z    16:46   0:00 [sh] <defunct>
root     22831  0.0  0.0      0     0 ?        Z    16:47   0:00 [sh] <defunct>
root     22855  0.0  0.0      0     0 ?        Z    16:48   0:00 [sh] <defunct>
root     22889  0.0  0.0      0     0 ?        Z    16:49   0:00 [sh] <defunct>
root     22953  0.0  0.0      0     0 ?        Z    16:50   0:00 [sh] <defunct>
root     23259  0.0  0.0      0     0 ?        Z    16:51   0:00 [sh] <defunct>
root     23563  0.0  0.0      0     0 ?        Z    16:52   0:00 [sh] <defunct>
root     23613  0.0  0.0      0     0 ?        Z    16:53   0:00 [sh] <defunct>
root     23693  0.0  0.0      0     0 ?        Z    16:54   0:00 [sh] <defunct>
root     23769  0.0  0.0      0     0 ?        Z    16:55   0:00 [sh] <defunct>
root     23909  0.0  0.0      0     0 ?        Z    16:56   0:00 [sh] <defunct>
...

Preguntando, acabo dando con el padre de todos esos monstruos. Resulta ser el PID 995, del programa PSAD (Port Scan Attack Detection) que se merece un artículo aparte. Aclarar desde el principio que el caustante del problema no es el programa en sí como veremos más adelante.

[root@jota-pc ~]# ps -ef | grep 23909
root     23909   995  0 16:56 ?        00:00:00 [sh] <defunct>
root     24060 22992  0 16:58 pts/0    00:00:00 grep --color=auto 23909
[root@jota-pc ~]# ps -ef | grep 995
root       995     1  0 06:59 ?        00:00:03 /usr/bin/perl -w /usr/sbin/psad
root      1002   995  0 06:59 ?        00:00:00 /usr/bin/perl -w /usr/sbin/psad
root      1995     2  0 07:00 ?        00:00:00 [scsi_tmf_8]
root      2741   995  0 07:00 ?        00:00:00 [sh] <defunct>
root      3778   995  0 07:01 ?        00:00:00 [sh] <defunct>
root      3801   995  0 07:02 ?        00:00:00 [sh] <defunct>
root      3822   995  0 07:03 ?        00:00:00 [sh] <defunct>
root      3841   995  0 07:05 ?        00:00:00 [sh] <defunct>
root      3850   995  0 07:06 ?        00:00:00 [sh] <defunct>
root      3868   995  0 07:07 ?        00:00:00 [sh] <defunct>
root      3880   995  0 07:08 ?        00:00:00 [sh] <defunct>
root      3890   995  0 07:09 ?        00:00:00 [sh] <defunct>
root      3982   995  0 07:10 ?        00:00:00 [sh] <defunct>
root      3988   995  0 07:11 ?        00:00:00 [sh] <defunct>
root      4014   995  0 07:12 ?        00:00:00 [sh] <defunct>
root      4031   995  0 07:13 ?        00:00:00 [sh] <defunct>
root      4040   995  0 07:14 ?        00:00:00 [sh] <defunct>
root      4409   995  0 07:15 ?        00:00:00 [sh] <defunct>
...

Lanzo dmesg -Tw me encuentro con una gran cantidad de bloqueos de iptables de tráfico saliente al puerto de destino (DPT) 43. Este puerto se utiliza para realizar consultas whois. Omito IP de origen y destino en la muestra por privacidad:

...
... LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=18576 DF PROTO=TCP SPT=40224 DPT=43 WINDOW=29200 RES=0x00 SYN URGP=0 UID=0 GID=0 
... LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=51708 DF PROTO=TCP SPT=40240 DPT=43 WINDOW=29200 RES=0x00 SYN URGP=0 UID=0 GID=0 
... LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=18878 DF PROTO=TCP SPT=58110 DPT=43 WINDOW=29200 RES=0x00 SYN URGP=0 UID=0 GID=0 
... LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=40251 DF PROTO=TCP SPT=40354 DPT=43 WINDOW=29200 RES=0x00 SYN URGP=0 UID=0 GID=0 
... LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=60852 DF PROTO=TCP SPT=58160 DPT=43 WINDOW=29200 RES=0x00 SYN URGP=0 UID=0 GID=0 
... LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=54542 DF PROTO=TCP SPT=40414 DPT=43 WINDOW=29200 RES=0x00 SYN URGP=0 UID=0 GID=0 
...

Tiene sentido, pues PSAD realiza por defecto una consulta whois cuando detecta una IP que es bloqueada por iptables. Esto se controla en la variable ENABLE_WHOIS_LOOKUPS en /etc/psad/psad.conf

### By default, enable whois lookups against scanning IP addresses.                                                                                                                                                
ENABLE_WHOIS_LOOKUPS        Y;

El problema es que mis propias reglas de iptables bloquean esta consulta whois, lo que provoca el comportamiento anteriormente comentado. Podría habilitar el tráfico saliente al puerto 43, pero no lo necesito. Cambio por tanto la variable a:

ENABLE_WHOIS_LOOKUPS        N;

Reinicio el servicio, lo cual automáticamente mata el proceso padre con PID 995:

systemctl restart psad.service

Comprobamos entonces que no queden procesos zombies como al principio con ps aux | grep 'Z'.

El caso descrito es uno más de los muchos que pueden acabar provocando una horda de procesos zombies que acaben comprometiendo la estabilidad del sistema. Haciendo un kill del proceso padre podremos eliminar todos los procesos zombies que se han ido generando, pero no soluciona el problema de fondo. Tendremos que ir a la causa raíz para que no se reproduzca de nuevo el problema en nuestro sistema.