Sécuriser l'accès SSH sur Debian
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:
- SSH, The Secure Shell: The Definitive Guide (en anglais)
- Debian GNU/Linux - Sécurité du système, sécurité des données, pare-feu, chiffrement, authentification...
- Hardening Linux
- Linux Server Security
Remerciements
- Merci à Essembeh pour Utiliser de l'authentification forte pour son serveur SSH.
- Merci aux Astuces d'Absolacom pour Filtrer les connexions SSH.
- Merci aux auteurs de Port-Knocking : sécuriser l'accès à un port dans la documentation Ubuntu francophone.
- Merci à ID's blog pour Knock Knock.