Categorías
DevOps Seguridad SysAdmin

Securizar el servidor ssh

Las puerta de entrada a nuestro servidor es el puerto 22/tcp, el servicio ssh/sshd. Es la entrada a nuestra casa, securizar el servicio ssh es primordial. Por aquí está siempre escuchando nuestro servidor y al introducir credenciales de acceso podremos acceder a una shell, copiar ficheros o redirigir el tráfico de las X Window.

SSH es el acrónimo de Secure SHell, es la evolución de rsh/rlogin (remote shell) donde te permite conectar a un equipo remoto y ejecutar una shell. La principal diferencia y la más importante es que la conexión es cifrada, así nadie puede ver ni la contraseña que introducimos ni los comandos que tecleamos.

Debido a todo esto es por donde lo malos quieren principalmente entrar, así que es algo muy importante para proteger. Así que utilizaremos estas estrategias para securizar el servicio ssh:

Deshabilitar el acceso de root por ssh

Es muy cómodo acceder como root por ssh, pero también es muy peligroso y poco recomendado. Así que es mucho mejor tenerlo deshabilitado. Será tan fácil como cambiar una línea en el fichero /etc/ssh/sshd_config

PermitRootLogin no

Y después no hay que olvidarse de reiniciar el servicio ssh, hay que tener cuidado porque es otra de esas pequeñas diferencias que hay entre Red Hat y Debian.

# service restart sshd.service
# service restart ssh.service

Cambiar el puerto ssh del 22 a otro diferente

22/tcp es el puerto estándar y donde estarán escuchando la mayoría de las máquinas que tengan un servicio ssh funcionando. A los malos les gusta escanear el puerto 22 de las máquinas -realmente les gusta escanear todos los puertos- y cuando encuentran un puerto abierto comienzan el ataque. Vamos a ponerselo un poco más difícil cambiando el número del puerto. Para elegir un nuevo número tenemos que tener en cuenta que hay 3 rangos de puertos:

  • Well-known ports (0-1023)
  • Registered ports (1024-49151)
  • Dynamic, private or ephemeral ports (49152-65535)

Yo recomiendo cualquier puerto al azar del tercer grupo, para lo cual he hecho un pequeño script en bash que te da un puerto que será:

  • Mayor de 1023
  • Menor de 65536
  • No estará definido en tu fichero /etc/services
#!/bin/bash
puerto=22
while [ $(cat /etc/services |grep -P "\t${puerto}/"|wc -l) -gt 0 \
        -a $puerto -lt 1023 ] ;
do
 puerto=$(expr $RANDOM \* 2 + $RANDOM % 2 )
done
echo $puerto

Vamos a suponer que cogemos el puerto 33979, el primer paso será otra vez cambiar el fichero /etc/ssh/sshd_config

Port 33979

Parecía fácil y no habría que hacer nada. Pero nos quedan dos cosas más por hacer: Etiquetar el puerto en SELinux -si lo tenemos activado- y revisar el firewall para que deje pasar el nuevo puerto.

SSH con SELinux

Si nuestro equipo es Red Hat o CentOS, seguramente tendremos activado SELinux. Lo podremos comprobar con el comando getenforce o sestatus:

[inthenite@centos8 ~]$ getenforce
Enforcing
[inthenite@centos8 ~]$ sestatus | head -1
SELinux status:                 enabled

Si lo tenemos activado entonces será «tan fácil» como etiquetar el puerto que queramos poner para ssh. Y si no lo hacemos no se levantará el servicio ssh diciéndonos que etiquetemos el puerto, el mensaje aparecerá entre otros sitios en /var/log/messages

[root@centos8 ~]# systemctl restart sshd.service
Job for sshd.service failed because the control process exited with error code.
See "systemctl status sshd.service" and "journalctl -xe" for details.
[root@centos8 ~]# journalctl -xe
may 19 16:58:51 centos8 setroubleshoot[2345]: SELinux is preventing /usr/sbin/sshd from name_bind access on the tcp_socket port 33979. For complete SELinux messages run: sealert -l a428798c-3dd3-4c49-afe0-f
0d5d1c85753
may 19 16:58:51 centos8 platform-python[2345]: SELinux is preventing /usr/sbin/sshd from name_bind access on the tcp_socket port 33979.

   *****  Plugin bind_ports (92.2 confidence) suggests   ************************

   If you want to allow /usr/sbin/sshd to bind to network port 33979
   Then you need to modify the port type.
   Do
   # semanage port -a -t PORT_TYPE -p tcp 33979
       where PORT_TYPE is one of the following: ssh_port_t, vnc_port_t, xserver_port_t.

