Cómo sincronizar los archivos de dos servidores mediante rsync

En este post voy a explicar cómo sincronizar los archivos de dos servidores remotos (s1.example.com y s2.example.com) usando una conexión SSH.

Una buena alternativa para sincronizar dos servidores es Lsyncd (Live Syncing Daemon), pero como en este caso no necesito que la sincronización sea en tiempo real, lo voy a hacer mediante rsync (a través de SSH), ejecutando el comando cada hora mediante el cron del usuario.

En ambos servidores está instalado Debian 9, pero la operativa es muy similar o idéntica en el resto de distribuciones Linux.

Necesito tener instalado el siguiente software:

  • s1.example.com. Cliente SSH y rsync.
  • s2.example.com. Servidor SSH.

Lo primero que voy a hacer es configurar las claves para que un usuario de s1.example.com (u1) pueda acceder a s2.example.com (u2).

Convenciones

# – indica que el comando que viene a continuación tiene que ser ejecutado con permisos de root directamente con el usuario root o mediante el comando sudo.
$ – indica que el comando que viene a continuación puede ser ejecutado por un usuario normal sin privilegios de administración.

Generación de las claves

Ejecuto, con el usuario u1 en el servidor s1.example.com, el siguiente comando para crear las claves de acceso a s2.example.com.

u1@s1.example.com:~$ ssh-keygen -t rsa -b 4096 -C "Clave de acceso para u1 de s1.example.com a u2 en s2.example.com" -f ~/.ssh/u1s1u2s2 -q -N ""

Los parámetros del comando indican:

  • -t rsa. Tipo de clave a crear. En este caso es de tipo RSA.
  • -b 4096. Número de bits que tendrá la clave. El valor por defecto es 2048, pero cuanto más grande más robusta es la clave.
  • -C “Clave de acceso para u1 de s1.example.com a u2 en s2.example.com”. Es un campo de comentarios, donde indico el uso que le doy a la clave que estoy generando. Este comentario se añade al final de la clave pública.
  • -f ~/.ssh/u1s1u2s2. Archivo donde se almacena la clave privada. La clave pública se almacena en un archivo con el mismo nombre y con la extensión “pub”.
  • -q. Genera la clave en modo silencioso, sin mostrar nada por la consola.
  •  -N “”. Indica la contraseña (passphrase) de uso de la clave. En este caso la dejo vacía.

Copia de la clave pública al servidor remoto

Lo siguiente es copiar la clave pública al segundo servidor (s2.example.com), para poder acceder usando el usuario u2

u1@s1.example.com:~$ ssh-copy-id -i ~/.ssh/u1s1u2s2.pub u2@s2.example.com

The authenticity of host 's1.example.com (1.2.3.4)' can't be established.
ECDSA key fingerprint is SHA256:+Drsm91Tzl3wsuY1mCkBsDWd3WeJ1KloIGjUgPmgcf8.

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/u1/.ssh/u1s1u2s2.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
u2@s2.example.com's password:

Number of key(s) added: 1

Now try logging into the machine, with: "ssh 'u2@s2.example.com'"
and check to make sure that only the key(s) you wanted were added.

Los parámetros del comando indican:

  • -i ~/.ssh/u1s1u2s2. Ubicación de la clave privada. La clave pública tiene el mismo nombre y la extensión “pub”. La clave pública es la que se copia a s2.example.com
  • u2@s2.example.com. Usuario (u2) y equipo (s2.example.com) al que se copia la clave pública para poder usarla para acceder a ese equipo.

Si me conecto al servidor s2.example.com (usuario u2) por SSH en otra consola nueva y veo el contenido de su directorio “.ssh”

u2@s2.example.com:~$ ls .ssh/
authorized_keys

aparece un archivo de claves autorizadas “authorized_keys”, donde se almacenan las claves públicas que tienen acceso a este usuario de este servidor

u2@s2.example.com:~$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDWm0gRSxFyyZKDLjvc4z10iQ87rj3TlIVo9+U1D1oHbPNjiCMBpF6xOQCqKAi+f5U2tTcZ23wDh1CVnTkCFC/LWsrMiv5UVaDIXVv/1NLnRz/n1REzSL+PemdIjE0R8Ll6DUae40brCmTn1yrDZnF9qOrRm6VWKr3BQ3nvV59P3O+zWUYLrNH6vs2nIlY7Xj9ss0I9BDVwdPFv8q0+mijyeld6VYLnnJ8clDaTBZmVEwWAADfD6a0ODPf61FItON0PCcnljU408aym6U2605cYuAfu70g5gqvis1gZadc9BbUw+6E748APmSN0oVHOHU2WSyX4UQNcaZzuaZxslKh/g7isWMV1tCN0MLfp13Kgjsa84xZEhT6LG3/+iTG9gdb1qxQ4tBtx0O7TNYvQH/U4SU0lCz6PNKjVVgXBNfBz4jxvMiVqrsRzwy5QnQnfwCWEm3whqqCuOL7meyMGY77IWkguqcGrn4Mj9n/m/bQ0dY1XoLKPbCgVBPEeMaQ96hoKNy13eExhksn/K6VH2qXRiChMyuj198e5l9KFqYrf+AY+SF8MGfHNjGJSPkQYdncqppHiN7491GmeUkFl1E8y5sZPCxCKGivLBzpR/BNnKfShSN6+9f43Wx/MydgH1Zmhzi5z3H1oLAVsGG/FjxGEYm33/OMy8payOv29Azy3lw== Clave de acceso para u1 de s1.example.com a u2 en s2.example.com

