Dimarts, juny 10, 2025
CLOUD

Connectar la teva màquina local per SSH a una instància al núvol

Quan treballes amb servidors al núvol, especialment en entorns on cal mantenir agilitat sense comprometre seguretat, la connexió per SSH es converteix en part dia a dia. I encara que sembli trivial —generar una clau, llançar una instància, copiar la IP i connectar—, hi ha força punts on és fàcil prendre dreceres que després es paguen cares.

Això no és una guia per a principiants ni una recepta ràpida. És un repàs amb criteri tècnic sobre les decisions que realment importen en establir una connexió SSH des d’una màquina local a una instància al núvol. I més enllà de connectar, que és la part fàcil, anem a mirar tot el que envolta aquest procés: configuracions que eviten errors subtils, decisions de seguretat que no es corregeixen fàcilment a posteriori, i tècniques que acaben marcant la diferència quan has de mantenir moltes màquines, o necessites fer debugging en producció sota pressió.

1. La generació de claus: la part que molts fan en pilot automàtic

Gairebé tothom comença amb un ssh-keygen sense paràmetres i es queda amb una clau RSA del 2048 bits per defecte. Això continua funcionant, però no és la millor elecció avui.

Recomanació: fes servir ed25519 llevat que tinguis una raó concreta per a una altra cosa. És més segura, més ràpida, i les claus són més curtes. El comandament:

ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_cloud_ed25519

-a 100 afegeix rounds de hashing amb bcrypt, cosa que mitiga atacs per força bruta si algú aconsegueix la clau privada. No és el mateix tenir una clau compromesa xifrada amb 16 rounds que amb 100.

Coses que sovint queden mal configurades:

  • Generar claus sense passphrase, per mandra o scripts trencats. A mig termini, sempre es filtra alguna clau privada. Millor fer servir ssh-agent ben configurat, o gpg-agent si ja tens una infraestructura de gestió de claus en el teu entorn local.
  • Deixar un reguitzell de claus diferents per a cada instància. Si no estàs fent servir alguna cosa com ssh_config o IdentityFile de forma explícita, el creixement de claus desorganitzades es torna incontrolable.

2. La primera connexió: del “ssh ubuntu@x.x.x.x” al caos en known_hosts

Connectar-te per primera vegada a una IP pública d’una instància nova et mostra el prompt de fingerprint. Acceptes, es guarda a ~/.ssh/known_hosts, i tot segueix.

Fins que fas un destroy + recreate de la instància, o canvies la imatge base. Llavors el fingerprint canvia, i SSH protesta amb el clàssic:

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

I toca netejar a mà el known_hosts.

Solucions que funcionen:

  • Si estàs en entorns on les IPs canvien constantment (per exemple, fent servir instàncies spot, o màquines de staging que es llancen/destrueixen per CI/CD), millor fer servir HostKeyAlias al teu ~/.ssh/config. Per exemple:
Host staging-web
    HostName 34.171.98.12
    User ubuntu
    IdentityFile ~/.ssh/id_cloud_ed25519
    HostKeyAlias staging-web

Així el fingerprint es guarda amb l’àlies i no amb la IP. Quan canviï la IP, no hi haurà conflicte si segueixes fent servir l’àlies. I si canvia el fingerprint de veritat (per una recreació), pots avaluar si ho acceptes o no, però sense llits amb altres entrades de l’arxiu.

  • Alternativa quan no pots fer servir HostKeyAlias: automatitza l’esborrat amb un script que faci alguna cosa com:
ssh-keygen -R "$OLD_IP"

Però això és més fràgil i tendeix a trencar coses si tens moltes màquines darrere de la mateixa IP (VPNs, jump hosts, etc.).

3. Configurar ~/.ssh/config bé des del començament

Molts desenvolupadors ignoren aquest arxiu fins que tenen 20 instàncies, i aleshores ja és tard per organitzar-lo.

Aquí és on estalvies temps i evites errors. Alguns patrons útils:

a) Àlies amb lògica clara:

Host prod-*
    User ubuntu
    IdentityFile ~/.ssh/id_cloud_ed25519
    ForwardAgent yes

Fer servir patrons ajuda a evitar duplicació. Però no abusis de * si no tens control estricte dels noms de host, o podries aplicar configuracions sense adonar-te’n.

b) Control de temps i verbosity:

LogLevel ERROR
ConnectTimeout 5
ServerAliveInterval 60
ServerAliveCountMax 3

Això evita connexions penjades durant minuts quan alguna cosa falla, i redueix el soroll de logs si estàs redireccionant sortides.

c) Agent de reenviament només quan ho necessites

ForwardAgent yes és pràctic, però un risc si el deixes actiu per defecte. En servidors compromesos, l’ agent pot fer-se servir per pivotar. Aplica’l només on calgui (ex. bastion/jump).

4. Connexió a través de bastion/jump hosts: el punt de fricció més habitual

