Conexión remota segura en Linux: SSH
SSH (Secure SHell) es un protocolo similar a Telnet que permite abrir un shell en una máquina remota, con la diferencia de que SSH encripta toda la información que viaja por la red utilizando criptografía híbrida. Este procolo se implementa con arquitectura cliente-servidor, por lo que necesita:
- un servidor SSH en la máquina remota (por defecto, en el puerto 22 TCP).
- un cliente SSH que nos permita conectarnos al servidor.
En Linux se utiliza la implementación SSH de OpenBSD, denominada OpenSSH (openssh.com/es/, paquetes openssh-server openssh-client), que proporciona varias aplicaciones:
- el servidor SSH (sshd, archivo de configuración /etc/ssh/sshd_config) y el cliente SSH (ssh, archivo de configuración /etc/ssh/ssh_config), que permiten obtener un shell remoto, ejecutar un comando remoto y entunelar protocolos.
- el comando scp (secure copy), que permite copia remota segura de archivos.
- el servidor y el cliente SFTP (Secure FTP) (sftp-server y sftp).
Recursos
- SSH - Smaldone: smaldone.com.ar/documentos/misdocumentos.shtml
- SSH - Luciano: lucianobello.com.ar/openssh/
Obtener un shell remoto con SSH
Veamos detallamente cómo funciona una conexión SSH:
- el servidor arranca con el script de inicio /etc/init.d/ssh.
- el cliente inicia la conexión:
$ ssh usuario@servidor
Podemos utilizar la IP o el nombre del servidor. Si no especificamos el usuario, utilizará el usuario que está realizando la conexión. Por ejemplo, si el usuario francis desde la máquina asterix quiere conectarse a obelix como mario, ejecutará:
francis@asterix:~$ ssh mario@obelix
- el servidor comprueba si el host del cliente tiene permiso para conectar, tras lo cual cliente y servidor intercambian en texto plano sus identificadores de versión, para comprobar si los protocolos soportados coinciden y la comunicación es posible.
- el servidor envía al cliente su clave pública DSA (algoritmo asimétrico) en texto sin cifrar, que el cliente usará para cifrar los mensajes hacia el servidor, haciéndolos sólo legibles para el propio servidor.
- si no es la primera vez que se conecta a ese servidor, el cliente compara la clave
pública recibida del servidor con la que tiene almacenada para verificar su autenticidad.
Si es la primera vez que se conecta a ese servidor y no la tiene almacenada, el cliente no sabe
si la clave pública recibida es realmente la del servidor o la de un impostor que ha
interceptado la conexión, lo que se conoce con el nombre de
ataque man in the middle,
por lo que pide confirmación al usuario para aceptarla como válida:
The authenticity of host obelix (192.168.1.3) can't be established. DSA key fingerprint is e9:df:72:2c:eb:1d:bf:b2:3a:38:96:2a:3b:6b Are you sure you want to continue connecting (yes/no)?
Para confirmarlo el usuario debería obtener el fingerprint por otro medio alternativo y seguro: correo electrónico cifrado, por teléfono, correo postal, en persona, etc. Confirmar la clave sin verificarla adecuadamente implica asumir el riesgo de una posible suplantación. Si confiamos en la clave, le decimos al cliente que continúe con la conexión:
yes Warning: Permanently added obelix (DSA) to the list of known hosts.
Como hemos confiado en la clave pública recibida, el cliente nos informa de que ésta se ha añadido al archivo ~/.ssh/known_hosts, donde se almacenan los hosts conocidos. En adelante cada vez que el cliente se conecte a ese servidor comparará la clave pública recibida al iniciar sesión con la almacenada:
- si son iguales, continuará con el proceso de conexión.
- si son diferentes, nos avisará y pedirá confirmación para el nuevo fingerprint:
key_read failed The authenticity of host obelix (192.168.1.3) can't be established. DSA key fingerprint is e9:df:72:2c:eb:1d:bf:b2:3a:38:96:2a:3b:6b Are you sure you want to continue connecting (yes/no)?
- el cliente genera una clave de sesión (válida sólo para la sesión en curso), selecciona un algoritmo de cifrado simétrico y envía un mensaje conteniendo la clave de sesión y el algoritmo simétrico seleccionado, cifrado con la clave pública DSA del servidor. A partir de este momento todo el tráfico entre cliente y servidor viaja cifrado utilizando el algoritmo de cifrado simétrico seleccionado y la clave de sesión.
- ahora el cliente se debe identificar ante el servidor, cosa que haremos mediante contraseña
(también puede hacerse mediante claves DSA, sin necesidad de password). El servidor solicita
al usuario la contraseña correspondiente a usuario:
mario@obelix's password:
Si el login es válido y no hay restricciones adicionales obtendremos un shell en el servidor SSH, de modo que podremos usar el sistema como si estuviéramos sentados allí, con los privilegios que tenga ese usuario:
mario@obelix:~$
Identificación del cliente mediante clave pública
El cliente puede identificarse mediante clave pública, sin password. Para ello:
- creamos en el cliente una clave RSA:
francis@asterix:~$ ssh-keygen -t rsa -f ~/.ssh/id_rsa
- activamos ssh-agent en el cliente para que no nos pida la pass-phrase:
francis@asterix:~$ eval `ssh-agent -s` Agent pid 12297 francis@asterix:~$ ssh-add Enter passphrase for /home/francis/.ssh/id_rsa: Identity added: /home/francis/.ssh/id_rsa (/home/francis/.ssh/id_rsa)
- copiamos en el servidor la clave pública (~/.ssh/id_rsa.pub):
francis@asterix:~$ scp ~/.ssh/id_rsa.pub mario@obelix:~/.ssh/id_rsa.pub
- la añadimos en el servidor al final del fichero ~/.ssh/authorized_keys:
mario@obelix:~$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
- y comprobamos que podemos iniciar una sesión SSH sin password ni pass-phrase:
francis@asterix:~$ ssh mario@obelix mario@obelix:~$
- para salir de la sesión SSH teclearemos exit, retornando al shell de la máquina cliente:
mario@obelix:~$ exit logout Connection to obelix closed francis@asterix:~$
Ejecutar un comando remoto con SSH
En vez de obtener un shell en la máquina remota, podemos simplemente ejecutar un comando en ella. Para ello, usaremos el cliente SSH con la siguiente sintaxis:
$ ssh usuario@servidor "comando"
Usaremos comillas dobles para evitar que el cliente interprete el comando. Una vez introducido el password se ejecutará el comando, retornando directamente al shell de la máquina cliente. Por ejemplo:
francis@asterix:~$ ssh mario@obelix "cat /etc/hostname"
mario@obelix's password:
obelix
francis@asterix:~$
Copiar un archivo con scp
El comando scp (secure copy) nos permite intercambiar ficheros o directorios (tanto enviar como recibir) entre el cliente y el servidor utilizando SSH. Para copiar recursivamente un directorio usaremos la opción -r. La sintaxis es:
$ scp origen destino
- Para subir archivos o directorios del cliente al servidor la sintaxis sería:
$ scp archivo_local usuario@servidor:directorio_remoto
Por ejemplo:
francis@asterix:~$ scp file1 mario@obelix:/home/mario/
- Para bajar archivos o directorios desde el servidor al cliente la sintaxis sería:
$ scp usuario@servidor:archivo_remoto directorio_local
Por ejemplo:
francis@asterix:~$ scp mario@obelix:/home/mario/file2 ./
En ambos casos nos pedirá el password. Introducimos la contraseña y se copiará el archivo, retornando directamente al shell de la máquina cliente:
Password: file1 100% 2837 KB 702.7 KB/s 00:06 mario@pc266:~$
Servidor SFTP (Secure FTP)
OpenSSH incluye un servidor SFTP que permite enviar y recibir ficheros utilizando SSH: es un servidor FTP encriptado. Cuando un cliente SFTP se conecta al servidor SSH bajo el esquema sftp://, el servidor SSH lanza el proceso hijo sftp-server, que pide el password y establece la conexión.
OpenSSH incluye también un cliente SFTP interactivo de línea de comandos, sftp, que utiliza los mismos comandos que ftp (cd, lcd, get, put, mkdir...) y cuya sintaxis es:
$ sftp usuario@servidor
sftp>
Pero es mucho más cómodo conectar desde un cliente SFTP gráfico como Konqueror:
Entunelar protocolos con OpenSSH (Port Forwarding)
Con OpenSSH se puede crear un túnel encriptado entre dos máquinas y enviar a través de él los datos de otros protocolos (es un tipo de VPN, Virtual Private Network, Red Privada Virtual). Esto es útil, por ejemplo:
- para entunelar protocolos que son inseguros por enviar la información sin cifrar, como Telnet, FTP, HTTP, MySQL, las X, etc.
- para atravesar un firewall donde sólo está permitido SSH.
El único requisito para configurar un túnel SSH es que sea un protocolo basado en TCP, por lo que este método no se puede aplicar a servicios UDP como DHCP, NFS, NetBIOS, etc.
Vamos a verlo con un ejemplo. Desde el cliente queremos hacer consultas al servidor de base de datos MySQL instalado en el servidor. Pero MySQL no soporta conexiones seguras entre los clientes y el servidor, de manera que la identificación de los usuarios remotos y los datos de las consultas serán visibles a cualquier máquina de la red. Por ello, utilizaremos SSH para establecer una conexión segura, de la siguiente manera:
- en el cliente, el cliente MySQL (mysql) hace una petición al puerto 3306 TCP de localhost, donde escucha el cliente SSH (ssh).
- el cliente SSH (ssh) escucha el puerto 3306 TCP y redirecciona las peticiones al servidor SSH (sshd) a través del túnel, de manera que todo el tráfico de datos entre el cliente y el servidor MySQL van cifrados por la red.
- en el servidor, el servidor SSH (sshd) redirecciona el tráfico procedente del túnel al puerto 5000 TCP de localhost, donde escucha el servidor MySQL (mysqld), de manera que éste ve las conexiones como procedentes de la propia máquina.
Veamos cuál es el procedimiento a seguir:
- configuramos el servidor MySQL para que escuche en el puerto 5000 TCP de localhost. Para ello,
editaremos el archivo de configuración /etc/mysql/my.cnf:
[mysqld] #skip-networking bind-address = 127.0.0.1 port = 5000
Una vez reiniciado el servidor MySQL, sólo podremos conectar con la base de datos desde localhost, en la máquina local.
- levantamos el túnel desde el cliente con el siguiente comando (el túnel se establecerá
una vez introducido el password):
francis@asterix:~$ ssh -N -L 3306:127.0.0.1:5000 usuario@servidor Password:
- 3306:127.0.0.1:5000: abre un túnel que conecta el puerto 3306 del cliente con el 5000 del servidor, en cuyos extremos están el cliente y el servidor SSH.
- -N: esta opción establece el túnel, ya que indica no ejecutar comandos remotos.
- -L: indica que este extremo es el cliente del túnel.
- para conectarnos al servidor MySQL desde el cliente tenemos que conectar con el extremo local
del túnel, ejecutando:
francis@asterix:~$ mysql -u root -h 127.0.0.1 -p test Enter password: mysql>
Conectar con un servidor SSH Linux desde Windows
El cliente SSH Putty (chiark.greenend.org.uk/~sgtatham/putty/) nos permitirá conectar con un servidor SSH Linux desde Windows.
9 Comentarios en “Conexión remota segura en Linux: SSH”
Deja un comentario
Me parece un buen post que explica muy bien el funcionamiento de ssh, me ha ayudado mucho.
Mira no se nada de linux, estoy comenzando en este mundo, pero de verdad, tremenda explicacion la que hacen ustedes, los felicito.
hola amigos ahi les dejo un programita en perl para hacer un acceso remoto, respaldar una bd y traerla de regreso. espero les sirva de algo.
se definen 2 variables para las 2 db que tengo pero en lo que puse solo respalda una para la otra se hace exactamente lo mismo.
#!/usr/bin/perl
# Definimos los modulos de perl que vamos a usar
use Net::SSH::Perl;
use Net::SCP::Expect;
# Host del servidor que contiene las BD
$host=”148.211.200.6″;
#Nombre que le pondremos al respaldo sql
$archivo=”CW-Horde.sql”;
$archivo1=”CW-mysql.sql”;
# Ruta donde se dejaran los archivos respaldados
$ruta=”/RESPALDO/BASESDEDATOS/CorreoWeb/”;
#Usuario SSH
$userS=”root”;
$passwordS=”**********”;
#Credenciales de Base de Datos
$user=”respaldo”;
$password=”********”;
# Se hace la conexion ssh al servidor a respaldar
$ssh=Net::SSH::Perl->new($host) or die $!;
$ssh->login($userS, $passwordS);
# Se Respalda la BD horde
($stdout, $stderr, $exit)=$ssh->cmd(”mysqldump -u $user –password=$password horde > $archivo”);
die $! unless (!$exit);
# Creamos la conexion para transferir el archivo – respaldo de BD
$scpe=Net::SCP::Expect->new(host => $host, user => $userS, password => $passwordS) or die $!;
# Transferimos el archivo para horde
#$ssh->cmd(”tar -cf $archivo.tar $archivo”);
$scpe->scp(”$host:$archivo”, “$ruta/$archivo”);
$ssh->cmd(”rm $archivo”);
#mandamos llamar a un sh.
#esto lo hago para mandarle estos parametros a un shell y en el sh le pongo al nombre y la fecha ya dentro de mi #servidor de respaldos
system(`/opt/mueve-nombre.sh $archivo $ruta`);
Muy útil tu información.
Gracias
Aqui dejo un tuto para usar conexión ssh de windows a linux http://notasalgo.es/2008/09/conexion-remota-windows-a-linux-ubuntu-con-ssh/
necesito urgente un software free que me encripte la informacion que se envia por la red inalambrica desde un servidos Centos hacia pc clientes que tienen winxp, en el cual se va a manejar un sistema hecho en PHP con una base hecha en mysql
la verdad es el primer articulo al q le entiendo la explicacion es detalladisima y me va a ayudar un monton con mi deber si pueden ayudarm seria un exito ya q recien estoy empezando y necesito una buena nota…
Se pasaron.
Sin ser un experto, debo admitir que llevo algo de linux en el cuerpo, por lo que siempre leo manuales de todas las paginas que existen de linux, que no son pocas, pero son realmente minoría los tutoriales con esta calidad, hechos para personas que no saben nada o que saben mucho.
Se agradece
Muy interesante el articulo, me ayudo mucho entender como funciona el SSH. Como puedo implementar para acceder a una base de datos SQL Server 2005 que esta detrás de un servidor linux que es mi servidor de Internet. El SQL Server 2005 esta en Windows 2003 y esta en la red local y tiene salida a Internet a través del servidor linux.
Seria algo parecido al ejemplo “Entunelar protocolos con OpenSSH (Port Forwarding)” solo que la base de datos esta en otra maquina (Windows).
Agradezco de ante manos cualquier ayuda que puedan darme.
Saludos.