Antivirus para Linux

El que utilizo yo, tanto en distribuciones de escritorio como en servidores es ClamAV.

Instalación

Para instalarlo:
apt-get install clamav

Para instalar el actualizador:
apt-get install clamav-freshclam

Actualizar las bases de virus

freshclam
Si recibes un error como este:
ERROR: /var/log/clamav/freshclam.log is locked by another process
ERROR: Problem with internal logger (UpdateLogFile = /var/log/clamav/freshclam.log).

No te preocupes, tendras funcionando freshclam como demonio / servicio, compruebalo:
service clamav-freshclam status

Y recibirás una salida como esta:

clamav-freshclam.service - ClamAV virus database updater
   Loaded: loaded (/lib/systemd/system/clamav-freshclam.service; enabled)
   Active: active (running) since jue 2017-01-12 08:58:33 CET; 3 days ago
     Docs: man:freshclam(1)
           man:freshclam.conf(5)
           http://www.clamav.net/lang/en/doc/
 Main PID: 439 (freshclam)
   CGroup: /system.slice/clamav-freshclam.service
           └─439 /usr/bin/freshclam -d --foreground=true

ene 15 21:25:27 server freshclam[439]: daily.cld is up to date (version: ...)
ene 15 21:25:27 server freshclam[439]: bytecode.cvd is up to date (versio...)
ene 15 22:25:27 server freshclam[439]: Received signal: wake up
ene 15 22:25:27 server freshclam[439]: ClamAV update process started at S...7
ene 15 22:25:27 server freshclam[439]: main.cvd is up to date (version: 5...)
ene 15 22:25:27 server freshclam[439]: Downloading daily-22899.cdiff [100%]
ene 15 22:25:29 server freshclam[439]: daily.cld updated (version: 22899,...)
ene 15 22:25:29 server freshclam[439]: bytecode.cvd is up to date (versio...)
ene 15 22:25:32 server freshclam[439]: Database updated (5580644 signatur...)
ene 15 22:25:32 server freshclam[439]: Clamd successfully notified about ....
Hint: Some lines were ellipsized, use -l to show in full.

O sencillamente así:

[ ok ] freshclam is running.

Escaner bajo demanda

La sintaxis general es esta:
clamscan [options] [file/directory/-]

Y las opciones más interesantes:

stdout: Write all messages (except for lib‐clamav output) to the standard output (stdout).
quiet: Be quiet (only print error messages).
remove[=yes/no(*)]: Remove infected files. Be careful!
move=DIRECTORY: Move infected files into DIRECTORY.
-r, —recursive: Scan directories recursively.
-i, —infected: Only print infected files.

Ejemplo:
sudo clamscan -r /var/www
Con este ejemplo escaneamos recursivamente la carpeta de las webs.

Si queremos algo más elaborado, además de recursivo que solo muestre los infectados, que guarde el log en cierto sitio y que excluya ciertos directorios del escaneo:
clamscan -r --infected --log=/root/clamscan-`date +%d-%m-%y.log` --exclude-dir=^/sys\|^/proc\|^/dev /
Aquí la ruta es ‘/’ es decir pretendemos escanear todo el sistema.

Eliminar virus

Esto conviene hacerlo de forma controlada, la opción es –remove, aunque podría interesar utilizar la opción –move según como queramos reaccionar ante una infección.
clamscan --infected --remove --recursive /

Programación de un cron para escanear el sistema

Lo mejor es olvidarse, y con cierta frecuencia ejecutar el escaner y enviarnos por email el resultado.

Para ello programamos una tarea cron:
crontab -e

Y añadimos una línea que se ejecute los domingos a las 2:00 am:

# m      h    dom           mon  dow                command
# minuto hora 'dia del mes' mes 'dia de la semana'  ...
# Minutos: de 0 a 59.
# Horas: de 0 a 23.
# Día del mes: de 1 a 31.
# Mes: de 1 a 12.
# Día de la semana: de 0 a 6, siendo 0 el domingo.
0 2 * * 0 clamscan -r --infected --exclude-dir=^/sys\|^/proc\|^/dev / | mail -s "Escaner ClamAV" jblancov@gmail.com

De forma que una vez a la semana se ejecute el escáner y nos envíe un reporte a nuestro email.

Que será algo parecido a esto:

----------- SCAN SUMMARY -----------
Known viruses: 5575169
Engine version: 0.99.2
Scanned directories: 20304
Scanned files: 90084
Infected files: 0
Data scanned: 6405.15 MB
Data read: 8352.78 MB (ratio 0.77:1)
Time: 478.312 sec (7 m 58 s)

Espero que os haya sido útil.

Desactivar el fichero wp-cron.php para evitar consumo en el VPS

wordpress

El archivo wp-cron.php cumple con características muy necesarias:

  • Verificación de actualizaciones
  • Pingbacks
  • Publicar artículos programados

