Tradicionalmente el intercambio de datos entre sistemas Unix (desde la
transferencia de ficheros o la compartición de archivos vía NFS hasta el
acceso remoto) se ha realizado utilizando mecanismos en los que la seguridad
era un factor poco importante frente a otros como la velocidad o la
disponibilidad. Sin embargo, conforme ha ido aumentando
la calidad de los medios de transmisión (en la actualidad cualquier pequeña
organización tiene al menos una red Fast Ethernet capaz de alcanzar
velocidades de 100 Mbps, cuando no una ATM, una FDDI o incluso una GigaEthernet
que alcanza los 1000 Mbps de velocidad), y también conforme ha ido aumentando
la peligrosidad de las redes, especialmente de Internet, se ha ido considerando
más el grave problema que implica una transmisión de datos en texto claro,
ya sea un telnet, un ftp o incluso la transmisión de datos que
tiene lugar al utilizar sistemas de ficheros en red. Por suerte, en la
actualidad, casi nadie sigue usando los medios clásicos de intercambio de
datos entre equipos Unix: por ejemplo, muy poca gente sigue conectando mediante
telnet a máquinas remotas, mientras que hace unos pocos años era
habitual ver estas conexiones incluso entre máquinas separadas por multitud
de redes. Casi todos los mecanismos clásicos se han reemplazado por
protocolos que incorporan el cifrado en mayor o menor medida, de forma que
un pirata que captura datos transmitidos entre sistemas lo tiene muy
difícil para conseguir información importante, como una clave de
usuario; ejemplos de protocolos que incorporan la criptografía son SSL
(Secure Socket Layer) o TCFS (Transparent Cryptographic File
System, del que ya hemos hablado en este proyecto).
Dentro de todo estos modelos considerados seguros está Secure Shell
(SSH), un software cuya principal función es permitir la
conexión remota segura a sistemas a través de canales inseguros, aunque
también se utiliza para la ejecución de órdenes en ese sistema remoto o
transferir ficheros desde o hacia él de manera fiable ([Ylo96]); es,
por tanto, el
sustituto ideal de órdenes como telnet, ftp o r de
Unix BSD. Todo esto utilizando RSA, SecurID, Kerberos, TIS o la autenticación
clásica de Unix (login y password). Además, y entre otras
características, SSH también soporta el cifrado automático
en sesiones X-Window o modelos de seguridad más avanzados, como el cifrado en
NFS o la construcción de redes privadas virtuales; su código fuente es
libre para uso no comercial (existe otro software casi completamente
compatible con ssh y completamente libre, denominado OpenSSH) y se
puede obtener en http://www.ssh.fi/. En la actualidad, SSH funciona sobre la mayoría de clones de Unix (también existen
versiones para Windows y MacOS), y es ampliamente utilizado en todo tipo de
entornos, desde universidades a bancos pasando por empresas de cualquier
sector.
SSH está formado por un programa servidor, sshd, varios
programas cliente (ssh y scp principalmente) y pequeñas
aplicaciones para su
configuración, como ssh-add, ssh-keygen o ssh-agent. El
programa demonio
(sshd) se ejecuta en la máquina contra la cual conectamos, mientras
que los clientes se han de ejecutar evidentemente en el sistema desde el cual
conectamos; así, podemos iniciar una sesión en la máquina remota con
una orden como la siguiente:
anita:~# ssh -l toni rosita
toni's password:
Last login: Thu Apr 6 03:58:32 2000 from anita
Linux 2.2.6
"A witty saying proves nothing."
-- Voltaire
rosita:~$
El parámetro `-l' nos permite indicar el nombre de usuario en el
sistema remoto (en caso contrario, se utilizará el mismo nombre que se posee
en la máquina local); SSH también permite especificar desde
línea de comandos una orden a ejecutar en la máquina a la que
conectamos, de forma que cuando esta orden finalice se cerrará la conexión
entre ambos sistemas:
anita:~# ssh -l toni luisa w
toni's password:
3:15am up 5 days, 1:30, 5 users, load average: 1.12, 1.04, 1.01
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty1 - Sat12am 5days 0.02s 0.02s bash
toni ttyp1 :0.0 Sun 3pm 1:02 0.18s 0.13s telnet rosita
toni ttyp2 :0.0 Sun 4am 2.00s 2.40s 2.04s vi tools.tex
toni ttyp4 anita Tue 1am 0.00s 1.31s 0.02s w
anita:~#
Como hemos podido ver, ssh se utiliza básicamente para iniciar sesiones
o ejecutar comandos en un sistema remoto; el otro programa cliente, scp,
es utilizado para transferir ficheros entre máquinas, de una forma similar
a rcp, lo que por ejemplo permite sustituir el ftp tradicional por
este mecanismo. Si por ejemplo deseamos copiar todos los ficheros del
directorio /export/home/toni/ conectando al sistema remoto bajo el nombre
de usuario toni en el directorio /tmp/ de la máquina local, lo
podemos conseguir con una orden como esta:
luisa:~# scp -r toni@anita:/export/home/toni/ /tmp/
toni's password:
luisa:~#
Como podemos ver, estamos indicando el nombre de usuario y el del sistema
remotos separados por `@', y separados a su vez de la ruta origen por
el signo `:'.
Pero, >qué es lo que realmente hace cualquiera de estos clientes contra el
servidor sshd? Si no indicamos lo contrario con la opción `-p',
el cliente
conecta al puerto 22 de la máquina servidora y verifica que esta máquina
es realmente con la que queremos conectar, intercambia las claves de cifrado
entre sistemas (cifradas a su vez, para evitar que un atacante pueda obtener
la información) y autentica utilizando .rhosts y /etc/hosts.equiv
(como los protocolos r-), RSA o claves de usuario; si todo es
correcto, el servidor asigna una terminal virtual (generalmente) a la conexión
y lanza un shell interactivo. Podemos ver con detalle este proceso
utilizando la opción `-v' del cliente:
luisa:~# ssh -v -l toni luisa
SSH Version 1.2.21 [i486-unknown-linux], protocol version 1.5.
Standard version. Does not use RSAREF.
luisa: Reading configuration data /etc/ssh_config
luisa: ssh_connect: getuid 0 geteuid 0 anon 0
luisa: Connecting to luisa [192.168.0.2] port 22.
luisa: Allocated local port 1023.
luisa: Connection established.
luisa: Remote protocol version 1.5, remote software version 1.2.21
luisa: Waiting for server public key.
luisa: Received server public key (768 bits) and host key (1024 bits).
luisa: Host 'luisa' is known and matches the host key.
luisa: Initializing random; seed file /root/.ssh/random_seed
luisa: Encryption type: idea
luisa: Sent encrypted session key.
luisa: Received encrypted confirmation.
luisa: Trying rhosts or /etc/hosts.equiv with RSA host authentication.
luisa: Remote: Rhosts/hosts.equiv authentication refused:\
client user 'root', server user 'toni', client host 'luisa'.
luisa: Server refused our rhosts authentication or host key.
luisa: No agent.
luisa: Doing password authentication.
toni's password:
luisa: Requesting pty.
luisa: Failed to get local xauth data.
luisa: Requesting X11 forwarding with authentication spoofing.
luisa: Requesting shell.
luisa: Entering interactive session.
Last login: Thu Apr 6 04:13:41 2000 from luisa
Linux 2.2.6
If you want divine justice, die.
-- Nick Seldon
luisa:~$ exit
logout
Connection to luisa closed.
luisa: Transferred: stdin 5, stdout 491, stderr 29 bytes in 2.6 seconds
luisa: Bytes per second: stdin 1.9, stdout 189.0, stderr 11.2
luisa: Exit status 0
luisa:~#
Como sucede en cualquier programa cliente-servidor, la configuración de la
parte cliente es mucho más sencilla que la de la parte servidora: ni
siquiera es necesario el fichero de configuración general /etc/ssh_config, donde se definen parámetros por defecto (que cada
usuario puede modificar para sí mismo en sus propios ficheros o en
línea de órdenes). Sólamente necesitamos el ejecutable (por ejemplo,
ssh),
que generará en el directorio $HOME/.ssh de quien lo ejecute varios
ficheros necesarios para su funcionamiento; quizás el más importante sea
known_hosts, donde se almacenan las claves públicas de los diferentes
sistemas a los que se conecta. Estas claves, una por línea, se guardan la
primera vez que se conecta a una determinada máquina, algo que el cliente
indica con un mensaje de esta forma:
rosita:~# ssh -l toni luisa
Host key not found from the list of known hosts.
Are you sure you want to continue connecting (yes/no)? yes
Host 'luisa' added to the list of known hosts.
toni's password:
Last login: Thu Apr 6 23:20:42 2000 from :0.0
Linux 2.2.6
Drive defensively. Buy a tank.
luisa:~$
Por su parte, la configuración del servidor es algo más compleja; en el
archivo /etc/sshd_config, fichero de configuración del demonio sshd, se especifican todos los parámetros necesarios para su funcionamiento.
Algunos de estos parámetros, quizás los más útiles, son AllowHosts
y DenyHosts, donde como su nombre indica se referencian los sistemas desde
los que la conexión a nuestro demonio se permite o se deniega; al contrario
de lo que mucha gente sigue pensando, utilizar SSH no implica tener
disponible el servicio para todo el mundo, y es aquí donde indicamos los
sistemas desde donde permitimos conexiones. Además, podemos servir sshd
desde inetd modificando convenientemente /etc/inetd.conf en lugar
de hacerlo como demonio independiente, de forma que podemos aprovechar un
software como TCP Wrappers para restringir conexiones; el único
inconveniente de este modelo es que cada vez que alguien conecta al demonio
éste tiene que generar una clave RSA para esa conexión, lo que en
determinadas situaciones puede sobrecargar demasiado al sistema. Si de cualquier
forma queremos seguir este mecanismo, hemos de modificar /etc/services
para añadir una línea como la siguiente:
ssh 22/tcp
Y también modificaremos /etc/inetd.conf añadiendo la configuración
del nuevo servicio:
ssh stream tcp nowait root /usr/sbin/tcpd /usr/local/sbin/sshd -i
Tras lo cual, como cada vez que modificamos este archivo, hemos de conseguir que
inetd lo relea enviándole al demonio la señal SIGHUP.
© 2002 Antonio Villalón Huerta