Utilisation De SSH

SSH est un outils qui permet d’accéder a un shell distant de façon sécurisé mais pas que.

Installation du serveur

apt install openssh-server

Les fichiers de configuration pour le mode client et serveur sont disponible dans /etc/ssh/.

La configuration par défaut du serveur fait que le service est en écoute sur le port 22.

Connexion

Selon le moyen d’accès à la machine distante.

ssh user@ip
ssh user@hostname
ssh user@ma.machine.distante

On peut également lancer des applications en mode graphique… si on dispose d’un mode graphique sur le poste client et sur le poste serveur.

L’interface du serveur sera visible sur le post client. Biensur toute les action réalisé sur l’interface, le seront sur le post serveur.

ssh -X user@hostname

C’est l’option -X qui permet cela.

Configuration client

Dans le répertoire ~/.ssh on peu creer un fichier de configuration du nom de config.

Ce fichier va surcharger la configuration par défaut du client présente dans /etc/ssh/ssh_config.

Définir une configuration pour un host

Dans le fichier ~/.ssh/config :

host serveur1
  hostname 192.168.20.2 # au choix: ip, fqdn,
  user mon_user
  port 22
  compression yes
  IdentityFile ~/.ssh/id_ed25519

Maintenir une connexion vers un host pour accélérer les connexions suivante

Dans le fichier ~/.ssh/config on va ajouter les lignes suivantes :

host *
# Gestion automatique des sessions
  ControlMaster auto
# stockage des sessions : Le répertoire qui stockera le 'bus' de données
  ControlPath ~/.ssh/mux/%r@%h:%p
# Persitance de session 10 minutes
  ControlPersist 10m

En terme de sécurité, cette fonction peu être dangereuse. En effet, il n’est plus necessaire d’entrer sa clef pour se connecter à un bus ouvert…

Utiliser un host comme proxy

On veut se connecter à une machine serveur 2.

  • serveur2 n’est pas accessible depuis internet.
  • La machine serveur1 est sur le même réseau et peut voir seveur2.
  • On va donc utiliser serveur1 pour accéder à serveur2.

La configuration est la suivante :

host serveur2
  hostname 192.168.20.6 # au choix: ip, fqdn,
  user mon_user
  port 22
  compression yes
  IdentityFile ~/.ssh/id_ed25519
  ProxyJump serveur1 # avec cette commande, on précise la machine via laquel on se connecte.

Execution distante

Execution d’un script local sur une machine distante

Le script est disponible sur la machine local dans le ~/script.sh.

ssh login@machine2 bash < ~/script.sh

Execution d’un script distant sur une machine distante

Le script est disponible sur la machine distance dans le ~/script.sh.

ssh login@machine2 ~/script.sh

Tunnel ssh

Tunnel Local

Nous souhaitons accéder au port d’une cible mais nous n’avons pas un accès direct à son réseau.

En revanche, nous avons accès à une machine qui a accès au deux réseau : le pont.

Nous allons demander au pont de devenir un proxy pour l’accès au port spécifique de la cible.

La commande suivante, est à réaliser sur la machine local.

ssh -NL <port local>:<machine cible>:<port machine cible> user@pont

Le port de la machine local sera directement relié au port de la cible via la connexion ssh au pont.

Donc si nous avons en cible un serveur web (port 80, ip du point de vue du pont 192.168.0.12), un pont accessible via ssh (ça configuration est dispo dans un fichier ~/.ssh/config) et nous choisissons le port local 8080, nous pouvons réaliser un tunnel qui liera le port local 8080 au port de la cible 80 avec la commande suivante :

ssh -NL 8080:192.168.0.12:80 user@pont

Ensuite avec un navigateur, on réalise une connexion sur http://localhost:8080 et nous aurons accès au serveur cible.

Tunnel Distant

La machine à laquelle on veut accéder est placé derrière une box qui fait du NAT. Cette machine sera le serveur. Nous n’avons pas accès à l’interface de la box. Ce qui fait que l’on ne peut pas faire de redirection de port.

Nous avons besoin d’une machine qui sera à la fois accessible depuis le serveur et le client. Cette machine sera le pont.

Nous allons faire un tunnel ssh entre le serveur et le pont. Le tunnel est initié sur le serveur avec la commande :

ssh -NR <port pont>:<ip serveur : localhost>:<port serveur> user@pont

par exemple

ssh -NR 8022:localhost:22 user@pont

Donc, ici, nous avons :

  • -N, pour une session non interactive
  • -R, pour faire un tunnel qui déporte un port local sur une machine distante.

Cette commande va ouvrir un port en écoute sur le pont et redirigé dans un tunnel ssh vers le port du serveur.

Le port ainsi ouvert n’est disponible que sur l’interface 127.0.0.1 donc uniquement en local sur le pont. Donc il faut se connecter via ssh au pont pour accéder au port.

Cette particularité est du a une option du serveur ssh du pont.

L’option GatewayPorts est à no par défaut.

Si on souhaite que le pont devienne un veritable proxy, il faut passer l’option à yes et le port sera attaché à l’interface 0.0.0.0. Ainsi, le port sera exposé à l’exterieur de la machine et accessible sans avoir besoin de posséder un accès au pont.

Contournement

NAT

On crée un tunnel ssh distant depuis la machine serveur avec la commande :

ssh -NR <port pont>:<ip serveur : localhost>:<port serveur> user@pont

Comme dans l’exemple donnée dans la partie tunnel ssh distant.

Cette commande positionné sur la machine pont un port qui permettra de remonter a travers le NAT jusqu’a la machine serveur.

On peut utiliser autosshpour que la connexion soit maintenu et reconstruite.

Parefeu

On a une connexion “bridé” par un proxy http, on peu placer sshd sur le port 80/443 du serveur afin que le flux ne soit pas filtré. Lors de la connexion, on précise que l’on passe par un proxy http.

Si on héberge un serveur web, sslh permet de démultiplexer les flux reçus et de l’orienter sur le bon service/port.

Nous avons le schèma suivant:

+------+
|Client|
+---+--+
    |
    |
    v
 +--+--+
 |Proxy|
 |web  |                                       +---------+          +-----------+
 +--+--+                             +-------->+Port 2443+--------->+Serveur web|
    |                                |         +---------+          +-----------+
    v                                |
+---+----+         +--------+     +--+-+
|Internet+-------->+port 443+---->+SSLH|
+--------+         |HTTPS   |     +--+-+
                   +--------+        |
                                     |         +-------+             +----+
                                     +-------->+Port 22+------------>+SSHD|
                                               +-------+             +----+

Il faut pensé à préciser dans la configuration du client les paremetre du proxy.

Sécurisation

Ressource

Connexion par clef

On génère une clef avec la commande suivante :

ssh-keygen

Ce qui va généré par défaut un couple de clefs : id_dsa la clef privé et id_dsa.pub la clef publique.

La commande suivante, sert à l’export la clef publique sur une machine distance afin de réaliser à l’avenir une connexion par la clef et plus par mot de passe.

ssh-copy-id user@host

On vous demandera alors le mot de passe lié au login et la clef publique sera copié.

La clef publique est inséré dans le fichier ~/.ssh/authorized_keys à la suite de celle déjà présente.

Point important :

  • Il ne faut jamais partager sa clef privé avec qui que ce soit. La personne qui aurait votre clef, si elle n’est pas protegé par un mot de passe, pourrait usurper vos accès sur les machines où la clef publique est déployé.
  • Si possible on protège sa clef privé avec un mot de passe (ssh-agent est un démon qui gère les mots de passe de clef de façon à ne pas les taper 50 fois par session)

Changer le port d’écoute par défaut

ça ne change rien, si l’attaquant prend sont temps pour ses tests, il saura déterminer a quoi sert un port ouvert mais ça aura le mérite de limiter les attaques configuré sur port par défaut. Le port 22 étant très solicité sur le net…

dans le fichier /etc/ssh/sshd_config, on trouve la ligne #Port 22 qu’il faut décommenter et changer.

On redémarre ensuite le service avec la comande suivante :

systemctl restart sshd

Il faut savoir qu’en redémarrant le service, la connexion en cour ne sera pas interromppu.

Il ne faut pas la couper avant d’avoir tenter une connexion avec la nouvelle configuration… ce serait dommage de se retrouver à la porte de son serveur.

fail2ban

Fail2ban est un outil qui va scruter les logs d’un service afin de detecter les tentatives de connection infructueuse. Souvent elle sont le signe d’attaque par force brute (Brute force) ou l’attaquant tente de se connecter a un service et essayant soit toutes les permutations possible, soit une liste prédéfini de login et de mot de passe.

