SSH por Claves: Configuración Segura en 3 Minutos

Si todavía usas contraseñas para SSH, estás jugando a la ruleta rusa con la seguridad de tu servidor. Hoy en día es obligatorio usar claves SSH.

Configuración Esencial

Edita /etc/ssh/sshd_config:

sudo nano /etc/ssh/sshd_config

Líneas clave:

PasswordAuthentication no
PubkeyAuthentication yes
PermitRootLogin no

La opción de PasswordAuthentication no, no permite login usando password. Así que nadie podrá probar contraseñas por fuerza bruta.
La opción de PubkeyAuthentication yes establece que sólo se puede entrar por ssh usando una clave pública.
La opción de PermitRootLogin no establece que no puedas entrar directamente como usuario root. Lo ideal es entrar con un usuario con menos privilegios que sea sudoer. Aunque es cómodo poner esta opción a yes en ciertas ocasiones.

Pasos Rápidos

  • Generar Claves
ssh-keygen -t ed25519
# Enter para todo (o pon passphrase)
  • Copiar Clave Pública
ssh-copy-id usuario@tu-servidor

También puedes añadir manualmente tu clave pública a ~/.ssh/authorized_keys en una nueva línea.

  • Aplicar Cambios
sudo systemctl reload sshsudo systemctl reload ssh
  • Verificación
ssh usuario@tu-servidor

Este último comando te debería permitir conectar sin usar password.

Y ya lo tenemos, ya podemos ir a dormir más tranquilos.

Advertencia: Fail2Ban puede ocupar mucho espacio en tu servidor (Así lo solucioné)

En mi personal cruzada por reducir y optimizar el espacio ocupado en mi servidor, descubrí que Fail2Ban ocupaba ¡3.8GB! Aquí te cuento mi proceso para reducirlo paso a paso.

Una de las mejores meneras de localicar problemas de espacio es usando ncdu. Si todavía no lo tienes ya lo puedes ir instalando apt install ncdu

ncdu /

Mientras navegaba por los directorios, algo en /var/lib llamó mi atención. Al entrar, vi esto:

ncdu fail2ban

¿De verdad? ¿Esa herramienta que supuestamente solo guarda unos cuantos logs? ¿3.8 gigabytes?

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "SELECT COUNT(*) FROM bans;"

Resultado: más de 2 millones de registros. ¡Dos millones de baneos! Y cuando verifiqué la antigüedad:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 "SELECT DATE(MIN(timeofban), 'unixepoch') FROM bans;"

Descubrí registros desde 2022. Tres años de ataques, intrusiones fallidas e intentos de brute force acumulándose sin control.

Después de leer documentación y varios intentos fallidos, llegué a la solución elegante:

sqlite3 /var/lib/fail2ban/fail2ban.sqlite3 \
"DELETE FROM bans WHERE DATE(timeofban, 'unixepoch') < '2025-06-01'; VACUUM;"

Traducción: «Elimina todos los baneos anteriores al 1 de junio de 2025 y luego compacta la base de datos.»

Ejecuté el comando y… funcionó. Los resultados fueron casi inmediatos

¡De 3.8GB a 3.9MB! Había recuperado el 99.9% del espacio ocupado.

Ahora tengo en mi /etc/fail2ban/jail.local:

[DEFAULT]
dbpurgeage = 30d

Lo que permite purgar la base de datos cada 30 días de manera automática.

¡Arreglado! y a seguir con otras cosas.

watch permite monitorizar tu sistema en tiempo real

Existen muchos comandos en Linux que la mayoría de los usuarios conocen y utilizan regularmente, como «ls» para listar los archivos en un directorio o «cd» para cambiar de directorio. Sin embargo, hay algunos comandos menos conocidos que pueden resultar muy útiles en determinadas situaciones. Uno de esos comandos es watch.

watch es un comando que permite ejecutar cualquier otro comando en un bucle continuo, mostrando la salida en la consola cada cierto tiempo que se especifique. Esto puede resultar muy útil cuando se quiere monitorear un proceso que se está ejecutando en el sistema, ya que permite ver cómo cambia su salida en tiempo real.

Un ejemplo común de uso del comando watch es para monitorear el uso de la memoria en un sistema. Por ejemplo, podemos ejecutar el comando «free -m» (que muestra el uso de la memoria en megabytes) en un bucle con watch de la siguiente manera:

watch -n1 "free -m"

Esto ejecutará el comando «free -m» cada segundo (-n1), mostrando la salida en la consola de la siguiente manera:

De esta forma, podemos ver cómo cambia el uso de la memoria en tiempo real, y tomar decisiones en consecuencia si es necesario.

Truco para mejorar el rendimiento de los procesos en Linux