Desde el servidor s1.example.com pruebo a acceder al s2.example.com mediante SSH usando la clave privada

u1@s1.example.com:~$ ssh -i ~/.ssh/u1s1u2s2 u2@s2.example.com
Linux s2.example.com 4.9.0-5-amd64 #1 SMP Debian 4.9.65-3+deb9u2 (2018-01-04) x86_64

Debian GNU/Linux 9 (stretch)

Linux s2.example.com 4.9.0-5-amd64 #1 SMP Debian 4.9.65-3+deb9u2 (2018-01-04) x86_64 GNU/Linux

u2@s2.example.com:~$

Los parámetros del comando indican:

  • -i ~/.ssh/u1s1u2s2. Ubicación de la clave privada. La clave pública tiene el mismo nombre y la extensión “pub”.
  • u2@s2.example.com. Usuario (u2) y equipo (s2.example.com) al que trato de acceder usando la clave privada indicada en el parámetro anterior.

A continuación pruebo el comando de sincronización mediante rsync

u1@s1.example.com:~$ rsync -arz --no-o --no-g --progress --delete --rsh="ssh -i /home/u1/.ssh/u1s1u2s2" /home/u1/backup/ u2@s2.example.com:"/home/u2/backup"
sending incremental file list

Los parámetros del comando rsync indican:

  • -a. Procesado manteniendo los parámetros de los ficheros copiados en el equipo remoto.
  • -r. Procesado de los ficheros de forma recursiva.
  • -z. Compresión de los archivos durante la transferencia.
  •  –no-o. Ignoro el usuario (owner).
  • –no-g. Ignoro el grupo (group).
  • –progress. Muestra el progreso de la transferencia. Esta opción no la usaré en el cron, ya que no se ejecuta de forma interactiva en la consola, sino en background.
  • –delete. Borra en el destino los ficheros no existentes en el origen.
  • –rsh. Ejecuto el comando de acceso SSH con la clave privada que se pasa como parámetro (-i).
  • /home/u1/backup/. Directorio origen que quiero copiar a s2.example.com
  • u2@s2.example.com:”/home/u2/backup”. Usuario remoto (u2), servidor remoto (s2.example.com) y directorio (/home/u2/backup) donde se va a realizar la copia.

Para probarlo creo un directorio y un par de ficheros en s1.example.com

u1@s1.example.com:~$ cd ~/backup
u1@s1.example.com:~/backup$ touch archivo1.txt
u1@s1.example.com:~/backup$ mkdir directorio1
u1@s1.example.com:~/backup$ cd directorio1
u1@s1.example.com:~/backup/directorio1$ touch archivo2.txt

Vuelvo a ejecutar el comando y compruebo en s2.example.com que se ha sincronizado correctamente.

u1@s1.example.com:~$ rsync -arz --no-o --no-g --progress --delete --rsh="ssh -i /home/u1/.ssh/u1s1u2s2" /home/u1/backup/ u2@s2.example.com:"/home/u2/backup"
sending incremental file list
sending incremental file list
./
archivo1.txt
 0 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=2/4)
