# rm-rf.es

Ejecutar comandos en equipos remotos vía SSH

Hoy vamos a ver como ejecutar a través de ssh comandos en equipos remotos. Esta práctica es de utilidad en el momento que gestionas muchos equipos y dispones de una máquina central para gestionar todos.
A partir de aquí tened en cuenta que es posible automatizar tareas en servidores remotos mediantes scripts, creación de llaves públicas ssh, etc.

El modo de ejecutar los comandos en un servidor remoto sería el siguiente:

$ ssh servidor_remoto comando

Ejemplo (ejecutamos el comando date en el servidor remoto 192.168.0.188 vía ssh a través del puerto 9999):

$ ssh root@192.168.0.188 -P9999 date
stdin: is not a tty
Sun Oct  4 20:15:14 CEST 2009

Si el comando que váis a ejecutar incorpora comillas, tendréis que entrecomillar todo el comando para evitar errores. Si el comando incluye comillas simples, entrecomilladlo con dobles, y si incluye comillas dobles, con simples:

$ ssh root@192.168.0.188 -P9999 'echo "Esto es una prueba"'
$ ssh root@192.168.0.188 -P9999 "echo 'Esto es una prueba'"

Os recomiendo revisar estos dos artículos sobre ssh, hablo sobre la securización del servicio y el acceso sin necesidad de clave:

Login SSH sin password de forma rápida y sencilla

Cómo securizar un servidor SSH

El comando rsync

El comando rsync sustituye al obsoleto rcp (remote-copy). Se trata de un comando de gran flexibilidad, permite encriptar las trasferencias de datos a través de ssh, permite realizar copias desde una máquina local a una remota (y viceversa), de local a local, y entre servidores rsync.

Lo que diferencia a rsync de otros comandos o utilidades es que usa un algoritmo mediante el cual, cuando se copian datos, solamente se copian aquellos que han sido modificados o que han cambiado desde la última vez que se copiaron. Si un fichero a cambiado solamente copiará aquellos datos diferentes entre el fichero antiguo y el nuevo. Esto supone un ahorro considerable de ancho de banda, tiempo y carga del sistema.

Como siempre, toda la información y opciones de rsync en su página man:

man rsync

Os dejo algunos ejemplos para que os vayáis familiarizando con la herramienta, esto y mucho más en la web oficial de rsync.

backup a un servidor de backups central cada 7 días de forma incremental

#!/bin/sh

# This script does personal backups to a rsync backup server. You will end up
# with a 7 day rotating incremental backup. The incrementals will go
# into subdirectories named after the day of the week, and the current
# full backup goes into a directory called "current"
# tridge@linuxcare.com

# directory to backup
BDIR=/home/$USER

# excludes file - this contains a wildcard pattern per line of files to exclude
EXCLUDES=$HOME/cron/excludes

# the name of the backup machine
BSERVER=owl

# your password on the backup server
export RSYNC_PASSWORD=XXXXXX

########################################################################

BACKUPDIR=`date +%A`
OPTS="--force --ignore-errors --delete-excluded --exclude-from=$EXCLUDES
      --delete --backup --backup-dir=/$BACKUPDIR -a"

export PATH=$PATH:/bin:/usr/bin:/usr/local/bin

# the following line clears the last weeks incremental directory
[ -d $HOME/emptydir ] || mkdir $HOME/emptydir
rsync --delete -a $HOME/emptydir/ $BSERVER::$USER/$BACKUPDIR/
rmdir $HOME/emptydir

# now the actual transfer
rsync $OPTS $BDIR $BSERVER::$USER/current

Backup a un disco spare

