Seguridad en SSH

Autenticación de dos pasos Para Login y SSH

Hace ya tiempo Google sacó un sistema novedoso, la autenticación en 2 pasos. Para aquellos que no lo conozcan, no es más que un extra se seguridad basado en un código temporal en base al que genera un código aleatorio que te permite acceder a tu cuenta de Gmail. Puesto que el código es aleatorio y se cambia cada ~30 segundos, es prácticamente imposible que alguien que esté a la escucha (ataque made in the middle) pueda capturar la contraseña.

Para dar más seguridad a nuestro equipo, lo instalaremos para que nos pida el codigo al momento de iniciar sesión y además también lo añadiremos para que lo solicite cuando iniciemos por ssh.

En este post vamos a ver cómo configurar este nuevo software con nuestro servidor SSH y cómo poder enlazarlo en nuestro celular (Android, iPhone o Blackberry).

Primero como siempre abrir una terminal y teclear:

sudo apt-get install libqrencode3

Descargar la aplicación Google Authenticator

Está disponible en las appstore de sus sistemas bajo el nombre de "Google Authenticator".

Instalar el software necesario en el sistema GNU/Linux

Si estás empleando Ubuntu, puedes añadir directamente el repositorio,

sudo add-apt-repository ppa:failshell/stable
sudo apt-get update
sudo apt-get install libpam-google-authenticator

Si estas en Debian 7 puedes descargar lo aquí

En caso de emplear otra distro, podrás descargarte el código desde aquí y compilarlo.

Para configurar SSH

Una vez tengas el software instalado, sólo quedará por realizar los pequeños cambios en los archivos de configuración oportunos.

Debemos editar el archivo /etc/pam.d/sshd

sudo nano /etc/pam.d/sshd

y añadir en el archivo la linea

auth required pam_google_authenticator.so

Luego editar el archivo /etc/ssh/sshd_config

sudo nano /etc/ssh/sshd_config 

y buscar la linea

ChallengeResponseAuthentication no

y cambiarla por

ChallengeResponseAuthentication yes

Luego reiniciar el servidor ssh

sudo service ssh restart

Para Login

Debemos editar el archivo /etc/pam.d/gdm3

sudo nano /etc/pam.d/gdm3

y añadir en el archivo la linea

auth required pam_google_authenticator.so

Para Login y/o SSH: Generar la clave para el usuario

Ahora que ya el administrador hizo todo su trabajo, sólo queda generar una nueva clave. Para ello habrá que ejecutar el comando 'google-authenticator' como usuario, lo que generará un código QR que será el que tengamos que leer con nuestro teléfono. A mayores, nos ofrece un 5 códigos de emergencia, los cuales debería de ser guardados en un lugar seguro y también una clave secreta, por si no tienes un lector de códigos QR, poder crear la nueva cuenta en la aplicación móvil.

google-authenticator #ejecurar comando como usuario

Y aparecera algo como lo siguiente en nuestra terminal (recuerda como usuario, no como rut):

[IMAGEN QR]

Your new secret key is: GSDRTXXXXMEHZ5545
Your verification code is 111xx
Your emergency scratch codes are:
  622945xx
  676497xx
  805598xx
  170280xx
  576423xx
Do you want me to update your "~/.google_authenticator" file (y/n) y
...
...

Ahora abres la aplicación en tu celular, presionas el signo + y seleccionas escanear código QR, enfocas el código de la terminal y listo, ya tienes enlazado tu celular al equipo.

para finalizar, en la terminal te pregunta una serie de opciones, dependiendo de tus gustos pones yes o no, yo puse a todo que si.

Sin duda es una forma muy útil de tener un extra se seguridad a muy bajo precio y aparte del software aquí comentado, lo único que se necesita es que ambos equipos (celular y equipo) estén con la hora sincronizada (NTP), para que la clave generada - clave esperada coincidan.

Desactivar login con root desde SSH

Una de las cosas que no se tienen que hacer, es usar el usuario root a la ligera. Así que vamos a denegar el acceso del usuario root para crear conexiones por SSH.

sudo nano /etc/ssh/sshd_config

Buscamos en la configuración "PermitRootLogin yes" y lo cambiamos por "PermitRootLogin no".

Límite de intentos

Lo más seguro es que se use un ataque de fuerza bruta para entrar a nuestro sistema. Para evitar esto, lo que vamos hacer es bloquear el número máximo de intentos fallidos desde una IP y el número máximo de sesiones simultáneas que se pueden abrir.

sudo nano /etc/ssh/sshd_config

Añadimos las siguientes líneas al final del archivo:

MaxAuthTries 2
MaxStartups 5

Cambiar contraseña con openssh