directorio1/
directorio1/archivo2.txt
 0 100% 0.00kB/s 0:00:00 (xfr#2, to-chk=0/4)

Borro un fichero, añado otro

u1@s1.example.com:~/backup/directorio1$ rm archivo2.txt
u1@s1.example.com:~/backup/directorio1$ touch archivo3.txt

y vuelvo a ejecutar la sincronización para ver si en el equipo s2.example.com se han añadido y se han borrado los archivos de forma adecuada.

u1@s1.example.com:~$ rsync -arz --no-o --no-g --progress --delete --rsh="ssh -i /home/u1/.ssh/u1s1u2s2" /home/u1/backup/ u2@s2.example.com:"/home/u2/backup"
sending incremental file list
deleting directorio1/archivo2.txt
directorio1/
directorio1/archivo3.txt
 0 100% 0.00kB/s 0:00:00 (xfr#1, to-chk=0/4)

Lo siguiente es programar el rsync en el cron del usuario cada hora sin la opción “progress”, ya que no se ejecuta de forma interactiva en la consola, sino en background.

u1@s1.example.com:~$ crontab -e

Y añado la línea

00 * * * * rsync -arz --no-o --no-g --progress --delete --rsh="ssh -i /home/u1/.ssh/u1s1u2s2" u2@s2.example.com:"/home/u2/backup" /home/u1/backup

A partir de ahora, cada hora se sincronizará el contenido del directorio origen y del destino, borrando en el destino los archivos inexistentes en el origen.

Más información:

Putty, SSH y claves RSA. Acceder a un servidor Linux desde Windows con Putty y claves RSA

En una entrada anterior expliqué cómo acceder por SSH a un servidor o equipo remoto sin introducir ni usuario ni contraseña entre equipos Linux o Unix (OS X incluido). En esta entrada voy a explicar cómo hacer lo mismo desde un equipo Windows, usando la aplicación de acceso remoto Putty.

Lo primero que tenemos que hacer es descargar e instalar Putty. Instala varias aplicaciones

Putty

Ejecutamos PuTTYgen para generar la clave pública/privada RSA (SSH-2) de 2048 bits. Selecciono estas dos opciones.

PuttyGen-Key-Generator

A continuación muevo el ratón por la zona vacía para generar aleatoriedad en la creación de las claves.

PuttyGen-Key-Generator

Y ya tengo generadas las 2 claves RSA.

PuttyGen-Key-Generator

Tras generar las 2 claves, las guardo, por ejemplo, en un directorio llamado “my_keys” en “Mis documentos”:

  • Clave pública: rsa-key-servidor
  • Clave privada: rsa-key-servidor.ppk

A continuación copio la clave pública haciendo clic con el botón derecho del campo que indica “Public key for pasting into OpenSSH authorized_keys file:”, usando los comandos “Seleccionar todo” y “Copiar”. Es importante comprobar que la clave empiece por el texto ssh-rsa AAAA.

PuttyGen-Key-Generator

Lo siguiente que tengo que hacer es acceder al servidor con el usuario que estoy configurando y pegar esta clave al final del archivo ~/.ssh/authorized_keys. En el peor de los casos, que no tenga creado el archivo ni el directorio .ssh, ejecuto los comandos:

# Creo el directorio
mkdir ~/.ssh
# Cambio los permisos para que solo pueda acceder el propietario
chmod 0700 ~/.ssh
# Creo el archivo vacio
touch ~/.ssh/authorized_keys
#Cambio los permisos del archivo
chmod 0644 ~/.ssh/authorized_keys

Y en este archivo “authorized_keys” tengo que pegar al final del archivo la clave pública copiada en el paso previo.

A continuación tengo que configurar Putty. Lo ejecuto.

En la sección Session introduzco los datos del servidor remoto: IP o host (campo “Host Name (or IP address)“) y puerto (campo “Port“).

Putty-RSA-login-configuration

En la sección Connection -> Data introduzco el nombre de usuario (campo “Auto-login username”) en el servidor remoto para el que estoy configurando las claves.

Putty-RSA-login-configuration

En la sección Connection -> SSH -> Auth le indico la ubicación de la clave privada (extensión .ppk) creada previamente.

Putty-RSA-login-configuration

Ya solo me queda guardar la sesión con un nombre determinado, que en este caso será la IP del servidor al que me quiero conectar, ya que es un servidor de la red local y lo identifico fácilmente. Para ello voy a la sección Session, selecciono una sesión existente (o creo una nueva introduciendo el nombre en el campo “Saved Sessions“) y hago clic en el botón “Save“.

Putty-RSA-login-configuration

Ya tengo todo configurado. Para conectarme automáticamente al servidor bastará con que haga doble clic sobre la sesión guardada.

Más información:

:wq

Acceder por SSH a un servidor o equipo remoto sin introducir ni usuario ni contraseña

Cuando nos conectamos a un servidor para poder administrarlo lo solemos hacer por SSH (espero que no uses telnet u otros métodos no seguros 😉 ). Tras instalarlo, para acceder usamos un usuario y una contraseña y empezamos a administrarlo.

Una de las implementaciones más habituales es OpenSSH (OpenBSD Secure Shell), un proyecto que nació en el año 1999 y cuya finalidad, tal y como indican en su web es:

OpenSSH is a FREE version of the SSH connectivity tools that technical users of the Internet rely on. Users of telnet, rlogin, and ftp may not realize that their password is transmitted across the Internet unencrypted, but it is. OpenSSH encrypts all traffic (including passwords) to effectively eliminate eavesdropping, connection hijacking, and other attacks. Additionally, OpenSSH provides secure tunneling capabilities and several authentication methods, and supports all SSH protocol versions.

Esta implementación está presente, tanto la parte de cliente como la de servidor, en la mayoría de máquinas no Windows: BSD (OpenBSD, FreeBSD, NetBSD,…), Cygwin, Mac OS X a partir de la versión 10.1, IBM AIX, Sun Solaris, máquinas Cisco, Novell NetWare, máquinas Dell, HP-UX, máquinas Juniper y todos los Linux.

La suite OpenSSH reemplaza rlogin y telnet con ssh, rcp con scp y ftp con sftp. También incluye la implementación del servidor, sshd, y otras utilidades, tales como ssh-add, ssh-agent, ssh-keysign, ssh-keyscan, ssh-keygen y sftp-server.

Como podemos ver es una suite de comunicaciones segura, muy completa y de uso muy extendido.

En este artículo explico como configurar un equipo con alguno de los sistemas operativos en los que podemos instalar OpenSSH y con el cuál queremos acceder desde una consola a un servidor mediante SSH sin tener que introducir contraseñas.

Para esto utilizaremos autentificación de clave pública; es decir, tenemos una clave pública y otra privada que usaremos para autentificarnos ante otros sistemas, como en este caso ante un servidor remoto.

Lo primero que hacemos en el equipo local es generar el conjunto de claves pública y privada. Para ello usamos el comando ssh-keygen, que permite la creación de claves de autentificación. Nos pedirá la ruta y el nombre del archivo que le vamos a dar a la clave privada (a la pública le añade la extensión .pub) y una contraseña de acceso para cuando queramos acceder a la clave privada. Si estáis en un equipo local controlado por vosotros podéis dejarla vacía.

$ ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/home/usuario/.ssh/id_rsa): /home/usuario/.ssh/usuario_local
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/usuario/.ssh/usuario_local.
Your public key has been saved in /home/usuario/.ssh/usuario_local.pub.
The key fingerprint is:
7f:6d:24:8b:d5:9c:8e:03:13:6c:dc:09:f2:c7:f2:ec usuario@equipo
The key's randomart image is:
+--[ RSA 2048]----+
| ..oo . |
| =..o |
| = o |
| * o . |
| o S . = . |
| + + + + |
| E + o o |
| . . . |
| |
+-----------------+

Acabamos de generar 2 claves de tipo RSA de 2048 bits:

  • /home/usuario/.ssh/usuario_local. Es la clave privada, que debemos de mantener segura en nuestro equipo.
  • /home/usuario/.ssh/usuario_local.pub. Es la clave pública, que llevaremos al servidor.

Copiamos la clave pública al servidor. Para ello ejecutamos en nuestro equipo el comando scp, mediante el cual copiamos la clave pública al servidor remoto.

$ scp -P 22 ~/.ssh/usuario_local.pub 

usuario_remoto@miequiporemoto.com:/home/usuario_remoto/.ssh/usuario_local.pub
The authenticity of host '[miequiporemoto.com]:22 ([11.22.33.44]:22)' can't be established.
ECDSA key fingerprint is 75:c5:23:ad:5a:f1:22:3b:f1:ef:a2:5e:f8:8a:2d:ab.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[miequiporemoto.com]:22,[11.22.33.44]:22' (ECDSA) to the list of known hosts.
usuario_remoto@miequiporemoto.com's password:
usuario_local.pub 100% 398 0.4KB/s 00:00

En el equipo remoto añadimos la clave pública al archivo “authorized_keys” del usuario remoto. Para ello ejecutamos en el equipo remoto

$ cat ~/.ssh/usuario_local.pub >> ~/.ssh/authorized_keys

Solo nos queda crear un shortcode en el archivo del equipo local ~/.ssh/config para poder acceder de una forma rápida al servidor. Para ello añadimos en este archivo las siguientes líneas:

Host miservidor
Hostname miequiporemoto.com
Port 22
User usuario_remoto
IdentityFile ~/.ssh/usuario_local

Y para acceder al equipo remoto desde el equipo local solo tenemos que ejecutar

$ ssh miservidor

Más información:

:wq

SSH. Evitar cortes continuos en una conexión SSH

A veces cuando estoy trabajando por consola a través de SSH en un equipo remoto, tras un tiempo de inactividad, la conexión se corta.

Para solucionar este problema sin tener que ser root en el equipo que realiza la conexión, simplemente hay que editar el archivo ~/.ssh/config e introducir la siguiente configuración

Host *
ServerAliveInterval 60
ServerAliveCountMax 3

Con esta configuración estamos configurando todas las conexiones SSH para que:

  • ServerAliveInterval 60: envíe un paquete vacío al servidor cada 60 segundos para mantener la conexión viva.
  • ServerAliveCountMax 3: número de mensajes vacíos que se enviarán al servidor sin que tengamos que recibir respuesta del servidor. Si se alcanza este tope sin recibir respuesta del servidor se corta la conexión.

Más info: