32blogby Studio Mitsu

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.

by omitsu16 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 (consulta nuestra guía de chmod y chown para profundizar en permisos Linux):

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. Para más sobre escritura de scripts robustos, revisa nuestra guía de shell scripting.

Técnicas avanzadas

Reenvío de agente SSH (ForwardAgent)

Cuando necesitas hacer SSH desde un servidor bastión a un servidor interno, no deberías almacenar claves privadas en el bastión. El reenvío de agente permite que los servidores internos usen tu clave local a través del túnel.

text
# ~/.ssh/config
Host bastion
    HostName bastion.example.com
    User admin
    ForwardAgent yes

Host internal-*
    User deploy
    ProxyJump bastion
    ForwardAgent yes
bash
# Conectar a través del bastión al interno, luego git pull funciona
ssh internal-web
git pull  # tu clave local se reenvía, así que la autenticación tiene éxito

Nota de seguridad: Solo configura ForwardAgent yes para servidores en los que confíes. Cualquiera con acceso root en el bastión puede acceder a tu socket de agente y usar tus claves. Nunca lo configures globalmente con Host * — especifícalo explícitamente por host.

Reanudación y progreso de rsync (-P)

Al transferir archivos grandes por conexiones inestables, -P te permite reanudar desde donde te quedaste.

bash
# -P es atajo para --partial --progress
rsync -avzP user@server:/data/large-dump.sql.gz ./backups/

--partial mantiene los archivos parcialmente transferidos en lugar de eliminarlos (comportamiento por defecto). La siguiente ejecución de rsync transfiere solo la porción restante. --progress muestra el progreso de la transferencia en tiempo real.

bash
# Sincronizar archivos grandes con parciales almacenados en un directorio oculto
rsync -avzP --partial-dir=.rsync-partial user@server:/data/ ./local-data/

--partial-dir almacena archivos incompletos en un directorio separado, limpiado automáticamente después de completar la transferencia. Mantiene tu directorio de trabajo limpio.

Limitación de ancho de banda en rsync (--bwlimit)

Evita que transferencias grandes saturen la red en servidores de producción.

bash
# Limitar ancho de banda a 5MB/s
rsync -avz --bwlimit=5000 ./release/ user@production:/app/

# Moderado durante horario laboral
rsync -avz --bwlimit=1000 ./data/ user@server:/backup/

--bwlimit está en KBytes/s. 5000 = aproximadamente 5MB/s. Añadirlo a scripts de despliegue previene el problema de "el sitio se puso lento después del deploy".

Montar sistemas de archivos remotos con sshfs

Monta el directorio de un servidor remoto localmente y trabaja con los archivos como si estuvieran en tu máquina. sshfs usa SFTP internamente.

bash
# Montar directorio remoto
mkdir -p ~/mnt/server
sshfs user@server:/var/www ~/mnt/server

# Editar archivos con tu editor local
code ~/mnt/server/index.html

# Desmontar
fusermount -u ~/mnt/server

Tu configuración de ~/.ssh/config se usa automáticamente, así que sshfs myserver:/var/www ~/mnt/server funciona con nombres cortos de host.

Ten en cuenta que sshfs se ve directamente afectado por la latencia de red, así que no es ideal para operaciones masivas de archivos. Es más adecuado para verificar archivos de configuración o ediciones pequeñas.

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 (mlkem768x25519-sha256) habilitado por defecto, proporcionando protección preventiva contra amenazas de computación cuántica

CVE-2025-26465 (ataque MITM)

Una vulnerabilidad descubierta por Qualys TRU en OpenSSH 6.8p1 hasta 9.9p1 permitía ataques man-in-the-middle cuando VerifyHostKeyDNS estaba habilitado. Corregido en 9.9p2 (febrero 2025). Ten en cuenta que VerifyHostKeyDNS está deshabilitado por defecto, así que solo afecta a usuarios que lo habilitaron explícitamente.

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ó seis CVEs críticos descubiertos por investigadores de Google Cloud, incluyendo CVE-2024-12084 (desbordamiento de búfer heap que permite ejecución remota de código). 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

Preguntas frecuentes

¿La autenticación por clave SSH es más segura que la de contraseña?

Significativamente más segura. La autenticación por contraseña es vulnerable a ataques de fuerza bruta y phishing. La autenticación por clave usa pares de claves criptográficas — sin el archivo de clave privada, el login es matemáticamente imposible. Los servidores de producción siempre deberían deshabilitar la autenticación por contraseña una vez configurada la autenticación por clave.

¿Puedo usar la misma clave SSH para múltiples servidores?

Sí. Copias la misma clave pública (~/.ssh/id_ed25519.pub) al ~/.ssh/authorized_keys de cada servidor. Sin embargo, algunos equipos con alta conciencia de seguridad prefieren claves separadas por entorno (por ejemplo, una para producción, otra para desarrollo) para limitar el radio de impacto si una clave se compromete.

¿Cómo soluciono errores "Permission denied (publickey)"?

Revisa en orden: (1) Asegúrate de que ~/.ssh sea 700 y ~/.ssh/authorized_keys sea 600 en el servidor. (2) Verifica que la clave pública correcta esté en authorized_keys. (3) Confirma que PubkeyAuthentication yes esté en sshd_config. (4) Revisa la salida de ssh -vvv user@server para ver la razón específica del rechazo.

¿Cuál es la diferencia entre scp y rsync?

scp copia archivos completos cada vez, mientras que rsync transfiere solo las partes que cambiaron (transferencia delta). rsync también soporta reanudación tras interrupción (--partial), compresión (-z), patrones de exclusión (--exclude) y espejado (--delete). Para cualquier cosa más allá de una copia rápida puntual, rsync es la mejor opción.

¿La barra final en rsync realmente importa?

Sí, y confundirla es uno de los errores más comunes con rsync. rsync -avz src/ dest/ copia el contenido de src en dest. Pero rsync -avz src dest/ copia src como directorio dentro de dest/src/. Siempre haz dry-run con -n si no estás seguro.

¿Puede rsync funcionar con un puerto SSH no estándar?

Sí. Usa el flag -e: rsync -avz -e 'ssh -p 2222' ./files/ user@server:/data/. Si ya configuraste el puerto en ~/.ssh/config, rsync lo detecta automáticamente cuando usas el alias del hostname.

¿Es seguro usar ForwardAgent?

Solo para servidores en los que confíes plenamente. Cuando ForwardAgent yes está activo, cualquiera con acceso root en ese servidor puede usar tu clave SSH reenviada para autenticarse como tú en otros servidores. Nunca lo configures globalmente con Host * — especifícalo por host, y solo para servidores bastión o servidores CI bajo tu control.

Artículos relacionados

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.