Asegurando el acceso por SSH

En lo que sigue resumimos algunas recomendaciones sobre cómo configurar y asegurar el acceso por SSH a un servidor. En particular desaconsejamos el acceso tradicional mediante usuario y clave. Es mucho más seguro emplear llaves criptográficas (private/public keys).

También se desaconseja permitir el acceso de root desde el exterior. Es preferible impedir el acceso directo de root y sólo habilitar el acceso de un usuario común, que después pueda escalar privilegios mediante su o sudo.

A su vez recomendamos limitar el acceso empleando tcpwrappers y utilizar herramientas como fail2ban o similares para limitar los intentos de acceso ilegal al servidor.

Configuración del cliente de SSH

Crear las llaves criptográficas

Las llaves deben crearse e instalarse en el directorio ~/.ssh (si no existe, crearlo):

cd ~/.ssh
ssy-keygen -t rsa -b 4096 -f nombre_de_la_llave

El comando ssh-keygen genera dos archivos: nombre_de_la_llave (que es la llave privada) y nombre_de_la_llave.pub (con la llave pública).

Cuando pida un passphrase, conviene asignarle uno, para proteger la llave privada. La llave pública se puede distribuir sin problema. La llave privada debe permanecer siempre protegida.

Siempre conviene declarar el tipo de llave (-t rsa) y su tamaño en bits (-b 4096). No conviene usar llaves de menos de 2048 bits. Si se va a utilizar más de una llave, conviene asignarles algún nombre. De no usarse la opción -f el comando ssh-keygen genera nombres automáticamente (id_rsa e id_rsa.pub), pero si ya existen llaves con esos nombres, los va a sobreescribir..

Crear el archivo config

Como la conexión a diferentes servidores puede involucrar diferentes opciones de ssh, conviene crear un archivo config en ~/.ssh, donde podamos declarar, para cada host, las opciones de ssh que queremos usar.

Supongamos que nos interesa ingresar al host servidor.fq.edu.uy, con el usuario juancito, usando la llave ~/.ssh/llave. Para conectarnos tendríamos que ejecutar el comando:

ssh -l juancito -i ~/.ssh/llave  servidor.fq.edu.uy 

En cambio si creamos la siguiente entrada en el archivo ~/.ssh/config:

host servidor
  hostname servidor.fq.edu.uy
  IdentityFile ~/.ssh/llave
  port 22
  user juancito
  protocol 2

Alcanza con ejecutar:

ssh servidor

El comando ssh toma del archivo ~/.ssh/config la configuración correspondiente al host servidor y usa todas las opciones que se declaren allí. El nombre que elijamos como host actúa como un alias y no se hace necesario ejecutar comandos tan largos explicitando las opciones que queremos usar (puede ser un nombre de fantasía). El nombre que usemos como hostname tiene que ser el que está registrado en el DNS, o también puede ser el número de IP.

En el archivo config se pueden agregar todas las opciones disponibles para ssh, conviene consultar el manual para ver todas las opciones diponibles. A su vez, en el archivo config se pueden agregar tantas entradas para host como uno desee o necesite.

Para cada host, se pueden asociar o declarar tantos parámetros como acepte el cliente ssh. Para ver la lista completa de opciones, conviene consultar el manual de ssh y de ssh_config:

man ssh_config
Verificar los permisos en ~/.ssh

Para poder usar las llaves generadas en ~/.ssh es necesario que los permisos sean los adecuados, de lo contrario ssh no va a usar las llaves. Los permisos de los archivos deben ser tales que sólo el usuario dueño de los mismos tenga posibilidad de leerlos y/o modificarlos:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/*

Configuración del servidor SSH

Referencia:

En el archivo /etc/ssh/sshd_config recomendamos agregar o modificar las siguientes opciones:

Obligatorio:

AddressFamily inet
AllowTcpForwarding no
AuthorizedKeysFile .ssh/authorized_keys
ChallengeResponseAuthentication no
GSSAPIAuthentication no
HostbasedAuthentication no
IgnoreRhosts yes
IgnoreUserKnownHosts no
KerberosAuthentication no
LoginGraceTime 30
LogLevel INFO
PasswordAuthentication no
PermitEmptyPasswords no
PermitUserEnvironment no
Protocol 2
PubkeyAuthentication yes
StrictModes yes
SyslogFacility AUTH
UseDNS no
UsePAM yes
X11Forwarding no
Subsystem sftp /usr/lib/openssh/sftp-server

Recomendado:

PermitRootLogin no
DenyUsers root
AllowUsers fulano mengano@192.168.1.10
AllowGroups grupo1 grupo2
ClientAliveInterval 2400

También recomendamos especificar el conjunto de MACs y tipo de cifrado empleado en la comunicación. Agregar las siguientes líneas al archivo sshd_config:

MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
KexAlgorithms curve25519-sha256@libssh.org

También conviene agregar estas últimas líneas a la configuración por defecto de los clientes, en el archivo ssh_config:

Host * 
    MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    KexAlgorithms curve25519-sha256@libssh.org

Verificar que la configuración del servidor quedó bien. Al ejecutar el comando:

sshd -t

no debería devolver ningún error.

Instalar las llaves públicas en el servidor

Ir al directorio ~/.ssh del usuario con el que se desea acceder al servidor. Si el directorio ~/.ssh no existe, crearlo. Agregar al archivo authorized_keys la o las llaves públicas que se desean emplear para acceder al servidor. Ejemplo:

cd ~/.ssh
cat llave.pub >> authorized_keys

Asegurarse que los permisos son los adecuados:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/*

El directorio sólo debería ser accesible y modificable por el usuario. Los archivos sólo deberían ser leibles y modificables por el usuario.

Reiniciar el servicio de SSH

Si usa systemd:

systemctl restart ssh

Verificar que quedó corriendo normalmente:

systemctl status ssh

Restringiendo acceso

Configrando TcpWrapper

En el archivo /etc/hosts.deny agregar:

sshd: ALL

En el archivo /etc/hosts.allow agregar los dominios, IPs o rangos de IPs (CIDR) desde donde sea permitido acceder por ssh al servidor:

sshd: anteldata.net.uy fq.edu.uy 180.34.23.15 164.73.160.0/22 

Si se desea limitar a IPs que estén registrados en DNS de Uruguay, se puede poner algo así:

sshd: .uy

Pero esto tiene el incoveniente de que no siempre los IPs están convenientemente registrados en los servidores de DNS. Para resolver el dominio a que perteneces un IP, debe existir el correspondiente registro reverso en el DNS y esto no siempre ocurre. En particular es bastante habitual que Antel no tenga todos sus IPs con el registro reverso. También ocurre algo parecido dentro de la UdelaR. En ese caso conviene emplear alguna otra estrategia, como por ejemplo emplear algún script para consultar una base de datos de IPs asignados a países.

Configurando un script para controlar acceso con tcpwrappers

En lugar de limitar por IP, rango de IP o dominio, también es posible configurar tcpwrappers para que use un script evalúe si aceptar o no una conexión. Si el script devuelve exit 0, la conexión se acepta, si devuelve un valor diferente de cero, la conexión se rechaza.

En /etc/hosts.allow poner:

sshd: ALL: aclexec /usr/local/bin/ipfilter.sh %a

donde el script /usr/local/bin/ipfilter.sh cumple la función de evaluar si el IP (recibido por %a) tiene permiso para acceder por ssh o no.

Control con fail2ban

fail2ban permite limitar los intentos de acceso por fuerza bruta y otro tipo de abusos que provengan del exterior. No sólo sirve para controlar el servicio ssh sino también cualquier otro servicio de iternet (ftp, email, pop3/imap, etc.).

fail2ban debe configurarse adecuadamente para que revise ciertos logs del sistema, a fin de detectar alguna situación de abuso y luego proceder a bloquear el IP de donde provenga.

Si bien fail2ban viene provisto de una amplia variedad de filtros y acciones, no alcanza con instalarlo, hay que habilitar explícitamente los servicios que se desean controlar y las acciones que se desean efectuar cuando se detecta el abuso de un servicio determinado.

Incluso conviene verificar, usando fail2ban-regex, si las expresiones regulares que tiene definidas en sus filtros, funcionan correctamente, haciendo alguna prueba con algún logfile que tenga los abusos que se desea detectar.

fail2ban <logfile>  <regex>

Auditar el servidor

Recomendamos instalar y correr algún software que verifique la vulnerabilidad del servidor. Puede ser ssh-audit, Lynis o similar.

Suele ser recomendable atender los consejos que éstas u otras herramientas similares sugieran como resultado de su diagnóstico.