Las claves que vienen en raspbian no son seguras, ya que vienen por defecto en la imagen que cargamos en la SD, por lo que todo el mundo las conoce, es por esto que es importante cambiarlas. En especial en el protocolo SSH ya que es común que nos conectemos por ahí a nuestro equipo.

Abre una terminal y teclea:

sudo rm /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server

Una vez hecho esto, hay que borrar el archivo ~/.ssh/known_hosts

 rm ~/.ssh/known_hosts

Cambiar puerto de conexión

No es algo que te vaya a servir de mucho, ya que con NMAP podemos saber que puertos tienes abiertos, pero si puedes evitar esos ataques automáticos de bots que circulan por Internet. Para eso vamos a cambiar el puerto de conexión:

Por defecto: port 22

Lo cambiamos por el que queramos. (ojo, el puerto tiene que ser superior a 1024)

Habilitar usuario root para conexiones por SSH

Abre una terminal y como root edita el siguiente archivo:

sudo nano /etc/ssh/sshd_config

También puede que sea este (depende de la distribución)

sudo nano /etc/ssh/sshd_conf

Luego busca la linea PermitRootLogin y déjala de esta forma:

PermitRootLogin yes

Luego reinicia ssh y ya podrás logearte como root sin problemas.

# /etc/init.d/ssh restart

Recuerdo que esto es muy poco seguro, por lo que recomiendo hacerlo solo para el momento y luego volver a dejarlo desactivado.

Proteger tu servidor de ataques de fuerza bruta

Si tienes un servidor SSH corriendo y alguna vez os habrás parado a mirar los logs, habrás visto una gran cantidad de intentos de acceso no autorizados.


Si estudian más detenidamente los logs veras que la mayoría de veces son ataques basados en diccionarios o similares, por tanto a no ser que nuestros passwords sean muy débiles es difícil que consigan acceder a nuestra máquina. Pero para que arriesgarnos...vamos a ver como protegernos de estos seres malignos e indeseables que intentan entrar en nuestro sistema.

Hay varios programas/scripts que sirven para proteger nuestro servidor SSH de ataques de fuerza bruta, como por ejemplo:

Después de probarlos , me quedo con Denyhosts, ya que es sencillo de instalar/configurar, apenas consume recursos y cumple su cometido de sobra. Vamos a ver como instalarnos Denyhosts en nuestra Ubuntu.


En Feisty Fawn (en Edgy creo que también) Denyhosts viene incluido en los repositorios, así que su instalación es tan sencillo como:

sudo apt-get install denyhosts


Una vez instalado debemos crear un par de archivos (si es que no existen ya), para ello nuestro colega touch nos será útil:

sudo touch /etc/hosts.allow
sudo touch /etc/hosts.deny


Con esto ya tenemos instalado denyhosts y con la configuración por defecto, para arrancarlo y pararlo manualmente haremos lo siguiente:

sudo /etc/init.d/denyhosts start
sudo /etc/init.d/denyhosts stop


La configuración de denyhosts se guarda en /etc/denyhosts.conf, vamos a ver algunas de las directivas que podemos modificar desde este archivo:

  • DENY_THRESHOLD_INVALID: Número de intentos fallidos (con un usuario que no exista) necesarios para banear esa IP.
  • DENY_THRESHOLD_VALID: Número de intentos fallidos (con un usuario existente) necesarios para banear esa IP.
  • DENY_THRESHOLD_ROOT: Número de intentos fallidos (intentando entrar como root) necesarios para banear esa IP.
  • BLOCK_SERVICE = sshd/ALL/etc... : Esta directiva indica los servicios que bloqueará a los usuarios baneados.
  • DAEMON_LOG = /var/log/denyhosts : Indica el archivo en el que se guardará el log de denyhosts.

Estas son las directivas más utilizadas, aunque tiene muchas más, dentro del propio archivo /etc/denyhosts.conf viene comentado para que sirve cada una, por tanto no me alargaré más en explicarlas todas. Otro de los consejos que os daría para evitar el 90% de los intentos de acceso es cambiar el puerto en el que tenemos corriendo el servidor de ssh por uno más alto (por encima del 1024 a ser posible), eso lo hacemos modificando la directiva port en el archivo /etc/ssh/sshd_config. Para terminar os aconsejaría que no permitas logearse por ssh como root, esto se desactiva en el mismo archivo etc/ssh/archivo sshd_config mediante la directiva "PermitRootLogin no"


Con todo esto tendremos algo más seguro (en informática pocas veces se esta seguro de algo un 100%) nuestro servidor SSH.

Desactivar Advertencia de contraseña

Para evitar el molesto mensaje cuando usamos la contraseña por defecto de ssh (en particular en raspbian)

SSH is enabled and the default password for the 'pi' user has not been changed.

