32blogby StudioMitsu

Guía práctica de ssh y rsync: lo esencial para servidores remotos

Configura autenticación por clave SSH, personaliza ssh_config, domina el reenvío de puertos y usa rsync para sincronización de archivos y respaldos eficientes.

11 min read
Contenido

¿Cansado de escribir contraseñas cada vez que te conectas por SSH a un servidor? ¿Necesitas enviar archivos a producción pero scp se siente dolorosamente lento? ¿Quieres acceder a un servidor de desarrollo remoto desde tu máquina local?

La respuesta es ssh y rsync. ssh proporciona conexiones remotas cifradas, y rsync maneja la sincronización eficiente de archivos transfiriendo solo lo que ha cambiado. Juntos, forman la base de la administración de servidores y los flujos de trabajo de despliegue.

Esta guía te lleva a través de la configuración de autenticación por clave, ajuste de archivos de configuración, reenvío de puertos y patrones de respaldo con rsync — todo con comandos listos para ejecutar.

¿Qué es SSH?

ssh (Secure Shell) es un protocolo y comando para operar máquinas remotas de forma segura a través de una red. Toda la comunicación está cifrada, así que las contraseñas y comandos nunca viajan en texto plano.

Su predecesor, telnet, enviaba todo sin cifrar. ssh lo reemplazó en 1995 y se ha convertido en el estándar de facto para la administración de servidores.

ssh hace mucho más que solo login remoto:

  • Ejecución remota de comandos: ejecuta one-liners como ssh user@server "ls -la /var/log"
  • Transferencia de archivos: transferencias cifradas vía scp y sftp
  • Reenvío de puertos: crea túneles entre puertos locales y remotos
  • Tunneling: úsalo como proxy SOCKS para funcionalidad similar a una VPN

La conexión básica es directa:

bash
ssh user@192.168.1.100

Para especificar un puerto, usa -p:

bash
ssh -p 2222 user@192.168.1.100

Configurar la autenticación por clave

ssh soporta dos métodos principales de autenticación: basada en contraseña y basada en clave.

Autenticación por contraseña requiere ingresar una contraseña en cada conexión. Es simple pero débil — vulnerable a ataques de fuerza bruta, y si la contraseña se filtra, todo está perdido.

Autenticación por clave usa un par de claves pública-privada. Sin la clave privada, el login es imposible, haciendo ineficaces los ataques de fuerza bruta. Para servidores de producción, la autenticación por clave es esencialmente obligatoria.

Generar claves

El estándar en 2026 es Ed25519. Proporciona seguridad igual o mejor que RSA con longitudes de clave más cortas, y firma y verificación más rápidas.

bash
ssh-keygen -t ed25519 -C "your_email@example.com"

Se te pedirá una ubicación para guardar y una frase de paso. Establecer una frase de paso es altamente recomendable — es la última línea de defensa si tu clave privada se ve comprometida.

Si necesitas RSA por compatibilidad con servidores antiguos, usa al menos 4096 bits:

bash
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

Copiar tu clave pública al servidor

El método más fácil es ssh-copy-id:

bash
ssh-copy-id user@server

Esto añade tu clave pública local (~/.ssh/id_ed25519.pub) al ~/.ssh/authorized_keys del servidor.

Si ssh-copy-id no está disponible, hazlo manualmente:

bash
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Establecer permisos

ssh es estricto con los permisos. La autenticación por clave puede ser rechazada si estos no están configurados correctamente:

bash
# Lado del servidor
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

# Lado del cliente
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Gestionar claves con ssh-agent

Si estableciste una frase de paso en tu clave, ingresarla en cada conexión se vuelve tedioso. Registra tu clave con ssh-agent para omitir las peticiones de frase de paso durante la sesión:

bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

El archivo ssh config

~/.ssh/config almacena parámetros de conexión para que no tengas que escribirlos cada vez.

Sintaxis básica

text
Host myserver
    HostName 192.168.1.100
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Ahora ssh myserver es equivalente a ssh -p 2222 -i ~/.ssh/id_ed25519 deploy@192.168.1.100.

Comodines

Aplica configuraciones comunes a múltiples servidores:

text
Host *.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519_work

Keep-alive

Evita que las conexiones SSH inactivas se corten:

text
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

Esto envía una señal de keep-alive cada 60 segundos. Si el servidor no responde 3 veces, la conexión se termina.

SSH multi-salto (ProxyJump)

