Hoy vengo a escribir sobre como asegurar SSH de forma más o menos eficiente, la cosa puede complicarse más, pero esto se hace en un momento y garantiza una seguridad más que aceptable.
Todas las directivas que voy a empezar a explicar deben colocarse en fichero de configuración de sshd, que suele estar localizado en /etc/ssh/sshd_config.
1- Cambiar el puerto de conexión y el protocolo
Cambiar el puerto de conexión por defecto puede librarnos de un buen puñado de ataques automatizados y de indexados que no deseamos. Esto no es una solución milagrosa, pero cuanto más nos salgamos de lo habitual, más difícil se lo ponemos a los chinofarmers.
Lo primero, es el puerto, que es bien sencillo. Cambiando la directiva Port a otro valor (por defecto el 22) estaríamos listos. En mi caso voy a poner el 600, por poner uno 2022 por asignarle un puerto de usuario (>=1024 && <= 49151), como nos apunta Alberto en los comentarios.
Port 2022
Lo siguiente es el protocolo. La mayoría de instalaciones modernas ya utilizan el protocolo correcto por defecto, pero comprobadlo nunca está de más. La directiva que buscamos es Protocol y debemos establecerla a un valor de 2.
Protocol 2
Esto es importante porque las versiones anteriores gozan de vulnerabilidades muy graves y fáciles de explotar.
2- Limitar el tiempo máximo de inactividad de una sesión
Esto es otro detalle importante para evitar que un terminal olvidado pueda caer en malas manos. Aquí buscamos dos directivas, ClientAliveInterval y ClientAliveCountMax.
SSHD, cada rato envía una señal para comprobar que el usuario sigue conectado y está activo. De no estarlo, suma uno a un contador interno. Cuando este contador iguala al valor establecido en el valor ClientAliveCountMax SSHD descarta la conexión. El tiempo que debe pasar entre cada intervalo es especificado por la otra directiva.
Como yo quiero estar seguro de esto, voy a configurar las directivas de tal forma que el sistema desconecte una sesión inactiva cada 200 segundos.
ClientAliveInterval 200 ClientAliveCountMax 0
De esta forma, pasados esos 200 segundos, la conexión se desconectará.
3- Denegar el acceso a root y limitar los usuarios que van a conectarse
Ambas muy importantes para evitar que se comprometa la cuenta de Root o que alguien gane acceso a la máquina gracias a alguna cuenta olvidada.
Lo primero es localizar los usuarios que van a conectarse a la máquina; una vez sepamos eso, solo tenemos que añadirlos usando la directiva AllowUsers. Si vamos a añadir más de un usuario deberemos separarlos con espacios. A mayores, si lo deseamos, podemos añadir el usuario usando el formato usuario@host y de esa forma SSHD solo aceptará los usuarios de ese host.
La directiva para denegar el acceso a root es PermitRootLogin y hay que establecerle un valor de «no».
En mi caso voy a permitir el acceso a los usuarios hluaces y logs.
PermitRootLogin no AllowUsers hluaces logs
4- Limitar el máximo de intentos de conexión y banear temporalmente a los usuarios que fallen demasiadas contraseñas
Esto es muy importante para evitar ataques por fuerza bruta. Lo primero que tenemos que hacer es limitar los intentos de conexión, para ello usaremos la directiva MaxAuthTries. Por defecto viene establecida a 6 conexiones, pero yo lo prefiero poner en 3.
MaxAuthTries 3
Lo siguiente es banear a los usuarios que fallen demasiadas contraseñas. Para eso vamos a usar el paquete fail2ban que se encarga de monitorizar logs y conexiones falladas y banear a la gente de forma apropiada.
La configuración de fail2ban se puede refinar mucho, pero en un principio estará bien como lo tenemos. Lo que si que hay que cambiar, es el puerto de conexión de SSHD de fail2ban, ya que por defecto asume que es el 22.
Para ello, localizaremos el fichero jail.conf que suele estar en /etc/fail2ban/jail.conf. Allí deberemos buscar la sección de SSH, que será algo tal que así:
[ssh] enabled = true port = ssh filter = sshd logpath /var/log/auth.log maxretry = 6
Cambiad el port = ssh por un port = 2022 (o el port que sea) y reiniciad el fail2ban con service fail2ban restart.
5- Prohibir la autentificación por contraseña y usar un par de claves
Esto es el paso final y lo que terminará garantizando una mayor seguridad. Lo primero será habilitar la autentificación por par de claves y, una vez funcione, deshabilitar la contraseña. No lo hagáis al revés, no sea que os llevéis un sustillo.
Empezamos por generar un par de claves. Para ello vamos a usar el comando ssh-keygen.
Al ejecutarlo nos pedirá 3 cosas:
- Un fichero donde guardar el par de llaves. Especificad un directorio con permisos 600 (o cambiádselo después).
- Una passphrase. Lo que viene a ser una frase para encriptar la llave. Hacedla lo más larga que podáis.
- La misma passphrase repetida para confirmarla.
Al terminar la ejecución tendremos dos ficheros: una parte pública y una parte privada. La que tiene extensión .pub es la pública, por si no estaba claro. Cambiadle los permisos a 600, moved la clave privada y copiad la clave pública al equipo desde el que os vais a conectar y pasamos a lo siguiente.
Ahora que tenemos un par de claves vamos a habilitar el SSHD para que permita la autentificación por par de claves. Para ello estableceremos las directivas PubKeyAuthentication y RSAAuthentication a «yes».
PubKeyAuthentication yes RSAAuthentication yes
Lo siguiente será mover nuestra clave pública al directorio del usuario remoto y decirle a SSHD donde se encuentran. Por lo general las llaves suelen guardarse en /home/<usuario>/.ssh/authorized_keys así que vamos a cambiar la directiva AuthorizedKeysFile a un valor que sea %h/.ssh/authorized_keys. Por si no lo habíais deducido, %h se expandirá para convertirse en el directorio home del usuario con el que estamos logueando.
AuthorizedKeysFile %h/.ssh/authorized_keys
Si queréis introducir más de una clave pública en el fichero authorized_keys usad el comando cat para concatenar la nueva clave pública tal cual al fichero.
Con esto ya estaría la mayor parte del trabajo hecha y deberíamos probar que todo funciona bien. Reiniciemos el servidor con service ssh restart y probemos a conectarnos usando nuestra clave privada.
Ya que hemos cambiado el puerto, tendremos que usar el comando tal que así:
ssh usuario@host -p ; -l <fichero de clave privada>
Aquí evidentemente hay que sustituir <puerto> por el puerto que hemos asignado a SSHD (en mi caso 2022) y debemos especificar la ruta local de nuestro fichero de clave privada.
Si todo va bien nos habremos conectado y no nos pedirá contraseña. Ahora solo queda eliminar la necesidad de usar contraseñas y eso se hará con la directiva PasswordAuthentication establecida en «no».
PasswordAuthentication no
Y listo. Nuestro servidor ya goza de una seguridad inicial sólida y que no ha requerido demasiado tiempo. Ahora solo faltaría reiniciar el servicio de nuevo con service sshd restart y ¡la cosa ya estaría lista!
La autentificación por par de claves, además de ser muy segura, es muy cómoda. Eso si, ¡proteged bien vuestra clave privada!
Para terminar, os dejo un par de lecturas interesantes.
Alberto Luengo
Ey! Buen artículo!
Lo único que podría remarcar es que yo suelo utilizar puertos de usuario para los servicios que monto en las máquinas (en los SSH 8022, 22022, etc) y que últimamente está sonando mucho el MOSH, que asegura mejor rendimiento cuando nos conectamos a máquinas con menor ancho de banda, etc (http://slashroot.in/mosh-better-alternative-ssh?goback=.gde_49301_member_216241405)
+1 al fail2ban, un gran software que nos ahorrará más de un disgusto en nuestros hostings.
Héctor Luaces Novo
Hombre, tú por aquí xD
Lo de los puertos no se me pasó por la cabeza la verdad, y lo del MOSH tocará mirárselo. Gracias por contribuir amigo!
Jocker
Muy buen artículo. Para mi la única excepción es el último punto, y es que habilitar la entrada sólo mediante las claves, digamos que te limita mucho el acceso al servidor. Si mañana tengo que conectar con un servidor desde un portátil que no es el mío, y no tengo las claves almacenadas en algún servicio de almacenamiento en cloud (y mi sombrero de papel albal, suele impedirme hacer eso) no voy a poder entrar.
No conocía el fail2ban, yo hasta el momento estoy usando DenyHosts que además tiene una especie de lista donde se van incluyendo las IPs que suelen ser clientas habituales!
Héctor Luaces Novo
Sabía de la existencia de cosas como DenyHosts pero nunca me había puesto a mirarlo con calma, así ya tengo por donde empezar.
Lo de las claves es algo que es llevarlo un poco al extremo y que la verdad no llevo mucho a la práctica a no ser que sepa que a un npc solo voy a entrar desde un sitio, porque la clave suelo hacer lo mismo que tú con el gorrito de papel xD
Jocker
El DenyHosts funciona bien, incluso envía reportes de las IPs que ha bloqueado por correo, pero si tienes un servidor escuchando en el 22, es un auténtico dolor recibir todas las notificaciones. De hecho, creo que en mi hosts.deny tengo unas 700 entradas así rápidas.
La mejor opción, sería crear un script que notificase al ISP que proporciona esas IPs el intento de login automático… si lo hace sólo uno, puede que te bloqueen o que pasen de tu culo, pero si lo usásemos todos los que administramos servidores, quizá se lo tomarían un poco más en serio.
Héctor Luaces Novo
No te falta razón en eso, ya me has convencido para darle un empujón