SSH es un protocolo de red y un conjunto de estándares que permiten una conexión encriptada entre dos computadoras. Usa criptografía de clave pública para autentificar al computador y al usuario. Por defecto suele usar el puerto TCP 22.
SSH soporta autentificación basada en RSA. RSA fué el primer algoritmo publicado que permite el encriptado y la firma digital. Se cree que es seguro si las claves son lo suficientemente largas. Se usa aún en comercio electrónico. Una opción alternativa es DSA que corresponde a Digital Signature Algorithm. DSA es propiedad del gobierno de los Estados Unidos de America.
Hay criptosistemas -a los que RSA pertenece - en los cuales el encriptado y desencriptado se hace utilizando claves separadas y no es posible derivar la clave de desencriptado del conocimiento de la clave de encriptado. El cliente utiliza un par de claves pública/privada para la autentificación. El servidor sólo conoce la clave pública. Funciona como una pareja llave/cerradura en la que el conocimiento de la cerradura no permite deducir la forma de la llave.
Para la generación de una pareja de claves pública-privada
se realiza ejecutando en el cliente ssh-keygen
:
$ ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/user/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/user/.ssh/id_rsa. Your public key has been saved in /home/user/.ssh/id_rsa.pub. The key fingerprint is: xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx user@machine
Las claves se almacenan por defecto en ~/.ssh/
,
quedando el directorio así:
$ ls -l total 12 -rw------- 1 user user 883 2005-08-13 14:16 id_rsa -rw-r--r-- 1 user user 223 2005-08-13 14:16 id_rsa.pub -rw-r--r-- 1 user user 1344 2005-08-04 02:14 known_hosts
Los ficheros id_rsa
e id_rsa.pub
contienen respectivamente
las claves privada y pública. El
fichero known_hosts
contiene
la lista de las claves públicas de las máquinas
reconocidas.
Ahora se debe copiar la clave pública al servidor,
al fichero ~/.ssh/authorized_keys
.
Para ello se utiliza el comando ssh-copy-id:
$ssh-copy-id -i ~/.ssh/id_rsa.pub user@machine1 $ssh-copy-id -i ~/.ssh/id_rsa.pub user@machine2
ssh-copy-id
es un script que se conecta a la máquina
y copia el archivo (indicado por la opción -i
) en
~/.ssh/authorized_keys
, y ajusta los permisos a
los valores adecuados.
Si no se dispone del programa ssh-copy-id
se puede realizar una
copia manual a la máquina remota del fichero conteniendo la clave
pública (por ejemplo usando scp
o sftp
)
y añadir su contenido al fichero ~/.ssh/authorized_keys
.
Ahora la conexión debería funcionar sin necesidad de introducir la clave. Si no es así es posible que sea un problema de permisos en los ficheros. Los permisos correctos deben ser similares a estos:
$ chmod go-w $HOME $HOME/.ssh $ chmod 600 $HOME/.ssh/authorized_keys
Es posible indicarle a ssh
nuestra identidad en máquinas
remotas
usando el fichero de configuración ~/.ssh/config
:
hp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n ~/.ssh/config 1 # man ssh_config 2 Host machine1.domain 3 user casiano 4 5 Host machine2.domain 6 user pp2
Para saber más sobre ssh
lea la sección
Conexiones con ssh
en los apuntes de Programación en Paralelo II.
El siguiente programa muestra un guión sencillo que permite ejecutar las pruebas en un conjunto de máquinas remotas con las que se ha establecido un sistema de autentificación automática. Al ejecutar el programa se transfiere la distribución, se desempaqueta y se pasan las pruebas sobre cada máquina:
lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_03/Algorithm-Knap01DP-0.25$ make remotetest remotetest.pl Algorithm-Knap01DP-0.25.tar.gz orion beowulf ************orion************ Checking if your kit is complete... Looks good Writing Makefile for Algorithm::Knap01DP cp lib/Algorithm/Knap01DP.pm blib/lib/Algorithm/Knap01DP.pm Manifying blib/man3/Algorithm::Knap01DP.3pm PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" \ "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/01alltests....ok t/02bench.......ok 1/2 skipped: Algorithm::Knapsack not installed All tests successful, 1 subtest skipped. Files=2, Tests=16, 0 wallclock secs ( 0.10 cusr + 0.01 csys = 0.11 CPU) ************beowulf************ Checking if your kit is complete... Looks good Writing Makefile for Algorithm::Knap01DP cp lib/Algorithm/Knap01DP.pm blib/lib/Algorithm/Knap01DP.pm Manifying blib/man3/Algorithm::Knap01DP.3pm PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" \ "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/01alltests....ok t/02bench.......ok 1/2 skipped: various reasons All tests successful, 1 subtest skipped. Files=2, Tests=16, 0 wallclock secs ( 0.11 cusr + 0.01 csys = 0.12 CPU) lhp@nereida:~/Lperl/src/perl_testing_adn_examples/chapter_03/Algorithm-Knap01DP-0.25$
Es posible entonces establecer la ejecución del guión anterior
extendiendo Makefile.PL
con una función
MY::postamble. La cadena retornada por esta función es añadida
al Makefile
construido:
lhp@nereida:$ cat -n Makefile.PL 1 use ExtUtils::MakeMaker; 2 # See lib/ExtUtils/MakeMaker.pm for details of how to influence 3 # the contents of the Makefile that is written. 4 WriteMakefile( 5 NAME => 'Algorithm::Knap01DP', 6 VERSION_FROM => 'lib/Algorithm/Knap01DP.pm', # finds $VERSION 7 PREREQ_PM => {}, # e.g., Module::Name => 1.1 8 ($] >= 5.005 ? ## Add these new keywords supported since 5.005 9 (ABSTRACT_FROM => 'lib/Algorithm/Knap01DP.pm', # retrieve abstract from module 10 AUTHOR => 'Lenguajes y Herramientas de Programacion <lhp@>') : ()), 11 ); 12 13 sub MY::postamble { 14 my @machines = qw( orion beowulf); 15 16 return <<"EOT"; 17 remotetest: 18 remotetest.pl \${DISTVNAME}.tar.gz @machines 19 EOT 20 }
El siguiente programa remotetest.pl
copia para cada máquina la distribucion y ejecuta las pruebas
en la máquina remota.
Forma parte de la distribución GRID::Machine
disponible en CPAN.
$ cat -n /usr/local/bin/remotetest.pl 1 #!/usr/bin/perl -w 2 3 eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}' 4 if 0; # not running under some shell 5 use strict; 6 use GRID::Machine; 7 . .................................................................... 28 29 my $dist = shift or die "Usage:\n$0 distribution.tar.gz machine1 machine2 ... \n"; 30 31 die "No distribution $dist found\n" unless -r $dist; 32 33 die "Distribution does not follow standard name convention\n" 34 unless $dist =~ m{([\w.-]+)\.tar\.gz$}; 35 my $dir = $1; 36 37 die "Usage:\n$0 distribution.tar.gz machine1 machine2 ... \n" unless @ARGV; 38 for my $host (@ARGV) { 39 40 my $m = eval { 41 GRID::Machine->new(host => $host) 42 }; 43 44 warn "Cant' create GRID::Machine connection with $host\n", next unless UNIVERSAL::isa($m, 'GRID::Machine'); 45 46 my $r = $m->eval(q{ 47 our $tmpdir = File::Temp::tempdir; 48 chdir($tmpdir) or die "Can't change to dir <$tmpdir>\n"; 49 } 50 ); 51 52 warn($r),next unless $r->ok; 53 54 my $preamble = $host.".preamble.pl"; 55 if (-r $preamble) { 56 local $/ = undef; 57 58 my $code = slurp_file($preamble); 59 $r = $m->eval($code); 60 warn("Error in $host preamble: $r"),next unless $r->ok; 61 } 62 63 $m->put([$dist]) or die "Can't copy distribution in $host\n"; 64 65 $r = $m->eval(q{ 66 my $dist = shift; 67 68 eval('use Archive::Tar'); 69 if (Archive::Tar->can('new')) { 70 # Archive::Tar is installed, use it 71 my $tar = Archive::Tar->new; 72 $tar->read($dist,1) or die "Archive::Tar error: Can't read distribution $dist\n"; 73 $tar->extract() or die "Archive::Tar error: Can't extract distribution $dist\n"; 74 } 75 else { 76 system('gunzip', $dist) or die "Can't gunzip $dist\n"; 77 my $tar = $dist =~ s/\.gz$//; 78 system('tar', '-xf', $tar) or die "Can't untar $tar\n"; 79 } 80 }, 81 $dist # arg for eval 82 ); 83 84 warn($r), next unless $r->ok; 85 86 $m->chdir($dir)->ok or do { 87 warn "$host: Can't change to directory $dir\n"; 88 next; 89 }; 90 91 print "************$host************\n"; 92 next unless $m->run('perl Makefile.PL'); 93 next unless $m->run('make'); 94 next unless $m->run('make test'); 95 96 # Clean files 97 $m->eval( q{ 98 our $tmpdir; 99 chdir "$tmpdir/.."; 100 system ('rm -fR $dir'); 101 }); 102 }