Universo Ssh I

Índice

Dentro de lo que conocemos como ssh, a parte de ser en la nomenclatura de la IATA del aeropuerto internacional Sharm el-sheij, es un protocolo de comunicaciones el cual se apoyan muchas herramientas no solo ssh como herramienta. Trabaja de forma parecida a telnet, pero impedimenta una seguridad basada en un sistema de intercambio de llaves seguro. Este sistema identifica la identidad de ambos extremos de la comunicación e implementa varios tipos de cifrado mediante un tunel impidiendo que los amigos de lo ajeno se apropien de lo trasmitimos en nuestras comunicaciones. No obstante como ya sabemos nada es !00% seguro, por medio de ataques de REPLAY se puede atacar. Pero nos da cierta seguridad, la cual podemos aumentar con medidas adicionales.

Como en todos los procesos de comunicación tenemos un cliente y un servidor. Lo mas utilizado es un ssh cliente en un extremo y conectar a un servidor para una gestión remota de host los cuales pueden ser servidores, routers, switches, etc. En una serie de artículos nos iremos adentrando por este mundo que nos permite realizar muchas tareas no solo la anteriormente descrita. Sin mas vueltas vamos al lio ya. Algún purista dirá que en articulo falta hablar de conceptos como cifrado asimétrico, hashing, etc. Pero prefiero que sea lo mas practico posible.

Administración remota

El comando ssh esta ampliamente extendido en cualquiera de los sistemas operativos de la familia *nix ( Linux, Bsd, Unix, etc ). En sistemas Windows es necesario instalar un cliente, entre los mas populares esta PuTTY. Pero existen muchísimos mas, para gustos los colores.Lo mas habitual es su utilización para conseguir una Shellremota, por ejemplo, de la siguiente manera:

ssh usuario@host_remmoto
host_remoto Nombre si un dns resuelve o bien dirección ip

Nota: si no se indica usuario se utilizara el que se este logueado en el host desde el que se inicia la comunicación.

Al cliente se le pueden indicar varios parámetros, los mas habituales son:

-p Puerto, por defecto el 22
-4 Fuerza a utilizar IPv4
-6 Fuerza a utilizar IPv6
-B Si tenemos varios interfaces red, indicamos cual utilizar
-b Si tenemos varias direcciones de red, indicamos cual utilizar
-l Usuario, otro modo de indicar el usuario sin @
-t Asignación de un tty remoto para ejecución
-V Muestra la versión
-v Modo depuración, en el caso se tener errores, máximo 3

Ahora vamos a ver una serie de ejemplos de uso para nuestro día a día.

Conexión añadiendo utilizando varios parámetros:

ssh -p 2020 -l usuario 192.168.1.25

Nos conectamos por el puerto 2020 a la ip 192.168.1.25 con el nombre de usuario “usuario”.

Ssh también nos permite la ejecucion de comandos remota de la siguiente manera:

ssh usuario@host_remmoto comando_ejecutar

Si la ejecución remota necesita asignación de un tty, si por ejemplo utilizamos mc es necesario añadir el modificador -t, ejemplo:

ssh usuario@<host_remmoto> mc

Con este comando estaremos ejecutando Midnight Commander en el host remoto. Tener en cuenta que el software que ejecutemos tiene que estar instalado en el host remoto.

El uso del cliente de Ssh desde el terminal nos ofrece cantidad de posibilidades, el tope nuestra imaginación y necesidades. Se pueden hacer cosas muy útiles e interesantes como:

Probar rendimiento de la red en tiempo real:

yes | pv | ssh usuario@<host_remmoto> "cat > /dev/null"

Nota: Lo cortamos con ctrl+c, es continuo si no.

Podemos comparar un archivo local con uno remoto:

ssh usuario@<host_remmoto> "cat archivo_remoto" | diff – archivo_local

Nota: Importante respetar las comillas en la ejecución de cat.

Gestión de paquetes rpm / yum :

ssh root@<host_remoto> 'rpm -qa' | xargs yum -y install

Gestión de paquetes deb :

ssh root@<host_remoto> 'dpkg --get-selections' | dpkg --set-selections && dselect install

De este modo podemos recuperar sesiones remotas utilizando Screen, monitorizar un sistema mediante Nmon, editar archivos remotos, instalar software remotamente, analizar trafico mediante Tsharky capturarlo en un archivo local, etc. Prácticamente lo cualquier cosa que se nos ocurra. Yo por ejemplo en mi archivo .zshrc, utilizo como Shell Zsh, alguno de los alias que tengo para mi trabajo diario son:

alias h1nmon="ssh -t host1 'nmon'"
alias h1vtop="ssh -t host1 'vtop'"
alias h1auth="ssh -t host1 'tail -f /var/log/auth.log | ccze'"

Nota: host1 es un alias configurado previamente en el cliente, configuración que veremos mas adelante.

Transferencia de archivos

La transferencia de archivos utilizando protocolo Ssh es común por muchos motivos, los dos principales seguridad y portabilidad de la solución. Desde el terminal se realiza básicamente de manera interactiva y no interactiva. Para ello el cliente de terminal cuenta con los comandos scp y sftp. A continuación veremos su funcionamiento básico y algún truco que otro.

Scp

El comando scp nos permite la copia de archivos desde un origen a un destino utilizando protocolo Ssh sin poder interactuar. Su uso básico desde un terminal es el siguiente:

scp <parámetro> <origen> <destino>

A continuación vamos a ver varios ejemplos para comprender mejor su funcionamiento y a su vez ver como nos puede ayudar en nuestro trabajo diario.

Copia de local a remoto, archivo:

scp mi_archivo.txt usuario_remoto@host_remoto:/home/usuario_remoto/

Copia de remoto a local, archivo:

scp usuario_remoto@host_remoto:/home/usuario_remoto/mi_archivo.txt home/usuario_local/

Para copiar directorios añadimos el parámetro -r en cualquiera de los dos casos. Podemos aplicar comodines para indicar que copiar, o bien trabajar con . para indicar la directorio donde se ejecuta el comando. Vamos a ver un ejemplo:

scp -r /home/mi_usuario/ usuario_remoto@host_remoto:/home/usuario_remoto/tmp

Con el comando anterior copiamos el home de nuestro usuario y todo su contenido recursiva mente al host remoto en un directorio llamado tmp del home de usuario remoto.

Una de las partes mas interesantes del funcionamiento de scp es que donde se dice origen y destino pueden ser host remotos, no es un condicionante que el alguno de los dos campos tenga que ser el host loca. Es decir si tenemos la necesidad de copiar algo entre dos host remotos al nuestro donde estamos actualmente no tendremos que copiar del host remoto A a nuestro host local y luego de nuestro host local al host remoto B. Vamos a ver un ejemplo para entender esto mejor:

scp usuario_remoto1@host_remoto1:/directorio/archivo.txt usuario_remoto2@host_remoto2:/directorio/

Con el comando anterior estamos ordenando desde nuestro host que se copie archivo.txt del host remoto A la host remoto B. Esto también es aplicable a lo visto anteriormente con directorios y de manera recursiva también.

Otro caso interesante es si queremos copiar solo dos o tres archivos y no podemos utilizar comodines o no queremos hacerlo. Simplemente los separamos con un espacio. Vamos a ver un ejemplo:

scp archivo1.txt informe.odt imagen.png usuario_remoto@host_remoto:/directorio/

Esto copia archivo1.txt informe.odt e imagen.png al host remoto en directorio.

Todo esto es aplicable también a directorios. Podemos combinar todo lo anterior como queramos, el limite nuestra imaginación o necesidad.

Resumen parámetros mas utilizados:

-r Recursivo. 
-P Puerto, por defecto 22.
-p Conserva atributos del origen de la copia.
-c Algoritmo de cifrado, por defecto Triple-DES.
-l Limitamos el ancho de banda a Kbits/s. Por defecto no tiene limite.
-4 Forzamos al uso de IPv4.
-4 Forzamos al uso de IPv6.
-v Activamos modo verbose, por si necesitamos diagnosticar un problema.
-C Habilita la compresión en la transferencia. Por defecto no lo hace.