I do local backups on several of my machines using rsync. I have an
extra disk installed that can hold all the contents of the main
disk. I then have a nightly cron job that backs up the main disk to
the backup. This is the script I use on one of those machines.

    #!/bin/sh

    export PATH=/usr/local/bin:/usr/bin:/bin

    LIST="rootfs usr data data2"

    for d in $LIST; do
	mount /backup/$d
	rsync -ax --exclude fstab --delete /$d/ /backup/$d/
	umount /backup/$d
    done

    DAY=`date "+%A"`

    rsync -a --delete /usr/local/apache /data2/backups/$DAY
    rsync -a --delete /data/solid /data2/backups/$DAY

The first part does the backup on the spare disk. The second part
backs up the critical parts to daily directories.  I also backup the
critical parts using a rsync over ssh to a remote machine.

mirroring vger CVS tree

The vger.rutgers.edu cvs tree is mirrored onto cvs.samba.org via
anonymous rsync using the following script.

    #!/bin/bash

    cd /var/www/cvs/vger/
    PATH=/usr/local/bin:/usr/freeware/bin:/usr/bin:/bin

    RUN=`lps x | grep rsync | grep -v grep | wc -l`
    if [ "$RUN" -gt 0 ]; then
	    echo already running
	    exit 1
    fi

    rsync -az vger.rutgers.edu::cvs/CVSROOT/ChangeLog $HOME/ChangeLog

    sum1=`sum $HOME/ChangeLog`
    sum2=`sum /var/www/cvs/vger/CVSROOT/ChangeLog`

    if [ "$sum1" = "$sum2" ]; then
	    echo nothing to do
	    exit 0
    fi

    rsync -az --delete --force vger.rutgers.edu::cvs/ /var/www/cvs/vger/
    exit 0

Note in particular the initial rsync of the ChangeLog to determine if
anything has changed. This could be omitted but it would mean that the
rsyncd on vger would have to build a complete listing of the cvs area
at each run. As most of the time nothing will have changed I wanted to
save the time on vger by only doing a full rsync if the ChangeLog has
changed. This helped quite a lot because vger is low on memory and
generally quite heavily loaded, so doing a listing on such a large
tree every hour would have been excessive.

Backup automatizado de home

I use rsync to backup my wifes home directory across a modem link each
night. The cron job looks like this

    #!/bin/sh
    cd ~susan
    {
    echo
    date
    dest=~/backup/`date +%A`
    mkdir $dest.new
    find . -xdev -type f \( -mtime 0 -or -mtime 1 \) -exec cp -aPv "{}"
    $dest.new \;
    cnt=`find $dest.new -type f | wc -l`
    if [ $cnt -gt 0 ]; then
      rm -rf $dest
      mv $dest.new $dest
    fi
    rm -rf $dest.new
    rsync -Cavze ssh . samba:backup
    } >> ~/backup/backup.log 2>&1

note that most of this script isn't anything to do with rsync, it just
creates a daily backup of Susans work in a ~susan/backup/ directory so
she can retrieve any version from the last week. The last line does
the rsync of her directory across the modem link to the host
samba. Note that I am using the -C option which allows me to add
entries to .cvsignore for stuff that doesn't need to be backed up.

Plugins para el cliente SSH PuTTY

Leo en The Geek Stuff una excelente lista de plugins para el conocido cliente SSH de Windows PuTTY. Paso a traducir lo esencial de dicha lista.

1. PuTTY Connection Manager

Sin duda algo imprescindible en un cliente SSH es la disponibilidad de pestañas y organización de las terminales, con este plugin podrás añadir pestañas a PuTTY. Necesita tener instalado .NET 2.0. Si al instalar el plugin las ventanas siguieran abriendose normal haced lo siguiente:

Tools -> Options -> Selecciona la check-box “Enable additional timing for PuTTY capture (ms)” -> cambia el valor a 300 ms

PuTTY Connection Manager main interface

2. PuTTYcyg

PuTTYcyg te permitirá usar PuTTY como una terminal local cygwi.

3. PuTTYtray

PuTTYtray, permite minimizar PuTTY en el system tray de Windows, además este plugin permite guardar las sesiones en un fichero para poder exportarlas a cualquier otro equipo, mientras que PuTTY originalmente las guarda en el registro de Windows.