El comando renice es una herramienta que permite cambiar la prioridad de un proceso en Linux y otros sistemas operativos basados en Unix en tiempo de ejecución. Esto significa que puedes hacer que un proceso consuma más o menos recursos del sistema, lo que puede ser útil si tienes varios procesos en activos y uno de ellos está consumiendo demasiados recursos.

Para utilizar el comando renice, primero debes conocer el ID del proceso al que quieres cambiar la prioridad. Puedes encontrar este ID ejecutando el comando ps -ef en tu terminal, lo que te mostrará una lista de todos los procesos en ejecución en tu sistema. Una vez que tengas el ID del proceso, puedes utilizar el comando renice seguido del nuevo valor de prioridad que quieres asignarle al proceso.

Cabe mencionar que el valor de prioridad que puedes asignar a un proceso va desde -20 (la más alta) hasta 19 (la más baja). Por lo general, se recomienda no asignar prioridades muy altas a procesos, ya que esto puede hacer que otros procesos en ejecución en tu sistema se vuelvan lentos o inestables. En cambio, asignar una prioridad muy baja a un proceso puede hacer que este consuma menos recursos y no afecte el rendimiento del sistema.

Para utilizar el comando renice, debes proporcionar el ID del proceso que deseas cambiar la prioridad y la nueva prioridad que deseas asignarle. Por ejemplo, supongamos que quieres cambiar la prioridad del proceso con ID 12345 a un nivel de prioridad de 10. Puedes hacerlo de la siguiente manera:

renice 10 -p 12345

Esto cambiará la prioridad del proceso con ID 12345 a 10, lo que significa que tendrá acceso a una mayor cantidad de recursos del sistema. La prioridad nice de un proceso en Linux por defecto depende del valor predeterminado que esté establecido en el sistema operativo. En muchos sistemas operativos Linux, la prioridad nice por defecto para un proceso es 0. Por lo tanto establecer una prioridad menor que 0, será otorgar una prioridad alta, mientras que una prioridad mayor que 0 otorgará una prioridad baja.

También puedes utilizar el comando renice sin especificar un ID de proceso en particular. Por ejemplo, si quieres cambiar la prioridad de todos los procesos que están siendo ejecutados por el usuario «usuario1» a un nivel de prioridad de 10, puedes usar el siguiente comando:

renice 10 -u usuario1

Esto cambiará la prioridad de todos los procesos que están siendo ejecutados por el usuario «usuario1» a un nivel de prioridad de 10.

Hay muchas otras opciones y formas de utilizar el comando renice, así que si quieres obtener más información, puedes consultar la documentación del comando en tu sistema operativo Linux.

man renice

Error en exim: Initialization failed: namespace configuration error

Si te encuentras con este error en el el log de dovecot, solucionarlo es bastante fácil, de hecho, está escrito en el propio error. El error en cuestión es:

Error: user your@username.tld: Initialization failed: namespace configuration error: inbox=yes namespace missing