Nota: Existe diferencia entre los parámetros en las mayusculas y minúsculas.

Sftp

El comando sftp es el que nos permite conectar con el servidor e interactuar con el. Lo primero es conectar con el servidor de la siguiente naneara:

sftp usuario@host_remoto

Esto nos proporciona shell interactiva. Una vez ya conectados lo mejor es teclear help o ?, es lo mismo. Lo cual nos muestra los comandos disponibles para empezar a interactuar. No todos los servidores tienen los mismos. Los mas comunes son:

sftp>help

bye,quit,exit	Cualquiera de los tres nos permite salir del servidor.
cd        Cambiar de directorio remoto.
df        Nos muestra el las estadísticas del directorio actual
get       Descarga archivo.
lcd       Cambia de directorio local.
lls       List contenido local.
lmkdir    Crea directorio local.
lpwd      Muestra directorio local.
ls        Lista contenido del del servidor.
mkdir     Crea directorio en el servidor.
progress  Activa la barra de proceso para la ejecución de comandos.
put       Sube archivo al servidor.
pwd       Muestra directorio actual remoto.
rm        Borra archivo remoto.
rmdir     Borra directorio remoto.
version   Muestra información sobre la versión.
!command  Ejecuta ‘command’ en la shell local.

Sistema de archivos remoto

En la mayoría de los sistemas *nix ( Linux, MacOs, BSD, etc ) tenemos como herramienta disponible para nuestro terminal sshfs, el cual nos permite montar mediante protocolo Ssh un directorio remoto en un directorio local. Su uso desde el terminal es el siguiente:

sshfs usuario@host_remoto:/directorio_remoto /directorio_local <parámetros>

Los parámetros mas habituales son:

-p Puerto si no se usa el estándar.
-C Usar compresión.

Llaves

Después de leer todo lo anterior suelen surgir una serie de dudas o tu mente inquieta a divagar.

  • Y si pudiera automatizar cosas, pero no seria seguro poner contraseñas en los scripts.
  • Que molesto es teclear siempre las contraseñas, alguna manera segura de automatizar el proceso a autenticación tiene que existir.
  • Me gustaría que alguien se conectara sin usuario y contraseña.
  • El utilizar usuario y password se esta quedando obsoleto, alguna otra manera de hacer esto tiene que existir.

Estas son algunas de las preguntas que te pueden asaltar, pues bien si todo esto y mucho mas se puede hacer. Como ?, pues mediante la gestión de identidades utilizando llaves. Ahora vamos a ver como hacer esto y luego como utilizarlas.

Generar identidad, las llaves

Ahora vamos a proceder a generar nuestra identidad. La cual esta compuesta de dos llaves. Una publica que es la que tendremos que distribuir a los servidores que nos proporcionen acceso a servicios vía Ssh y una privada que la guardaremos a buen recaudo.

Para generar nuestras llaves utilizaremos la siguiente linea de comando desde nuestro home de usuario en un terminal:

ssh-keygen -b 4096 -t rsa -C "$(whoami)@$(hostname)-$(date -I)"

Aqui se puede observar el proceso:

Explicación de los parámetros utilizados:

ssh-keygen Comando que genera el par de llaves.
-b 4096    Tamaño de clave simétrica sea de de 4096 bits.
-t rsa     Algoritmo que utilizaremos para generar el par de llaves.
-C         Inserta un comentario.«$(whoami)@$(hostname)-$(date -I)», opcional.

Después de ejecutar el comando, nos preguntará donde queremos guardar las llaves y su nombre. Presionaremos la tecla Enter, dejamos las opciones por defecto, Las llaves se guardarán en el directorio estándar donde esta nuestra configuración de Ssh, que es /home/usuario/.ssh/, y tendrán el nombre estándar.

A continuación nos preguntará si queremos introducir una contraseña para cifrar nuestra clave privada. Como nuestro objetivo conectarnos sin necesidad de introducir ninguna contraseña, presionamos Enter sin introducir ninguna.

