La pregunta rara vez surge de la nada. El servidor se ha vuelto más lento, el proveedor ha escrito sobre tráfico saliente, o en el correo hay un aviso de acceso que usted no realizó. Después empieza lo más desagradable: no está claro qué mirar ni en qué orden, y el primer impulso —borrarlo todo e instalar de nuevo— resulta casi siempre prematuro.

A continuación, un orden de comprobación que lleva unos veinte minutos y que en la mayoría de los casos da una respuesta clara. Va de lo más barato a lo más costoso: primero lo que se ve de inmediato, después lo que exige una comparación.

Paso uno: quién entró

Empiece por los accesos. Si alguien ajeno entró, casi con seguridad lo hizo por SSH, y ha quedado rastro.

last -20
lastb | head -20
who

last muestra los últimos accesos correctos, lastb los fallidos, who quién está conectado ahora mismo. Lo que importa no es la cantidad sino la forma. Miles de intentos fallidos desde direcciones que no vuelven nunca son el ruido de fondo habitual; ocurre en cualquier dirección pública sin interrupción y no significa nada.

Lo inquietante es otra cosa:

  • un acceso correcto desde una dirección donde no hay nadie de los suyos;
  • un acceso con un nombre de usuario que usted nunca creó;
  • intentos fallidos con un nombre que sí existe en esta máquina: eso significa que alguien conoce la lista de sus usuarios y no está recorriendo un diccionario;
  • una sesión abierta en este momento que usted no abrió.

Compruebe además si han aparecido claves ajenas. El archivo ~/.ssh/authorized_keys es la forma más habitual de afianzarse: la contraseña puede cambiarse cuantas veces se quiera, la clave permanece.

cat ~/.ssh/authorized_keys
sudo cat /root/.ssh/authorized_keys

Cada línea de ahí es el acceso de alguien. Si no puede decir de quién, considérelo ajeno.

Paso dos: qué ha cambiado en el sistema

Una intrusión deja casi siempre rastros en el disco: un binario sustituido, una línea añadida a una configuración, un archivo nuevo en el directorio del servidor web. Comprobar eso a simple vista es inútil: hace falta una referencia.

En Debian y Ubuntu la referencia ya existe: cada paquete conoce las sumas de verificación de sus propios archivos.

sudo apt install debsums
sudo debsums -c

El comando enumera los archivos que difieren de lo que instaló la distribución. Parte de los hallazgos será legítima: los archivos de configuración bajo /etc existen precisamente para modificarse. En cambio, un ejecutable modificado en /usr/bin, /usr/sbin o /bin en un servidor que usted nunca tocó a mano ya es otro asunto.

La segunda fuente son los archivos recientes donde no debería haberlos. Un web shell suele estar en el directorio de subidas y parece un .php inofensivo:

find /var/www -type f -name '*.php' -mtime -14 -ls

Catorce días son solo un punto de partida; ponga el periodo durante el cual está seguro de no haber publicado nada.

Paso tres: qué sale hacia fuera

Un servidor comprometido rara vez se toma por sí mismo. Se usa: para enviar spam, para minar, para llegar a otras redes, para alojar archivos ajenos. Todo eso crea conexiones salientes que antes no existían.

ss -tulpn
ss -tp state established

El primer comando muestra qué está a la escucha, el segundo qué está establecido ahora. Hay que leer la columna del proceso. Levantan preguntas: un proceso desconocido escuchando en 0.0.0.0; conexiones salientes a puertos altos hacia direcciones con las que su aplicación no tiene nada que ver; y sobre todo un proceso lanzado desde /tmp o /dev/shm: de esos directorios no se ejecuta nada legítimo.

Mire de paso la carga. Un minero se delata porque el procesador está ocupado de forma permanente mientras el sitio no goza de popularidad alguna.

Si aparecen las señales

El primer impulso es limpiar deprisa: borrar la clave ajena, matar el proceso, eliminar el archivo. No lo haga: destruiría precisamente aquello que después permitiría entender por dónde entró. Y si eso queda sin entender, volverá, quizá mañana.

Un orden que preserva tanto los datos como el cuadro general:

  1. Tomar una instantánea del disco en el proveedor, si es posible. Es el único paso que después no puede repetirse.
  2. Aislar la máquina de la red o cerrar todo salvo su propia IP, pero no apagarla. Al apagarla pierde la lista de procesos y las conexiones abiertas, que son la mitad de las pruebas.
  3. Guardar los registros fuera: /var/log/auth.log, los del servidor web, la salida de los tres comandos anteriores.
  4. Solo entonces averiguar cómo se obtuvo el acceso.

Una reinstalación desde cero es el final correcto si el acceso se obtuvo con privilegios de root. Ninguna limpieza garantiza que no haya quedado nada. Pero reinstalar sin haber entendido la causa carece de sentido: devolvería el mismo agujero a un sistema nuevo.

Para que la pregunta no llegue de golpe

Todo lo anterior es una comprobación manual puntual y responde a la pregunta «qué está pasando ahora mismo». Lo malo es que suele plantearse tarde: cuando el proveedor ya ha escrito o el sitio se ha caído.

Cada una de estas comprobaciones existe como herramienta independiente capaz de vigilar de forma continua: los accesos fallidos, fail2ban; los cambios de archivos, AIDE; la integridad de los paquetes, debsums; los puertos abiertos, una instantánea periódica de ss. Instalarlas por separado no es difícil; lo difícil es acostumbrarse a leer cada día seis salidas distintas, motivo por el cual en la práctica no se leen.

Ese es exactamente el sentido de un panel unificado: los mismos datos, pero en una sola página y con histórico, para que «esto no era así ayer» se vea sin tener que ir a buscarlo. Debajo están las páginas de demostración que muestran cómo se ve todo junto.