Para solucionarlo, tan sólo hay que editar el archivo /etc/dovecot/conf.d/*-mailboxes.conf  y añadir lo siguiente dentro de  namespace inbox { }

inbox = yes

Luego tan sólo queda reiniciar exim con el comando:

systemctl restart exim.service

Y listo! ya tenemos funcionando de nuevo el email

Nota: También podemos añadir la linea auto=subscribe en cada mailbox para que quede así:

mailbox Trash {
  auto = subscribe
  special_use = \Trash
}

Ahora cualquier cliente de correo, al configurar esa cuenta, se suscribirá por defecto a la carpeta de Trash.

Modificar las conexiones máximas por IP de dovecot

Mi cliente de email a veces se quejaba de que no podía conectar al servidor. El caso es que la configuración de la cuenta de email era correcta, porque normalmente accedía sin problemas. Pues mirando en /var/log/maillog he visto que aparecía este mensaje:

dovecot: imap-login: Maximum number of connections from user+IP exceeded

He encontrado la solución al problema, sólo es necesario cambiar la configuracíon de la variable mail_max_userip_connections e incrementarlo de manera que permita más conexiones simultáneas. Si el límite de conexiones es muy bajo, es muy facil llegar a él, ya que por cada cuenta de email que tengamos en el servidor, y por cada «carpeta» (Inbox, Spam, Trash, etc..) realiza una conexión individual. Esto optimiza la descarga de emails, pero también debe realizar muchas más conexiones.

Para cambiar este parámetro, editamos el fichero de configuración

nano /etc/dovecot/conf.d/imap.conf

y añadimos un limite de 50 conexiones por IP (o las que necesites)

protocol imap {
   mail_plugins = $mail_plugins autocreate
   mail_max_userip_connections = 50
}

Sólo queda reiniciar el servicio

systemctl restart dovecot.service

Y ya está!

Cómo arreglar el gráfico de uso de memoria de Vesta si no funciona en Centos7

Acabo de realizar una instalación limpia de CentOS7 en mi servidor, seguidamente he instalado la última versión de Vesta, actualmente la Vesta 0.9.8-16, como panel de control y me he dado cuenta de que el gráfico de uso de memoria (Memory Usage) no está mostrando nada. Hace tiempo leí cómo arreglar este problema aquí, y parece que estará corregido para la próxima versión. Aún así dejo el workaround, ya que seguro que resulta útil.

  1. Editamos el fichero /usr/local/vesta/bin/v-update-sys-rrd-mem y buscamos las siguientes líneas de código
     used=$(echo "$mem" |awk '{print $3}'|head -n3 |tail -n1)
     free=$(echo "$mem" |awk '{print $4}'|head -n3 |tail -n1)
  2. Las sustituimos por estas
     used=$(echo "$mem" |awk '{print $3}'|head -n2 |tail -n1)
     free=$(echo "$mem" |awk '{print $4}'|head -n2 |tail -n1)
  3. Guardar, salir y listo!

El truco está en cambiar el head -n3 por head -n2. Por lo visto el resultado del comand free -m es diferente para Centos6 y 7 por lo que necesita ese pequeño ajuste.

Tendremos que esperar un rato para que empezemos a ver los datos que empezarán a entrar en el gráfico, pero acabará viéndose perfectamente, os dejo mi ejemplo!

memory-usage-working-centos7

Registrar información más detallada en el log de exim

Exim va escribiendo en un archivo de log todas las peticiones de conexión que se realizan al servidor. Quedan registradas las IP’s, emails, y las sesiones que se crean y se cierran, así como si la conexión ha sido correcta o ha habido algún error. En general, es información más que suficiente. Aún así hay algo que no se guarda en el log y que puede sernos útil. En concreto, vamos a ver cómo guardar también un registro de los emails eliminados, o movidos de carpeta. Vamos allá:

El fichero en el que queda registro de toda actividad, en mi caso es /var/log/maillog y tiene una pinta parecida a esta:

Sep 11 11:37:06 servername dovecot: imap-login: Login: user=<user@example.com>, method=PLAIN, rip=123.456.789.123, lip=123.456.789.123, mpid=9007, TLS, session=<QVpx3dfsC1DU>

Sep 11 08:25:03 servername dovecot: pop3(user@example.com): Disconnected: Logged out top=0/0, retr=2/41769, del=1/47, size=15946098, bytes=50/43374

Sep 11 08:45:10 servername dovecot: imap(user@example.com): Logged out in=409, out=1405, bytes=409/1405

En la primera linea, el usuario se ha conectado y muestra la IP remota (rip), la IP local (lip), así como el tipo de conexión (TLS) y el identificador de la sesión al final. También nos indica que ha sido una conexión usando imap.

En la segunda línea, el usuario se ha desconectado de su sesión, su conexión era de tipo pop3 y hay un parámetro, que he resaltado en negrita que dice del=1/47. Esto nos indica que durante la sesión, ese usuario ha borrado 1 mensaje de los 47.

En la tercera linea, también se han desconectado de una sesión, en este caso imap, pero ahí sólo aparece los bytes que se han recibido/enviado (in/out) durante la conexión.

Para detallar más el log, hay que activar el plugin MailLog de exim. Esto nos dará detalles sobre los emails eliminados, movidos de una carpeta a otra, ¡perfecto!

Lo primero es editar el fichero de configuración de devecot

nano /etc/dovecot/dovecot.conf

Y buscaremos la linea que contiene mail_plugins, y añadiremos los plugins mail_log notify. En micaso quedará así

mail_plugins = quota quota_clone mail_log notify

Luego, buscaremos dentro de ese mismo fichero el apartado de Plugin settings y deberemos escribir estas lineas:

##
## Plugin settings
##

plugin {

  # Events to log. Defined in src/plugins/mail-log/mail-log-plugin.c - also available: flag_change save mailbox_create
  mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename

  # Also available: Defined in src/plugins/mail-log/mail-log-plugin.c - flags vsize from subject
  mail_log_fields = uid box msgid size
  (...)

Ya está, sólo tendremos que reiniciar el servicio

/etc/init.d/dovecot restart

Ahora, si borramos o movemos un email dentro de nuestro cliente de correo, quedará detallado en el log. Se verá algo así:

Sep 13 11:46:02 servername dovecot: imap(user@example.com): copy from INBOX: box=INBOX.Trash, uid=1433, msgid=<abc.123@example.com>, size=3143

Sep 13 11:46:02 servername dovecot: imap(user@example.com): expunge: box=INBOX, uid=4750, msgid=<abc.123@example.com>, size=3143

Sep 13 11:46:16 servername dovecot: imap(user@example.com): delete: box=INBOX.Trash, uid=1433, msgid=<abc.123@example.com>, size=3143

Eso sí, contad conque el log aumentará considerablemente de tamaño cada día.

Un saludo!

Comandos útiles para gestionar exim desde el terminal

Acceder por ssh a un servidor remoto para comprobar el estado de los emails es bastante habitual. Exim, es el MTA más común para servidores linux, y es con el que me encuentro a diario. Aquí dejo una lista de comandos que me han resultado útiles en más de una ocasión para el mantenimiento de los servidores.

Mostrar el número de emails en cola

exim -bpc

Eliminar todos los emails en cola

exim -bp | awk '/^ *[0-9]+[mhd]/{print "exim -Mrm " $3}' | bash

Mostrar los emails en cola

exim -bp

Se mostrará algo parecido a esto

46h  1.7K 1bi4YL-000123-AB <> *** frozen ***
          root@your-server.net

43h  1.7K 1bi7MY-000123-AB <> *** frozen ***
          root@your-server.net

(...)

Resumen de emails en cola

exim -bp | exiqsumm

Se mostrará

Count  Volume  Oldest  Newest  Domain
-----  ------  ------  ------  ------

   16    27KB     46h     82m  your-server.net
---------------------------------------------------------------
   16    27KB     46h     82m  TOTAL

Actividad actual de exim

exiwhat
783 daemon: -q1h, listening for SMTP on port xxx (IPv6 and IPv4) port xxx (IPv6 and IPv4) port xxx (IPv6 and IPv4) and for SMTPS on port xxx (IPv6 and IPv4)

Mostrar configuración de exim

exim -bP

Mostrar emails enviados desde remitente

exiqgrep -f usuario@dominio.tld

Mostrar emails para un destinatario

exiqgrep -r usuario@dominio.tld

Mostrar emails en cola más antiguos de n segundos (en este ejemplo 1h)

exiqgrep -o 3600

Mostrar emails en cola creados hace menos de n segundos (en este ejemplo 1h)

exiqgrep -y 3600

Comprobar la ruta de una direccion de email

exim -bt usuario@dominio.tld
test@gmail.com
  router = dnslookup, transport = remote_smtp
  host gmail-smtp-in.l.google.com      [2a00:1450:400c:c08::1a] MX=5
  host gmail-smtp-in.l.google.com      [74.125.140.27]          MX=5
  host alt1.gmail-smtp-in.l.google.com [2a00:1450:4010:c03::1a] MX=10
  host alt1.gmail-smtp-in.l.google.com [209.85.233.27]          MX=10
  host alt2.gmail-smtp-in.l.google.com [2404:6800:4003:c01::1a] MX=20
  host alt2.gmail-smtp-in.l.google.com [74.125.130.27]          MX=20
  host alt3.gmail-smtp-in.l.google.com [2404:6800:4008:c03::1a] MX=30
  host alt3.gmail-smtp-in.l.google.com [74.125.203.27]          MX=30
  host alt4.gmail-smtp-in.l.google.com [2404:6800:4008:c01::1a] MX=40
  host alt4.gmail-smtp-in.l.google.com [173.194.72.26]          MX=40

Procesar los emails en cola

exim -q -v

Eliminar un email concreto de la cola

exim -Mrm <id_email>
Message 1bi4YL-000123-AB has been removed

Congelar un email (no se enviará)

exim -Mf <id_email>

Procesar un email tanto si está congelado como si no (se enviará)

exim -M <id_email>

Forzar el fallo de un email y retornar el estado «cancelado por administrador»

exim -Mg <id_email>

Eliminar todos los emails congelados

exiqgrep -z -i | xargs exim -Mrm
Message 1bi4YL-000123-AB has been removed
(...)
Message 1bi7MY-000123-AB has been removed

Eliminar emails más antiguos de n segundos (en este ejemplo 1h)

exiqgrep -o 3600 -i | xargs exim -Mrm

Congelar todos los emails de un remitente

exiqgrep -i -f usuario@dominio.tld | xargs exim -Mf

Mostrar las cabeceras de un email

exim -Mvh <id_email>

Mostrar el contenido del email

exim -Mvb <id_email>

Mostrar el log de un email

exim -Mvl <id_email>

Añadir un destinatario a un email

exim -Mar <id_email> usuario@dominio.tld [ <usuario2@dominio.tld> [...] ]

Modificar el remitente de un email

exim -Mes <id_email> usuario@dominio.tld

Parar exim (diferentes maneras según tu sistema operativo)

systemctl stop eximd.service
service exim stop
/etc/init.d/exim stop

Iniciar exim (según tu sistema operativo)

systemctl start eximd.service
service exim start
/etc/init.d/exim start

Reiniciar exim (según tu sistema operativo)

systemctl restart eximd.service
service exim restart
/etc/init.d/exim restart

Comprobar el estado de exim (según tu sistema operativo)

systemctl status eximd.service
service exim status
/etc/init.d/exim status