Al final nos pregunta que volvamos a introducir la contraseña anterior,como no introducimos ninguna volvemos a presionar Enter.

Nota: Al no teclear una contraseña, la llave privada se almacena guarda en nuestro disco duro sin cifrar. Esto es un riesgo de seguridad. Por este motivo tendremos que ponerla a buen recaudo, podemos cifrar el disco o utilizar ssh-agent con contraseña, entre otras contramedidas. Una vez finalizado el proceso se crearan las llaves en nuestro directorio que almacena nuestra configuración ~/.ssh.

Distribución de las llaves a los servidores

Para copiar nuestra llave publica utilizaremos la siguiente linea de comando desde nuestro home de usuario en un terminal:

ssh-copy-id usuario@host_remoto

Parámetros :

ssh-copy-id Comando que copia la llaves
-i          Indica el archivo de la llave, si fuera necesario
-p          Puerto, por si no fuera el estándar

Yo personalmente prefiero utilizar Magic-Wormhole para el intercambio de llaves. Esto lo explicare en otro post.

Configuración

La configuración de las herramientas de uso del terminal relacionadas protocolo Ssh ( ssh, scp, sftp, etc ) se almacenan en el directorio .ssh de cada usuario. Dentro de este directorio podemos encontrar varios archivos:

id_rsa.pub  Llave publica
id_rsa      Llave privada
known_hosts Lista de llaves publicas conocidas

Bien ahora vamos a añadir un archivo con el nombre config, el cual nos servirá para crear alias, parámetros comunes a uso de las herramientas de terminal, etc, entre otras cosas. Las cuales nos facilitara el trabajo diario. Vamos a ver un ejemplo y comentarlo:

Añadiremos el siguiente bloque al principio del archivo:

### configuración por defecto para todas las conexiones ##
Host *
     User sistemas
     Port 22
     Protocol 2
     IdentityFile ~/.ssh/id_rsa
     IdentitiesOnly yes
     ServerAliveInterval 60
     ServerAliveCountMax 30

Nota: el símbolo ~ es path del home de usuario.

Vamos a ir revisando y explicando cada linea del bloque:

#:                   Nos permite añadir comentarios, no se procesa.
Host:                Define para qué host o hosts se aplica la sección, podemos utilizar comodines como expresión regular (*,!,?). La sección termina con una nueva sección de Host.
User:                Usuario que se utilizara para la conexión.
Port:                Puerto que se utilizara para la conexión.
Protocol:            Versión del protocolo.
IdentityFile:        Especifica la llave de autenticación.
IdentitiesOnly:      Indica que Ssh solo debe usar los archivos de identidad de autenticación, se utiliza por defecto para uso con múltiples identidades.
ServerAliveInterval: Establece un intervalo de tiempo de espera en segundos después del cual, si no se han recibido datos del servidor, evita corte por inactividad.
ServerAliveCountMax: Establece el número veces que se repetirá e “ServerAliveInterval”.

Una vez que tenemos los parámetros globales, al utilizar *, vamos a añadir bloques de host con configuraciones especificas. Veremos varios ejemplos:

## Alias host server1 si coincide algún parámetro general anterior sobre escribe ##
Host server1
     Hostname 10.0.34.10
     User lobezno
     Port 4242
     IdentityFile /nfs/shared/users/lobezno/keys/server1/id_rsa

Que cambia o añade al bloque general:

Hostname:     Indica la ip o nombre de dns al que se conecta.
User:         Indica un usuario especifico distinto al general.
Port:         Indica un puerto especifico distinto al general.
IdentityFile: Indica una llave distinta a la general.

Como se puede observar podemos realizar configuraciones globales o bien especificas según necesidades. Se puede jugar con una gran cantidad de parámetros . Para realizar esta tarea si disponemos de un entorno grafico, no siempre es así, tenemos herramientas como SSH Config Editor para MacOs. Pero nunca esta de mas saber como funciona el archivo para poder sacar el máximo partido. Como consejo final es importante comentar todo lo que se pueda el archivo, que luego tenemos que tocar algo y no sabemos el por que de un parámetro o valor.

SSH Config Editor