Conectarse a través de un host bastión para llegar a servidores internos es un patrón común. ProxyJump lo maneja en un solo comando:

text
Host bastion
    HostName bastion.example.com
    User admin

Host internal
    HostName 10.0.0.5
    User deploy
    ProxyJump bastion

ssh internal se enruta automáticamente a través del bastión para llegar al servidor interno.

Multiplexación de conexiones (ControlMaster)

Acelera las conexiones posteriores al mismo servidor. La primera conexión crea un socket, y las conexiones siguientes lo reusan:

text
Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 600

Crea primero el directorio de sockets:

bash
mkdir -p ~/.ssh/sockets

ControlPersist 600 mantiene el socket vivo durante 600 segundos después de cerrar la última conexión. Esto marca una diferencia notable en scripts de despliegue que se conectan al mismo servidor repetidamente.

Reenvío de puertos

El reenvío de puertos SSH crea túneles cifrados para retransmitir tráfico entre puertos. Es invaluable para acceder a servicios detrás de firewalls o exponer servicios locales externamente.

Reenvío local (-L)

Reenvía un puerto remoto a tu máquina local. Este es el patrón más común:

bash
ssh -L 8080:localhost:3000 user@server

Accede a localhost:8080 en tu máquina, y el tráfico se reenvía a localhost:3000 en el servidor remoto. Úsalo cuando necesites alcanzar un servidor de desarrollo remoto o panel de administración desde tu navegador local.

Ejemplo práctico: conectar a una instancia PostgreSQL remota

bash
ssh -L 5433:localhost:5432 user@db-server

En otra terminal:

bash
psql -h localhost -p 5433 -U myuser mydb

Puedes conectarte al PostgreSQL remoto como si estuviera corriendo localmente. Combina con tmux para gestionar múltiples terminales.

Reenvío remoto (-R)

Expón un puerto local a través del servidor remoto:

bash
ssh -R 8080:localhost:3000 user@server

Accede a localhost:8080 en el servidor remoto, y el tráfico se reenvía a localhost:3000 en tu máquina. Útil para mostrar una aplicación de desarrollo local a tu equipo.

Reenvío dinámico (-D)

Crea un proxy SOCKS:

bash
ssh -D 1080 user@server

Configura localhost:1080 como proxy SOCKS de tu navegador, y todo el tráfico se enruta a través del túnel SSH. Útil para cifrar tráfico en WiFi público o acceder a servicios con restricción geográfica.

Ejecutar túneles en segundo plano

Si solo necesitas el reenvío y no necesitas un shell, usa -fN:

bash
ssh -fNL 8080:localhost:3000 user@server

-f ejecuta ssh en segundo plano, -N le dice que no ejecute comandos remotos.

¿Qué es rsync?

rsync es una herramienta de sincronización de archivos especializada en transferencias delta. Detecta qué partes de los archivos han cambiado y transfiere solo esas partes, haciendo que las sincronizaciones posteriores sean dramáticamente más rápidas.

Así se compara con scp:

Característicascprsync
Modo de transferenciaCopia completa cada vezSolo delta
Reanudación tras interrupciónNoSí, con --partial
CompresiónNoSí, con -z
Patrones de exclusiónNo--exclude flexible
EspejadoNoSí, con --delete

Para cualquier transferencia de archivos no trivial, rsync es el claro ganador.

Sintaxis básica:

bash
rsync [opciones] origen destino

Opciones más usadas:

  • -a (archive): copia recursiva preservando permisos, marcas de tiempo y propiedad
  • -v (verbose): mostrar nombres de archivos durante la transferencia
  • -z (compress): comprimir datos de transferencia
  • -n (dry-run): mostrar qué pasaría sin transferir realmente
  • --progress: mostrar progreso de la transferencia

rsync en la práctica

Sincronización básica de archivos

Local a remoto:

bash
rsync -avz ./dist/ user@server:/var/www/

Remoto a local:

bash
rsync -avz user@server:/var/log/ ./logs/

Siempre haz un dry run primero. Solo añade -n:

bash
rsync -avzn ./dist/ user@server:/var/www/

Patrones de exclusión

Excluir archivos o directorios específicos de la transferencia:

bash
rsync -avz --exclude='node_modules' --exclude='.git' --exclude='.env' ./project/ user@server:/app/

Cuando tienes muchas exclusiones, ponlas en un archivo. Crea .rsyncignore:

text
node_modules
.git
.env
*.log
.DS_Store

Luego referéncialo con --exclude-from:

bash
rsync -avz --exclude-from='.rsyncignore' ./project/ user@server:/app/

Respaldos

Respaldo espejo mantiene el destino como una copia exacta del origen. --delete elimina archivos del respaldo que ya no existen en el origen:

bash
rsync -avz --delete /data/ /backup/data/

Respaldo generacional guarda archivos eliminados o modificados en un directorio con fecha:

bash
rsync -avz --backup --backup-dir="/backup/$(date +%Y%m%d)" --delete /data/ /backup/current/

/backup/current/ siempre contiene el estado más reciente, mientras que los archivos eliminados y actualizados se preservan en directorios como /backup/20260308/.

Script de despliegue

Un ejemplo práctico de automatización del despliegue de una aplicación web con rsync:

bash
#!/bin/bash
set -euo pipefail

REMOTE_USER="deploy"
REMOTE_HOST="server.example.com"
REMOTE_PATH="/var/www/myapp"
LOCAL_PATH="./dist/"

echo "Iniciando despliegue a ${REMOTE_HOST}..."

rsync -avz --delete \
  --exclude='.git' \
  --exclude='node_modules' \
  --exclude='.env' \
  --exclude='*.log' \
  "${LOCAL_PATH}" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/"

echo "Despliegue completado."

set -euo pipefail es esencial para el manejo de errores en scripts — detiene la ejecución tan pronto como cualquier comando falla.

Consideraciones de seguridad

La seguridad SSH y la seguridad del servidor van de la mano. Aquí está lo mínimo que deberías estar haciendo.

Cambios clave en OpenSSH 10.0

OpenSSH 10.0 (abril 2025) introdujo cambios de seguridad significativos:

  • DSA eliminado completamente: las claves DSA ya no pueden generarse ni usarse. Migra a Ed25519
  • Soporte ML-KEM: algoritmo de intercambio de claves post-cuántico (ML-KEM) habilitado por defecto, proporcionando protección preventiva contra amenazas de computación cuántica

CVE-2025-26465 (ataque MITM)

Una vulnerabilidad en OpenSSH 9.9p1 y anteriores permitía ataques man-in-the-middle cuando VerifyHostKeyDNS estaba habilitado. Corregido en 9.9p2 y posteriores. Si usas VerifyHostKeyDNS, verifica tu versión.

Configuración recomendada de sshd_config

Configura /etc/ssh/sshd_config en el lado del servidor:

Solo establece PasswordAuthentication no después de que la autenticación por clave esté completamente funcionando. Hacerlo antes te deja fuera del servidor.

Seguridad de rsync

rsync 3.4.0 (enero 2025) corrigió múltiples CVEs críticos. Si estás ejecutando 3.3.x o anterior, actualiza inmediatamente. La versión 3.4.1 es un release de corrección de regresiones, así que 3.4.1 es el objetivo recomendado.

Verifica tu versión:

bash
rsync --version

Firewall y fail2ban

Restringe el acceso al puerto SSH (por defecto: 22) por IP:

bash
# Usando ufw
sudo ufw allow from 203.0.113.0/24 to any port 22
sudo ufw deny 22

fail2ban detecta intentos de login fallidos y bloquea automáticamente las IPs ofensoras. Es la defensa estándar contra ataques de fuerza bruta SSH:

bash
sudo apt install fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Conclusión

ssh y rsync son la base del trabajo con servidores remotos. Autentícate de forma segura con claves, agiliza las conexiones con archivos de configuración y sincroniza archivos eficientemente con rsync.

Puntos clave:

  • Usa claves Ed25519. DSA fue eliminado en OpenSSH 10.0
  • Centraliza los parámetros de conexión en ~/.ssh/config. Usa ProxyJump para conexiones multi-salto
  • El reenvío de puertos te permite acceder a servicios remotos desde localhost
  • Lo básico de rsync: -avz para la mayoría de operaciones. Siempre haz dry-run con -n primero
  • La barra final cambia completamente el comportamiento de rsync — verifícala hasta que sea memoria muscular
  • En el lado del servidor, establece PasswordAuthentication no y PermitRootLogin no

Combina ssh con tmux para hacer el trabajo en terminal remoto significativamente más cómodo. Para la visión general completa del kit de herramientas CLI, consulta el Kit de herramientas CLI.