Módulo 5: Máquinas remotas, redes y scripting
4. Conectarse con SSH y autenticación por llaves
Descripción
Hasta ahora, cuando algo fallaba en la lección anterior, el problema vivía completo dentro de tu propia terminal: resolvías un nombre, medías si había alcance, mirabas si un puerto respondía. Todo el diagnóstico ocurría de tu lado. Hoy cruzas esa línea: vas a entrar a otra máquina, con tu propia terminal corriendo dentro de una que no es la tuya, y vas a hacerlo sin escribir una contraseña cada vez.
Al final de esta lección vas a poder conectarte a un servidor remoto con ssh, entender exactamente qué te está preguntando ese mensaje de "fingerprint" que aparece la primera vez y por qué existe, generar tu propio par de llaves con ssh-keygen -t ed25519, instalar tu llave pública en un servidor con ssh-copy-id (y entender qué hace ese comando por dentro, en vez de tratarlo como magia), y escribir un ~/.ssh/config que recuerde por ti el usuario, el puerto y la llave de cada servidor al que te conectas.
Conexión con el módulo: esto no es un ejercicio de sintaxis. Es la puerta de entrada real a cualquier trabajo con infraestructura remota: conectarte a la instancia donde corre un despliegue, entrar al servidor de un cliente para revisar un log en producción a las once de la noche, o darle acceso a un nuevo integrante del equipo sin compartir una contraseña que después nadie sabe quién más tiene. Cada una de esas situaciones se resuelve bien o mal según entiendas o no lo que estás a punto de ver: qué garantiza realmente SSH, por qué una llave reemplaza a una contraseña sin ser "una contraseña más larga", y por qué el sistema es tan estricto con los permisos de esos archivos — que es exactamente el criterio de mínimo privilegio del módulo 4, aplicado ahora a las llaves con las que te identificas ante otra máquina.
Un canal cifrado que además comprueba con quién hablas
Imagina que necesitas entregar un sobre confidencial en una oficina de un edificio al que nunca fuiste. Antes de soltar el sobre tienen que pasar dos verificaciones, en este orden. Primero, tú necesitas estar seguro de que el edificio frente al que estás parado es realmente el que buscabas, y no uno idéntico armado tres puertas más allá por alguien que quiere interceptar tu correspondencia. Segundo, una vez que confirmaste el edificio correcto, la persona del mostrador necesita estar segura de que quien entrega el sobre eres realmente tú, y no alguien que encontró tu tarjeta de presentación tirada en la calle. Y todo lo que se dicen desde que cruzas la puerta hasta que el sobre llega a destino viaja dentro de un tubo sellado que nadie en el pasillo puede abrir para leer.
Eso, sin metáfora, es exactamente lo que garantiza SSH (Secure Shell) en cada conexión: autenticación del servidor (confirmas que la máquina del otro lado es la que crees que es, no un impostor), autenticación tuya ante el servidor (el servidor confirma que eres quien dices ser, normalmente con una llave en vez de una contraseña) y un canal cifrado entre ambos extremos, de modo que nadie que intercepte el tráfico en el camino — tu proveedor de internet, una red wifi pública, un router comprometido — puede leer ni un comando ni una línea de salida de lo que hagas dentro de esa sesión. Las tres cosas son necesarias: cifrar el canal sin autenticar a nadie te protegería de que alguien escuche, pero no de que te conectes al servidor equivocado o de que alguien se haga pasar por ti.
Tu laboratorio a costo cero
Todo lo que sigue lo vas a correr contra una máquina remota real, sin pagarle a nadie ni pedir una cuenta de nube: tu propia computadora, actuando al mismo tiempo de cliente y de servidor. Habilita el servidor SSH según tu sistema:
macOS (activa "Remote Login" desde la línea de comandos, sin abrir Configuración del Sistema):
sudo systemsetup -setremotelogin on
Linux basado en Debian/Ubuntu (si sshd todavía no está instalado o corriendo):
sudo apt update && sudo apt install -y openssh-server
sudo systemctl enable --now ssh
(En distribuciones basadas en Red Hat/Fedora, el paquete se instala con dnf y el servicio se llama sshd en vez de ssh.)
Si prefieres no tocar la configuración de red de tu propio equipo — por ejemplo, en una laptop corporativa administrada — puedes montar el mismo laboratorio dentro de un contenedor aislado, sin instalar nada en el host: docker run -d --name ssh-lab -p 2222:22 ubuntu:24.04 sleep infinity, y adentro del contenedor (docker exec -it ssh-lab bash) instalas openssh-server, generas las llaves del host con ssh-keygen -A y arrancas el demonio con /usr/sbin/sshd -D &. A partir de ahí, todos los comandos de esta lección son idénticos, solo cambia el puerto (-p 2222) y el destino (localhost en vez del hostname de tu máquina).
Ejemplo trabajado: tu primera conexión y el mensaje de fingerprint
Con el servidor ya habilitado, conéctate a ti mismo:
ssh $(whoami)@localhost
Por defecto, ssh asume que el servidor escucha en el puerto 22 — el puerto estándar de SSH. Si el tuyo escucha en otro (por ejemplo, el contenedor Docker del laboratorio alternativo de arriba, mapeado al 2222), lo indicas con -p:
ssh -p 2222 $(whoami)@localhost
Nota el orden: -p <puerto> va antes del destino usuario@host, como la mayoría de los flags en la terminal que ya conoces de módulos anteriores.
Qué esperar — si es la primera vez que tu cliente SSH habla con este servidor (o con este puerto, en este host), vas a ver algo como esto antes de que te pida ninguna contraseña:
The authenticity of host 'localhost (127.0.0.1)' can't be established.
ED25519 key fingerprint is SHA256:qR7yq3+2Z8pXk1s4Vd0Fh6mCw9tL2aB5jN8xE1yU7oQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
(El texto exacto puede variar levemente según la versión de OpenSSH, pero la estructura — pregunta sobre un fingerprint que no reconoce — se mantiene igual desde hace años.)
Esa pregunta es la mitad de la autenticación de la que hablamos arriba: tu cliente nunca había visto la identidad criptográfica (la host key) de este servidor, y te está preguntando si confías en que es quien dice ser, con base únicamente en esa huella. Este primer salto de fe se llama TOFU (trust on first use, confiar la primera vez): en un laboratorio contra tu propia máquina es perfectamente seguro responder yes, porque sabes con certeza que el servidor eres tú mismo. En un servidor de producción de un tercero, la práctica correcta es comparar ese fingerprint contra uno que el administrador te haya compartido por otro canal (no por el mismo chat donde te pasó la IP) antes de aceptar.
Responde yes y vas a ver:
Warning: Permanently added 'localhost' (ED25519) to the list of known hosts.
Esa línea se guardó en ~/.ssh/known_hosts, un archivo de texto plano con una entrada por servidor conocido (host o IP, tipo de llave, y la llave pública del servidor en base64):
cat ~/.ssh/known_hosts
Qué esperar:
localhost ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKj3f8s...
Desde la próxima vez que te conectes, ssh va a comparar la llave que el servidor presente contra esta línea sin preguntarte nada, porque ya la conoce. Si algún día esa llave cambia — porque reinstalaste el servidor, o porque alguien está intentando suplantarlo — vas a ver un mensaje de advertencia mucho más agresivo que el de la primera vez. De eso hablamos en los errores comunes.
Llaves en vez de contraseña: el par que realmente te identifica
Piensa en una contraseña como una llave física que fabricas tú mismo y que, para que funcione, tienes que entregarle una copia idéntica al portero cada vez que quieres que te reconozca — y esa copia viaja de tu mano a la suya en cada intento de entrada. Una llave SSH funciona al revés: fabricas un par inseparable de piezas, una que jamás sale de tu bolsillo (la llave privada) y otra diseñada específicamente para ser repartida sin ningún riesgo (la llave pública). Le entregas la pieza pública al portero de antemano, una sola vez. Cuando llegas, el portero no te pide que le muestres nada: te plantea un acertijo que solo la pieza privada que nunca compartiste puede resolver, tú lo resuelves de tu lado sin que la pieza privada viaje a ningún lado, y el portero verifica la respuesta con la pieza pública que ya tenía. Nunca, en ningún punto de ese intercambio, la llave privada cruzó la red.
Eso es autenticación por par de llaves asimétrico, y es la razón de fondo por la que reemplaza a la contraseña: no es "una contraseña más larga que es más difícil de adivinar" (aunque también lo sea), es un mecanismo donde el secreto real jamás se transmite, ni siquiera cifrado, en ningún intento de conexión.
Ejemplo trabajado: generar tu llave, instalarla y entrar sin contraseña
Genera tu par de llaves con el algoritmo recomendado hoy por la propia documentación de OpenSSH, Ed25519 (más corto y más rápido de verificar que RSA, con seguridad equivalente o mejor):
ssh-keygen -t ed25519 -C "alex@laptop"
El flag -C solo agrega un comentario identificador al final de la llave pública (típicamente tu usuario y máquina), para que reconozcas de un vistazo cuál llave es cuál cuando tengas varias. ssh-keygen te va a hacer tres preguntas:
Generating public/private ed25519 key pair.
Enter file in which to save the key (/Users/alex/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
La primera pregunta es dónde guardar el archivo — presiona Enter para aceptar la ubicación por defecto salvo que ya tengas una llave ahí y quieras conservarla. Las otras dos son la frase de paso (passphrase): un segundo secreto, este sí solo tuyo, que cifra el archivo de la llave privada en disco. Piénsalo como una caja fuerte adicional alrededor de la pieza que nunca debía salir de tu bolsillo: si alguien roba tu laptop o copia tu archivo id_ed25519, sin la frase de paso ese archivo robado no les sirve de nada. Dejarla vacía (Enter dos veces) es válido y common en laboratorios de práctica, pero en cualquier llave que uses contra un servidor real, ponle una — es la única defensa que te queda si el archivo cae en manos equivocadas.
Qué esperar:
Your identification has been saved in /Users/alex/.ssh/id_ed25519
Your public key has been saved in /Users/alex/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:9fK2mQ7pR1vN8xL3wB6tC4hJ0aS5dY2eU9oI7gM1kFc alex@laptop
The key's randomart image is:
+--[ED25519 256]--+
| .oo=+. |
| . +o+o. |
| o.=o. |
| . . oS. |
| o o. o |
| . +.o . |
| +.*.E |
| ..*.O. |
| .+=+*. |
+----[SHA256]-----+
Dos archivos nuevos en ~/.ssh/: id_ed25519 (privada, nunca sale de tu máquina) e id_ed25519.pub (pública, la que vas a repartir). Verifica sus permisos:
ls -l ~/.ssh/id_ed25519*
Qué esperar:
-rw------- 1 alex staff 411 Jul 20 10:02 /Users/alex/.ssh/id_ed25519
-rw-r--r-- 1 alex staff 100 Jul 20 10:02 /Users/alex/.ssh/id_ed25519.pub
Esto no es cosmético. Aplicando exactamente la tabla del módulo anterior: la llave privada nace en 600 (rw-------, solo tú lees y escribes) y la carpeta ~/.ssh completa debe estar en 700 (rwx------, solo tú puedes atravesarla). Si esos permisos son más abiertos de lo esperado, OpenSSH se niega en seco a usar la llave — no es una sugerencia de buenas prácticas, es una condición que el propio cliente y servidor SSH verifican antes de aceptar la conexión, precisamente porque una llave privada legible por cualquier otra cuenta deja de ser privada.
Ahora instala tu llave pública en el servidor (en este laboratorio, tu propia máquina) con ssh-copy-id:
ssh-copy-id $(whoami)@localhost
Qué esperar:
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/Users/alex/.ssh/id_ed25519.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
alex@localhost's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'alex@localhost'"
and check to make sure that only the key(s) you wanted were added.
Te pidió tu contraseña una última vez — la necesita para poder escribir en el servidor. ssh-copy-id no hace magia: toma tu llave pública, se conecta al servidor con el método de autenticación que sí tengas disponible todavía (la contraseña), y del otro lado ejecuta exactamente estos tres pasos, que puedes replicar a mano si alguna vez trabajas en un sistema donde ssh-copy-id no está disponible:
cat ~/.ssh/id_ed25519.pub | ssh alex@servidor \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
El archivo que crea o modifica se llama ~/.ssh/authorized_keys, y su lógica es simple: una llave pública por línea, cualquiera que aparezca ahí queda autorizada a entrar como ese usuario. Confírmalo:
cat ~/.ssh/authorized_keys
Qué esperar (una sola línea larga, empezando con el tipo de llave):
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKj3f8s... alex@laptop
Ahora conéctate de nuevo:
ssh $(whoami)@localhost
Qué esperar: si le pusiste frase de paso a tu llave, te la va a pedir a ti (para desbloquear el archivo local, un secreto que nunca sale de tu máquina); si la dejaste vacía, vas a entrar directo, sin ningún prompt. En ningún caso te va a pedir la contraseña de tu cuenta en el servidor — esa autenticación ya la resolvió la llave.
~/.ssh/config: un alias por servidor, no un comando eterno
Con un único servidor, escribir ssh alex@localhost es tolerable. En cuanto trabajas con dos o tres servidores distintos — cada uno con su propio usuario, su propio puerto y a veces su propia llave — repetir toda esa información cada vez que te conectas, o peor, tratar de memorizarla, es exactamente el tipo de fricción que la terminal está diseñada para eliminar. ~/.ssh/config es un archivo de texto donde defines, una sola vez por servidor, un alias corto y todo lo que ese alias implica.
Ejemplo trabajado: un alias con usuario, puerto y llave
Crea (o edita) el archivo:
mkdir -p ~/.ssh && chmod 700 ~/.ssh
nano ~/.ssh/config
Y agrega un bloque como este:
Host lab
HostName localhost
User alex
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
Cada línea responde una pregunta concreta: Host define el alias que vas a escribir tú (puede ser cualquier palabra, no tiene que parecerse al hostname real); HostName es la dirección o dominio real al que se traduce ese alias; User y Port evitan que tengas que escribirlos cada vez; IdentityFile fija qué llave privada usar sin que ssh tenga que probar una por una todas las que tengas en ~/.ssh/; y IdentitiesOnly yes le dice a ssh que se limite a esa llave específica, en vez de ofrecerle al servidor todas las que encuentre — útil en cuanto tengas más de una llave y quieras evitar bloqueos por demasiados intentos fallidos con la llave equivocada.
Ajusta también los permisos del archivo — no es una llave privada, pero sí contiene hostnames y usuarios que no necesitan estar expuestos a otras cuentas del sistema:
chmod 600 ~/.ssh/config
Ahora conéctate usando solo el alias:
ssh lab
Qué esperar: la misma conexión de antes, sin escribir usuario, puerto ni ruta de la llave — ssh los resolvió todos desde el bloque Host lab.
Antes de conectarte de verdad, puedes pedirle a ssh que te muestre exactamente qué configuración va a usar para un alias dado, sin abrir ninguna conexión — el mismo espíritu de "revisa antes de ejecutar" que ya viste con otras herramientas:
ssh -G lab
Qué esperar (una lista larga de parámetros resueltos; las líneas relevantes para lo que configuraste):
...
hostname localhost
user alex
port 22
identityfile ~/.ssh/id_ed25519
...
Si algo no coincide con lo que esperabas — el puerto equivocado, la llave equivocada — lo vas a ver aquí antes de que ssh intente conectar, no después de un mensaje de error confuso.
Por qué la industria dejó de confiar en las contraseñas para SSH
No es una moda ni una preferencia estética. Un servidor con SSH expuesto a internet en el puerto 22 recibe, todo el tiempo, intentos automatizados de bots que prueban combinaciones comunes de usuario y contraseña sin descanso — es tráfico de fondo constante en cualquier IP pública, no un ataque dirigido a ti en particular. Una contraseña razonable para un humano (algo memorizable) es, para ese tipo de ataque por fuerza bruta sostenido durante meses, un objetivo alcanzable tarde o temprano. Una llave Ed25519 no: el espacio de combinaciones posibles no es "más grande", es de un orden de magnitud que hace la fuerza bruta directa una estrategia sin sentido con el cómputo disponible hoy.
Hay una segunda razón, menos técnica y más operativa: revocar acceso. Si una contraseña compartida por el equipo se filtra, tienes que cambiarla y avisarle a todo el mundo que la usaba legítimamente. Si la llave pública de una persona que dejó el equipo está en authorized_keys, revocar su acceso es borrar una línea de ese archivo — nadie más se entera, nadie más tiene que cambiar nada. Por estas dos razones, la mayoría de los proveedores de servidores en la nube configuran sus imágenes por defecto con la autenticación por contraseña desactivada para SSH, aceptando exclusivamente llaves desde el primer arranque.
Vale una advertencia práctica: vas a encontrar la opción -o StrictHostKeyChecking=no en incontables scripts de integración continua y tutoriales apurados en internet. Lo que hace, literalmente, es desactivar la pregunta del fingerprint que viste al principio de esta lección — es decir, apaga la mitad de la garantía de SSH (la autenticación del servidor) a cambio de que el script no se detenga esperando un yes. Es una decisión defendible dentro de un contenedor efímero que tú mismo creaste hace treinta segundos; es una mala idea en cualquier conexión a un servidor que le importa a alguien.
Errores comunes
"Le di chmod 600 a la carpeta ~/.ssh en vez de a los archivos de adentro, y ahora nada funciona — ni siquiera con contraseña." Lo que pasa: aplicaste el permiso de un archivo secreto a un directorio. Por qué ocurre: como viste en la lección de chmod del módulo anterior, un directorio necesita el bit x para poder atravesarse — incluso su propio dueño lo necesita. 600 (rw-------) no incluye x; 700 (rwx------) sí. Sin ese bit en ~/.ssh, ni tú ni el proceso de ssh pueden entrar a leer config, id_ed25519 ni authorized_keys, aunque cada uno de esos archivos tenga sus propios permisos perfectamente correctos. Cómo detectarlo: ssh -v (verbose) hacia ese host muestra un error explícito de permisos sobre el directorio antes de siquiera intentar la autenticación, y ls -ld ~/.ssh te muestra el permiso real del directorio (no el de lo que contiene). Cómo corregirlo: chmod 700 ~/.ssh para el directorio, y deja 600 únicamente para los archivos con contenido secreto de adentro (id_ed25519, authorized_keys, config).
"Acepté el mensaje de fingerprint sin mirarlo, siempre respondo yes sin pensar." Lo que pasa: tratas esa pregunta como un trámite molesto en vez de como la única defensa real contra que te conectes al servidor equivocado. Por qué es un problema conceptual, no solo de hábito: si algún día ves este mensaje — mucho más alarmante que el de la primera conexión — en un servidor al que ya te habías conectado antes:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
eso significa que la llave del servidor cambió desde la última vez, y hay exactamente dos explicaciones: alguien reinstaló ese servidor legítimamente (nueva llave de host generada de cero), o alguien está intentando hacerse pasar por ese servidor para interceptar tu sesión. Cómo detectarlo: el mensaje aparece solo, no lo puedes ignorar — ssh se niega a continuar sin confirmación explícita. Cómo corregirlo: antes de aceptar nada, confirma por otro canal (con quien administra ese servidor, por chat o llamada, no por la misma conexión que estás intentando abrir) si el cambio era esperado. Si lo confirmas, elimina la entrada vieja con ssh-keygen -R nombre-del-host y vuelve a conectarte para registrar la nueva llave. Si no lo confirmas, no continúes.
"Copié y pegué la llave pública a mano en authorized_keys con un editor, y sigue pidiéndome la contraseña." Lo que pasa: authorized_keys espera exactamente una llave completa por línea, sin saltos de línea en medio. Copiar y pegar manualmente en algunos editores de texto (sobre todo si el terminal envuelve la línea larga visualmente) inserta un salto real donde solo había un ajuste visual, partiendo la llave en dos líneas inválidas. Cómo detectarlo: cat ~/.ssh/authorized_keys en el servidor y cuenta las líneas — si esperabas una llave y ves dos o tres líneas cortas en vez de una larga, ahí está el problema; ssh -v desde el cliente además muestra que ofrece la llave pero el servidor la rechaza. Cómo corregirlo: usa ssh-copy-id en vez de copiar y pegar a mano siempre que puedas — automatiza exactamente este paso sin el riesgo de edición manual; si no tienes esa opción, usa cat archivo.pub >> ~/.ssh/authorized_keys desde la terminal en vez de un editor visual.
Ejercicios
1. Interpreta el mensaje antes de responder
Te conectas a un servidor al que ya entraste decenas de veces sin problema, y hoy ssh te muestra la advertencia REMOTE HOST IDENTIFICATION HAS CHANGED! con un fingerprint distinto al que recordabas. ¿Qué deberías hacer antes de responder cualquier cosa, y por qué no basta con confiar en que "seguro fue un mantenimiento"?
Ver solución
Antes de responder nada, confirmar con quien administra ese servidor — por un canal distinto al que usas para conectarte — si hubo un cambio legítimo (reinstalación, migración a otra máquina, rotación de llaves de host). No basta con asumir que fue mantenimiento porque esa suposición es exactamente lo que un ataque de intermediario (machine-in-the-middle) necesita que hagas: si alguien está interceptando la conexión y presentando su propia llave en vez de la del servidor real, el mensaje se ve idéntico. Solo después de confirmar por otro canal tiene sentido borrar la entrada vieja con ssh-keygen -R host y volver a conectar.
Por qué funciona: el mensaje de cambio de identidad es la única señal automática que tienes de que la llave del servidor no es la que tu cliente registró antes; verificarla por un canal independiente es la única forma de distinguir un cambio legítimo de una suplantación, porque el canal comprometido (si lo hay) no puede mentir en dos lugares distintos a la vez.
2. Genera y clasifica
Corriste ssh-keygen -t ed25519 -C "ana@server" y aceptaste todas las opciones por defecto, incluida una frase de paso. Nombra los dos archivos que se crearon, cuál se comparte y cuál nunca sale de tu máquina, y los permisos que cada uno debería tener.
Ver solución
id_ed25519 (privada): nunca sale de la máquina donde se generó, permiso 600 (rw-------). id_ed25519.pub (pública): la que se comparte e instala en cada servidor, permiso 644 (rw-r--r--) — ser legible por cualquiera es el punto, no un riesgo.
Por qué funciona: la seguridad del esquema depende enteramente de que la mitad privada del par jamás se transmita ni sea legible por nadie más que su dueño; la mitad pública, en cambio, no revela nada útil para un atacante aunque la vea todo el mundo — es matemáticamente inviable reconstruir la privada a partir de la pública.
3. Escribe el bloque de configuración
Necesitas conectarte seguido a un servidor de respaldo con alias backup, en el host real backup.example.com, puerto 2222, usuario ops, usando específicamente la llave ~/.ssh/id_backup. Escribe el bloque completo de ~/.ssh/config y el comando que usarías para verificar que quedó bien resuelto sin conectarte todavía.
Ver solución
Host backup
HostName backup.example.com
User ops
Port 2222
IdentityFile ~/.ssh/id_backup
IdentitiesOnly yes
Para verificar sin conectar: ssh -G backup, que imprime toda la configuración resuelta para ese alias (hostname, usuario, puerto, llave) sin abrir ninguna conexión real.
Por qué funciona: ssh -G evalúa exactamente las mismas reglas de resolución de ~/.ssh/config que usaría una conexión real, pero se detiene antes de intentar el paso de red — te deja confirmar usuario, puerto y llave equivocados antes de que se conviertan en un error de conexión confuso.
4. Diagnostica un ssh-copy-id que no funcionó
Un compañero corrió ssh-copy-id contra un servidor, vio el mensaje de éxito ("Number of key(s) added: 1"), pero al conectarse de nuevo el servidor le sigue pidiendo contraseña. Nombra dos causas posibles y cómo confirmaría cada una desde la terminal.
Ver solución
Causa 1 — permisos rotos en el servidor: si ~/.ssh en el servidor quedó con permisos más abiertos de lo esperado (por ejemplo, escribible por el grupo), OpenSSH puede rechazar la autenticación por llave por completo. Se confirma con ssh -v usuario@host y revisando la salida detallada, o entrando todavía por contraseña y corriendo ls -ld ~/.ssh && ls -l ~/.ssh/authorized_keys en el servidor para comparar contra 700 y 600.
Causa 2 — el cliente está usando una llave distinta a la que se instaló: si la persona tiene varias llaves y no especificó cuál usar (ni con -i ni con IdentityFile en ~/.ssh/config), ssh puede estar ofreciendo una llave diferente a la que quedó en authorized_keys. Se confirma con ssh -v usuario@host, buscando la línea que dice qué llave está ofreciendo, y comparándola contra el contenido de authorized_keys en el servidor.
Por qué funciona: ssh -v expone justo el paso donde la autenticación por llave se decide — qué llave ofrece el cliente y por qué la rechaza o acepta el servidor — que es información que el mensaje de éxito de ssh-copy-id no puede garantizar por sí solo, porque ese mensaje solo confirma que la escritura del archivo funcionó, no que la conexión futura vaya a aceptarla.
Resumen y siguiente paso
Antes de avanzar deberías poder:
- explicar, sin mirar notas, las tres garantías de SSH (autenticación del servidor, autenticación tuya, canal cifrado) y por qué el mensaje de fingerprint la primera vez es la mitad de esa garantía, no un trámite;
- generar un par de llaves con
ssh-keygen -t ed25519, decir cuál archivo es cuál y qué permisos le corresponde a cada uno, aplicando directamente lo que ya sabías dechmod; - instalar una llave pública con
ssh-copy-idy explicar qué hace ese comando por dentro si algún día no está disponible; - escribir un bloque de
~/.ssh/configcon alias, usuario, puerto y llave, y verificarlo conssh -Gantes de conectar de verdad.
Hoy resolviste cómo entrar a otra máquina de forma segura y repetible. Todavía no resolviste qué hacer una vez adentro con algo más grande que un comando suelto: mover archivos completos entre ambas máquinas, o dejar un proceso corriendo ahí sin que muera en cuanto cierres tu laptop. Eso es exactamente lo que viene en la próxima lección — scp, rsync y tmux — y todo va a apoyarse en la conexión por llave que acabas de dominar: cada uno de esos comandos, por debajo, abre exactamente el mismo tipo de sesión SSH que abriste hoy.
Recursos
- ssh(1) — OpenSSH manual pages — referencia completa del cliente:
-p,-i,-v,-Gy el resto de las opciones. - ssh-keygen(1) — OpenSSH manual pages — todos los algoritmos y flags de generación de llaves, incluidas las diferencias entre Ed25519 y RSA.
- ssh_config(5) — OpenSSH manual pages — sintaxis completa de
~/.ssh/config:Host,HostName,User,Port,IdentityFiley todas las demás directivas. - ssh-copy-id(1) — Ubuntu Manpage Repository — qué hace exactamente el comando y sus opciones (
-i,-p). - SSH Essentials: Working with SSH Servers, Clients, and Keys — DigitalOcean — recorrido práctico complementario sobre el flujo completo cliente-servidor.