Si gestiones VPCs tancades, gairebé segur que passes per un bastió. Fer salts manuals (ssh -J bastion target) està bé al començament, però en entorns reals acaba generant errors subtils:

  1. SSH lent perquè s’estableix una nova connexió TCP per cada salt.
  2. Problemes amb scp, rsync, o reenviament de ports.
  3. Mala gestió de reenviament d’ agents o claus errònies enviades en el salt.

Configuració fiable per a salts:

Host bastion
    HostName 203.0.113.10
    User ec2-user
    IdentityFile ~/.ssh/id_bastion_ed25519 

Host internal-*
    ProxyJump bastion
    User ubuntu
    IdentityFile ~/.ssh/id_cloud_ed25519

També pots controlar el forwarding de ports o de X11 de forma explícita. I si necessites debuggejar connexions SSH que es queden penjades, prova amb:

ssh -vvv internal-app

L’opció -vvv mostra cada pas del handshake i sovint revela si el problema està en la clau, en la xarxa o en el firewall.

5. Casos on SSH es trenca per una cosa externa

a) Instància viva però port 22 tancat.

Això és més comú del que sembla. Un equip de xarxes canvia una regla de firewall, i tu penses que el servidor ha caigut. Fes sempre un nmap o telnet abans d’assumir que la màquina ha mort:

nc -v 203.0.113.25 22

b) Connexió rebutjada en cloud-init.

En màquines que es llancen amb cloud-init, és habitual que SSHd no estigui disponible els primers segons. El port respon però la connexió es tanca. Si fas ssh just després del boot, falla, però 10 segons després funciona.

Per evitar la frustració: fes servir retries als scripts de connexió automàtica. O espera a un cloud-init status –wait si tens accés per consola.

c) Claus mal injectades des de la consola web.

AWS, GCP i altres plataformes et permeten carregar claus públiques en llençar una instància. Si després canvies la clau local però no la re-injectes, l’accés falla encara que la resta estigui bé. Això és fàcil d’oblidar si comparteixes imatges amb altres equips.

El que sovint faig és injectar claus amb user-data i assegurar-me de que les claus públiques estan en control de versions.

6. Seguretat: allò que és còmode tendeix a ser insegur

  • Evita deixar el port 22 obert a tot internet. Fes servir regles de firewall per IP fixa o rangs CIDR limitats.
  • Desactiva PasswordAuthentication al sshd_config sempre que puguis.
  • Si fas servir Fail2Ban, ajusta el ban time. Les configuracions per defecte són insuficients si t’estan atacant des de xarxes rotatives.
  • Per a entorns més estrictes, considera OpenSSH amb certificats (ssh-keygen -s) en comptes de claus estàtiques. No és trivial de muntar, però redueix el risc de claus perdudes sense control.

7. Automatització i eines

Quan has de gestionar moltes màquines o entorns canviants, el SSH manual no escala.

Algunes pràctiques que ajuden:

  • Fes servir Ansible o scripts amb ProxyCommand perquè el salt de bastió sigui transparent.
  • Per a desenvolupament local, sshfs permet muntar un sistema remot com si fos local. Útil, però sensible a latència.
  • mosh és excel·lent si treballes amb connexions inestables (per exemple des del tren o Wi-Fi amb talls). Fes servir UDP i manté la sessió viva fins i tot si canvies d’IP.

8. Debugging de connexions lentes o inestables

Una connexió SSH que “funciona però va lenta” és pitjor que una que falla del tot. Aquí van alguns punts que val la pena revisar quan la sessió es queda enganxada o respon amb retards:

a) Resolució inversa de DNS en el servidor

SSHd, per defecte, intenta fer una recerca inversa del hostname des de la IP de qui es connecta. Si no hi ha un PTR vàlid, o si hi ha latència de xarxa, això introdueix una pausa de 5–10 segons al connectar-se. Pots desactivar-ho al servidor:

UseDNS no

En moltes distros això ja ve desactivat, però no en totes. El mateix amb GSSAPIAuthentication yes, que també pot introduir latència innecessària si no estàs en un entorn Kerberos.

b) MTU incorrecte o paquets fragmentats

Connexions lentes o que es tallen a meitat de reenviament d’ arxius es poden deure a problemes de MTU. Si hi ha túnels de per mig (VPNs, GRE, IPSec) i la MTU és massa alta, alguns paquets es fragmenten i es perden. Scp es queixa, i ssh sembla “penjat “.

La forma ràpida de provar-ho és fer servir:

ping -M do -s 1472 remote-ip

I baixar fins que trobis una mida que passi sense fragmentar-se.

c) Reenviament de ports i NAT agressiu

Si estàs darrere d’una NAT simètrica o un firewall que tanca connexions inactives, pots perdre la sessió SSH sense previ avís. En aquests casos, ServerAliveInterval en el client i ClientAliveInterval en el servidor són els teus aliats:

ServerAliveInterval 30
ServerAliveCountMax 2

Això envia keepalives cada 30 segons i considera morta la sessió després de 2 fallades. També pots fer servir el sistema operatiu, però SSH té el seu propi mecanisme.