This is a security risk - please login as the 'pi' user and type 'passwd' to set a new password.

Podemos desactivarla eliminando el siguiente archivo:

sudo rm /etc/profile.d/sshpasswd.sh

o si da error prueba con:

sudo rm /etc/profile.d/sshpwd.sh

Connection reset by {ssh hostname} port 22 (solución)

Cuando configuré mi raspberry habilite SSH como siempre pero una vez que intente conectarme me mandaba el mensaje "Connection reset", entonces la solución que necontre es realizar los siguientes 2 comandos:

sudo rm /etc/ssh/ssh_host_*
sudo dpkg-reconfigure openssh-server

Cerrar Sesiones de usuarios de forma remota (SSH)

Si se tiene un servidor ssh al que seguramente se conectan clientes desde otros equipos como Linux o Windows con clientes de ssh como putty, pues sucederá que algunas veces se requiere terminar la conexión desde el lado del servidor, sobre todo ¡¡si es una conexión sospechosa!!. Te voy a presentar un par de formas de lograrlo al matar los procesos que generan este tipo de conexiones.

Utilizando PS y KILL

La manera de terminar la conexión ssh desde el servidor es matando el número de proceso (PID) relacionado al socket de red de la conexión establecida. Si usamos netstat con las opciones correctas podremos observar esta conexión:

# netstat -pnat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address  Foreign Address State PID/Program name
tcp    0    0 0.0.0.0:902     0.0.0.0:*     LISTEN      4869/xinetd
tcp    0    0 0.0.0.0:139     0.0.0.0:*     LISTEN      5213/smbd
tcp    0    0 0.0.0.0:10000   0.0.0.0:*     LISTEN      5459/perl
tcp    0    0 0.0.0.0:6000    0.0.0.0:*     LISTEN      5177/X
tcp    0    0 0.0.0.0:80      0.0.0.0:*     LISTEN      5222/httpd
tcp    0    0 0.0.0.0:443     0.0.0.0:*     LISTEN      5222/httpd
tcp    0    0 :::22           :::*          LISTEN      5160/sshd
tcp    0    0 ::ffff:192.168.1.72:22      ::ffff:192.168.1.100:55855  ESTABLISHED 6950/sshd: juan

En la última línea claramente se observa que el equipo remoto (cliente) 192.168.1.100 esta conectado al puerto 22 del equipo 192.168.1.72 que en este caso sería el servidor ssh, también en la última columna, tenemos el PID 6950 y al usuario juan. Datos que nos indican el proceso del socket que se estableció en la conexión ssh y el usuario que se logeo desde el equipo remoto.

Si el usuario remoto que se hubiera conectado fuera root, entonces ya bastaría con matar el PID mostrado y terminaríamos la conexión, pero en este caso (que debe ser lo correcto por seguridad) un usuario normal (juan) fue el que se conectó y en este caso se generan dos PID’s para la conexión, veámoslo con un ps:

    # ps -ef | grep juan
    root      6950  5160  0 20:06 ?   00:00:00 sshd: juan [priv]
    juan    6953  6950  0 20:06 ?   00:00:00 sshd: juan@pts/3

Un usuario normal genera dos procesos, habrá que matar a los dos o con que termines el proceso asignado al usuario que en este caso sería 6953:

    # kill -9 6953

Del lado del cliente, vera el siguiente mensaje:

    $ Connection to 192.168.1.72 closed by remote host.
    Connection to 192.168.1.72 closed.

El mensaje dice que la conexión fue cerrada por el ‘remote host’ host remoto, confirmando que fue desde el lado del servidor que se interrumpió o “mató” el enlace.

Utilizando WHO y PKILL

En el listado de ps anterior, además de ver su número de proceso también observamos a que terminal esta ligado el proceso, en la última columna está el dato y es: `juan@pts/3', lo mismo se obtiene más simplemente con el comando who:

  # who
  juan   :0           2007-11-05 19:28
  juan   pts/3        2007-11-05 20:23 (192.168.1.100)

Sabiendo entonces que hay un usuario en la pseudo terminal 3, es posible usar pkill que permite enviar señales (signals) a los procesos basado no en su PID sino en sus atributos o características, en este caso el número de la terminal:

    # pkill -9 -t pts/3

Del lado del cliente, verá el siguiente mensaje:

    $ Connection to 192.168.1.72 closed.

Se envió la señal -9 que indica matar (KILL) el proceso, la opción -t indica que se basará en un atributo de nombre de terminal y se indica después el nombre de la terminal en si pts/3.

Si administras un servidor ssh, ten a la mano estos útiles comandos que te permitirán terminar conexiones cuando tu lo desees, sin necesidad de terminar todo el servicio de ssh.