🔐 Transferencia Segura de Archivos con SCP

El comando SCP (Secure Copy Protocol) permite transferir archivos de forma segura entre equipos locales y remotos en sistemas Linux. Utiliza el protocolo SSH para garantizar la confidencialidad e integridad de los datos.


📦 ¿Para qué sirve SCP?

✅ Ventajas de SCP

🔄 Actualización del Servidor

Antes de comenzar con la configuración de SCP y la automatización de respaldos, es fundamental asegurarse de que el servidor esté actualizado. Esto garantiza estabilidad, seguridad y compatibilidad con las herramientas que se utilizarán.

sudo apt update && sudo apt upgrade -y

💡 Consejo: Puedes agregar apt dist-upgrade si deseas actualizar también los paquetes que cambian dependencias o eliminan otros.

🔐 Instalación de Herramientas de Seguridad

Para facilitar la autenticación sin intervención manual durante las transferencias, instala sshpass:

sudo apt install sshpass -y

🔑 Generación de Claves SSH

Genera un par de claves pública/privada para establecer una conexión segura entre el servidor local y el remoto:

ssh-keygen

Presiona Enter en cada paso para aceptar los valores por defecto. Luego, copia la clave pública al servidor remoto:

Generating public/private rsa key pair.
Enter file in which to save the key (/home/debian/.ssh/id_rsa):[Pulse Intro aquí]
Enter passphrase (empty for no passphrase): [Pulse Intro aquí]
Enter same passphrase again: [Pulse Intro aquí]
Your identification has been saved in /home/debian/.ssh/id_rsa.
Your public key has been saved in /home/debian/.ssh/id_rsa.pub.
The key fingerprint is:
33:b3:fe:af:95:95:18:11:31:d5:de:96:2f:f2:35:f9 debian@local-host

Copie la clave pública al host remoto usando ssh-copy-id:

ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.1.200

debian@remote-host's password:
Now try logging into the machine, with "ssh 'remote-host'", and check in:
.ssh/authorized_keys
to make sure we haven't added extra keys that you weren't expecting.

✅ Esto permitirá conectarte sin necesidad de ingresar la contraseña cada vez.

Nota: ssh-copy-id añade las claves para el control remoto ssh-anfitrión / authorized_key.

Entrar al host remoto sin introducir la contraseña:

ssh 192.168.1.200

Last login: Sun Nov 16 17:22:33 2012 from 192.168.1.2

[Note: SSH no preguntará por el password.]

Si ha cargado llaves del ssh-agent con el ssh-add, entonces ssh-copy-id recibirá las llaves del ssh-agent para copiar en el host remoto, es decir, que copia las claves proporcionadas por el comando ssh-add -L para el host remoto, cuando no pasa la opción -i para el ssh-copy-id.

>> Si al escribir, obtenemos un resultado similar a este:
debian@debian:~$ ssh-add -L
The agent has no identities.

>> Escribimos lo siguiente para pasar la "shell al sistema remoto".
debian@debian:~$ ssh-agent $SHELL  

>> Introducimos la clave (si procede, vacía, para no pedirla)
debian@debian:~$ ssh-add 
Identity added: /home/debian/.ssh/id_rsa (/home/debian/.ssh/id_rsa) 

>> Lo verificamos
debian@debian:~$ ssh-add -L 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsJIEILxftj8aSxMa3d8t6JvM79DyBV
aHrtPhTYpq7kIEMUNzApnyxsHpH1tQ/Ow== /home/debian/.ssh/id_rsa

>> (En princpio, podría no hacer falta, pero si quieres puedes copiar la Id al host remoto.)
debian@local-host$ ssh-copy-id -i remote-host 
debian@remote-host's password: 
Now try logging into the machine, with "ssh 'remote-host'", 
and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. 

[Nota: Esto ha añadido la clave mostrado por ssh-add -L]

Crear la relación entre los servidores:

sshpass -p "debian" scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -r debian@192.168.1.200:/home/debian /home/debian/

Crear un archivo de nombre scp.sh

nano scp.sh

Incrustar el siguiente código:

#!/bin/bash

date

# Shell script que es ejecutado por medio de crontab, el
# cual contiene código que servirá para eliminar carpetas
# de respaldo que no hayan sido modificados en 90 días.
# ------------------------------------------------------

find /home/debian/backups/* -type f -ctime +18 | xargs rm -rf
sshpass -p "debian" ssh debian@192.168.1.200 "find backups/debian/* -type f -ctime +18 | xargs rm -rf"

# Scrip Basico de Respaldo de MySQL

# Directorio de Trabajo
backup_parent_dir="/home/debian/backups"


# MySQL - Ingresar las credenciales de un usuario con permisos para usar mysqldump para exportar las BDs
mysql_user="root"
mysql_password="debian"


# Verificacion de MySQL password
echo exit | mysql --user=${mysql_user} --password=${mysql_password} -B 2>/dev/null
if [ "$?" -gt 0 ]; then
  echo "Contraseña del usuario ${mysql_user} incorrecto"
  exit 1
fi


# Creando Respaldo y Configurando los Permisos
backup_date=`date +%d-%m-%Y_%H%M`
backup_dir="${backup_parent_dir}/${backup_date}"
echo "Directorio de respaldo: ${backup_dir}"
mkdir -p "${backup_dir}"
chmod 700 "${backup_dir}"

# Capturar la Base de Datos de MySQL
mysql_databases=`echo 'show databases' | mysql --user=${mysql_user} --password=${mysql_password} -B | sed /^Database$/d`

# Respaldando y Comprimiendo las Bases de Datos
for database in $mysql_databases
do
  if [ "${database}" == "information_schema" ] || [ "${database}" == "performance_schema" ]; then
        additional_mysqldump_params="--skip-lock-tables"
  else
        additional_mysqldump_params=""
  fi
  echo "Creando respaldo de base de datos \"${database}\"."
  mysqldump ${additional_mysqldump_params} --user=${mysql_user} --password=${mysql_password} ${database} | gzip > "${backup_dir}/${database}.gz"
  chmod 600 "${backup_dir}/${database}.gz"
done

echo "Copiando archivos"
cp -R /home/debian "${backup_dir}/debian"
echo "Copia finalizada"

echo "Se hara compresion"
tar -C backups/ -zcf backups/"${backup_date}".tar.gz "${backup_date}" --remove-files
echo "Compresión finalizada"


# Mandar carpeta a servidor remoto (se necesita el equipo ya
# esté autorizado para ssh con el fin de evitar autenticación
echo "Iniciando subida de archivo a servidor"
sshpass -p "debian" scp -r "${backup_dir}.tar.gz" debian@192.168.1.200:/home/debian/backups/

echo "Terminada la subida de respaldo a servidor"

echo "Fin del script"

date

Ejecutar el archivo

sudo bash scp.sh

Pasando el tiempo de espera de la transferencia de archivos el resultado sera el siguiente en el servidor remoto:

Tres pequeñas molestias de ssh-copy-id

A continuación se presentan algunas molestias menores del ssh-copy-id.

Default public key: ssh-copy-id utiliza ~/.ssh/ identity.pub como el archivo predeterminado de clave pública (es decir, cuando no hay valor se pasa a la opción -i). En su lugar, me gustaría utilizar id_dsa.pub o id_rsa.pub o identity.pub como claves predeterminadas. es decir, si cualquiera de ellos existe, se debe copiar para el host remoto. Si dos o tres de ellos existen, se debe copiar identity.pub como predeterminado.

El agente no tiene identidadCuando el ssh-agent se está ejecutando y ssh-add -L devuelve «El agente no tiene identidad» (es decir, no hay claves que se agregan al ssh-agent), el ssh-copy-id todavía copiará el mensaje «El agente no tiene identidad» para la entrada de la máquina remota de authorized_keys.

Duplicar entrada en authorized_keys: Deseo ssh-copy-id valida la entrada duplicada en authorized_keys del host remoto. Si ejecuta ssh-copy-id varias veces en el host local, se mantendrá anexar la misma clave en el archivo de authorized_keys del host remoto sin comprobación de duplicados. Incluso con las entradas duplicadas, todo funciona como se esperaba. 

Archivo de ejemplo funcionando:

#!/bin/bash

date

# Shell script que es ejecutado por medio de crontab, el
# cual contiene código que servirá para eliminar carpetas
# de respaldo que no hayan sido modificados en 90 días.
# ------------------------------------------------------

find /home/debian/backups/* -type f -ctime +18 | xargs rm -rf
sshpass -p "debian" ssh debian@192.168.1.11 "find /home/debian/backups/* -type f -ctime +18 | xargs rm -rf"

# Scrip Basico de Respaldo de MySQL

# Directorio de Trabajo
backup_parent_dir="/home/debian/backups"


# MySQL - Ingresar las credenciales de un usuario con permisos para usar mysqldump para exportar las BDs
mysql_user="root"
mysql_password="debian"


# Verificacion de MySQL password
echo exit | mysql --user=${mysql_user} --password=${mysql_password} -B 2>/dev/null
if [ "$?" -gt 0 ]; then
  echo "Contraseña del usuario ${mysql_user} incorrecto"
  exit 1
fi


# Creando Respaldo y Configurando los Permisos
backup_date=`date +%d-%m-%Y_%H%M`
backup_dir="${backup_parent_dir}/${backup_date}"
echo "Directorio de respaldo: ${backup_dir}"
mkdir -p "${backup_dir}"
chmod 700 "${backup_dir}"

# Capturar la Base de Datos de MySQL
mysql_databases=`echo 'show databases' | mysql --user=${mysql_user} --password=${mysql_password} -B | sed /^Database$/d`

# Respaldando y Comprimiendo las Bases de Datos
for database in $mysql_databases
do
  if [ "${database}" == "information_schema" ] || [ "${database}" == "performance_schema" ]; then
        additional_mysqldump_params="--skip-lock-tables"
  else
        additional_mysqldump_params=""
  fi
  echo "Creando respaldo de base de datos \"${database}\"."
  mysqldump ${additional_mysqldump_params} --user=${mysql_user} --password=${mysql_password} ${database} | gzip > "${backup_dir}/${database}.gz"
  chmod 600 "${backup_dir}/${database}.gz"
done

echo "Copiando archivos"
cp -R /home/debian "${backup_dir}/debian"
echo "Copia finalizada"

echo "Se hara compresion"
tar -C backups/ -zcf backups/"${backup_date}".tar.gz "${backup_date}" --remove-files
echo "Compresión finalizada"


# Mandar carpeta a servidor remoto (se necesita el equipo ya
# esté autorizado para ssh con el fin de evitar autenticación
echo "Iniciando subida de archivo a servidor"
sshpass -p "debian" scp -r "${backup_dir}.tar.gz" debian@192.168.1.11:/home/debian/backups/

echo "Terminada la subida de respaldo a servidor"

echo "Fin del script"

date

Videos:

Referencias:

linuxize.com (2020). How to Use SCP Command to Securely Transfer Files. Recuperado Julio 12, 2021 de https://linuxize.com/post/how-to-use-scp-command-to-securely-transfer-files/

haydenjames.io (2020). SCP Linux – Securely Copy Files Using SCP examples. Recuperado Julio 12, 2021 de https://haydenjames.io/linux-securely-copy-files-using-scp/

hypexr.org (2021). Example syntax for Secure Copy (scp). Recuperado Julio 12, 2021 de http://www.hypexr.org/linux_scp_help.php