Conexiones seguras con SSH en Linux

Share on facebook
Share on twitter
Share on linkedin
Share on whatsapp
Share on telegram
Share on email

SSH es un protocolo de comunicaciones que proporciona seguridad criptográfica cuando nos conectamos a un servidor para iniciar una sesión o transfereir archivos por SFTP o SCP.

Los comandos SSH, SFTP y SCP utilizan el mismo puerto de comunicaciones, que es el 22.

De hecho, SSH se ha convertido en el estándar de conexión a cualquier servidor UNIX, precisamente, para que los hackers no puedan espiar los datos que enviamos a los servidores a los que nos conectamos, como nuestro usuario y contraseña, por ejemplo.

Antiguamente, nos conectábamos a los servidores mediante telnet o relogin, por ejemplo, pero estos protocolos no estaban cifrados y, por lo tanto, eran vulnerables a un ataque.

En Linux, el demonio SSH se arranca con el boot del sistema y está configurado como servicio.

Ejemplo en Centos 7:

# ps -ef |grep ssh |grep -v grep
root 965 1 0 Sep23 ? 00:00:17 /usr/sbin/sshd -D
root 30020 965 0 10:18 ? 00:00:00 sshd: centos [priv]
centos 30022 30020 0 10:18 ? 00:00:00 sshd: [email protected]/0
# systemctl list-unit-files |grep -i ssh
sshd-keygen.service static
sshd.service enabled
[email protected] static
sshd.socket disabled
#

Si el servicio SSH está arrancado y disponemos de un usuario y contraseña, podremos utilizar un cliente SSH para conectarnos al servidor o utilizar el comando SSH.

# ssh 192.168.1.2
[email protected]'s password: 
#

Creación de una relación de confianza SSH entre dos servidores

A los administradores de sistemas y aplicaciones les puede ser muy útil conectarse por SSH a un servidor remoto sin que éste pida usuario y contraseña.

Para ello podemos crear una relación de confianza entre un usuario y servidor origen y un usuario y servidor destino.

Lo primero que tenemos que hacer es crear un fichero de intercambio de claves:

[[email protected] ~]$ ssh-keygen -t rsa Generating public/private rsa key pair. 
Enter file in which to save the key (/home/usuario1/.ssh/id_rsa): 
Created directory '/home/usuario1/.ssh'. 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/usuario1/.ssh/id_rsa. 
Your public key has been saved in /home/usuario1/.ssh/id_rsa.pub. 
The key fingerprint is: 
1f:2a:14:34:4c:fb:22:37:c4:45:79:1f:d6:6f:c3:11 [email protected] The key's randomart image is: 
+--[ RSA 2048]----+ 
| o.. | 
| o +.. | 
| . + .o | 
| . E .o | 
| =S.+ . | 
| oo+o o | 
| . .+o . | 
| o.... | 
| .oo. | 
+-----------------+ 
[[email protected] ~]$

Con este comando habremos generado el fichero de clave pública y el de clave privada.

[[email protected] .ssh]$ ls -la 
total 12 drwx------ 2 usuario1 usuario1 36 nov 25 19:23 . drwx------ 8 usuario1 usuario1 4096 nov 25 19:23 .. -rw------- 1 usuario1 usuario1 1679 nov 25 19:23 id_rsa 
-rw-r--r-- 1 usuario1 usuario1 399 nov 25 19:23 id_rsa.pub 
[[email protected] .ssh]$

El contenido del fichero de la clave pública lo añadiremos al fichero $HOME/.ssh/authorized_keys del usuario y servidor destino. Lo podemos copiar y pegar, directamente o utilizar el comando ssh-copy-id de la siguiente manera:

ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected]

Una vez creada la relación de confianza ya podemos entrar al servidor de destino sin que nos pida contraseña. Por ejemplo:

[[email protected] .ssh]$ ssh [email protected]
[[email protected] .ssh]$

Evitar que SSH pregunte por la autenticidad del servidor

La primera vez que establecemos una conexión SSH contra un servidor remoto, SSH nos avisa de que la autenticidad del servidor todavía no ha sido establecida:

-bash-4.1$ ssh lremdot1
The authenticity of host 'lremdot1 (10.49.0.186)' can't be established.
RSA key fingerprint is 7d:56:4e:b0:8f:42:4d:01:40:0b:f0:67:10:82:8b:46.
Are you sure you want to continue connecting (yes/no)?

