Universo Ssh I
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.