Ya veis que nos decía hasta el comando que teníamos que poner

# semanage port -a -t ssh_port_t -p tcp 33979
Firewall para SSH

Si una vez que has realizado el cambio e intentas conectar pero empieza a tardar muuuucho tiempo y al final obtienes el mensaje Connection timed out significa que tienes que modificar las reglas del firewall para que se permita la conexión al nuevo puerto de ssh. Aquí hay bastantes opciones, así que para no agrandar este post crearé uno diferente con este tema.

Deshabilitar el acceso por usuario y contraseña al servicio ssh

De esta forma en lugar de permitir que se estén probando pares de usuarios y contraseñas por parte de los malos de forma ilimitada vamos a hacer que sólo pueda entrar el que previamente tenga el certificado. Otra vez volveremos a modificar el fichero /etc/ssh/sshd_config y cambiaremos el valor a no de PasswordAuthentication.

PasswordAuthentication no

Pero antes de reiniciar el servicio de ssh para que coja los cambios en el fichero de configuración hay que crear los certificados para poder acceder. Así que desde una máquina remota ejecutaremos estos dos comandos:

inthenite@debianWP:~$ ssh-keygen
inthenite@debianWP:~$ ssh-copy-id -i .ssh/id_rsa.pub 192.168.1.111

Con el primero comando dejaremos todas las opciones en blanco para no introducir contraseña y para crear los ficheros por defecto id_rsa y id_rsa.pub. Después los copiaremos a la máquina 192.168.1.111 y la próxima vez que intentemos conectar con nuestro usuario a esa máquina nos autenticaremos con el certificado y no con la contraseña, por lo que entraremos directamente. Ya podemos reiniciar el servicio ssh.

Si quieres hacer una conexión desde un Tru64 en vez de un Linux te explico cómo hacerlo.

fail2ban para evitar ataques por fuerza bruta

Si la anterior opción no os interesa por algún motivo y seguís permitiendo entrar a los usuarios introduciendo sus credenciales por teclado entonces os hará falta la herramienta fail2ban que bloquea a las direcciones IP que intentan hacer login con ataques de fuerza bruta. Sirve tanto para nuestro servicio ssh, como para servidores web: apache, nginx, lighttpd; como para clientes de correo web: roudcube, openwebmail, horde; proxys, servidores ftp… En general todo lo que pueda generar en un fichero de log que ha habido un intento de entrada erróneo. A partir de ahí creará una regla en el firewall para bloquear a la dirección IP de donde vienen los intentos de entrada.

Para instalarlo en Debian 10

# apt-get install fail2ban

Para instalarlo en CentOS 8 habrá que añadir primero el repositorio EPEL que es donde está el paquete

# yum install epel-release
# yum install fail2ban fail2ban-systemd

Una vez instalado hay que copiar el fichero de configuración por defecto -que será machacado con la siguiente actualización- a nuestra configuración local

# cd /etc/fail2ban
# cp jail.conf jail.local

Y finalmente activaremos que revise las conexiones entrantes por ssh con la pareja enabled = true esto sirve para cualquier servicio que queramos activar, ya que vienen todos activados por defecto. Yo recomiendo añadir/modificar estos valores. (No los pongáis 2 veces en la misma sección, que entonces no arrancará el servicio fail2ban)

[DEFAULT]
bantime = 8h  # 8 horas de bloqueo al que intente
findtime = 1h # durante la última hora
maxretry = 4  # 4 intentos erróneos de entrada
[sshd] #Jaula para el servicio sshd
enabled = true # Activado! porque por defecto no lo está

Finalmente como todos los servicios hay que hacer que se levanten con el inicio de la máquina y activarlo para que empiece a funcionar

# systemctl enable fail2ban
# systemctl start fail2ban

Como ejemplo podemos ver que después de haber intentado entrar más de maxretry veces desde la IP 192.168.1.93 por ssh se introducen estas reglas en el firewall:

[root@centos8 ~]# iptables -nvL
Chain INPUT (policy ACCEPT 27955 packets, 42M bytes)
 pkts bytes target     prot opt in     out     source               destination
   43  2892 f2b-sshd   tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 22
Chain f2b-sshd (1 references)
 pkts bytes target     prot opt in     out     source               destination
   16   916 REJECT     all  --  *      *       192.168.1.93         0.0.0.0/0            reject-with icmp-port-unreachable
   27  1976 RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0

Resumiendo: Cambia el puerto estándar, deshabilita el acceso root, bloquea los ataques por fuerza bruta y autentícate por certificado. Así de fácil es el hardening o securizar ssh en tu servidor.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.