Para evitar que SSH nos haga esta pregunta, algo que viene bien cuando administramos cientos de servidores y tenemos playbooks con Ansible para administrarlos, tenemos que configurar el siguiente fichero:

[[email protected] .ssh]# pwd
/root/.ssh
[[email protected] .ssh]# cat config
Host *
   StrictHostKeyChecking no
   UserKnownHostsFile=/dev/null
[[email protected] .ssh]#

Copiar ficheros por SCP a un servidor remoto

El comando scp copia ficheros o directorios completos de manera recursiva de un servidor origen a un servidor y path destinos de manera completamente cifrada. La sintaxis es muy sencilla:

# scp -p vgdisplay.txt servidor2:$PWD
vgdisplay.txt 100% 16KB 
16.3KB/s 00:00 
#

Exportar una variable de entorno por SSH

Es posible que necesitemos exportar el valor de una variable al servidor remoto para que pueda funcionar correctamente la ejecución de un script en bash. Lo haremos de la siguiente manera:

ssh remote_server -n “export PATH=$PATH:/scripts; mi_script.sh”

Creación de un túnel SSH

Los túneles SSH se utilizan para conectarnos a una IP y un puerto remotos a los que no tenemos acceso directo pero sí mediante un servidor intermedio.

Hace tiempo creé el siguiente manual para un equipo de aplicaciones de mi empresa que me servirá:

Escenario

  • Queremos acceder desde nuestro PC local hacia una IP y puerto remota a la que no tenemos acceso directamente.
  • Servidor destino:
    • caifor.es
    • IP fija del servidor destino: 172.23.66.42
    • IP NAT del servidor destino, al que solamente tenemos acceso desde la estación de salto sshgreiemea01.omc.hp.com: 29.80.0.22
    • IP virtual del servicio al que realmente queremos acceder (ubicada en el servidor secaiasp05): 172.23.66.55:7009.
    • Desde la estación de salto no hay conexión directa a la IP y puerto del servicio. Solamente tenemos conexión SSH.

Creación del primer túnel

  • Nos conectamos por SSH a la estación de salto.
  • Desde la estación de salto nos conectamos al servidor de destino por SSH, pero redirigimos el puerto del servicio (172.23.66.55:7009) al puerto local de la estación de salto 1234.

-bash-3.2$ netstat -an |grep 1234
-bash-3.2$ ssh -L 1234:172.23.66.55:7009 secaiasp05.caifor.es
Password:

  • Si volvemos a entrar en la estación de salto, podremos comprobar que ahora hay escuchando el puerto 1234.
-bash-3.2$ netstat -an |grep 1234
tcp        0      0 127.0.0.1:1234              0.0.0.0:*                   LISTEN
tcp        0      0 ::1:1234                    :::*                        LISTEN
-bash-3.2$

Creación del segundo túnel

Como desde nuestro PC local no tenemos acceso al puerto 1234 de la estación de salto, tenemos que crear un segundo túnel. Lo haremos con nuestro cliente de SSH que utilizamos actualmente.

En este ejemplo, abriremos el puerto 1234 en nuestro PC local, para que se conecte al puerto 1234 de la estación de salto (que está redirigido a la IP y puerto del servicio al que queremos acceder 172.23.66.55:7009).

Lo haremos de la siguiente manera. En este caso, utilizo el cliente de ssh SecureCRT.

A continuación, abriremos nuestro navegador local para acceder al servicio mediante la URL: http://localhost:1234/console (en realidad, el servicio está sirviendo en el servidor mediante la URL http://172.23.66.55:7009/console).

Túnel SSH con Putty

Si usamos Putty, uno de los programas más utilizados para conexiones SSH, en vez de SecureCrt, crearemos el túnel desde el menú «Tunnels», tal y como muestro en la siguiente captura de pantalla:

Creacion de un Tunel SSH con putty

Túnel SSH con Moba XTerm

Moba XTerm es otro de los clientes SSH más utilizados. El mismo túnel que hemos creado previamente con Putty, lo haríamos de la siguiente manera con Moba XTerm:

Túnel SSH con Moba XTerm
Arrancar el tunel SSH creado con Moba XTerm

Probemos un túnel SSH con Moba Xterm al puerto 22 para conectarnos a un servidor final al que sólo podemos conectarnos a través de una estación de salto:

