Vous êtes ici : Accueil / Debian GNU/Linux / Système / Sécurité / Sécuriser l'accès SSH sur Debian

Sécuriser l'accès SSH sur Debian

Par Pierre-Yves Landuré Dernière modification 11/11/2017 10:44

L'accès Secure SHell (cad. SSH) est le principal outil d'administration à distance d'un serveur Unix. Par défaut, la sécurité de cette accès se limite au chiffrement des connexions et à la saisie d'identifiant et un mot de passe. Ce guide présente différentes méthodes durcissant la sécurité d'un serveur SSH.

Ce guide est testé sur:

  • Debian 6.0 Squeeze
  • Debian 7.0 Wheezy

Pré-requis

Assurez-vous que le serveur Secure SHell est installé:

command apt-get install openssh-server

Paramètres

Renseignez le nom d'un compte utilisateur standard à créer s'il n'existe pas déjà sur le serveur. Pour des raisons de simplicité, vous pouvez utiliser le nom d'utilisateur utilisé sur votre ordinateur personnel:

STD_USER="myuser"

Protection contre les attaques DDOS et brute-force

Fail2ban est un outil surveillant les échecs de connexion au serveur SSH, et bloquant pour un temps donné les adresses IP à l'origine de 5 échecs successifs. Ce comportement permet de bloquer la plupart des attaques de déni de service, et la récupération des mots de passes des utilisateurs par la force brute.

Installez l'outil:

command apt-get install fail2ban

Activez les règles de fail2ban pouvant s'appliquer à la connexion SSH:

if [ ! -e '/etc/fail2ban/jail.local' ]; then
command touch '/etc/fail2ban/jail.local'
fi
if [ -z "$(command grep "\[ssh-ddos\]" '/etc/fail2ban/jail.local')" ]; then
echo "[ssh-ddos]
enabled = true

[pam-generic]
enabled = true
" >> '/etc/fail2ban/jail.local'
fi

Rechargez la configuration de l'outil:

/etc/init.d/fail2ban restart

Désactiver l'accès direct au compte root

L'identifiant "root" est le premier ciblé par les attaques. Une bonne pratique est de désactiver l'identification au compte root par SSH. L'accès à ce compte reste disponible via les commandes "su" et "sudo".

Création d'un compte utilisateur non-privilégié

Avant de bloquer l'accès SSH du compte root, assurez-vous de disposer d'un compte utilisateur alternatif couplé à un mot de passe suffisament complexe. Si vous ne disposez pas d'un compte utilisateur normal, votre machine ne sera plus accessible par SSH.

Installez un outil de génération de mots de passe:

command apt-get install apg

Générez un mot de passe complexe:

command apg -q -m 12 -a  0 -n 1 -M NCLS

Créez un compte utilisateur sans privilèges:

command adduser "${STD_USER}"

Créez un dossier .ssh pour cet utilisateur:

command mkdir --parents "/home/${STD_USER}/.ssh"
command chown "${STD_USER}":"${STD_USER}" "/home/${STD_USER}/.ssh"

Désactivation de l'accès root

Configurez le serveur SSH de façon à ce qu'il n'accepte pas les connexions avec l'utilisateur root:

command sed -i -e 's/PermitRootLogin.*/PermitRootLogin no/' '/etc/ssh/sshd_config'
/etc/init.d/ssh reload

Filtrer les utilisateurs ayant un accès SSH

Afin de limiter le nombre de comptes accessibles directement via SSH, il est possible de filtrer les utilisateurs pouvant se connecter selon leur groupe d'appartenance.

Créez le groupe "ssh-users" contenant les utilisateurs pouvant se connecter en SSH:

if [ -z "$(command grep "^ssh-users" '/etc/group')" ]; then
  command addgroup --system "ssh-users"
fi

Configurez le serveur SSH pour refuser la connexion des utilisateurs n'appartenant pas à ce groupe:

command echo '
# Limit access to users of group ssh-users
AllowGroups ssh-users' >> /etc/ssh/sshd_config

Rechargez la configuration:

/etc/init.d/ssh reload

Ajoutez les utilisateurs autorisés a utiliser l'accès SSH au groupe "ssh-users":

command adduser "${STD_USER}" ssh-users

Mise en place d'une identification par clef publique

Sur le poste client

Créez le certificat unique (clefs privée et publique) identifiant votre utilisateur :

if [ ! -e "${HOME}/.ssh/id_rsa" ]; then
command ssh-keygen -t rsa -f "${HOME}/.ssh/id_rsa"
fi

Important: Sauvegardez et protégez précieusement les fichiers:

  • ${HOME}/.ssh/id_rsa
  • ${HOME}/.ssh/id_rsa.pub

Mettez en place la clef publique de votre utilisateur sur le serveur (remplacez la valeur en gras par le nom de domaine ou l'adresse IP du serveur):

command ssh-copy-id -i "${HOME}/.ssh/id_rsa.pub" user@www.ssh-server.com

Remarque: si ssh-copy-id n'est pas disponible sur votre système (Mac OS X), utilisez:

command cat "${HOME}/.ssh/id_rsa.pub" \
| command ssh user@www.ssh-server.com 'umask 077;
test -d ~/.ssh || mkdir ~/.ssh ;
cat >> ~/.ssh/authorized_keys \
&& (test -x /sbin/restorecon \
&& /sbin/restorecon ~/.ssh ~/.ssh/authorized_keys >/dev/null 2>&1 \
|| true)'

Sur le serveur

Autorisez l'identification par clef publique:

command sed -i -e 's/^[#\t ]*PubkeyAuthentication[\t ]*.*$/PubkeyAuthentication yes/' \
'/etc/ssh/sshd_config'

Rechargez la configuration:

/etc/init.d/ssh reload

Remarque: Il est possible de désactiver complètement l'identification par mot de passe, mais je ne le recommande pas, car il est très difficile de récupérer un accès au serveur si vous perdez votre clef privée.

Modifier le port d'écoute du serveur SSH

Par défaut, le serveur SSH écoute sur le port 22. Utiliser un autre port que celui par défaut limite de manière considérable le nombre d'attagues automatisées.

Sur le serveur

Renseignez le numéro de port personnalisé (valeur entre 2048 et 65536):

SSH_PORT="16022"

Modifiez la configuration du serveur SSH:

command sed -i -e "s/^[#\t ]*Port[\t ]*.*\$/Port ${SSH_PORT}/" \
'/etc/ssh/sshd_config'

Rechargez la configuration:

/etc/init.d/ssh reload

Mettez à jour la configuration de fail2ban:

echo "
# Custom SSH port
[ssh]
port = ${SSH_PORT}" >> '/etc/fail2ban/jail.local'

Redémarrez fail2ban:

/etc/init.d/fail2ban restart

Sur le poste client

Renseignez le nom d'hôte du serveur:

SSH_HOST="www.ssh-server.com"

Renseignez le numéro de port personnalisé (valeur entre 2048 et 65536) utilisé par le serveur SSH (cf. ci-avant):

SSH_PORT="16022"

Ajoutez une section dédiée au serveur cible dans le fichier de configuration du client SSH:

if [ ! -e "${HOME}/.ssh/config" ]; then
touch "${HOME}/.ssh/config"
fi
if [ -z "$(command grep "${SSH_HOST}" "${HOME}/.ssh/config")" ]; then
echo "Host ${SSH_HOST}" >> "${HOME}/.ssh/config"
fi

Spécifiez le port du serveur dans le fichier de configuration du client SSH:

command sed -i -e "/${SSH_HOST}/a\\
Port ${SSH_PORT}" "${HOME}/.ssh/config"

Mettre en place un Port Knocking

Le Port Knocking consiste à bloquer les connexions à un port (ici le port SSH) à moins qu'une séquence d'ouverture de connexion sur différents ports ne soit effectuée. Cette séquence correspond à "frapper à la porte" du serveur. C'est une méthode efficace pour masquer le port SSH d'un serveur aux visiteurs malveillants.

Sur le serveur

Détectez le numéro de port utilisé par le serveur SSH:

SSH_PORT=$(command grep '^Port' '/etc/ssh/sshd_config' \
| command sed -e 's/^Port[\t ]*//g') 

Renseignez la liste des ports entrainant l'ouverture du port SSH:

SSH_KNOCK="9345,2193,37303"

Si vous le souhaitez, vous pouvez obtenir une liste aléatoire:

SSH_KNOCK="$((((${RANDOM} + ${RANDOM}) % 63488) + 2048)),$((((${RANDOM} + ${RANDOM}) % 63488) + 2048)),$((((${RANDOM} + ${RANDOM}) % 63488) + 2048))" 
echo "SSH_KNOCK='${SSH_KNOCK}'"

Installez le démon knockd:

command apt-get install knockd

Insérez la règle opencloseSSH dans la configuration de knockd. Cette règle ouvre le port SSH pendant 10 secondes après un "knock".

command echo "
[opencloseSSH]
sequence      = ${SSH_KNOCK}
seq_timeout   = 5
tcpflags      = syn
start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport ${SSH_PORT} -j ACCEPT
cmd_timeout   = 10
stop_command  = /sbin/iptables -D INPUT -s %IP% -p tcp --dport ${SSH_PORT} -j ACCEPT
" >> '/etc/knockd.conf'

Supprimez les règles openSSH et closeSSH d'origine:

command sed -i \
    -e '/\[openSSH\]/,/^[\t ]*$/{d}' \
    -e '/\[closeSSH\]/,/^[\t ]*$/{d}' \
  '/etc/knockd.conf'

Activez le démon:

command sed -i \
-e 's/^START_KNOCKD=.*/START_KNOCKD=1/' \
'/etc/default/knockd'

Démarrez le démon:

/etc/init.d/knockd start

Mettez en place une règle iptables bloquant par défaut les connexions au SSH. Les règles knockd se chargent d'ouvrir l'accès sélectivement:

command echo "#"\!"/bin/bash
# Allow SSH access from domU
command iptables -C INPUT -p tcp -m state --state NEW --dport ${SSH_PORT} -j DROP > '/dev/null' \\
|| command iptables -A INPUT -p tcp -m state --state NEW --dport ${SSH_PORT} -j DROP" \
  > '/etc/network/if-up.d/iptables-ssh-reject'
command chmod +x '/etc/network/if-up.d/iptables-ssh-reject'

Chargez la règle:

/etc/network/if-up.d/iptables-ssh-reject

Important: Par sécurité, restez connecté à votre session SSH tant que vous ne vous êtes pas assuré de pouvoir ouvrir une nouvelle session depuis le poste client.

Sur le poste client

Renseignez le nom d'hôte du serveur:

SSH_HOST="www.ssh-server.com"

Renseignez la liste des ports entrainant l'ouverture du port SSH sur le serveur:

SSH_KNOCK="9345,2193,37303"

Installez le paquet knockd (contenant l'outil knock) et l'outil socket:

command apt-get install knockd socket

Ajoutez une section dédiée au serveur cible dans le fichier de configuration du client SSH:

if [ ! -e "${HOME}/.ssh/config" ]; then
touch "${HOME}/.ssh/config"
fi
if [ -z "$(command grep "${SSH_HOST}" "${HOME}/.ssh/config")" ]; then
echo "Host ${SSH_HOST}" >> "${HOME}/.ssh/config"
fi

Spécifiez l'option ProxyCommand à utiliser pour "toquer" aux portes du serveur SSH:

command sed -i -e "/${SSH_HOST}/a\\
TcpKeepAlive yes\\
ServerAliveInterval 150\\
ProxyCommand /bin/bash -c 'command knock %h $(echo ${SSH_KNOCK} | command tr ',' ' '); sleep 1; exec socket %h %p'" "${HOME}/.ssh/config"

Remarque: Pour les postes sous Microsoft Windows, il existe le client KnockKnock.

Références

Ces livres peuvent vous aider:

Remerciements