User Tools

Site Tools


informatique:logiciels:ssh

SSH

recueil d'informations concernant SSH

SSH, ou Secure SHell permet de communiquer avec une machine distante de manière chiffrée, donc sécurisée.

Configuration du serveur

aptitude install openssh-server

Le fichier de configuration /etc/ssh/sshd_config par défaut se suffit à lui-même ; cependant on peut modifier/ajouter les directives suivantes :

# désactivation du login pour le compte root
PermitRootLogin no
# limiter les connexions au seuls utilisateurs toto, et titi depuis la machine 1.2.3.4
AllowUsers toto titi@1.2.3.4
 
# on n'accepte que les utilisateurs membres du groupe ssh_users
AllowGroup ssh_users
 
# on veut que le serveur écoute sur un port supplémentaire
Port 22 2222
 
# Limiter les tentatives de login à 5
MaxAuthTries 5
 
# bon, là ça rentre en conflit avec la directive ci-dessus mais c'est pour l'exemple
# 10 tentatives de connexion simultanées max ; puis 30% de refus : puis 100% à la 15e
MaxStartups 10:30:15
 
# pour partager une redirection de port avec n'importe qui qui se connecte dessus
# en gros la redirection se fait sur 0.0.0.0:x et non plus 127.0.0.1:x donc elle redirige tous
# les paquets arrivant sur son port x, pas seulement ceux en provenance de ma connexion SSH
GatewayPorts yes

On (re)lance le service :

/etc/init.d/ssh restart

Mep d'une bannière

Par défaut la bannière qui est utilisée est le contenu du fichier /etc/motd. On peut donc modifier le contenu de ce fichier, ou utiliser la directive

banner <fichier>

dans le fichier de conf.

Limitation d'une paire de clé

Pour ne permettre à un utilisateur s'authentifiant avec une paire de clé à ne lancer qu'une seule commande, il faut spécifier command=<cmd> devant la clé dans le fichier .ssh/authorized_keys :

command="ls" ssh-rsa AAAB3[..]

Dans le cas précédent, la commande ls sera lancée, puis la connexion se terminera.

Afficher la liste des paramètres