Tunel SSH al puerto 22 de un servidor remoto con Moba XTERM

La conexión SSH desde mi portátil a localhost:22 llega al servidor de destino:

Conexion SSH con un tunel creado con Moba Xterm

Evitar la desconexión de una sesión SSH en Linux

Es una buena práctica configurar reglas de firewalls para eliminar las conexiones «zombies», por ejemplo, cada 2h, ya que no sería normal establecer una sesión durante tanto tiempo sin que se envíe nada de tráfico. De esta manera, cuidamos de los recursos de red del entorno y liberamos los sockets que no están en uso.

Sin embargo, puede ser útil en algunos casos establecer un parámetro de Keep alive para enviar algo de tráfico cada cierto tiempo para que no se nos caiga la conexión. Esto lo podemos hacer tanto del lado del servidor SSH como del cliente.

Configuración del KeepAlive para conexiones SSH desde el cliente MoBaXTerm

Ejemplo de activación del keepAlive desde el cliente SSH Moba XTerm:

Configuración de KeepAlive desde el servidor SSH en Linux

En cuanto a la configuración del servidor SSH, en Linux RedHat configuraremos los siguientes parámetros:

[root ~]# grep -i alive /etc/ssh/sshd_config
TCPKeepAlive yes
ClientAliveInterval 60
ClientAliveCountMax 5
[root ~]#

Una vez configurados, reiniciaremos el servicio de SSH.

El parámetro ClientAliveInterval 60 se refiere a que se enviará tráfico cada 60 segundos para que no muera la sesión SSH.

Conexiones SFTP enjauladas

Cuando configuramos un servicio SFTP para transferir archivos de manera segura, es conveniente que el usuario externo que se conecta únicamente pueda ver el contenido del directorio donde están los datos que queremos que vea y nunca los directorios del resto del sistema.

Por ejemplo, podemos enjaular una conexión SFTP en el directorio /sftp y el usuario no podrá ir más atrás. Por ejemplo, no podrá ir a «/» o a «/opt».

Mejor vemos con un ejemplo cómo enjaular usuarios por SFTP:

  • Creamos el usuario que vamos a enjaular:
# groupadd -g 60000 sftpusers
# useradd -c "chrooted SFTP user" -s /bin/false -G sftpusers -u 50016 sftpuser
# id sftpuser
uid=50016(sftpuser) gid=50016(sftpuser) groups=50016(sftpuser),60000(sftpusers)
#

A modo de recordatorio, en caso de que te equivoques a la hora de crear el usuario o el grupo, siempre puedes modificarlos con los comandos usermod groupmod, respectivamente.

  • Habilitamos la shell de SFTP:
# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/tcsh
/bin/csh
/bin/dash
/bin/mksh
/usr/libexec/openssh/sftp-server
/bin/false
#
  • Configuramos los permisos correspondientes en el directorio /sftp:
# chown root:root /sftp
# chown sftpuser:sftpusers /sftp/sftpuser
#
  • Configuramos las siguientes directivas el fichero /etc/ssh/sshd_config:
UsePAM yes 
UsePrivilegeSeparation yes 
StrictModes yes 
PermitEmptyPasswords no 
# change default 
# Subsystem sftp /usr/libexec/openssh/sftp-server 
Subsystem sftp internal-sftp 
#Enjaulamiento del usuario sftpuser en /sftp
Match User sftpuser
ChrootDirectory /sftp
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
  • Reiniciamos el servicio ssh (service sshd restart o systemctl restart sshd).
  • Nos conectamos por SFTP:
$ sftp [email protected]
Connecting to testserver...
[email protected]'s password: 
sftp> cd /
sftp> ls -la
drwxr-xr-x 4 0 0 1024 Feb 11 07:50 .
drwxr-xr-x 4 0 0 1024 Feb 11 07:50 ..
drwx------ 2 0 0 12288 Feb 11 07:34 lost+found
drwxr-xr-x 2 50016 60000 1024 Feb 11 07:50 sftpuser
sftp>

Como vemos, el directorio raíz es /sftp y no podemos ir más atrás.

Puede que te interese saber cómo crear una clave informática en Amazon AWS IAM, que nos servirá para la conexión por SSH a los servidores Linux del cloud de Amazon.

Conexión SFTP en modo Batch