Es una función muy útil y que necesitamos en nuestro WordPress, pero tiene su parte negativa:  este script php se ejecuta cada vez que la página recibe un impacto. Lo cual son peticiones a apache innecesarias, por lo que os sugiero una configuración alternativa para el caso de los VPS Linux, teniendo en mente que estas tareas se podrían hacer una sola vez al día, de madrugada por ejemplo.

Cómo desactivar wp-cron.php?

Debemos editar wp-config.php y añadir esta directiva:

define('DISABLE_WP_CRON', true);

Ahora convendría añadir un cron Linux real, para ello vía SSH en el VPS editamos el crontab de root:

crontab -e

Y añadimos en el minuto y hora deseados, o bien a una frecuencia, para que el script /var/www/vhosts/wordpress/wp-cron.php se ejecute 1 vez al día en mi caso a las 2:30am, en lugar de en cada visita:

30 02 * * * php -q /var/www/vhosts/wordpress/wp-cron.php

 

Aquí tienes un pequeño script que ejecutaría todos los cron de todos los WordPress que haya a partir de la carpeta /var/www/webs/:
nano /var/www/webs/cronWP.sh

for i in `find . -iname "wp-cron.php"`
do
	echo "$i"
	php -q $i
done

Y después podemos programar el crontab cada 30 minutos;
crontab -e

*/30 * * * * /var/www/webs/cronWP.sh

Aquí tienes un script que actualiza todas las configuraciones de todos los WordPress que haya por debajo de la carpeta /var/www/webs/ para desactivar crontab:

for i in `find . -iname "wp-cron.php"`
do
  ruta=`dirname $i`
  echo "
/* jblanco: cron */
define('DISABLE_WP_CRON', true);" >> $ruta/wp-config.php
done

Usuario y grupo en WordPress

wordpress

Es posible obtener este error al intentar realizar la actualización (realmente un upgrade, con actualizaciones menores no lo había notado hasta la fecha) automática en WordPress:

Descargando paquete de instalación desde https://downloads.wordpress.org/release/es_ES/wordpress-4.6.zip…

Descomprimiendo actualización…

Verificando los archivos descomprimidos…

No se ha podido descomprimir la actualización.

Instalación fallida

Antes de aventuraros con la actualización manual (tediosa y dado que podéis meter la pata si no hacéis un buen backup), os recomiendo revisar permisos del sistema de ficheros, y si son correctos revisad toda la cadena siguiente:

  • Usuario (Linux/FTP) que gobierna la web / dominio, en este caso basada en el cms WordPress.org, para los ejemplos del articulo usaré “joselito“, este ha de ser el dueño o propietario de toda la carpeta sobre la que descansa el cms, en nuestro artículo será la carpeta “blog/”:
ls -l
total 36
drwxrwxr-x 6 joselito www-data 4096 Aug 22 16:03 blog
  • Los permisos para una carpeta como la que se aprecia arriba, deberían permitir escritura a usuario y a grupo (775 en octal, en cambio para un fichero 664)
  • Grupo del servidor Web en el caso de apache2 basado en sistemas Debian es el usuario / grupo “www-data“, en otros sistemas suele ser www, nobody, …
  • Que el usuario “joselito” tenga como grupo primario o secundario “www-data”. La pertenencia a grupos se puede comprobar con el comando id de Linux. Si estáis logados como el usuario en cuestión sin parámetros, y la salida que produce es como esta:
id
uid=2003(webmaster) gid=2003(webmaster) grupos=2003(webmaster),33(www-data)
  • Si queréis interrogar la pertenencia a grupos de otro usuario, siempre que tengáis permiso para ello:
id webmaster
uid=2003(webmaster) gid=2003(webmaster) grupos=2003(webmaster),33(www-data)
  • No es nada recomendable que la carpeta que aloja la web pertenezca al usuario/grupo del servidor web, funcionaría pero es una brecha de seguridad.
  • El grupo “www-data” ha de ser el grupo de toda la carpeta sobre la que descansa el cms:
  • ls -l
    total 36
    drwxrwxr-x 6 joselito www-data 4096 Aug 22 16:03 blog

Si tenemos mal configurado el usuario que maneja la instalación de wordpress, o bien el grupo, mediante el comando chown, podemos cambiar el propietario y el grupo de forma recursiva:

chown -R joselito:www-data blog

Repito: Se recomienda por seguridad que el propietario (owner) de la carpeta no sea el demonio sobre el que corre apache2, en nuestros ejemplos www-data.

Por lo que el propietario debería ser un usuario al uso, del sistema Linux, en nuestros ejemplos “joselito” y además este usuario debe pertenecer al grupo sobre el que corre el servidor web.

En uno de los VPS que administro di de alta el usuario de forma demasiado manual e hice que su grupo primario fuese www-data directamente (mediante la orden useradd), y ayer tras este error me di cuenta de que en el fichero /etc/group, a la altura de www-data no había ningún usuario:

cat /etc/group|grep ^www
www-data:x:33:

En otros servidores este mismo comando:

cat /etc/group|grep ^www
www-data:x:33:webmaster[, ...]