Ceci permet d'afficher en vrac la liste des paramètres du serveur SSHd. Il faut utiliser -T (test) avec l'option -C user=<un_user>, qui permet de spécifier un utilisateur pour le contexte de test (sinon on obtient l'erreur : 'Match User' in configuration but 'user' not in connection test specification.)

sshd -T -C user=guest

Utilisation du client

On l'utilise dans un terminal (ou grâce à Putty si on tourne sous Windows) selon la syntaxe de base :

ssh -p <port> [login@]server

Si c'est la première connexion SSH depuis ce client vers ce serveur, il vous demande si le fingerprint de la clé publique présentée par le serveur est bien le bon. Si c'est la bonne, répondez “yes” : la clé publique du serveur est alors rajoutée au fichier ~/.ssh/known_hosts.

Fichier ~/.ssh/config

Pour éviter d'avoir à saisir tous ces paramètres (utilisateur, port, etc) à chaque connexion vers un serveur, on peut les enregistrer dans le fichier ~/.ssh/config.

Par exemple pour simplifier la commande : ssh -l toto -p 2222 -D 1025 exemple.fr :

 cat ~/.ssh/config
Host ex
	Hostname exemple.fr
	User toto
        Port 2222
	DynamicForward 1025

Il suffit maintenant de saisir :

ssh ex

… pour se connecter au serveur. La liste exhaustive des paramètres est disponible dans le man ssh_config.

Gérer des clés

Pour générer une paire de clés sécurisées utiliser les valeurs par défaut :

$ ssh-keygen

Actuellement (en 2021) il est raisonnable d'utiliser au moins du chiffrement RSA 4096 bits (-t rsa -b 4096), et dans l'idéal du ED25519 (-t ed25519) qui utilise une variante de chiffrement par courbes elliptiques.

Pour formater une clé publique au format RFC 4716 :

$ ssh-keygen -ef ~/.ssh/id_rsa -mRFC4716
---- BEGIN SSH2 PUBLIC KEY ----
Comment: "4096-bit RSA, converted by dude@technodrome from OpenSSH"
AAAAB3NzaC1yc2EAAAADAQABAAABAQCzU4exWqu4tsgWIJleq1AJ98cGHswD80cphWYOas
spBoOPgdv
[blabla sur quelques lignes]
15ukAsdfsdgg3h5f4h6dfh3fj84tK1
---- END SSH2 PUBLIC KEY ----

Alternatives : convertir au format PEM -mPEM ou PKCS8 -mPKCS8.

Se connecter sans mdp

Sur la machine cliente :

  • générer un couple de clé rsa :
cd ~/.ssh
ssh-keygen -t rsa
 Generating public/private rsa key pair.
 Enter file in which to save the key (/home/<user>/.ssh/id_rsa): 
 Enter passphrase (empty for no passphrase): 
 Enter same passphrase again: 
 Your identification has been saved in /home/<user>/.ssh/id_rsa.
 Your public key has been saved in /home/<user>/.ssh/id_rsa.pub.
 The key fingerprint is:
 5a:1d:34:b1:44:dc:1f:94:58:f2:e9:ae:ab:5c:0c:97 <user>@<host>

id_rsa est la clé privée ; id_rsa.pub la clé publique La passphrase n'est pas indispensable, mais recommandée pour des questions de sécurité.

  • envoyer sa clé publique sur le serveur <host>
ssh-copy-id [-i [identity_file]] [user@]machine

… ou moins simple en copiant à la main sa clé publique dans ~/.ssh/authorized_keys

cat ~/.ssh/id_rsa.pub | ssh <user>@<host> "cat - >> ~/.ssh/authorized_keys"

NB : la commande ssh-copy-id ne gère pas plusieurs arguments (wtf ?!) ; donc, si le serveur SSH distant est sur un port autre que celui par défaut (tcp/22), vous devez passer les arguments entre “ ” ; exemple :

ssh-copy-id -i /home/dude/.ssh/id_rsa.pub 10.0.0.1:2222
ssh: Could not resolve hostname 10.0.0.1:2222: Name or service not known
 
ssh-copy-id -i /home/dude/.ssh/id_rsa.pub -p 2222 10.0.0.1
ssh: Could not resolve hostname umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys: Name or service not known
 
# la solution :
ssh-copy-id -i /home/dude/.ssh/id_rsa.pub "-p 2222 10.0.0.1"

On peut rencontrer des problèmes d'authentification si les droits du fichier authorized_keys ne sont pas en 600 (il ne doit pas être lisible par les autres utilisateurs du système). Le dossier ~/.ssh/ doit être en 700 parait-il (à vérifier).

Pour interdire à cet utilisateur de lancer un shell, il faut ajouter no-pty devant sa clé, par exemple :

vi ~/.ssh/authorized_keys
no-pty ssh-dss AAAAB3NzaC..qxX/27ZZ9X5vAVA= backup
  • si l'on utilise une passphrase, il faudra la saisir à chaque ssh qu'on fera. Pour ne pas avoir à la retaper à chaque fois, on utilise ssh-agent :
eval 'ssh-agent'
SSH_AUTH_SOCK=/tmp/ssh-00021836aa/agent.21836; export SSH_AUTH_SOCK;
SSH_AGENT_PID=5683; export SSH_AGENT_PID;
echo Agent pid 5683;
ssh-add ~/.ssh/id_rsa
Enter passphrase for /home/<user>/.ssh/id_rsa: 
Identity added: /home/<user>/.ssh/id_rsa (/home/<user>/.ssh/id_rsa)

On lance ssh-agent, qui est un processus qui va saisir la passphrase à notre place ; puis on lui spécifie notre clé privée (id_rsa) et on saisit (une fois pour la session) notre passphrase. Tant que la session sera ouverte, ssh-agent sera en mémoire et dispensera de saisir la passphrase.

ssh-add

Cet outil sert à ajouter ou supprimer des identités (clés) au ssh-agent :

  • pour lister toutes les identités déjà chargées : ssh-add -l (fingerprints) ou ssh-add -L (clé publique).
  • pour ajouter une nouvelle identité : ssh-add ~/.ssh/id_rsa-perso ; si lancé sans argument, il ajoutera ce qu'il trouve parmi les fichiers existants : ~/.ssh/id_rsa, ~/.ssh/id_dsa et ~/.ssh/identity.
  • pour supprimer une identité : ssh-add -d ~/.ssh/id_rsa-perso. Pour supprimer toutes les identités : ssh-add -D.

Par défaut le client SSH va présenter toutes les identités qu'il trouvera ; pour désactiver ce comportement (et éviter tous les failed login qui en découlent) :

~/.ssh/config
IdentitiesOnly yes

Attention il faudra soit utiliser ssh-agent, soit préciser l'identité en CLI avec l'option -i <id_file.key> : ssh -i ~/.ssh/id_rsa_example serveur

  • pour plus de sécurité on peut restreindre l'utilisation des clés à une machine ou un sous-domaine en rajoutant from=“<host>” en début de ligne correspondante dans le fichier authorized_keys :
cat authorized_keys
from="*.stuff.net" ssh-rsa AAA..

Ici on filtre sur le sous-domaine stuff.net

Transfert de fichier avec SCP

Tunnels SSH

Faire un tunnel SSH, c'est créer une connexion SSH pour y faire passer (encapsuler) des données de manière sécurisée. En lançant une connexion SSH depuis mon poste client vers serveurSSH.com, je spécifie que tous les paquets à destination de mon port local 10080 seront envoyés dans le tunnel SSH, reçus par serveurSSH.com, qui les redirigera à destination de serveurWEB.com sur le port 80 :

ssh -L 10080:serveurWEB.com:80 serveurSSH.com

Concrètement, en saisissant dans mon navigateur http://localhost:10080, on accèdera à http://serveurWEB.com via serveurSSH.com (dans les logs de serveuWEB.com c'est donc l'IP de serveurSSH qui apparaitra).

La syntaxe est la suivante : -L <port_local>:<IP cible>:<port de l'IP cible>.

Les redirections des ports systèmes (<1024 ) nécessitent l'accès root sur le serveur SSH.

Exemple d'application : contourner les restrictions (excessives bien sur) du réseau de votre boulot.
But : avoir accès à tous les sites web en évitant les filtrages éventuels d'un admin réseau fasciste.
Condition : que ledit réseau d'entreprise ne filtre pas les paquets qui initient une connexion SSH, et qu'il ne fasse pas de l'analyse application (niveau 7) avec un IPS par exemple.

Situation :

  • installer un proxy (Squid par exemple) sur un PC chez soi, sur le port 3128 (c'est le port par défaut). Inutile de préciser que vous devez connaitre l'IP du PC, le laisser allumé, qu'il doit faire tourner un serveur SSH, et avoir configurer votre firewall éventuel pour accepter les connexions sur ce port.
  • lancer la commande ssh -L 1111:127.0.0.1:3128 toto@<votre-ip> depuis un poste distant, pour créer le tunnel sécurisé.
  • dans la configuration de votre navigateur, régler le proxy sur l'adresse 127.0.0.1 et le port 1111.

C'est tout. Votre navigateur va interroger la machine sur lequel vous surfez (127.0.0.1 c'est l'adresse IP locale) sur le port 1111. Or tout ce qui est envoyé à destination de ce port est envoyé dans le tunnel SSH. La requête arrive donc sur l'ordinateur <votre-IP>, qui va rediriger le flux vers l'IP:port spécifié lors de la création du tunnel, soit 127.0.0.1:3128. Cette IP on la reconnait, c'est l'IP locale ; le port c'est le 3128, soit celui du serveur proxy Squid qui tourne sur votre PC “serveur”.

Inutile de préciser que dans cet exemple il y a 2 IP locales distinctes (127.0.0.1). Cette IP désigne la machine elle-même : elle est relative à la machine. Dans le premier cas il s'agit du poste client, dans le second du serveur SSH distant.

CQFD, tout votre trafic Internet sera masqué par le tunnel et vous pourrez surfer sans restriction de site (le traffic Internet est chiffré pour le réseau d'entreprise). Attention toutefois, ce n'est pas de cas à partir de votre PC : lorsque vous surferez, les sites visitez vous verrons comme si vous étiez en train de surfer depuis le PC de chez vous.

Back connexion

Il existe un moyen de faire une back connexion, c'est à dire une redirection de requête via une autre machine. Supposons que je sois sur une machine (cliente) A et que je veuille rediriger les requêtes qu'une machine B (serveur) fait sur le port 8022

Sur la machine A je fais un :

ssh -R 8022:toto.com:22 B

Sur la machine B je fais un :

ssh -p 8022 localhost

Cette dernière commande envoie une requête en local sur la machine B, sur le port 8022. Or ce port est redirigé vers la machine A, via la connexion ssh établie précédemment, et envoyé vers toto.com:22 à partir de A, soit vers son serveur SSH.

Export display

L'export display consiste à se logguer à distance en mode graphique, comme on le fait avec un client et un serveur SSH en mode texte. On peut alors exécuter des applications graphiques sur le serveur distant : la fenêtre graphique de l'application et son contenu seront envoyés par le réseau vers la machine cliente. Il faut cependant avoir une bonne connexion.

Sur le serveur SSH, dans le fichier /etc/ssh/sshd_config, vérifier la présence de la directive

X11Forwarding yes

Sur le client, qui doit être muni d'un serveur X :

ssh -X [-C] serveur

-X permet l'export display et -C (facultatif) permet d'activer la compression des données (permet un gain de bande passante au détriment de la consommation CPU).

Puis lancer une application graphique.

Pour les postes clients sous Windows, on peut passer par l'installation de Cygwin avec un serveur X (http://cygwin.com/ Cygwin ou http://x.cygwin.com/ Cygwin/X). Dans le cas de Cygwin/X : on le lance, on lance le serveur X

startxwin.sh

Cela lance un xterm (et une icone dans la taskbar). Ensuite on procède comme normalement :

ssh -X serveur

Après un su/sudo

Le X11 ne passe pas les su et sudo ; pour créer la continuité de l'affichage, il faut :

# afficher le DISPLAY avant le sudo
echo $DISPLAY
 localhost:10.0
 
# afficher les xauth et copier la ligne qui correspond à notre DISPLAY (ici le ":10")
xauth list
[..]
serveur/unix:10  MIT-MAGIC-COOKIE-1  58ff4f8de36bdddb68ad47bc0e29ac4d
 
# ajouter l'xauth dans la session du su/sudo
sudo -i
xauth add serveur/unix:10  MIT-MAGIC-COOKIE-1  58ff4f8de36bdddb68ad47bc0e29ac4d
 
xclock&

Exécuter un script local sur le serveur distant

Pour cela, on lance la commande bash distante, en précisant le paramètre -s qui lui demande de lire l'entrée standard. Et on envoie le script sur l'entrée standard comme n'importe quelle commande, avec <.

ssh user@remoteserver 'bash -s' < script.sh

Si le script n'est pas dans un fichier, on peut envoyer les commandes sur plusieurs lignes en usant d'un Heredoc :

ssh user@remoteserver 'bash -s' << EOF
hostname
pwd
EOF

Tips

Stream audio over SSH

Stream audio over SSH : on transmet le fichier file.mp3 dans la connexion SSH ; le flux est lu par le logiciel mpg321 sur le serveur distant.

ssh [user]@[address] "mpg321 -" < file.mp3

Lister les options du ssh

Pour lister les paramètres effectifs avec lesquels se lance le démon sshd (c'est utile notamment pour voir la valeur des paramètres non spécifiés dans le fichier de configuration /etc/ssh/sshd_config) :

sshd -T

Côté client, on peut afficher les paramètres courants avec l'option -G :

ssh -G <serveur>

Mode debug/verbose

Pour débugger une connexion SSH récalcitrante, utiliser l'option -v pour activer le mode bavard (~ debug). Il existe 3 niveaux de verbosité que l'on spécifie en fonction du nombre de “v” : par exemple pour le debug2 (niveau intermédiaire mais déjà très causant) :

ssh -vv user@server
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to server [10.1.1.51] port 22.
debug1: Connection established.
debug1: identity file /home/user/.ssh/identity type -1
[..]

Lister les clés présentes

Une commande pratique pour lister les clés SSH présentent localement, et afficher leur niveau de sécurité (taille, algo, etc) :

for keyfile in ~/.ssh/id_*; do ssh-keygen -l -f "${keyfile}"; done | uniq
 1024 c1:ec:c8:00:05:32:5f:a7:fa:ef:69:4e:ea:90:1b:55 /root/.ssh/id_dsa.pub (DSA)
 2048 53:16:df:00:10:fb:cc:fb:51:e9:80:e5:a6:4a:86:ab /root/.ssh/id_rsa.pub (RSA)

Modifier une passphrase

Pour changer la passphrase d'une clé SSH existante :

ssh-keygen -f ~/.ssh/id_rsa -p
 Key has comment 'id_rsa'
 Enter new passphrase (empty for no passphrase): 
 Enter same passphrase again: 
 Your identification has been saved with the new passphrase.

Séquence d'échappement

Lorsqu'une connexion telnet est bloquée, on peut taper une séquence d'échappement qui permet de sortir de telnet et récupérer la main sur son terminal : Ctrl ° (le ° se saisit avec AltGr + ) ) (souvent suivi de quit).

La même avec le client SSH est : ~. (<Enter> + ~ + .) ; elle permet de fermer la connexion et de rendre la main sur le terminal.

Saisir un mot de passe via SSH

Lorsqu'on lance un script via SSH et que ce dernier demande un mot de passe, on obtient l'erreur suivante : pas de tty présent et pas de programme askpass spécifié.

Pour transmettre le mot de passe via la connexion SSH il faut ajouter l'option -t à la commande SSH, pour forcer l'allocation d'un pseudo-tty :

ssh USER@SERVER "sudo whoami"
USER@SERVER''s password: 
sudo: pas de tty présent et pas de programme askpass spécifié
 
ssh -t USER@SERVER "sudo whoami"
USER@SERVER''s password: 
[sudo] Mot de passe de USER : 
root
Connection to SERVER closed.

src : https://stackoverflow.com/questions/10310299/proper-way-to-sudo-over-ssh

Timeout d'établissement de connexion SSH

Lorsqu'on lance une connexion SSH, si le serveur cible ne répond pas instantanément, le client SSH va attendre un certain délais (le timeout TCP du système) avant de rendre la main et d'afficher le triste constat d'échec suivant : ssh: connect to host serveur-down port 22: Connection timed out.

On peut limiter ce timeout pour ne pas avoir à attendre 3 plombes qu'il nous rende la main, en utilisant l'option ConnectTimeout :

# réglage du temps maximal d'attente à 5 secondes, si serveur-down ne répond pas
ssh -o ConnectTimeout=5 serveur-down

Si “serveur-down” possède plusieurs adresses IP, le client SSH les essayera les unes après les autres jusqu'à ce qu'une réponde. Pour éviter ce comportement, on peut limiter le nombre d'IP essayé avec l'option ConnectionAttempts :

host serveur-down
 serveur-down has address 10.0.0.1
 serveur-down has address 10.0.1.1
 
# limiter les essais à une seule IP
ssh -o ConnectionAttempts=1 serveur-down

Connexion SSH via webproxy

Pour se connecter en SSH à travers un proxy web, disons “proxy.corp” port “80” pour l'exemple, il faut utiliser l'option ProxyCommand : ssh -o “ProxyCommand=nc -X connect -x proxy.corp:80 %h %p” ssh-user@ssh-server. Pour ne pas se fatiguer à le préciser à chaque fois, on peut l'ajouter à son ssh config :

~/.ssh/config
Host ssh-server
   ProxyCommand /bin/nc -X connect -x proxy.corp:80 %h %p

Ainsi on se connectera simplement avec : ssh ssh-user@ssh-server

Depuis Windows il est plus facile d'utiliser le petit Putty, en renseignant le menu Connection/Proxy (remplir le Proxy hostname et Port), il fera le taf tout seul.

Certaines versions de netcat (nc) ne possèdent pas l'option -X et provoquent l'erreur : /bin/nc: invalid option -- 'X' C'est le cas sous CentOS/Rocky Linux par exemple. On peut le contourner avec d'autres options :

ProxyCommand nc --proxy-type http --proxy proxy.corp:80 %h %p

Connexion SSH par rebond

Pour se connecter à un serveur SSH cible par rebond, via un autre serveur SSH “bastion” ou proxy, de cette façon :

client ---> serveur_bastion ---> serveur_cible

Il suffit de saisir l'option -J :

ssh -J bastion cible

Sur de plus ancienne version de SSH on doit remplacer le -J par :

ssh -o ProxyCommand="ssh -W %h:%p bastion" cible

Et sur les plus anciennes versions de SSH on peut utiliser le trick (-tt force l'allocation d'un terminal) :

ssh -tt bastion "ssh -tt cible"

Pour automatiser cela il faut éditer, sur le poste client, le fichier de config perso (~/.ssh/config) :

~/.ssh/config
Host cible
   Hostname cible.domain.com
# nouvelle méthode
   ProxyJump bastion
# ou:   ProxyCommand ssh bastion -W %h:%p
   User login_sur_bastion
   #alternative : ProxyCommand ssh bastion nc %h 22
   # on peut préciser le certificat à utiliser pour éviter le double prompt
   #IdentityFile ~/.ssh/id_rsa.pub    # préciser la clé à utiliser, si pas celle par défaut
   ForwardAgent yes                   # utiliser les credentials locaux sur les systèmes distants

Pour éviter de saisir plusieurs fois son mot de passe, penser à copier sa clé dans les authorized_keys du serveur bastion avec la commande :

# si pas encore fait, générer une paire de clé sur le poste client
client $ ssh-keygen
[blabla OK OK]
# copier la clé sur le bastion
client $ ssh-copy-id user@bastion

On peut enchainer plusieurs serveurs en enfilade pour se connecter sur le serveur cible :

~/.ssh/config
Host cible
# on sépare les serveurs intermédiaires par une virgule
   ProxyJump bastion,bastion2
#
# ou avec l'option -W :
   ProxyCommand ssh bastion2 -W %h:%p
Host bastion2
   ProxyCommand ssh bastion -W %h:%p

Connexion SSH par rebonds via webproxy

On mixe les astuces : on veut se connecter à CIBLE via un premier webproxy, puis un bastion SSH :

CLIENT ----- WEBPROXY(SOCKS 5) ----- BASTION ----- CIBLE
# on défini le mode de connexino à BASTION (via WEBPROXY sur le port 3128)
Host BASTION
        Hostname BASTION.FQDN
        ProxyCommand /bin/nc -X connect -x WEBPROXY:3128 %h %p
# on défini le mode de connexion à CIBLE (via BASTION en passant la commande ProxyCommand)
Host CIBLE
        Hostname CIBLE.FQDN
        ProxyCommand ssh BASTION -W %h:%p
        ProxyJump BASTION

Depuis Windows, je n'ai pas trouvé de solution avec Putty qui ne gère pas ProxyJump. Il faut passer par le client OpenSSH intégré depuis Windows 10, ou via WSL (idem pour avoir le client OpenSSH), et utiliser la conf sus-citée.

Unable to negotiate...

Certains clients récents ne sont plus compatibles avec les paramètres négociés avec les serveurs trop vieux (ou inversement…). En effet les anciennes versions sont vulnérables à différentes failles de sécurité. C'est donc une bonne chose de désactiver par défaut la possibilité d'établir une connexion SSH si elle n'est pas sûre.

Cependant avec certains vieux équipements, c'est soit vieux SSH soit telnet. Dans mon cas :

ssh admin@upgrayedd
Unable to negotiate with 10.0.2.240 port 22: no matching key exchange method found. Their offer: diffie-hellman-group1-sha1

Il faut donc forcer le client SSH a accepter ces protocoles:

ssh -o KexAlgorithms=+diffie-hellman-group1-sha1 upgrayedd

Ou, plus pérenne, dans le fichier de préférences du client SSH :

~/.ssh/config
Host upgrayedd
  KexAlgorithms +diffie-hellman-group1-sha1

Dans mon cas j'avais également ce paramètre qui bloquait :

ssh admin@upgrayedd
Unable to negotiate with 10.0.2.240 port 22: no matching host key type found. Their offer: ssh-dss
~/.ssh/config
Host upgrayedd
  KexAlgorithms +diffie-hellman-group1-sha1
  HostKeyAlgorithms +ssh-dss

Il existe une page qui décrit les méthodes pour contourner les problèmes de compatibilité SSH : SSH legacy options

src: https://unix.stackexchange.com/questions/340844/how-to-enable-diffie-hellman-group1-sha1-key-exchange-on-debian-8-0/340853

key_verify failed

Les vieilles croûtes - les vieilles machines - qui utilisent des vieilles implémentations de SSH peuvent bloquer votre client SSH :

ssh_rsa_verify: RSA modulus too small: 512 < minimum 768 bits
key_verify failed for server_host_key

Pour bypasser ce prérequis de sécurité (ce n'est pas conseillé mais on n'a pas toujours le choix), il faut préciser l'option -1 au client SSH pour qu'il accepte de se connecter :

ssh -1 vieille-croute

Connexion en arrière-plan

Dans certains cas il peut être utile de lancer la connexion SSH en background, ce qui permet au terminal de rendre la main tout en conservant la connexion active. Cela se fait avec l'option -f :

ssh -f host xterm

Pour faire une redirection de port, il faut ajouter -N pour préciser que l'on n'exécute aucune commande distante :

# sans -N
ssh -f -L 5901:127.0.0.1:5901 <host>
 Cannot fork into background without a command to execute.
 
ssh -f -N -L 5901:127.0.0.1:5901 <server>

Et si l'on veut fermer la connexion après utilisation ? On ne peut pas, fallait réfléchir avant.

Bon, en fait, il suffit de killer le process SSH qui écoute sur le port redirigé localement, sur le client :

kill -9 $(ss -lnpt | awk ' $4 ~ /:5901$/ {sub(/.*pid=/,"",$6); sub(/,.*$/,"",$6); print $6}')''

Mais openssh permet de faire les choses proprement, de (au moins) 2 manières :

  1. ne pas utiliser -N, et lancer la commande sleep 60. Cela a pour effet de maintenir le tunnel ouvert 60 secondes, et si aucune connexion ne l'utilise au bout de cette durée, de fermer le tunnel. En revanche, si une appli utilise le tunnel (par exemple un vncviewer127.0.0.1:5901:1), alors le client SSH attend la fermeture de cette dernière (= la libération du tunnel) puis ferme le tunnel.
  2. utiliser une connexion SSH en mode “master”, qui permet d'utiliser un socket (fichier) de contrôle pour lui envoyer une commande de fermeture de connexion (exit) :
ssh -f -N -M -S <path-to-socket> -L 5901:127.0.0.1:5901 <server>
# (utilisation de la connexion...) puis fermeture :
ssh -S <path-to-socket> -O exit <server>

source: How to kill SSH session that was started with the -f option (run in background) ? sur StackExchange

Connexion forcée par mot de passe

Pour forcer l'authentification par mot de passe (afin d'éviter un “failed login” avec une mauvaise clé publique par exemple), lancer le client SSH avec l'option PreferredAuthentications=password, afin de privilégier l'authentification par mot de passe (par défaut l'ordre de préférence est “gssapi-with-mic, hostbased, publickey, keyboard-interactive, password”) ; il faut vérifier que cette option ne soit pas désactivée sur le serveur.

On peut l'agrémenter de PubkeyAuthentication=no afin de désactiver l'auth par clé publique (idem pour les autres modes d'authentification).

ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no <SERVER>

Ces options peuvent se positionner dans le fichier de conf : ~/.ssh/config pour ne pas avoir à les saisir à chaque fois.

Comment transmettre un quote en SSH

C'est toujours une galère en informatique pour utiliser les caractères interprétés, que ça soit les parenthèses ( ), les guillemets ou les apostrophes '.

Pour transmettre une apostrophe (ou simple quote en anglais) dans une commande SSH, on ne peut pas juste l'échapper (la préfixer par un \) :

ssh serveur ls /tmp/fic\'.test
 
bash: -c: ligne 1: fin de fichier (EOF) prématurée lors de la recherche du « ' » correspondant

Il faut utiliser :

  • soit un triple backslash (on “double échappe” le quote) : \'\\\'
  • un heredoc, plus lisible (surtout quand il y a beaucoup de caractères spéciaux) :
ssh serveur <<END
ls /tmp/fic\'.test
END
 
/tmp/fic'.test

Notification sur Signal d'un login SSH

Pour recevoir une notification lorsqu'un utilisateur se log en SSH sur un serveur, voici un article qui décrit la mise en place de :

  • une ligne de configuration dans pam.d pour catcher l'événement login
  • un script générant le message de notification et l'appel REST vers…
  • un conteneur docker : bbernhard/signal-cli-rest-api servant de passerelle vers Signal via une API REST

Ce dernier nécessite l’appairage avec un compte Signal existant.

NB : j'ai rencontré des erreurs avec la version signal-cli-rest-api:latest actuelle (17/09/2024) de l'image docker, aussi sur recommandation de l'auteur bbernhard j'ai utilisé la version 0.167-dev, qui génère une erreur mais envoie quand même le message ! En personnalisant également le réseau du conteneur, ça donne ce compose :

docker-compose.yml
version: "3"
services:
  signal-cli-rest-api:
#    image: bbernhard/signal-cli-rest-api:latest
    image: bbernhard/signal-cli-rest-api:0.167-dev
    container_name: signal-cli-rest-api
    networks:
      - br-sig
    environment:
      - MODE=native #supported modes: json-rpc, native, normal (by speed order)
    ports:
      - "8081:8080" #map docker port 8081 to host port 8080.
    volumes:
      - "../../data/signal-cli-rest-api:/home/.local/share/signal-cli"

networks:
  br-sig:
    external: true

Ce script basique :

/root/login.sh
#!/bin/sh
# envoyer une notif signal lors d'un login
NUMBER="+336xxxxxxxx"
URL=http://localhost:8081
MESSAGE="New connexion by ${PAM_USER} on $(hostname -s)\nDate: $(date +"%d/%m/%Y %H:%M:%S"), Ip: ${PAM_RHOST}"
 
if [ "$PAM_TYPE" != "close_session" ]; then
        curl -X POST -H "Content-Type: application/json" "${URL}/v2/send" \
                -d "{\"message\": \"${MESSAGE}\", \"number\": \"${NUMBER}\", \"recipients\": [ \"${NUMBER}\" ]}"&
fi

Et ce “hook” (ajouter le ligne à la fin du fichier /etc/pam.d/sshd) :

/etc/pam.d/sshd
session optional pam_exec.so seteuid /root/login.sh

Liens

informatique/logiciels/ssh.txt · Last modified: 2024/11/05 09:11 by pteu