Type to search…

SSH

SSH és un protocol segur utilitzat com a mitjà principal per connectar-se a servidors Linux de forma remota

Introducció

SSH vol dir Secure Shell, i et permet connectar-te a una altra màquina mitjançant un shell remot.

Un cop t’has connectat, totes les ordres que escrius en el terminal s’envien al servidor remot i s’executen en aquella màquina (no en la teva).

Clau ssh

El més habitual en les connexions ssh és utilitzar claus assimètriques (s’explica a Criptografia) per autenticar usuaris als servidors remots.

Obre un terminal de Powershell

Verifica que tens instal·lat Win32-Openssh:

ps
ssh -V
OpenSSH_for_Windows_9.5p2, LibreSSL 3.8.2

Si ssh no està habilitat al teu sistema, instal·la openssh amb Scoop:

ps
scoop install openssh

Clau ed25519

Les claus ed25519 són claus asimètriques de corba el·líptica.

Genera un parell de claus de tipus ed25519 SSH (privada i pública) en la màquina client.

La ID de la clau (-C "david@xtec") pot ser la que vulguis: és perquè et sigui més fàcil identificar la clau en el fitxer authorized_keys!

Quan et preguntin la contrasenya, prem la tecla “enter” (sense contrasenya):

ps
ssh-keygen -t ed25519 -C "david@xtec"
Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\david/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\david/.ssh/id_ed25519
Your public key has been saved in C:\Users\david/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:BYNx9n5iURFUDsB9h8tDLIO3tfMOZ8U07zX1Z/gCw+A david@xtec
The key's randomart image is:
+--[ED25519 256]--+
|      .o=..=*=.. |
|      .o ++.=o*.+|
|         .++ O.B=|
|         oE.= B.O|
|        S + .o B=|
|         . o  o *|
|               * |
|                .|
|                 |
+----[SHA256]-----+

Pots veure el contingut de la teva clau pública:

ps
gc ~/.ssh/id_ed25519.pub
ps
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPfc8GctAnRJpVUhKmewqabRNuJNBQQrGl94froIGclk david@xtec

Permisos (Windows)

Com que has generat una clau privada aquesta només l’has de poder llegir tu.

Et pot passar que ssh no funciona perquè es nega a funcionar perquè els permisos són massa amplis.

$key és la ruta al fitxer de la teva clau privada que acabes de crear.

ps
$key = "$env:USERPROFILE\.ssh\id_ed25519"

Mira els permisos de la teva clau privada:

ps
icacls.exe $key
C:\Users\david\.ssh\id_ed25519_box BUILTIN\Administradores:(F)
                                   NT AUTHORITY\SYSTEM:(F)
                                   ELITE\david:(M)

Desactiva l’herència i elimina els permisos heretats

ps
icacls $key /inheritance:r
icacls.exe $key /c /t /Grant ${env:UserName}:F  # Set Ownership to Owner

Hauries de veure només el teu usuari amb permisos de control total (F):

ps
icacls.exe $key

Clau RSA

PENDENT de revisar a partir d’aquí

Alguns cops et pots trobar que el servidor no admet claus asimètriques ed25519 i has d’utilitzar les antigues claus RSA.

Les claus RSA són claus asimètriques que utilitzen factorització d’enters:

shell
client$ ssh-keygen -t rsa -C "box@client"
Generating public/private rsa key pair.
Enter file in which to save the key (/home/box/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/box/.ssh/id_rsa
Your public key has been saved in /home/box/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:sJiAYYhGA+ffguKfVSu5z4si8DSTXN1c3gtcUaBKd9A box@client
The key's randomart image is:
+---[RSA 3072]----+
|B+.       ..o+.  |
|+*.       .oE    |
|o o  ..o.+oo.    |
|   +.+.+oo+..    |
|...o= o.S  . .   |
|o.*  .o .   .    |
|.+ o + .         |
| .o.o =          |
|  .o.o.+.        |
+----[SHA256]-----+

Si mires el contingut de la clau rsa pots veure que la clau és molt més gran:

shell
client$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC/4kPhxXrwzbBATmhZ5ZKhYeck94z3xYK5/Nv/VRfZfgP43/HSi75hl7bjNjw+qYD4EsKpA8820WdNgFjRgz29vSunqfNjZXhI+pQzGQ7HhcqiKAmAhRp9RxA9IauaBKlAuYm7yJn2W3bQsfFaBpvlP0jm+IWqBn6xE8HE/uEp/843tSCDaARPOxc/6iEefgsD61I+C5bvDlcxLQ0raVlEc7pUUH+lmvx0NoRop3rXFJr7p/Qt7wGEyRPPaV+IELykWXVftwCSWwJSvdhg+al8PcGIAV19qnYnPDEBSFKZIY1EDeo39R5oY0Hmx2AUH1yMLn589i7zdhaUjAOL1Cdq9lEsWsG2odc0aw4meKAWU4cAFBfR4GU3heUOfEzXk4tBlviYPaw1MEUo4y0IP25IWO5OOTdTR8b84med5m7d4uHub76nzO5Ex8P/S/n//3REjsAUYqcRvwWlOC4rnWSCULp2Puawto7qUJeVFJhkQPZJQJkOwGsqqMxDtc/UDK0= box@client

Servidor

Ves a Isard.

Crea una màquina Ubuntu 24.04 Server v1.0 amb el nom server.

Arrenca la màquina.

Client

Arrenca una màquina virtual Linux amb Windows Subsystem for Linux (WSL).

shell
> connect-wsl client -new

Perquè el client pugui accedir al servidor necessita poder connectar-se a la xarxa del servidor:

La màquina virtual en aquest cas “server” té una interfície Wireguard.

Aquesta interfície està vinculada a una xarxa del sistema que assigna una adreça IP fixa a la màquina virtual “server” i permet connectar-se des d’una màquina que està fora d’Isard mitjançat una xarxa privada virtual (VPN).

Ves a Isard

Accedeix al menú desplegable de l’usuari i selecciona l’opció VPN, que descarregarà el fitxer isard-vpn.conf a l’equip amfitrió.

Instal·la i configura wireguard a la màquina client:

shell
$ sudo apt update && sudo apt install -y wireguard
$ sudo cp /mnt/c/Users/david/Downloads/isard-vpn.conf /etc/wireguard/wg0.conf
$ sudo wg-quick up wg0

Verifica que s’ha creat la interfície wg0:

shell
$ ip addr | grep wg0
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 10.0.29.109/32 scope global wg0
...

Verifica que la mtu la interfície eth0 és igual al de la interfície enp1s0 (1500) de la màquina servidor.

shell
$ ip addr | grep eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    inet 172.22.152.27/20 brd 172.22.159.255 scope global eth0

Observació. wg0 és una interfície virtual que crea un túnel a través de la interfície eth0.

Si no és el cas, modifica la mtu de la interfície eth0:

shell
$ sudo ip li set mtu 1500 dev eth0

Mira quina és la IP de la màquina remota:

ps
> get-isard
Nom     Estat   IP        
---     -----   --        
server  Started 10.2.53.164

Prova que el túnel funciona fent un ping a la màquina virtual.

Important! Fes servir la IP de la teva màquina.

shell
client$ ping -c 1 10.2.53.164
PING 10.2.53.164 (10.2.53.164) 56(84) bytes of data.
64 bytes from 10.2.53.164: icmp_seq=1 ttl=63 time=45.0 ms

--- 10.2.53.164 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 45.002/45.002/45.002/0.000 ms

Connecta’t amb ssh a la màquina virtual amb l’usuari de la màquina d’Isard: ssh usuari_remot@ip_remota

shell
client$ ssh isard@10.2.53.164
The authenticity of host '10.2.53.164 (10.2.53.164)' can't be established.
ED25519 key fingerprint is SHA256:d2ftziPI68LJO/16FBh7W6LFvak2XUoVaZkXY7VA6d0.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

El primer cop que et connectes a la màquina servidora, et pregunten si confies que aquesta és la màquina a la qual et vols connectar.

El servidor proporciona una clau publica asimètrica de tipus ED255519 que identifica al servidor.

I se suposa que tu … 😒

Fes com fa tothom, digues que sí, i endavant …

shell
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.2.53.164' (ED25519) to the list of known hosts.
isard@10.2.53.164's password: 

Et demanen la contrasenya de l’usuari_remot isard:

shell
Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-36-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

 System information as of dom 13 oct 2024 09:13:50 UTC

  System load:  0.02              Processes:               166
  Usage of /:   7.3% of 87.04GB   Users logged in:         0
  Memory usage: 3%                IPv4 address for enp1s0: 192.168.120.182
  Swap usage:   0%
server$

I ja estàs dins de la màquina servidora!

Activitat: server-desktop

Ves a Isard.

Crea una màquina “Ubuntu Mate Desktop 24.04 LTS v1.1” amb el nom server-desktop.

Arrenca la màquina.

La connexió SSH s’implementa mitjançant un model client-servidor.

Per tant, la màquina remota ha d’executar un servidor SSH.

Obre un visor a la màquina server-desktop.

ps
> connect-isard server-desktop

Instal.la un servidor SSH:

shell
server-desktop$ sudo apt install -y openssh-server
server-desktop$ sudo systemctl enable ssh --now

Connecta’t per ssh a la màquina server-desktop.

Show solution

Miro quina és la IP de la màquina des d’un terminal de powershell

ps
> get-isard
Nom        Estat   IP
---        -----   --
server     Started 10.2.53.164
server-desktop    Started 10.2.21.48

Ara em connecto per SSH des de la màquina client:

shell
client$ ssh isard@10.2.21.48
...
Ara ja puc connectar-me a qualsevol de les dues màquines remotes (server i server-desktop)

Activitat: hosts

Modifica el fitxer /etc/hosts de la màquina client per tal que resolgui les IP de server i server-desktop:

Show solution
shell
client$ printf "10.2.53.164\tserver\n10.2.21.48\tdesktop\n" | sudo tee -a /etc/hosts > /dev/null
client$ more /etc/hosts
127.0.0.1       localhost
127.0.1.1       client.  client
10.2.53.164     server
10.2.21.48      server-desktop

Verifica que et pots connectar a la màquina server amb el seu nom:

Show solution
shell
client$ ssh -v isard@server

Si mires el fitxer

TODO

Clau pública

Connecta’t per ssh a la màquina server.

shell
client$ ssh -v isard@server

Afegeix el contingut de la clau pública id_ed25519.pub de la màquina client al fitxer authorized_keys de la màquina server:

shell
server$ echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPfc8GctAnRJpVUhKmewqabRNuJNBQQrGl94froIGclk box@client" >> ~/.ssh/authorized_keys

Surt de la màquina server.

Connecta’t de nou per ssh a la màquina server.

Aquest cop no et demanen la contrasenya:

shell
client$ ssh -v isard@server
server$

Com funciona?

  1. El client diu al servidor que utilitzarà la clau pública ssh-ed25519 AAAA...clk box@client.
  2. El server verifica que aquesta clau està en el fitxer authorized_keys.
  3. El server genera un text aleatori, el xifra amb la clau pública de client i l’envia al client.
  4. El client desxifra el text, el combina amb un identificador de sessió que han negocaiat prèviament i genera un hash MD5.
  5. El client envia el hash al server.
  6. Com que el server té el text original i l’identificador de sessió, genera el hash i verifica que el que li ha enviat el client és igual.

Missatge de benvinguda

Cada cop que crees una sessió, l’usuari root executa els scripts que estan a la carpeta /etc/update-motd.d.

motd vol dir “Message of the day” i és el que apareix cada cop que et conectes a les màquines remotes.

Connecta’t a la màquina server i elimina el permís d’execució dels scripts que estan a la carpeta /etc/update-motd.d

shell
server$ sudo chmod -x /etc/update-motd.d/*

Usuari

Si el nom d’usuari de la màquina client és diferent del servidor remot, has de passar el nom de l’usuari remot.

El motiu és que una clau no està associada a cap usuari en concret: una mateixa clau pública la pot utilitzar més d’un usuari a la màquina server.

El servidor el que fa es buscar la clau pública en el fitxer ~/.ssh/authorized_keys del home de l’usuari.

Crea un nou usuari sasha a server:

Show solution
shell
server$ sudo adduser sasha

Afegeix la clau pública ed25519 de client al fitxer ~/.ssh/authorized_keys de sasha:

Show solution
shell
sever$ sudo su sasha
server$ cd
server$ mkdir .ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPfc8GctAnRJpVUhKmewqabRNuJNBQQrGl94froIGclk box@client" >> ~/.ssh/authorized_keys

Surt de la màquina server.

Connecta’t a la màquina server amb l’usuari sasha:

Show solution
shell
client$ ssh -v sasha@server
server$ $ pwd
/home/sasha

Claus diferents

Si vols utilitzar una clau específica per un usuari remot ho pots fer.

shell
client$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_toto -C "toto@server"

Crea l’usuari toto a la màquina server.

A continuació copia la clau ~/.ssh/id_ed25519_toto.pub a server:

Com que ets pots autenticar amb contrasenya pots utilitzar ssh-copy-id:

shell
client $ ssh-copy-id -i .ssh/id_ed25519_toto.pub toto@server
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_ed25519_toto.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
toto@server's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'toto@server'"
and check to make sure that only the key(s) you wanted were added.

Si intentes accedir a server amb l’usuari toto pots veure que el sistema de clau no funciona:

shell
$ ssh -v toto@server
toto@server's password:

El motiu és que ssh està utilitzant la clau id_ed25519, no la clau id_ed25519_toto.

Has d’indicar a l’ordre ssh que utilitzi la clau de toto:

shell
client$ ssh -i .ssh/id_ed25519_toto toto@server
server$ pwd
/home/toto

ssh-config

Analitzem a la màquina server-desktop la configuració de l’arxiu de configuració global per al client. Alguns exemples incloent la configuració del port, l’ús de claus privades, temps d’espera, etc.

/etc/ssh/ssh_config

shell
Host *
#   ForwardAgent no
#   ForwardX11 no
#   ForwardX11Trusted yes
#   PasswordAuthentication yes
#   HostbasedAuthentication no
#   GSSAPIAuthentication no
#   GSSAPIDelegateCredentials no
#   GSSAPIKeyExchange no
#   GSSAPITrustDNS no
#   BatchMode no
#   CheckHostIP no
#   AddressFamily any
#   ConnectTimeout 0
#   StrictHostKeyChecking ask
#   IdentityFile ~/.ssh/id_rsa
#   IdentityFile ~/.ssh/id_dsa
#   IdentityFile ~/.ssh/id_ecdsa
#   IdentityFile ~/.ssh/id_ed25519
#   Port 22
# etc

TODO

scp

scp (“secure copy”) et permet copiar fitxers i directoris de manera segura entre dos màquines.

L’ordre scp utilitza ssh: per tant, primer verifica que ssh funciona.

Copiar un fitxer local a un sistema remot

Baixa “Don Quijote” a la màquina client:

shell
client$ wget -q https://www.gutenberg.org/cache/epub/2000/pg2000.txt -O don-quijote.txt

Copia don-quijote.txt a `server:

shell
client$ scp don-quijote,txt isard@server:/home/isard
don-quijote.txt                100% 2174KB   5.9MB/s   00:00

Molt ràpid, menys d’1 segon. S’haurà copiat ? 🤔

shell
$ ssh isard@server 'ls -l'
total 2176
-rw-r--r-- 1 isard isard 2225845 oct 13 15:01 don-quijote.txt

Doncs si!

Has vist que puc executar directament una ordre en el servidor remot 😃

scp funciona com cp excepte que abans del path puc posar el servidor.

Per exemple puc copiar un fitxer dins la mateixa màquina com si fos cp:

shell
client$ scp don-quijote.txt don-quijote.txt.copy
client:~$ ls
don-quijote.txt  don-quijote.txt.copy

Si vols pots copiar el fitxer amb un altre nom:

shell
client$ scp don-quijote.txt isard@server:/home/isard/don-quixote.txt
don-quijote.txt                         100% 2174KB   4.2MB/s   00:00
client:~$ ssh isard@server 'ls -l'
total 4352
-rw-r--r-- 1 isard isard 2225845 oct 13 15:01 don-quijote
-rw-r--r-- 1 isard isard 2225845 oct 13 15:10 don-quixote.txt

I com passa amb cp els permissos de fitxers es respecten.

L’usuari isard no pot copiar un fitxer a una carpeta de l’usuari sasha en la màquina server:

shell
$ scp don-quijote.txt isard@server:/home/sasha
scp: dest open "/home/sasha/don-quijote.txt": Permission denied
scp: failed to upload file don-quijote.txt to /home/sasha

Si no especifiques la ruta de destí, per defecte es copia a la carpeta “home” de l’usuari:

shell
client$ scp don-quijote.txt sasha@server:
don-quijote.txt                    100% 2174KB   5.7MB/s   00:00
client:~$ ssh sasha@server 'ls -l'
total 2176
-rw-r--r-- 1 sasha sasha 2225845 oct 13 15:14 don-quijote.txt

Fixa’t que el destí és sasha@server: … els dos punts finals són molt importants.

Si no els poses, scp pensa que el destí és un fitxer local (típic error d’examen) 😮‍💨

shell
client$ scp don-quijote.txt sasha@server
client:~$ ls -l
total 6528
-rw-r--r-- 1 box box 2225845 Oct  1 18:42 don-quijote.txt
-rw-r--r-- 1 box box 2225845 Oct 13 17:08 don-quijote.txt.copy
-rw-r--r-- 1 box box 2225845 Oct 13 17:17 sasha@server

També pots copiar un directori de manera recursiva amb el flag -r (igual que amb cp):

shell
$ scp -r /usr/bin isard@server:
truncate                         100%   39KB 335.8KB/s   00:00
dbus-monitor                     100%   26KB 562.2KB/s   00:00
pkttyagent                       100%   22KB 576.6KB/s   00:00
dh_bash-completion               100% 4527   105.9KB/s   00:00
perl5.38-x86_64-linux-gnu        100%   14KB 361.7KB/s   00:00
gp-archive                       100%  159KB   1.3MB/s   00:00
lzgrep                           100%   10KB 241.0KB/s   00:00
readelf                          100%  771KB   1.7MB/s   00:00
loadunimap                       100%   34KB 858.4KB/s   00:00
uname                            100%   35KB 870.5KB/s   00:00
localectl                          0%    0     0.0KB/s   --:-- ETA^Cbox@client:~$

Copiar un fitxer remot a un sistema local

És el mateix que abans, però ara al fitxer origen li hem de dir de quina màquina.

shell
client$ rm *
client $ scp isard@server:don-quijote.txt .
don-quijote.txt                             100% 2174KB   3.8MB/s   00:00
client$ ls -l
total 2176
-rw-r--r-- 1 box box 2225845 Oct 13 17:27 don-quijote.txt

Copiar un fitxer entre dos sistemes remots

Copia la clau id_ed25519 a la màquina desktop:

Show solution
shell
$ ssh-copy-id -i .ssh/id_ed25519.pub isard@desktop

Borra el fitxer don-quijote.txt de la màquina local.

Còpia don-quijote.txt de server a desktop:

Show solution
shell
client$ scp isard@server:don-quijote.txt isard@desktop:
don-quijote.txt                             100% 2174KB   3.1MB/s   00:00
client:~$ ssh isard@desktop 'ls -l'
total 2216
drwxr-xr-x 2 isard isard    4096 ago  5 12:37 Desktop
drwxr-xr-x 2 isard isard    4096 jul  3 21:56 Documents
-rw-r--r-- 1 isard isard 2225845 oct 13 17:34 don-quijote.txt
...

Opcions

TODO

scp ofereix una sèrie d’opcions que controlen tots els aspectes del seu comportament.

  1. L’opció -p conserva els temps de modificació i accés dels fitxers.
  2. L’opció -q suprimeix el mesurador de progrés i els missatges sense error.
  3. L’opció -C obliga a scp a comprimir les dades a mesura que s’envien a la màquina de destinació.

rsync

Google Docs - SSH

Servidor SSH

Google Docs - SSH Server

Python

Crea un projecte ssh a la màquina client amb Poetry

shell
$ sudo apt install -y python3-poetry
$ $ poetry new ssh --name app
Created package app in ssh
$ skills ssh

Entra dins la carpeta ssh i instal·la la llibreria paramiko:

shell
$ poetry add paramiko

Executar una ordre

Crea l’script app/main.py:

python
import paramiko

try:
    client = paramiko.client.SSHClient()
    # Let know Paramiko that you validate your trust with the machine for the first time you try to connect to the server.
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect("server", username="isard")

    stdin, stdout, _ = client.exec_command("ls -l")
    print(stdout.read().decode())
    stdin.close()

finally:
    client.close()

Executa l’script:

shell
$ poetry run python3 app/main.py 
total 4368
drwxr-xr-x  2 isard isard    4096 oct 13 15:21 bin
-rw-r--r--  1 isard isard 2225845 oct 13 15:01 don-quijote.txt
-rw-r--r--  1 isard isard 2225845 oct 13 15:10 don-quixote.txt

Transferir un fitxer

Baixa el llibre “Frankestein”:

shell
$ wget -q https://www.gutenberg.org/cache/epub/84/pg84.txt -O frankestein.txt

Modifica el fitxer app/main.py:

python
import paramiko

try:
    client = paramiko.client.SSHClient()
    # Let know Paramiko that you validate your trust with the machine for the first time you try to connect to the server.
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect("server", username="isard")

    ftp_client = client.open_sftp()
    ftp_client.put("frankestein.txt", "frankestein.txt")
    ftp_client.close()


finally:
    client.close()

Transfereix el llibre:

shell
$ poetry run python3 app/main.py 
$ ssh isard@server 'ls -l | grep fran'
-rw-rw-r--  1 isard isard  448937 oct 13 16:04 frankestein.txt