Con el comando usermod, y las opciones -aG podemos agregar cierto usuario a un grupo:

usermod -aG www-data joselito

Estoy agregando el usuario “joselito” al grupo apache2 “www-data”

Si volvemos a hacer el cat sobre el fichero de grupos filtrando el del servidor web obtenemos que nuestro usuario ya pertenece al mismo:

cat /etc/group|grep ^www
www-data:x:33:joselito

Si intentamos actualizar wordpress de nuevo debería poder hacerlo sin problemas. En ocasiones hace falta cerrar la sesión (de joselito) para forzar la lectura del archivo de grupos Linux. Mediante el comando id podemos saber a qué grupo/s pertenecemos o pertenece un usuario:

id
uid=2003(joselito) gid=33(www-data) groups=33(www-data)

Si por alguna de aquellas todavía no funciona la actualización, es posible que en algún rincón haya algún archivo que si no pertenece a “www-data” no pueda sobreescribirse.

En estas situaciones, sobre todo si se trata de upgrade (4.5.3 a 4.6)  y no de update (4.5.2 a 4.5.3), la solución temporal pasa por hacer propietario a “www-data” de toda la estructura y después volver a hacer propietario al usuario FTP / Linux, en el caso que nos ocupa “joselito”:

chown -R www-data blog/

Con la opción -R de chmod lo estamos aplicando recursivamente a la carpeta blog y todas las subcarpetas/archivos.

Y después, tras poder actualizar recordad, de nuevo por seguridad, volver a restablecer como propietario al usuario “joselito” con el que conectamos vía FTP, o SSH, o usuario Linux asociado al dominio en cuestión:

chown -R joselito blog/

Hasta la próxima.

find: `/var/lib/amavis/virusmails/’: No such file or directory

find: `/var/lib/amavis/virusmails/': No such file or directory

Los que usáis la solución http://www.iredmail.org/ como servidor de correo es posible que en alguna ocasión recibáis por correo una alerta como la del título de esta entrada.

Existe un crontab para el usuario amavis que elimina periódicamente los virus encontrados en el correo electrónico, para ello trabaja con la carpeta /var/lib/amavis/virusmails donde va dejando los rastros encontrados.

# Delete virus mails which created 15 days ago.
1 5 * * * find /var/lib/amavis/virusmails/ -ctime +15 | xargs rm -rf {}

Se puede editar con la orden siguiente:

crontab -e -u amavis

Si no se reciben virus en 15 días se borrará el directorio virusmails, y con el próximo virus como mucho se irán concatenando los mismos en un fichero llamado igual, con lo que la orden find (que espera sea una carpeta) dejará de funcionar y recibiremos el mencionado error:

find: `/var/lib/amavis/virusmails/’: No such file or directory

La solución pasa por cambiar justo antes de la búsqueda, la fecha de modificación de la mencionada carpeta: un simple touch delante del find, que se ejecute justo antes de la limpieza, así como y usar -mtime en lugar de -ctime. El crontab del usuario ‘amavis’ debería quedar así:

# Delete virus mails which created 15 days ago.
1 5 * * * touch /var/lib/amavis/virusmails; find /var/lib/amavis/virusmails/ -mtime +15 | xargs rm -rf {}

Si seguís recibiendo el Warning

Debe ser porque la carpeta ya no existe, basta recrearla mediante un mkdir, pero dejando los permisos correctos de usuario y grupo ‘amavis‘, tal y como aparece en la salida de este comando ls:

ls -ld /var/lib/amavis/virusmails
drwxr-x--- 2 amavis amavis 4096 sep 6 2014 /var/lib/amavis/virusmails

Para ello tenemos varias alternativas, os dejo dos:

  1. Ubicaros en la carpeta anterior /var/lib/amavis/, y crear el directorio virusmails habiendo suplantado mediante el comando su al usuario ‘amavis‘ (lo podéis hacer si sois root)
cd /var/lib/amavis/

su amavis

mkdir virusmails

2. Cread la carpeta y después mediante chown cambiad tanto usuario propietario como pertenencia a grupo de la misma:

cd /var/lib/amavis/

mkdir virusmails

chown amavis:amavis virusmails

Sólo por si os apetece probar una tercera alternativa, podríamos en lugar de touch, probar a recrear en el crontab la carpeta, y redireccionar el posible error si existe a /dev/null. Por lo que un crontab alternativo (que no he probado) seria este:

# Delete virus mails which created 15 days ago.
1 5 * * * mkdir /var/lib/amavis/virusmails 2> /dev/null; find /var/lib/amavis/virusmails/ -mtime +15 | xargs rm -rf {}

De esta forma, y hablando “teóricamente” crearía si no existe todavía la carpeta y después realizaría la búsqueda, en caso de que exista desbiaría cualquier salida de error 2> a /dev/null, de nuevo teóricamente no sería necesario ya que crontab se ejecuta desatendido, aunque y por tercera vez de forma teórica, posiblemente recibamos un mensaje de error al email diciendo algo así como: “la carpeta ya existe”.

Hasta la próxima