Ya has usado SSH en este curso decenas de veces: entras en srv-tramontana desde portatil-alumno, copias ficheros con scp y sincronizas con rsync. Lo has usado como quien usa un ascensor, sin preguntarte cómo funciona. Esta lección abre la caja, porque SSH es la puerta principal de tu servidor y en este momento esa puerta acepta contraseñas, permite entrar como root y lleva acumulados 47 intentos fallidos desde 203.0.113.44 que nadie ha mirado.
Al terminar tendrás claves ed25519 en lugar de contraseñas, un sshd_config endurecido directiva por directiva, un ~/.ssh/config que hace el trabajo pesado por ti, túneles para llegar a la base de datos de Tramontana sin exponerla a nadie, y la costumbre —que aquí no es opcional— de no cerrar nunca la puerta por la que estás entrando.
Contenido
- Qué resuelve SSH y por qué Telnet y FTP están muertos
- Arquitectura y las tres fases del protocolo
- Autenticación del servidor: claves de host y
known_hosts - Autenticación con claves: generar, instalar y proteger
ssh-agent, reenvío de agente yProxyJump- El fichero de configuración del cliente
- Endurecer
/etc/ssh/sshd_config - El procedimiento seguro para no quedarte fuera
- Túneles: local, remoto y SOCKS
- Transferencia de ficheros:
scp,sftpyrsync - Sesiones persistentes con
tmux - Auditoría: los 47 intentos desde 203.0.113.44
- Qué resuelve SSH y por qué Telnet y FTP están muertos
Antes de SSH, administrar una máquina remota significaba Telnet: un protocolo que envía usuario, contraseña y todos los comandos en texto plano por la red. Cualquiera con acceso al mismo segmento —o al router de en medio— leía la sesión entera. Lo mismo con FTP, rlogin y rsh.
SSH resuelve tres problemas a la vez, y conviene distinguirlos porque cada uno se ataca de forma distinta:
| Problema | Qué garantiza SSH | Cómo |
|---|---|---|
| Confidencialidad | Nadie en medio lee lo que envías | Cifrado simétrico del canal |
| Integridad | Nadie altera los datos sin que se note | MAC / cifrado autenticado |
| Autenticación mutua | El servidor es quien dice ser y tú también | Claves de host + claves de usuario |
La tercera es la que más se olvida y la más importante: un canal cifrado hacia el atacante equivocado no protege absolutamente nada. Por eso la lección dedica un apartado entero a known_hosts.
- Arquitectura y las tres fases del protocolo
En srv-tramontana corre el demonio sshd, gestionado por systemd. En Ubuntu 24.04 hay un detalle que sorprende a mucha gente: el servicio está activado por socket.
$ systemctl status ssh --no-pager
● ssh.service - OpenBSD Secure Shell server
Active: active (running) since Mon 2026-08-18 09:15:02 CEST
TriggeredBy: ● ssh.socketssh.socket escucha el puerto y arranca ssh.service cuando llega una conexión. La consecuencia práctica es importante y la retomamos en el apartado 7: la directiva Port de sshd_config se ignora mientras la activación por socket esté en marcha.
Una conexión SSH atraviesa tres fases en este orden:
sequenceDiagram
participant C as Cliente (portatil-alumno)
participant S as Servidor (srv-tramontana)
C->>S: 1. Versiones y algoritmos soportados
S->>C: Clave pública de host + intercambio de claves
Note over C,S: Canal cifrado establecido (Diffie-Hellman efímero)
C->>C: 2. ¿Coincide la huella con known_hosts?
C->>S: 3. Autenticación: firma con la clave privada del usuario
S->>C: Verificada contra authorized_keys → sesión concedida
- Intercambio de claves y canal cifrado. Cliente y servidor negocian algoritmos y derivan una clave de sesión con Diffie-Hellman efímero. A partir de aquí todo va cifrado, incluida la fase 3.
- Autenticación del servidor. El servidor demuestra que posee la clave privada correspondiente a su clave de host; el cliente comprueba esa clave contra
known_hosts. - Autenticación del cliente. Ahora, y solo ahora, el usuario se identifica —con clave o con contraseña—. Es fundamental que vaya después: por eso la contraseña nunca viaja en claro.
- Autenticación del servidor: claves de host y
known_hosts
known_hostsEl servidor tiene sus propias claves en /etc/ssh/, generadas en la instalación:
$ ls /etc/ssh/ssh_host_*_key
/etc/ssh/ssh_host_ecdsa_key /etc/ssh/ssh_host_ed25519_key /etc/ssh/ssh_host_rsa_key
$ ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:9dK3nQpX2vTfL8mRc1sYwZ0aB4eHgJ7iOu5N6xVpQrE root@srv-tramontana (ED25519)La primera vez que te conectas ves esto:
The authenticity of host '10.0.2.15 (10.0.2.15)' can't be established. ED25519 key fingerprint is SHA256:9dK3nQpX2vTfL8mRc1sYwZ0aB4eHgJ7iOu5N6xVpQrE. Are you sure you want to continue connecting (yes/no/[fingerprint])?
Qué significa de verdad ese aviso, y no lo que hace todo el mundo: SSH te está diciendo «no tengo forma de saber si esta máquina es la que buscas». La respuesta correcta no es teclear yes a ciegas, sino comparar esa huella con la que has obtenido por un canal distinto —la consola de la VM, el panel del proveedor de nube, un correo firmado de quien instaló el servidor—. Si aceptas sin comprobar, aceptas la primera máquina que responda, y ese es exactamente el hueco del ataque de intermediario (man-in-the-middle): alguien se coloca entre tú y el servidor, te presenta su clave de host, tú aceptas, y a partir de ahí descifra tu sesión, ve tu contraseña y la reenvía al servidor real. Todo con el candado verde puesto.
Tras aceptar, la clave se guarda en ~/.ssh/known_hosts y las conexiones siguientes se verifican solas. Si un día cambia, verás un aviso enorme con REMOTE HOST IDENTIFICATION HAS CHANGED! y la conexión se rechaza. Las causas legítimas son tres: se reinstaló el servidor, se regeneraron sus claves de host, o la IP se reutilizó para otra máquina. La causa ilegítima es un intermediario. Averigua cuál es antes de borrar nada, y cuando lo sepas, borra solo esa entrada:
Nunca rm ~/.ssh/known_hosts: eso destruye la confianza acumulada con todas las máquinas y te deja aceptando huellas nuevas a ciegas durante semanas.
- Autenticación con claves: generar, instalar y proteger
La criptografía asimétrica usa un par de claves relacionadas matemáticamente: lo que firma la privada solo lo verifica su pública correspondiente, y de la pública no se puede deducir la privada en un tiempo razonable. En SSH, tú guardas la privada en tu portátil y subes la pública al servidor. Para autenticarte, el servidor te lanza un reto, tú lo firmas con la privada y él verifica la firma con la pública que tiene en authorized_keys. La clave privada nunca sale de tu máquina, ni siquiera cifrada: eso es lo que hace que sea radicalmente mejor que una contraseña, que sí viaja (aunque sea por un canal cifrado) y que sí se puede adivinar a fuerza de intentos.
$ ssh-keygen -t ed25519 -C "operador@portatil-alumno-2026-08"
Enter file in which to save the key (/home/alumno/.ssh/id_ed25519):
Enter passphrase for "/home/alumno/.ssh/id_ed25519" (empty for no passphrase):
Your identification has been saved in /home/alumno/.ssh/id_ed25519
The key fingerprint is:
SHA256:tR7xK2mP9wQ4vZ1cN8bY0aL6sJ3fH5gD operador@portatil-alumno-2026-08Por qué ed25519 y no RSA: ed25519 ofrece seguridad equivalente a RSA de 3072 bits con claves de 68 caracteres, firma y verifica más rápido, no depende de un generador de números aleatorios de calidad en cada firma y no tiene parámetros que puedas elegir mal. Usa RSA de 4096 bits solo si necesitas compatibilidad con equipamiento antiguo que no soporte ed25519. El comentario -C no es decorativo: identifica de quién y de cuándo es la clave cuando revises authorized_keys dentro de dos años.
La frase de paso cifra la clave privada en disco. Es la segunda capa: si te roban el portátil, tienen un fichero inútil sin ella. El coste —teclearla en cada uso— lo resuelve ssh-agent.
Los permisos son obligatorios, no una recomendación. SSH se niega a usar una clave privada legible por otros:
$ chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_ed25519 && chmod 644 ~/.ssh/id_ed25519.pub
$ ssh [email protected]
Permissions 0644 for '/home/alumno/.ssh/id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.Instalar la pública en el servidor, con la herramienta o a mano:
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected] # o, a mano:
$ cat ~/.ssh/id_ed25519.pub | ssh [email protected] \
'install -d -m 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'Cada línea de authorized_keys admite opciones por clave delante del tipo, y son una capa de control que casi nadie usa:
from="10.0.2.0/24,192.0.2.10" ssh-ed25519 AAAAC3Nza...QrE operador@portatil-alumno restrict,command="/home/operador/scripts/respaldo_tramontana.sh --solo-lectura" ssh-ed25519 AAAAC3Nza...tYu copias@nas
| Opción | Efecto |
|---|---|
from="patrón" |
La clave solo vale desde esas IP o nombres |
command="..." |
Se ejecuta eso y nada más, ignorando lo que pida el cliente |
restrict |
Desactiva de golpe túneles, agente, X11 y pty (lo más seguro por defecto) |
no-port-forwarding |
Prohíbe túneles con esa clave |
La combinación restrict,command= es la forma correcta de dar acceso a un proceso automático —una copia, un despliegue— sin darle una shell.
ssh-agent, reenvío de agente y ProxyJump
ssh-agent, reenvío de agente y ProxyJumpssh-agent guarda tu clave descifrada en memoria para no teclear la frase de paso cada vez:
$ eval "$(ssh-agent -s)"
Agent pid 4821
$ ssh-add -t 4h ~/.ssh/id_ed25519
Enter passphrase for /home/alumno/.ssh/id_ed25519:
Identity added: /home/alumno/.ssh/id_ed25519 (operador@portatil-alumno-2026-08)
Lifetime set to 14400 seconds-t 4h hace que la clave caduque en el agente: si dejas el portátil desbloqueado en una cafetería, la ventana de exposición es limitada. ssh-add -D las borra todas de golpe.
El reenvío de agente (ssh -A) permite usar tus claves desde el servidor al que has entrado, para saltar a un tercero. Su riesgo real: mientras la sesión está abierta, cualquiera con root en esa máquina intermedia puede usar tu agente —hablar con el socket de /tmp/ssh-*/agent.* y firmar con tus claves para entrar en cualquier sitio donde valgan—. No te roba la clave, pero puede usarla, que a efectos prácticos es lo mismo.
La alternativa correcta es ProxyJump, que no expone el agente: el cliente abre un túnel a través del salto y negocia el cifrado de extremo a extremo con el destino final.
$ ssh -J [email protected] [email protected]Regla práctica: usa ProxyJump siempre; usa -A solo si no hay alternativa, y entonces con ssh-add -c (pide confirmación en cada uso).
- El fichero de configuración del cliente
Todo lo anterior se escribe una vez en ~/.ssh/config (permisos 600) y desaparece de tu memoria muscular:
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
HashKnownHosts yes
Host tramontana
HostName 10.0.2.15
User operador
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
ControlMaster auto
ControlPath ~/.ssh/cm-%r@%h:%p
ControlPersist 10m
Host tramontana-luis
HostName 10.0.2.30
User luis
IdentityFile ~/.ssh/id_ed25519
ProxyJump tramontana| Directiva | Para qué sirve |
|---|---|
HostName / User / Port |
Los datos reales tras el alias: ssh tramontana y ya |
IdentityFile |
Qué clave usar con este destino |
IdentitiesOnly yes |
Ofrecer solo esa clave: sin esto el agente prueba todas y puedes agotar MaxAuthTries |
ServerAliveInterval |
Envía un latido cada 30 s: evita que el NAT corte sesiones inactivas |
ControlMaster/ControlPersist |
Multiplexado: la segunda conexión reutiliza el canal de la primera y abre en milisegundos |
ProxyJump |
Salto intermedio sin exponer el agente |
El multiplexado es el que más se nota: rsync y scp repetidos dejan de renegociar el cifrado cada vez.
- Endurecer
/etc/ssh/sshd_config
/etc/ssh/sshd_configEste es el corazón de la lección. Ubuntu 24.04 lee /etc/ssh/sshd_config y, dentro de él, un Include /etc/ssh/sshd_config.d/*.conf al principio del fichero. Como en SSH gana el primer valor encontrado, lo que pongas en un fichero de sshd_config.d/ tiene prioridad sobre el fichero principal. Esa es la forma limpia de endurecer sin tocar el original ni pelearte con la próxima actualización del paquete.
$ sudo cp /etc/ssh/sshd_config /root/sshd_config.bak-$(date +%F)
$ sudo tee /etc/ssh/sshd_config.d/60-tramontana.conf > /dev/null <<'CONF'
# Endurecimiento SSH de srv-tramontana — ver /opt/tramontana/HISTORIAL
PermitRootLogin no
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no
AllowGroups sshusers
MaxAuthTries 3
MaxSessions 5
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
X11Forwarding no
AllowTcpForwarding yes
AllowAgentForwarding no
PrintMotd no
LogLevel VERBOSE
CONF
$ sudo chmod 600 /etc/ssh/sshd_config.d/60-tramontana.conf| Directiva | Qué protege | Matiz honesto |
|---|---|---|
PermitRootLogin no |
Elimina la cuenta que todo atacante prueba primero; obliga a entrar con nombre propio y sudo, que además deja rastro |
Con prohibit-password root sigue entrando con clave; no es más claro |
PasswordAuthentication no |
La medida más eficaz de todas: mata la fuerza bruta de raíz | Asegúrate antes de que tu clave funciona |
KbdInteractiveAuthentication no |
Cierra la vía alternativa por la que PAM podría seguir pidiendo contraseña | Sin esto, lo anterior se puede sortear |
AllowGroups sshusers |
Lista blanca: aunque exista, becario no entra si no está en el grupo |
Crea el grupo antes de recargar |
MaxAuthTries 3 |
Corta la sesión tras 3 intentos y multiplica el coste del ataque | Cuidado si el agente ofrece muchas claves |
LoginGraceTime 30 |
Menos conexiones a medio autenticar abiertas | 120 s por defecto es demasiado |
ClientAliveInterval 300 |
Cierra sesiones muertas de administradores olvidados | Complementa a ServerAliveInterval del cliente |
X11Forwarding no |
Superficie que un servidor sin escritorio no necesita | — |
AllowAgentForwarding no |
Impide que un compromiso del servidor use los agentes de quien entra | — |
LogLevel VERBOSE |
Registra la huella de la clave usada en cada acceso | Imprescindible para auditar; sin él no sabes qué clave entró |
Y el debate honesto sobre cambiar el puerto: mover SSH del 22 al 2222 reduce muchísimo el ruido de los escaneos automáticos y, por tanto, el tamaño de tus logs. Lo que no hace es protegerte: cualquier nmap de diez segundos encuentra el puerto nuevo, y a cambio complicas la vida a tus herramientas y a tus compañeros. Es higiene de logs, no seguridad; no lo cuentes nunca como control. Si aun así lo haces en Ubuntu 24.04, recuerda la activación por socket: Port 2222 en sshd_config no tiene efecto y hay que tocar el socket.
La primera línea vacía borra la lista heredada; sin ella, el servicio escucharía en los dos puertos.
- El procedimiento seguro para no quedarte fuera
La regla de oro de este módulo: nunca cierres la puerta por la que estás entrando. En SSH se traduce en cinco pasos que no se saltan nunca.
# 1. Crear lo que la configuración da por hecho
$ sudo groupadd -f sshusers && sudo usermod -aG sshusers operador
# 2. Validar la sintaxis SIN aplicar nada
$ sudo sshd -t && echo "sintaxis correcta"
sintaxis correcta
# 3. Ver la configuración EFECTIVA tras los Include
$ sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|allowgroups|maxauthtries)'
permitrootlogin no
passwordauthentication no
allowgroups sshusers
maxauthtries 3
# 4. Recargar (no reiniciar): las sesiones abiertas sobreviven
$ sudo systemctl reload ssh
# 5. Probar desde una TERCERA sesión, sin cerrar las dos anteriores
$ ssh -v [email protected] 'echo OK'
debug1: Authentications that can continue: publickey
debug1: Offering public key: /home/alumno/.ssh/id_ed25519 ED25519
debug1: Server accepts key
OKsshd -t valida sintaxis; sshd -T te muestra el resultado después de resolver los Include, que es lo único que cuenta. reload relee la configuración sin tocar las sesiones establecidas: si la has liado, tus dos sesiones abiertas siguen vivas y puedes revertir. Y por encima de todo está la consola de la VM en VirtualBox, que no pasa por la red y es tu último recurso. Con activación por socket, un cambio de puerto necesita además sudo systemctl restart ssh.socket.
- Túneles: local, remoto y SOCKS
Un túnel SSH transporta una conexión TCP arbitraria dentro del canal cifrado. Tres formas, tres casos de uso reales en Tramontana:
# LOCAL (-L): conectar a PostgreSQL de srv-tramontana desde el portátil,
# sin que la base de datos escuche en ninguna interfaz pública.
$ ssh -N -L 15432:127.0.0.1:5432 tramontana
$ psql -h 127.0.0.1 -p 15432 -U operador tramontana
# REMOTO (-R): exponer temporalmente un servicio del portátil al servidor,
# por ejemplo un repositorio de artefactos durante una prueba de despliegue.
$ ssh -N -R 9000:127.0.0.1:9000 tramontana
# SOCKS (-D): proxy dinámico para navegar como si estuvieras en la red interna.
$ ssh -N -D 1080 tramontanaLee -L 15432:127.0.0.1:5432 así: «abre el puerto 15432 en mi máquina; lo que llegue ahí, sácalo por el otro extremo del túnel y entrégalo a 127.0.0.1:5432 visto desde el servidor». Es exactamente lo que necesitas para administrar la base de datos con una herramienta gráfica sin abrir el 5432 en el firewall. -N significa «no ejecutes ningún comando, solo el túnel».
Aviso importante: por defecto los túneles remotos (-R) solo escuchan en localhost del servidor, y eso está bien. Abrirlos a todas las interfaces requiere GatewayPorts yes en sshd_config, que es una forma estupenda de saltarte tu propio cortafuegos sin darte cuenta. Déjalo como está.
- Transferencia de ficheros:
scp, sftp y rsync
scp, sftp y rsync| Herramienta | Estado hoy | Cuándo usarla |
|---|---|---|
scp |
Desaconsejado: su protocolo tenía problemas de seguridad y en OpenSSH 9 ya usa SFTP por debajo | Copias sueltas y rápidas |
sftp |
El sustituto oficial | Sesiones interactivas, automatización con -b |
rsync -e ssh |
El mejor para volumen | Sincronizar, reanudar, filtrar, verificar |
$ rsync -avz --partial --progress -e ssh \
/home/operador/datos/reservas.csv tramontana:/srv/tramontana/backups/
sending incremental file list
reservas.csv
1.248 100% 1,19MB/s 0:00:00 (xfr#1, to-chk=0/1)--partial conserva lo transferido si la conexión se corta, y --progress te dice si merece la pena esperar. Combinado con el ControlPersist del apartado 6, un rsync repetido ni siquiera renegocia el cifrado.
- Sesiones persistentes con
tmux
tmuxSi tu conexión se corta a mitad de un apt upgrade o de un desplegar.sh, el proceso recibe SIGHUP y muere a medias. Un despliegue interrumpido entre el rsync del release y el systemctl restart deja la aplicación en un estado que nadie diseñó.
$ tmux new -s despliegue
$ ./desplegar.sh --version 3.2.2 # se corta la conexión...
$ ssh tramontana
$ tmux attach -t despliegue # ...y aquí sigue, corriendotmux (o screen, más antiguo) mantiene la sesión en el servidor, independiente de tu conexión. Regla profesional: toda operación larga en producción se lanza dentro de tmux. Es gratis y evita incidentes de los que se cuentan durante años.
- Auditoría: los 47 intentos desde 203.0.113.44
Todo lo que hace sshd acaba en el journal y en /var/log/auth.log.
$ sudo journalctl -u ssh --since "-24h" | grep -c 'Failed password'
47
$ sudo journalctl -u ssh --since "-24h" | grep 'Failed password' | tail -1
ago 18 03:14:55 srv-tramontana sshd[2843]: Failed password for invalid user admin from 203.0.113.44 port 51288 ssh2
$ sudo lastb -F | head -2
root ssh:notty 203.0.113.44 mar ago 18 03:14:52 2026 - mar ago 18 03:14:52 (00:00)
admin ssh:notty 203.0.113.44 mar ago 18 03:14:55 2026 - mar ago 18 03:14:55 (00:00)lastb lee /var/log/btmp, el registro de intentos fallidos (last lee wtmp, los correctos). Con lo aprendido en el Módulo 3, el resumen por IP y por usuario probado sale en una línea:
$ sudo lastb | awk '{print $3}' | sort | uniq -c | sort -rn
47 203.0.113.44
2 10.0.2.77
$ sudo lastb | awk '{print $1}' | sort | uniq -c | sort -rn | head -3
19 root
11 admin
9 postgresInterpretación: 47 intentos desde una sola IP, probando root, admin, postgres y ubuntu en tres minutos. No es alguien que se equivoque de contraseña: es un bot de fuerza bruta, uno de los miles que barren Internet. Los dos intentos desde 10.0.2.77 son de la red interna y probablemente sean Luis tecleando mal.
Lo bueno: con PasswordAuthentication no acabas de convertir esos 47 intentos en ruido inofensivo, porque ya no existe la vía que estaban probando. Lo malo: el bot sigue llamando, consume recursos, ensucia tus logs y seguirá ahí mañana con otra técnica. Bloquearlo en la puerta —y automatizar el bloqueo— es exactamente el trabajo de la lección siguiente.
Advertencia de seguridad y compliance: srv-tramontana trata datos personales de huéspedes, así que el acceso remoto es un control sujeto al RGPD. En un entorno real eso implica accesos nominativos (nunca cuentas compartidas), registro de quién entra y cuándo con retención acordada, revisión periódica de authorized_keys para retirar las claves de quien ya no está, y revisión del cambio por el responsable de seguridad. Y el análisis de logs de acceso, que identifica a personas trabajadoras, tiene límites legales: se hace con finalidad de seguridad y con la política informada, no para vigilar a nadie.
Errores Comunes y Consejos
- Activar
PasswordAuthentication nosin haber probado la clave. El clásico que deja a gente fuera de servidores en producción. Prueba primerossh -o PreferredAuthentications=publickey, y solo entonces recarga. - Permisos incorrectos en
~/.ssh. SSH ignora en silencio (o casi) claves yauthorized_keysdemasiado abiertos.700el directorio,600las claves privadas yauthorized_keys. Si algo «no funciona sin motivo»,ssh -vvvte lo dice en la líneaAuthentications that can continue. - Borrar
known_hostsentero ante un aviso de huella cambiada. Investiga la causa y usassh-keygen -R <host>. systemctl restart sshen vez dereload. Con configuración rota,restartte deja fuera;reloadmantiene vivas las sesiones existentes.- Copiar la clave privada a los servidores «para saltar de uno a otro». La privada no sale de tu portátil: para eso están
ProxyJumpy, con reservas, el agente. - Olvidar que el grupo de
AllowGroupsdebe existir. Si escribesAllowGroups sshusersy el grupo está vacío, no entra nadie. Créalo y añade a la gente antes de recargar. - Consejo: documenta cada clave de
authorized_keyscon su comentario-C(persona, máquina, fecha) y revísalo cada trimestre. Una clave huérfana es una puerta abierta con nombre olvidado.
Ejercicios
- Acceso restringido para las copias. El NAS de Tramontana (10.0.2.90) debe ejecutar, y solo eso,
/home/operador/scripts/respaldo_tramontana.sh --solo-lecturaen el servidor. Escribe la línea exacta deauthorized_keysy justifica cada opción. - Túnel a la base de datos. Marta quiere que Luis consulte PostgreSQL desde
portatil-luiscon una herramienta gráfica, sin que el 5432 quede expuesto. Da el comando, explica cada parámetro y di qué se configura en la herramienta. - Recuperación de un cambio desastroso. Aplicas
AllowGroups admins(grupo inexistente) y recargas. Tienes una sesión SSH abierta y la consola de la VM. Detalla el diagnóstico y la reparación, y qué paso del procedimiento te habría evitado el susto.
Soluciones
1. Una sola línea, con doble candado —quién y desde dónde— más el confinamiento del comando:
from="10.0.2.90",restrict,command="/home/operador/scripts/respaldo_tramontana.sh --solo-lectura" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...tYu nas-copias@tramontana-2026-08
from="10.0.2.90"— aunque roben la clave del NAS, solo sirve desde esa IP. Es una capa extra que no cuesta nada.restrict— desactiva de golpe túneles, reenvío de agente, X11 y asignación de pty. Es el valor por defecto seguro: en lugar de ir prohibiendo cosas una a una, se prohíbe todo y se habilita lo necesario.command="..."— se ejecuta ese comando pase lo que pase; si el NAS pidebash, obtiene igualmente el script. El original queda enSSH_ORIGINAL_COMMAND, así que el script podría inspeccionarlo, pero nunca ejecutarlo a ciegas.- El comentario final identifica la clave para la revisión trimestral.
Con esas tres opciones, un compromiso del NAS no te da una shell en srv-tramontana: da como mucho una copia de solo lectura ejecutada desde una IP concreta.
2. Un túnel local desde el portátil de Luis:
$ ssh -N -f -L 15432:127.0.0.1:5432 [email protected]-L 15432:127.0.0.1:5432— abre el 15432 enportatil-luis; lo que llegue ahí sale por el túnel y se entrega a127.0.0.1:5432desde el punto de vista del servidor. La base de datos sigue escuchando solo enlocalhost.-N— no ejecutar ningún comando remoto: solo queremos el túnel.-f— pasar a segundo plano una vez autenticado, para recuperar la terminal.
En la herramienta gráfica, Luis configura host 127.0.0.1, puerto 15432, su usuario y su base de datos. Lo que protege esto: PostgreSQL no está expuesto a la red, la autenticación la controla SSH (con clave, no contraseña) y el tráfico va cifrado. Lo que no protege: si el portátil de Luis está comprometido, el atacante tiene el mismo acceso; y cualquier usuario local de ese portátil puede usar el 15432, así que la forma estricta sería -L 127.0.0.1:15432:127.0.0.1:5432.
3. Diagnóstico y reparación desde la sesión que sigue abierta (o desde la consola de la VM):
$ sudo sshd -T | grep allowgroups
allowgroups admins
$ getent group admins || echo "el grupo NO existe"
el grupo NO existe
$ sudo journalctl -u ssh -n 5 --no-pager
sshd[3102]: User operador from 10.0.2.50 not allowed because none of user's groups are listed in AllowGroups
Dos reparaciones posibles, según lo que quisieras hacer:
$ sudo sed -i 's/^AllowGroups admins/AllowGroups sshusers/' /etc/ssh/sshd_config.d/60-tramontana.conf
$ sudo sshd -t && sudo systemctl reload ssh # alternativa: groupadd -f admins && usermod -aG admins operador
$ ssh [email protected] 'echo OK'
OKEl paso que te habría evitado el susto es el 3 del procedimiento: sudo sshd -T muestra la configuración efectiva, y comprobar getent group admins antes de recargar habría revelado en dos segundos que el grupo no existía. sshd -t no lo detecta, porque la sintaxis es perfectamente válida: el fichero está bien escrito y dice exactamente lo que no querías. Esa es la diferencia entre validar la sintaxis y validar la intención — y la razón de que la segunda sesión abierta no sea negociable.
Conclusión
La puerta principal de srv-tramontana ya tiene cerradura. Has entendido las tres fases del protocolo y por qué la contraseña nunca viaja en claro; sabes qué significa de verdad la huella que te piden aceptar la primera vez y cómo reaccionar cuando cambia; tienes un par ed25519 con frase de paso, un agente que la caduca a las cuatro horas y un ~/.ssh/config que multiplexa conexiones y salta con ProxyJump en vez de exponer el agente. En el servidor, un fichero en sshd_config.d/ prohíbe root, elimina la autenticación por contraseña, restringe el acceso al grupo sshusers y registra en modo VERBOSE la huella de cada clave que entra — todo aplicado con sshd -t, sshd -T, reload y tres sesiones abiertas, porque nunca se cierra la puerta por la que estás entrando. Y llegas a la base de datos por un túnel -L sin exponer un solo puerto de más.
También has puesto nombre al ruido: 47 intentos desde 203.0.113.44 probando root, admin, postgres y ubuntu en tres minutos. Contra esa IP concreta has ganado —ya no hay contraseñas que adivinar—, pero el bot sigue tocando el timbre, y mañana probará el 8080, que sigue abierto de par en par a cualquiera que llegue a la máquina, igual que lo estaría PostgreSQL si algún día escuchara fuera de localhost. SSH era un servicio; lo que falta es una política de qué puede llegar siquiera a hablar con este servidor. Eso es la lección 06-03: Firewall y Seguridad Perimetral, donde conocerás netfilter y nftables por dentro, levantarás ufw en el orden correcto para no perder la sesión, escribirás un ruleset completo para Tramontana, ajustarás los sysctl de red con impacto en seguridad y pondrás a fail2ban a bloquear automáticamente a 203.0.113.44 y a todos los que vengan detrás.
Curso de Linux: De Principiante a Administrador de Sistemas
Módulo 1: Introducción a Linux
- ¿Qué es Linux?
- Historia de Linux
- Distribuciones de Linux
- Instalando Linux
- Primer Contacto con el Sistema
- Estructura del Sistema de Archivos de Linux
Módulo 2: Comandos Básicos de Linux
- Introducción a la Línea de Comandos
- Obtener Ayuda y Documentación del Sistema
- Navegando el Sistema de Archivos
- Operaciones con Archivos y Directorios
- Visualización y Edición de Archivos
- Enlaces Duros y Simbólicos
- Permisos y Propiedad de Archivos
Módulo 3: Habilidades Avanzadas en la Línea de Comandos
- El Entorno del Shell: Variables, Alias e Historial
- Uso de Comodines y Expresiones Regulares
- Búsqueda de Archivos y Contenido: find, locate y grep
- Tuberías y Redirección
- Procesamiento de Texto: cut, sort, uniq, sed y awk
- Gestión de Procesos
- Programación de Tareas con Cron
- Comandos de Redes
Módulo 4: Scripting en Shell
- Introducción al Scripting en Shell
- Variables y Tipos de Datos
- Entrada, Salida y Argumentos de un Script
- Estructuras de Control
- Funciones y Librerías
- Depuración y Manejo de Errores
- Scripts de Producción: Buenas Prácticas
Módulo 5: Administración del Sistema
- Gestión de Usuarios y Grupos
- sudo y Permisos Especiales
- Gestión de Paquetes
- Gestión de Discos
- systemd y la Gestión de Servicios
- Registros del Sistema: journald y syslog
- Monitoreo del Sistema y Optimización del Rendimiento
- Respaldo y Restauración
Módulo 6: Redes y Seguridad
- Configuración de Redes
- SSH y Acceso Remoto
- Firewall y Seguridad Perimetral
- Sistemas de Detección de Intrusos
- Gestión de Secretos y Certificados TLS
- Asegurando Sistemas Linux
Módulo 7: Temas Avanzados
- El Proceso de Arranque y la Recuperación del Sistema
- Diagnóstico Avanzado: strace, perf y eBPF
- Optimización del Kernel de Linux
- Virtualización con Linux
- Contenedores de Linux y Docker
- Automatización con Ansible
- Alta Disponibilidad y Balanceo de Carga