4. PuttyTabs

PuttyTabs muestra en un icono flotante un listado desplegable con las sesiones activas en PuTTY, útil si usamos gran cantidad de terminales a la vez.

5. Modified PuTTY

El plugin modified PuTTY guarda las sesiones en una carpeta en lugar de en el registro, y será capaz de mostrar todas las disponibles en el programa, tanto las del registro como las de carpeta.

6. PocketPuTTY

PocketPuTTY funciona en Windows Mobile 2003/5., lo que te permitirá utilizarlo en moviles, blackberrys, pda’s, etc.

Pocket PuTTY

7. PuTTY Portable

PuTTY Portable es parte de la suite de aplicaciones PortableApp, y te permitirá lanzar PuTTY desde una unidad USBy guardar en ella las sesiones.

8. PuTTY Session Manager

PuTTY Session Manager permite organizar las sesiones de PuTTY en carpetas y además asignarles hotkeys. Requiere Microsoft .NET 2.0.

9. PuTTY Command Sender

PuTTYCS es una utilidad que permite realizar tareas repetitivas en servidores de forma sencilla. Uando PuTTYCS,  puedes mandar un comando unix a múltiples sesiones de PuTTY a la vez.

Comprimir directorio remoto a través de SSH

ssh usuario@servidor "cd /directorio && tar cvz * --exclude=*log" > backup.$( date +%y%m%d ).tgz

Esta es una forma rápida y sencilla de hacer backups remotos vía SSH de una determinada carpeta, la explicación es sencilla, primero hacemos ssh al servidor remoto, al cual le pasamos la primera parte del comando:

cd /directorio && tar cvz * --exclude=*log

Entramos a la carpeta a comprimir y le decimos que comprima todo excepto los ficheros “que acaben en log”, esto lógicamente puede ser modificado al gusto de cada uno, después, simplemente redirigimos los datos comprimidos al fichero backup + fecha actual .tgz:

 > backup.$( date +%y%m%d ).tgz

Este y muchos otros tips de consola los puedes encontrar en shell-fu ;)

Login SSH sin password de forma rápida y sencilla

En el artículo de securización del servicio SSH ya hablamos de las llaves SSH, hoy os voy a comentar de forma rápida y sencilla, como tener acceso de un servidor a otro vía SSH sin tener que escribir usuario y password.

1) En el servidor origen ejecutar la siguiente línea de comandos en la shell (no introducir passphrase) :

origen# ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/home/a/.ssh/id_rsa):
Created directory '/home/a/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/a/.ssh/id_rsa.
Your public key has been saved in /home/a/.ssh/id_rsa.pub.
The key fingerprint is:
3e:4f:05:79:3a:9f:96:7c:3b:ad:e9:58:37:bc:37:e4 a@A

Con este comando creamos las llaves publica y privada de autenticación.

2) En el servidor de destino, creamos, en caso de que no exista, la carpeta ~/.ssh

destino# mkdir ~/.ssh

3) Finalmente, introducimos la llave pública del servidor origen en el fichero de llaves autorizadas del servidor destino:

El siguiente comando añade nuestra llave pública en el final del fichero authorized_keys del servidor destino:

origen# cat .ssh/id_rsa.pub | ssh usuario@servidordestino 'cat >> .ssh/authorized_keys'

Nota: En este comando nos pedirá la clave al ejecutar un SSH, no obstante, será la última vez pues después ya estará la llave dentro de .ssh/authorized_keys

4) Ya podemos acceder vía ssh sin clave:

origen# ssh usuario@servidordestino

Cómo securizar un servidor SSH

SSH (Secure SHell) es el nombre de un protocolo y del programa que lo implementa, y sirve para acceder a máquinas remotas a través de una red. Permite manejar por completo la computadora mediante un intérprete de comandos, y también puede redirigir el tráfico de X para poder ejecutar programas gráficos si tenemos un Servidor X arrancado.

Wikipedia

Con unas pequeñas y sencillas pautas, podemos securizar un servidor SSH, con la finalidad de evitar accesos no deseados. Nos vamos a centrar primero en el fichero de configuración del servicio, normalmente ubicado en:

/etc/ssh/sshd_config

Pautas a seguir para securizar el servicio SSH:

Cambiar el puerto de acceso(por defecto 22) por uno alternativo, por ejemplo el 1242 (debe ser superior a 1024:

Port 1242

Deshabilitar el acceso root vía SSH si no es estrictamente necesario:

PermitRootLogin no

Utilizar autenticación mediante llaves públicas/privadas (SSH Public-Key / Private-Key Authentication). De este modo, y si deshabilitamos el acceso mediante autenticación con clave de acceso, solamente podrá acceder al sistema aquel equipo que tenga una llave autorizada en el servidor. La forma más rápida de crear una llave, es ejecutar el siguiente comando en el equipo que va a conectarse al servidor ssh:

 ssh-keygen -t rsa

Este comando generará una llave pública y una privada (no voy a detarllar ahora el uso del mismo, investigando encontraréis todas sus opciones), deberemos añadir el contenido de la llave pública en el servidor SSH, concretamente en el fichero authorized_keys del usuario con el que vayamos a conectar. Si fueramos a conectar como root, en el servidor destino añadiríamos el contenido al fichero:

/root/.ssh/authorized_keys

De este modo accederíamos sin clave al servidor, pues nuestra llave pública SSH está autorizada en el servidor. Si quisieramos entonces permitir solamente el acceso por llave, y no por passwords, lo configuraríamos de tal forma:

PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
RSAAuthentication no
PasswordAuthentication no
UsePAM no
KerberosAuthentication no
GSSAPIAuthentication no

Por supuesto, si dejamos activa la autenticación vía password, es encarecidamente necesario que no sea un password sencillo de averiguar.

En caso de permitir el acceso con password, es conveniente limitar el número de veces que un usuario puede introducir “incorrectamente” una clave, en este caso 5 veces:

MaxAuthTries 5

Otra parte extremadamente importante, independiente del fichero de configuración SSH, es permitir el acceso SSH solamente a redes o ips conocidas. Para ello, utilizaremos los siguientes ficheros:

/etc/hosts.deny
/etc/hosts.allow

Lo más recomendable es prohibir el acceso SSH a cualquier IP o rango a través del fichero hosts.deny, y posteriormente permitir acceso a determinadas IPs/Rangos en el fichero hosts.allow:

Hosts.Deny (Denegamos acceso total a SSH):

$ cat /etc/hosts.deny
#
# hosts.deny	This file describes the names of the hosts which are
#		*not* allowed to use the local INET services, as decided
#		by the '/usr/sbin/tcpd' server.
#
# The portmap line is redundant, but it is left to remind you that
# the new secure portmap uses hosts.deny and hosts.allow.  In particular
# you should know that NFS uses portmap!

sshd: all

Hosts.Allow (Permitimos acceso a determinadas IPs):

$ cat /etc/hosts.allow
#
# hosts.allow This file describes the names of the hosts which are
#  allowed to use the local INET services, as decided
#  by the '/usr/sbin/tcpd' server.
#
sshd: 93.42.132.43 86.34.22.122

Esto es básicamente lo principal a la hora de securizar el servicio, probablemente me haya dejado algo, en caso de querer añadir o debatir alguna opción podéis comentarlo.

Cambiar mensaje de bienvenida servicio SSH

Cambiar el mensaje de bienvenida al servicio SSH es algo tan simple como añadir el texto que deseemos en el fichero:

/etc/motd

De este modo, cuando accedamos vía SSH al servidor, aparecerá como mensaje de bienvenida el texto que incluya dicho fichero.

Muy sencillo, pero quizás alguien no lo sabía (o no lo recordaba) ;)