Podemos ejecutar instrucciones por lotes por SFTP para enviar comandos SFTP en una línea de comandos:

  • Opción 1 – Los comandos SFTP los guardamos en un fichero de texto
[root]# cat mia.batch 
ls
[root]#

[root]# ./prueba_sftp.sh 217.125.40.69 55689 mia_sftp mia314987 mia.batch 
spawn /usr/bin/sftp -o BatchMode no -b mia.batch -o port=55689 [email protected]
[email protected]'s password: 
sftp> ls
IN_DES    IN_PROD   OUT_DES   OUT_PROD  
[root]#
  • Opción 2 – Los comandos SFTP son introducidos en una sola línea de comandos:
[root]# sftp -oBatchMode=no -b - lhpilox01 << END
> lcd /var/opt/OV/conf/OpC
> get /planific/bin/admsys/menu_post_provisioning/menu/aprov/OVO/UXMONperf_PRO.cfg
> END
sftp> lcd /var/opt/OV/conf/OpC
sftp> get /planific/bin/admsys/menu_post_provisioning/menu/aprov/OVO/UXMONperf_PRO.cfg
Fetching /planific/bin/admsys/menu_post_provisioning/menu/aprov/OVO/UXMONperf_PRO.cfg to UXMONperf_PRO.cfg
[root]#

Modificación de la máscara por defecto de un SFTP enjaulado (umask)

Si nos interesa que un usuario que se conecta por SFTP deje los ficheros con unos permisos concretos, lo que tenemos que hacer es configurar la máscara de SFTP para ese usuario concreto.

Para ello, editaremos el fichero /etc/ssh/sshd_config y reiniciar el servicio de SSH. Veamos un ejemplo:

  • Configuramos el fichero sshd_config para el usuario «test»:
Match User test
#OpenSSH inferior a 5.4
ForceCommand internal-sftp -m 700
# OpenSSH igual o superior a 5.4
# ForceCommand internal-sftp -u 007
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp

Importante: La directiva «ForceCommand internal-sftp -m 700» tiene que estar debajo de «Match User», sino, se ignora.

  • Reiniciamos el servicio de ssh con el comando service sshd restart en RedHat 6 o systemctl restart sshd en RedHat 7.
  • Subimos un fichero de test para comprobar que su máscara es la que hemos configurado:
[[email protected] ssh]# sftp [email protected]
Connecting to localhost...
+---------------------------------------------------------------------+
|                                                                     |
|  Use of this network is restricted to authorized users only. User   |
|  activity may be monitored and/or recorded. Anyone using this       |
|  network expressly consents to such monitoring and/or recording.    |
|                                                                     |
|  BE ADVISED: if possible criminal activity is detected, these       |
|  records, along with certain personal information, may be provided  |
|  to law enforcement officials.                                      |
|                                                                     |
+---------------------------------------------------------------------+

[email protected]'s password:
Permission denied, please try again.
[email protected]'s password:
sftp> put /tmp/test.txt
Uploading /tmp/test.txt to /home/test/test.txt
/tmp/test.txt                                                                                                                                                   100%    0     0.0KB/s   00:00
sftp> ls -la
drwx------    2 test     test         4096 Feb 25 12:50 .
drwxr-xr-x   20 root     root         4096 Feb 25 12:46 ..
-rw-r--r--    1 test     test           18 Feb 15  2017 .bash_logout
-rw-r--r--    1 test     test          176 Feb 15  2017 .bash_profile
-rw-r--r--    1 test     test          124 Feb 15  2017 .bashrc
-rw-r--r--    1 test     test          500 Nov 27  2014 .emacs
-rw-r--r--    1 test     test          124 Oct 21  2016 .mkshrc
-rwx------    1 test     test            0 Feb 25 12:50 test.txt
sftp> exit

Como vemos, el fichero «test» tiene máscara rwx para el propietario del fichero y ningún permiso para el grupo y resto de usuarios.

Te podría interesar

¿Te ha gustado? ¡Compártelo!

Share on facebook
Share on twitter
Share on linkedin
Share on whatsapp
Share on telegram
Share on email

SUSCRÍBETE A PUERTO53

Recibe un email periódico con los artículos más interesantes de Puerto53.com

Antes de suscribirte lee los términos y condiciones. Gracias.

Contenido Relacionado

Artículos Recientes

Deja un comentario

About Author