apt install fail2ban

Plus d’information sur le wiki ubuntu-fr.

sshguard

C’est une alternative a fail2ban que je ne connais pas encore mais qui a le merite d’être légère et avoir un bon retour de la communauté. Le projet est activement maintenu. Quoi qu’il en soit je n’ai aucun sousi avec fail2ban… Comme fail2ban l’outil est en mesure de protéger plusieurs protocol différent. il n’est pas limité à ssh.

Le fichier : authorized_key

La documentation sur ce fichier est disponible dans le man.

man authorized_keys

Le fichier est présent dans le répertoire $HOME/.ssh/.

Le fichier contient la liste des clefs public autorisé à se connecter au compte.

Une entrée prend une ligne et est de la forme :

OPTIONS ssh-ed25519 sziuqfhligubiusfgbqlirgqer3gb1q3e51bh3etbetb!qetbq# ma_clef@mon_pc

Le champ option n’est pas initialisé lorsque l’on déploie une clef vie l’outils de déploiement ssh-copy-id.

On va placer dans ce fichier certain paramètre limitant l’utilisation du compte. Ces paramètre sont séparé par des ,.

La liste des options est dans le man.

Exemple

On peu construire un shell capable de limiter à des actions précises.

Par exemple, un script qui limite l’accès à l’utilisation de scp :

#!/bin/bash

if [[ \"$SSH_ORIGINAL_COMMAND\" =~ ^scp.? ]]
then
    $SSH_ORIGINAL_COMMAND
    exit 0
else
    echo Access Denied
    exit 1
fi

Ce script doit être appelé lors de la connexion. C’est ce que l’instruction command= placé dans le champ ‘‘option’’ doit nous permetre.

Il n’y a pas de limitation concernant le langage, un script python peut aussi servir de validateur.

#!/usr/bin/env python3

from os import environ
import logging
from logging.handlers import TimedRotatingFileHandler
#from logging.handlers import RotatingFileHandler

log = logging.getLogger()
log.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s :: %(module)s :: %(levelname)s :: %(message)s')

file_handler = TimedRotatingFileHandler(environ['HOME']+'/.ssh/limitation.log',
                                         when='D',
                                         interval=1,
                                         backupCount=7)

#file_handler = RotatingFileHandler(environ['HOME']+'/.ssh/limitation.log', 'a', 1000000, 1)
file_handler.setFormatter(formatter)
log.addHandler(file_handler)

if 'SSH_ORIGINAL_COMMAND' in environ.keys():
    log.debug(environ["SSH_ORIGINAL_COMMAND"])
    import subprocess
    cmd = environ['SSH_ORIGINAL_COMMAND']
    cmds = cmd.split(" ")
    if 'scp' in cmd or 'tar' in cmd or 'mkdir' in cmd or 'rm' in cmd :
        if 'scp' in cmds[0]:
            log.debug("Commande de transfert identifié")
        if 'tar' in cmds[0]:
            log.debug("Commande d'archivage identifié")
        if 'mkdir' in cmds[0]:
            log.debug("Commande de création de répertoire identifié")
        if 'rm' in cmds[0]:
            log.debug("Commande de suppression identifié")
        subprocess.run(cmds)
        exit(0)
    else:
        log.error("La commande ne contient pas le bon mot clef.")
        exit(1)
else:
    log.error("L'env ne contient pas la variable 'SSH_ORIGINAL_COMMAND'.")
    exit(1)

Debug

Les log du serveur sshd sont disponible dans /var/log/auth.log on peut également voir des traces sur /var/log/syslog.

Coté client l’option -vvvvv passe les log au niveau debug ce qui donnera un déroulé des étapes de négociation d’une connexion ssh.

Droit sur les répertoires

ssh refuse de fonctionner si les droits sur le répertoire parent du répertoire .ssh donne la fonction o+w soit l’écriture au autres ;).

Donc le plus simple reste d’être le seul a avoir un accès en lecture/écriture sur ses dossiers perso.

nithir [drwx------]
└── .ssh [drwx------]

On peut executer dans l’ordre (source) :

chmod go-w ~/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/*
chmod 644 ~/.ssh/*.pub