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.
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..
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
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/*
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.
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.
Si usa systemd
:
systemctl restart ssh
Verificar que quedó corriendo normalmente:
systemctl status ssh
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.
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.
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>