En esta página

SSH sin miedo

SSH (Secure Shell) es un túnel cifrado entre tu máquina y otra. Sirve para entrar a un servidor, subir archivos, autenticarte contra GitHub y redirigir puertos. Casi todo lo que haces en remoto pasa por aquí.

Qué pasa cuando te conectas

tu máquina                                  servidor
┌──────────────┐                          ┌──────────────┐
│ clave privada│  ── canal cifrado ──►    │ clave pública│
└──────────────┘                          └──────────────┘

Dos verificaciones distintas, que conviene no mezclar:

PreguntaQuién la respondeCon qué
¿El servidor es de verdad?tu clientehost key del servidor
¿Yo soy quien digo ser?el servidortu clave pública

El detalle clave: tu clave privada nunca viaja. El servidor manda un desafío, tu cliente lo firma con la privada, y el servidor verifica la firma con la pública. Si alguien intercepta la conexión, no puede reusar nada.

Generar un par de claves

ssh-keygen -t ed25519 -C "tu@email.com"
ParteSignificado
-t ed25519tipo de clave: moderna, corta y segura
-Ccomentario, normalmente el email (para identificarla)

Te va a preguntar dónde guardarla (Enter = ~/.ssh/id_ed25519) y una passphrase. Ponla: si te roban el archivo, sin passphrase tienen tu identidad.

Genera dos archivos:

~/.ssh/id_ed25519       ← privada. NUNCA se comparte.
~/.ssh/id_ed25519.pub   ← pública. Se copia a servidores y a GitHub.

Permisos: el 90 % de los problemas

SSH es estricto a propósito: si las claves son legibles por otros usuarios, se niega a usarlas.

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub
ArchivoPermisoPor qué
~/.ssh700solo tú entras
clave privada600solo tú lees
clave pública644se puede compartir
~/.ssh/config600puede tener rutas privadas
~/.ssh/authorized_keys (servidor)600mismas razones

El agente SSH

Si tu clave tiene passphrase, el agente la mantiene desbloqueada durante la sesión para no escribirla en cada operación.

eval "$(ssh-agent -s)"     # arranca el agente
ssh-add ~/.ssh/id_ed25519  # carga la clave (pide la passphrase una vez)
ssh-add -l                 # lista lo cargado

En macOS suele integrarse con el llavero; en Linux, agrega las dos líneas al ~/.bashrc o ~/.zshrc para que arranque solo.

Autorizar la clave

En un servidor

ssh-copy-id usuario@servidor

Eso agrega tu clave pública a ~/.ssh/authorized_keys del servidor. Después:

ssh usuario@servidor

En GitHub

  1. Copia el contenido de la clave pública:
    cat ~/.ssh/id_ed25519.pub
    
  2. GitHub → Settings → SSH and GPG keys → New SSH key.
  3. Pega la línea completa y guarda.

Prueba:

ssh -T git@github.com

La respuesta esperada es algo como:

Hi usuario! You've successfully authenticated, but GitHub does not provide shell access.

Ese "no shell access" es normal: GitHub no te da una terminal, solo usa el túnel para autenticar.

La primera conexión: known_hosts

La primera vez que te conectas a un host, SSH te muestra su huella:

The authenticity of host 'ejemplo.com' can't be established.
ED25519 key fingerprint is SHA256:...
Are you sure you want to continue connecting (yes/no)?

Si escribes yes, guarda la huella en ~/.ssh/known_hosts. En las siguientes conexiones compara: si cambia, corta con un warning enorme. Puede ser que reinstalaron el servidor… o que hay un ataque. Verificá la huella por un canal confiable antes de borrar la entrada.

El archivo ~/.ssh/config

Aquí está la diferencia entre "uso SSH" y "uso SSH cómodo". Sirve para poner alias, usuarios, puertos y claves por host.

Host gh
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_github
    IdentitiesOnly yes

Host vps
    HostName 203.0.113.10
    User laura
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Con eso:

ssh vps                       # en lugar de ssh -p 2222 laura@203.0.113.10
git clone gh:usuario/repo.git # en lugar de git@github.com:usuario/repo.git

IdentitiesOnly yes evita el clásico Too many authentication failures: le dice a SSH que use solo la clave indicada y no pruebe todas las que tenga el agente.

Cambiar un repo de HTTPS a SSH

git remote -v
git remote set-url origin git@github.com:usuario/repo.git
ssh -T git@github.com
git fetch

Las URL git@github.com:... usan SSH; las https://... usan usuario y token. No son intercambiables: si copiaste una y tu clave está configurada para la otra, no va a autenticar.

Copiar archivos

scp archivo.txt usuario@servidor:/ruta/destino
scp -r carpeta usuario@servidor:/ruta/
scp usuario@servidor:/ruta/archivo.txt .

rsync es mejor para carpetas grandes: copia solo lo que cambió y se puede reanudar.

rsync -avz --progress carpeta/ usuario@servidor:/ruta/

El / final en carpeta/ importa: copia el contenido, no la carpeta.

Túneles: traer un puerto remoto a tu máquina

ssh -L 8080:localhost:80 usuario@servidor

Ahora http://localhost:8080 en tu máquina llega al puerto 80 del servidor. Muy útil para ver un servicio que solo escucha en la red interna.

ssh -N -L 5433:localhost:5432 usuario@servidor

-N = no ejecutes comandos, solo el túnel (queda en primer plano; Ctrl+C para cortar). Al revés, -R, expone un puerto tuyo en el servidor.

Reglas de seguridad

ReglaMotivo
La privada nunca sale de tu máquinacon ella, eres tú
Passphrase siempreun archivo robado sin passphrase es acceso total
Una clave por propósito (personal, trabajo, GitHub)si se filtra una, revocas solo esa
600 en las clavesSSH no las usa si son públicas
Nunca commitear ~/.sshse filtra en el repo y en el historial
Rotar si se filtróborrarla del repo no alcanza: ya está en la historia
Verificar huellas la primera vezevita un ataque de intermediario

Diagnóstico

ssh -v usuario@servidor     # un nivel de detalle
ssh -vvv usuario@servidor   # tres niveles: qué clave probó y por qué falló
MensajeCausaSolución
Permission denied (publickey)la clave no está autorizada o no se ofrecessh-add, revisar authorized_keys
Bad permissionspermisos abiertoschmod 600 / chmod 700
Too many authentication failuresel agente prueba demasiadas clavesIdentitiesOnly yes en el config
Connection refusedSSH no escucha en ese puertorevisar el servidor y el puerto
Connection timed outred o firewallprobar otro puerto/red
Host key verification failedla huella cambióverificar y, si corresponde, borrar la entrada
Could not resolve hostnamenombre mal escrito o DNSrevisar HostName

Siguiente parada: Bash, Zsh y Fish.


Hecho con amor para Laura, por Bogdan.