9. Bones pràctiques per a entorns multiusuari

Quan més d’una persona necessita accés a una instància, moltes vegades s’opta per “compartir la clau”. Això és una drecera que acaba malament en entorns on cal revocar accessos o auditar connexions.

El que funciona millor:

  • Un usuari comú (ubuntu, ec2-user, etc.) amb múltiples claus públiques en ~/.ssh/authorized_keys, una per cada persona. Nomena les claus amb el nom de l’ usuari, o afegeix comentaris identificatius al final de cada clau.
ssh-ed25519 AAAAC3NzaC1... alice@laptop
ssh-ed25519 AAAAC3NzaC1... bob@home
  • Fes servir ssh -i per especificar la teva clau privada en connectar. O bé configura un host específic per persona si cal fer seguiment.
  • En màquines més controlades, fes servir sshd_config amb AuthorizedKeysCommand per carregar claus dinàmicament (per exemple des de LDAP, Vault, o una API interna). Això dona flexibilitat per revocar accessos sense haver de tocar disc local.

10. Quan has de fer túnels o port forwarding

És habitual haver d’exposar un port remot a la teva màquina local (per exemple, una base de dades al núvol que no té IP pública). Aquí el clàssic:

ssh -L 5432:localhost:5432 user@remote

Això et permet connectar-te a localhost:5432 i parlar amb PostgreSQL que corre en el servidor remot.

Errors comuns:

  • No fer servir GatewayPorts no, cosa que permet accidentalment que d’altres a la xarxa facin servir el teu túnel.
  • Oblidar que el port remot pot estar escoltant només en 127.0.0.1, i per tant localment funciona des de la instància però no des de fora.
  • Túnels que es cauen sense avís. Pots fer servir autossh per mantenir-los vius automàticament:
autossh -M 0 -f -N -L 5432:localhost:5432 user@remote

També hi ha eines com sshuttle, que crea una VPN basada en SSH, útil quan has d’accedir a múltiples IPs privades darrere d’una jump box sense configurar rutes específiques.

11. Coses que es trenquen quan automatitzes

Si estàs generant instàncies automàticament (terraform, cloud-init, Ansible, etc.), és fàcil oblidar-se de coses que en mode manual sí que fas bé.

Errors que es repeteixen:

  • Injectar malament el authorized_keys per permisos incorrectes. ~/.ssh/authorized_keys n’ha de tenir 600, i .ssh n’ha de tenir 700. Si no, SSH ho ignora sense avís clar.
  • Deixar sessions penjades per falta de sudo amb requiretty en sistemes que l’imposen.
  • No validar que sshd ha arrencat realment (alguns scripts suposen que el port 22 estarà obert després del boot).

12. Alternatives i extensions quan SSH es queda curt

Quan gestiones moltes màquines, o necessites auditar connexions, hi ha eines que estenen SSH de forma útil:

  • Teleport: centralitza accessos SSH amb autenticació basada en certificats, control d’ expiració, i gravació de sessions.
  • Vault + signed SSH keys: si ja fas servir Vault, pots emetre claus SSH amb TTL i rotar-les sense tocar les màquines.
  • Bastion-as-a-service: moltes plataformes tenen ara solucions tipus “Session Manager” (AWS) o “IAP tunneling” (GCP). No requereixen port 22 obert, funcionen per HTTPS, i auditen tot per defecte.

13. El patró que es repetirà en projectes nous

Després de provar moltes combinacions, hi ha una configuració base que aplico en projectes nous i que poques vegades em dona problemes:

  1. Claus ed25519 amb passphrase.
  2. SSH config amb àlies per entorn (dev-web-1, prod-api-2, etc.).
  3. Jump hosts explícits i gestionats amb ProxyJump.
  4. Keepalives actius per evitar sessions trencades.
  5. Port forwarding només en túnels explícits, no en la sessió normal.
  6. .ssh/config en control de versions, sense claus.
  7. Repositori privat amb les claus públiques que s’han d’instal·lar a cada instància (Ansible o cloud-init les còpia).

Aquest setup em dona connexió immediata, previsibilitat i control. I quan alguna cosa falla, sé on mirar i no tinc que desfer capes de hacks acumulats.

Tancament

SSH no és el complicat. El complicat és mantenir-lo net al llarg del temps, quan les màquines es multipliquen, els equips canvien i els entorns s’automatitzen.

Connectar des de la teva màquina local a una instància remota és trivial. Fer-ho de forma segura, repetible i sense fricció al cap de sis mesos, quan tens 30 instàncies i diversos usuaris, és un altre tema. Els detalls que semblen “micro” —com l’ordre dels Host al .ssh/config, o els flags a ssh-keygen— són just els que defineixen si tens control o caos.

Si tens una configuració que sempre fas servir, o un patró que t’ha salvat més d’una vegada, documentar-lo i mantenir-lo com a base redueix molt el desgast. I quan algú nou arriba a l’equip, que pugui clonar la teva setup sense reinventar la roda és gairebé tan útil com una bona documentació.

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *