SSH : autoriser les connexions root en toute sécurité (si !)

[size=150]Principes de base de sécurisation SSH[/size]

Ceci n’est pas un tuto pour apprendre à sécuriser son serveur SSH, il y en a suffisamment sur Internet. Mais une rapide piqûre de rappel ne fait jamais de mal, et ça aide à comprendre la raison de ce tuto.
Comme tout le monde sait (ou devrait savoir) les premières choses à faire pour bien sécuriser un serveur SSH sont :
[ul][li] désactiver le login root[/li]
[li] changer de port[/li]
[li] n’autoriser que la deuxième version du protocole[/li]
[li] désactiver l’authentification par mot de passe au profit de l’authentification par clé publique (de préférence de grande taille la clé, 4096 bits est un strict minimum, 8192 bits est bien, 16384 bits pour les paranoïaques comme moi)[/li]
[li] restreindre qui peut se connecter[/li][/ul]

Pour se connecter en root on doit donc passer par un des utilisateurs autorisés à se connecter, puis su / taper le mot de passe. C’est sécurisé, c’est bien.

[size=150]Oui mais ![/size]

Il est tout de même parfois utile de pouvoir se connecter en root, par exemple si on veut faire un montage SSHFS pour pouvoir accéder un peu plus facilement à de nombreux fichiers système (genre pendant la phase de configuration d’un serveur).
Problème : si on autorise root à se connecter directement, c’est un bout de sécurité qui s’en va (oui, même si une clé publique 16384 bits est le seul moyen d’y accéder, ça fait toujours un mot de passe en moins en travers du chemin d’un attaquant). On est foutus ? Non…

[size=150]Automatiser la gestion d’un deuxième serveur SSH, restreint à votre IP[/size]

Le principe c’est de lancer (à la demande) un deuxième serveur SSH sur un autre port, avec une autre configuration qui autorise les connexions root, et de paramétrer iptables pour ne laisser passer que les connexions provenant de votre propre IP. Le tout de manière simple et adaptée aux IPs dynamiques (en IP fixe c’est facile, y’a pas besoin de s’emmerder comme ça).
[ul][li] connexion classique sécurisée (utilisateur => su)[/li]
[li] ssh-unrestricted start qui va détecter automatiquement votre IP actuelle[/li]
[li] on peut maintenant se connecter directement en root sur un port différent[/li]
[li] ssh-unrestricted stop quand c’est fini[/li][/ul]

[size=125]1) Dupliquer et adapter votre fichier de configuration[/size]

# cp /etc/ssh/sshd_config /etc/ssh/sshd_config-unrestricted

[ul][li] modifier /etc/ssh/sshd_config-unrestricted de telle sorte que root puisse se connecter*. Les options importantes à prendre en compte sont Port 1234 ; PermitRootLogin yes ; et éventuellement inclure root dans AllowUsers si vous utilisez cette option.[/li]
[li] IMPORTANT : changer le port d’écoute (dans ce tuto on utilisera le port 1234, le serveur SSH actuel écoutant sur le port 1222)[/li]
[li] IMPORTANT : changer le le fichier de PID, sinon il va y avoir confusion avec le serveur d’origine (lors d’un service ssh restart par exemple). Directive PidFile.[/li][/ul]

b Note :[/b] la technique que je propose ici n’est pas limitée à autoriser les connexions root. Vu qu’il s’agit de lancer un deuxième serveur SSH avec une configuration différente (qu’on suppose moins sécurisée, d’où la restriction par IP) vous pouvez très bien modifier le nouveau fichier de configuration d’une autre manière.

[size=125]2) Adapter votre firewall[/size]

Typiquement, pour autoriser les connexions SSH votre firewall doit déjà contenir une règle ressemblant à ça (1222 étant le port du serveur SSH actuel) :

-A INPUT -p tcp --dport 1222 -j ACCEPT

Immédiatement à la suite, rajoutez les deux règles suivantes (pensez à changer le port) :

-N SSH_UNRESTRICTED -A INPUT -p tcp --dport 1234 -j SSH_UNRESTRICTED

[size=125]3) Installer le script[/size]

Copier/coller le code suivant dans un nouveau fichier /usr/local/sbin/ssh-unrestricted :

[code]#!/bin/sh
set -e

COLOR_ERROR="\033[01;31m"
COLOR_SAFE="\033[01;32m"
COLOR_WARN="\033[01;33m"
COLOR_NONE="\033[00m"

SSH_PID="$(ps x -U root -o pid,args | grep -E ’ /usr/sbin/sshd -f /etc/ssh/sshd_config-unrestricted$’ | sed ‘s@^ *([0-9]+) /usr/sbin/sshd -f /etc/ssh/sshd_config-unrestricted$@\1@g’)"

case “$1” in
start)
SSH_IP="$(echo -n “~${SSH_CONNECTION}~” | sed ‘s@^~([0-9.]+) .* [0-9]+~$@\1@g;s@^~.*~$@~@g;s@^$@~@g’)"
if [ “$SSH_IP” = “~” ]; then
echo “${COLOR_ERROR}Impossible de déterminer votre adresse IP (êtes-vous déjà connecté via SSH ?). Arrêt.${COLOR_NONE}”
exit 1
fi
if [ “$SSH_PID” = “” ]; then
/usr/sbin/sshd -f /etc/ssh/sshd_config-unrestricted
iptables -A SSH_UNRESTRICTED -s “$SSH_IP” -j ACCEPT
echo “${COLOR_WARN}Le serveur SSH secondaire est maintenant démarré (accès uniquement à partir de ${SSH_IP}).${COLOR_NONE}”
else
echo “${COLOR_WARN}Le serveur SSH secondaire était déjà démarré.${COLOR_NONE}”
fi
;;
stop)
if [ “$SSH_PID” != “” ]; then
kill “$SSH_PID”
echo “${COLOR_SAFE}Le serveur SSH secondaire est maintenant arrêté.${COLOR_NONE}”
else
echo “${COLOR_SAFE}Le serveur SSH secondaire était déjà arrêté.${COLOR_NONE}”
fi
iptables -F SSH_UNRESTRICTED
;;
restart)
SCRIPT_NAME="$(readlink -f “$0”)"
“$SCRIPT_NAME” stop
“$SCRIPT_NAME” start
;;
*)
if [ “$SSH_PID” != “” ]; then
echo “${COLOR_WARN}Le serveur SSH secondaire est actuellement démarré.${COLOR_NONE}”
else
echo “${COLOR_SAFE}Le serveur SSH secondaire est actuellement arrêté.${COLOR_NONE}”
fi
echo “Adresses IP autorisées :”
ADDRESSES="$(iptables -S SSH_UNRESTRICTED | grep -vxE ‘^-N SSH_UNRESTRICTED$’ | sed ‘s@^-A SSH_UNRESTRICTED -s ([^ /]+)/32 -j ACCEPT *$@ \1@g’)"
if [ “$ADDRESSES” = “” ]; then
echo " (aucune)"
else
echo “$ADDRESSES”
fi
;;
esac[/code]
Lui donner les bons droits :

[code]# chown root:root /usr/local/sbin/ssh-unrestricted

chmod a-rwx,u+rx /usr/local/sbin/ssh-unrestricted[/code]

[size=125]4) Se connecter directement en root sans risque supplémentaire de sécurité[/size] :icon-ugeek:

Démarrer le nouveau serveur : (uniquement à partir d’une connexion SSH existante, ça ne marchera pas en terminal/tty local)

[code]$ ssh -p 1222 utilisateur@serveur
(authentification)
$ su
Mot de passe :

ssh-unrestricted start

Le serveur SSH secondaire est maintenant démarré (accès uniquement à partir de 1.2.3.4).[/code]
Vérifier l’état :

# ssh-unrestricted Le serveur SSH secondaire est actuellement démarré. Adresses IP autorisées : 1.2.3.4
Arrêter le nouveau serveur : (à partir de n’importe où même un terminal/tty local)

# ssh-unrestricted stop

Enjoy. :006

TODO : pouvoir ajouter plusieurs IP différentes dans le firewall. J’ai la flemme, si quelqu’un se sent de modifier le script il est le bienvenu et je le mettrai à jour (c’est pour ça que j’ai utilisé une chaîne iptables au départ, mais je suis jamais allé aussi loin).

Un petit démon à rajouter qui se configure très simplement et rajoute un peu de complexité à qui veux tenter de percer le coffre fort :033

Le port knocking :

paquet à installer : knockd

pour la configuration c’est ultra légère à vous de détailler la combinaison de port à appeler pour débloquer le port final de connexion.

[options]
        logfile = /var/log/knockd.log

[openHTTP]
        sequence    = [color=#4000FF]7000,8000,9000[/color]
        seq_timeout = 5
        command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport [color=#00BF00]22[/color] -j ACCEPT
        tcpflags    = syn

[closeHTTP]
        sequence    = [color=#4000FF]9000,8000,7000[/color]
        seq_timeout = 5
        command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport [color=#00BF00]22[/color] -j ACCEPT
        tcpflags    = syn

La combinaison de ports à paramétrer selon votre bon vouloir pour la connexion/déconnexion est en bleu, quant au port finale à atteindre est en vert.
Vous pouvez aussi personnaliser l’adresse IP de contact, etc …

Reste à mettre ça en place en supplément avec vos méthode habituel de connexion, dans l’exemple définit au dessus ( qui j’ai d’ailleurs pris en note :083 ).

@ syam c’est car tu parle de paranoïa que je me permets d’adjoindre ceci, si il le faut un modo peu me le spécifié de déplacer ce petit truc ou le déplacer, je ne dirai rien :whistle: .

J’aurais bien vu le port knoking pour démarrer le second serveur ssh.

Carrément j’ai pas encore mis en place la solution de syam pour tester le bouzin mais l’idée est là, c’est pour ça que je poste simplement le trucs de façon brut :whistle:

Au passage, je n’ai pas essayé mais d’après ce lien noplay.net/Utilisation-des-clefs-SSH.html
Tu peut sur une même instance OpenSSH avoir un serveur configuré comme tu le veux et une connexion limité à une IP pour root.
Il devrait être facile à partir du port knocking, de modifier ce fichier pour autorisé les connexions uniquement à partir de l’IP qui viens de lancer la bonne séquence.

Effectivement ça peut se faire.
Perso j’aime pas trop le principe, je préfère la double vérification préalable (authentification SSH + su) mais bon c’est à chacun de voir. :slightly_smiling:
En fait de mon point de vue le port knocking c’est juste une petite protection supplémentaire pour masquer un service qui doit tout le temps rester allumé. Mais si le service est mal sécurisé (accès root) en l’absence de port knocking alors je trouve ça plus dangereux qu’autre chose, il devrait pouvoir tourner sans. Oui je sais je suis parano. C’est pas nouveau. :mrgreen:

[quote=“MisterFreez”]Au passage, je n’ai pas essayé mais d’après ce lien noplay.net/Utilisation-des-clefs-SSH.html
Tu peut sur une même instance OpenSSH avoir un serveur configuré comme tu le veux et une connexion limité à une IP pour root.[/quote]
Pas mal ça, c’est vrai que je pense jamais aux options de clés.

Tu fais chi… Misterfreez :005 encore un lien de plus dans mon marque ta page à trier :033 ( continue comme ça j’adore ça en fait :wink: ).

Voila en tout et pour tout ce qu’il y a de neuf dans ce lien :

[quote]Vous pouvez mettre des options [1] devant chaque clef [2] se trouvant dans authorized_keys2.

Il existe surtout deux options très utilisée :

  • from : permet de limiter l’accès en fonction de l’IP (ou du nom de domaine)
  • command : permet de restreindre l’utilisateur a certaine commande

Par exemple :

from="192.168.0.*,!192.168.0.1",command="cvs server" <la clef>

[/quote]

Effectivement ça peut se faire.
Perso j’aime pas trop le principe, je préfère la double vérification préalable (authentification SSH + su) mais bon c’est à chacun de voir. :slightly_smiling:
En fait de mon point de vue le port knocking c’est juste une petite protection supplémentaire pour masquer un service qui doit tout le temps rester allumé. Mais si le service est mal sécurisé (accès root) en l’absence de port knocking alors je trouve ça plus dangereux qu’autre chose, il devrait pouvoir tourner sans. Oui je sais je suis parano. C’est pas nouveau. :mrgreen: [/quote]
Je ne comprends pas très bien. Le port knocking c’est ajouter un mot de passe à (16 000*2)^3 d’entropie si tu veux 3 ports (16 000 ports, en udp ou en tcp). Tu crains une faille dans port knocking ? Une attaque du type icmp de la mort ?

Au passage tu as des chiffres sur la factorisation de clef 1 024 ou 2 048 pour pouvoir dire que 4 096 bits est « un strict minimum » ?
J’ai vu que la décomposition a était faite en 2010 mais rien sur le temps que ça a pris.

Le réseau ça se sniffe, et le port knocking transite obligatoirement en clair. C’est suffisant pour ne pas considérer ça comme fiable (ne me dis pas “qui irait sniffer ton serveur”, dans ce cas autant abandonner SSH et revenir au bon vieux telnet). :mrgreen:

[quote=“MisterFreez”]Au passage tu as des chiffres sur la factorisation de clef 1 024 ou 2 048 pour pouvoir dire que 4 096 bits est « un strict minimum » ?
J’ai vu que la décomposition a était faite en 2010 mais rien sur le temps que ça a pris.[/quote]
Les clés 1024 bits ne sont plus considérées comme sûres (cf. certificats SSL qui sont tous passés à 2048). Et comme on ne peut pas dire que les CA soient très à cheval sur la sécurité, 2048 est bien trop proche des 1024 pour rester sécurisant. Je me base simplement sur les pratiques d’une industrie qui a suffisamment prouvé son “savoir faire” (hahaha).
CQFD. :stuck_out_tongue:

Le réseau ça se sniffe, et le port knocking transite obligatoirement en clair. C’est suffisant pour ne pas considérer ça comme fiable (ne me dis pas “qui irait sniffer ton serveur”, dans ce cas autant abandonner SSH et revenir au bon vieux telnet). :mrgreen:[/quote]

J’ai simplement proposé de rajouter un “port knocking” pour éviter les scannent de ports sur le ssh trop en évidence et de te faire inonder par la suite de tentative foireuse, le principe des clés reste de toute façon la seule manière de procéder de façon sécuritaire.

Vois le “port knocking” comme simplement une manière simple de dissimuler ton vrai port “ssh” plus longtemps, les combinaison pouvant être revue régulièrement et avec une combinaison de 7 à 11 ports même si le gars te sniffe ça laisse du temps avant qu’il ne te casse les bonbons.

[quote=“syam”][quote=“MisterFreez”]Au passage tu as des chiffres sur la factorisation de clef 1 024 ou 2 048 pour pouvoir dire que 4 096 bits est « un strict minimum » ?
J’ai vu que la décomposition a était faite en 2010 mais rien sur le temps que ça a pris.[/quote]
Les clés 1024 bits ne sont plus considérées comme sûres (cf. certificats SSL qui sont tous passés à 2048). Et comme on ne peut pas dire que les CA soient très à cheval sur la sécurité, 2048 est bien trop proche des 1024 pour rester sécurisant. Je me base simplement sur les pratiques d’une industrie qui a suffisamment prouvé son “savoir faire” (hahaha).
CQFD. :stuck_out_tongue:[/quote]

Personnellement mes clés sensibles sont en 4096, les moins sensibles en 2048, et juste une qui est particulièrement sensible qui elle est en 8192 ( ça reste surtout psychologique d’après moi de dépasser les 4096 :033 ).

[quote=“Clochette”]J’ai simplement proposé de rajouter un “port knocking” pour éviter les scannent de ports sur le ssh trop en évidence et de te faire inonder par la suite de tentative foireuse, le principe des clés reste de toute façon la seule manière de procéder de façon sécuritaire.

Vois le “port knocking” comme simplement une manière simple de dissimuler ton vrai port “ssh” plus longtemps, les combinaison pouvant être revue régulièrement et avec une combinaison de 7 à 11 ports même si le gars te sniffe ça laisse du temps avant qu’il ne te casse les bonbons.[/quote]
C’est exactement comme ça que je vois le port knocking, t’inquiète. :wink:

(en me relisant je me rends compte que ma phrase est pas forcément super claire, mais ça veut bien dire ça : le port knocking en lui-même ne sécurise pas un service, c’est juste du bonus pour un service déjà sécurisé, ce sur quoi nous sommes d’accord tous les deux, et probablement aussi MisterFreez qui me contredit par habitude* :stuck_out_tongue:)

(*) mais c’est de bonne guerre, je lui fais toujours le coup aussi. :mrgreen:

[quote=“syam”]
(en me relisant je me rends compte que ma phrase est pas forcément super claire, mais ça veut bien dire ça : le port knocking en lui-même ne sécurise pas un service, c’est juste du bonus pour un service déjà sécurisé)[/quote]

J’adore être d’accord :033

Sur ce c’est l’heure “na zdrowie” :030

Pour info, j’ai rajouté une précision (PidFile dans le nouveau fichier de config).

changer le port, se connecter par clé ssh et ne permettre que la v2, ok c’est la base

du reste, plutôt que se casser la tête avec iptables, bien qu’il ajoute un filtre en cas de loupé, on peut aussi utiliser /etc/hosts.deny et /etc/hosts.allow
Ca a le même effet non ?
-> ip autorisée -> lancement connexion ssh par clé
-> ip non autorisée -> merci au revoir !

# /etc/hosts.allow
sshd: ip_1_autorisée
sshd: ip_2_autorisée
# par range ip
sshd: 192.168.0.0/255.255.255.0
# /etc/hosts.deny
sshd: ALL

[quote=“Mitsu”]du reste, plutôt que se casser la tête avec iptables, bien qu’il ajoute un filtre en cas de loupé, on peut aussi utiliser /etc/hosts.deny et /etc/hosts.allow
Ca a le même effet non ?[/quote]
Oui ça a le même effet au final, mais c’est pas non plus exactement pareil. Le “cassage de tête avec iptables” c’est surtout à cause des IP dynamiques, pour faire la même chose dans hosts.allow c’est pas moins compliqué mais c’est surtout moins robuste (manipulation de fichier texte ; sed -i pour changer l’IP, sérieusement ?), de plus tout le monde ne conserve pas les tcpwrappers… donc moins générique aussi.
En fait je pense que ce que tu dis rentrerait plus dans le cas que j’ai résumé ainsi : (en IP fixe c’est facile, y’a pas besoin de s’emmerder comme ça) :033

Mais tu fais bien de le mentionner, ça peut intéresser des gens aussi. C’est clairement pas un problème où il n’y a qu’UNE solution correcte. :slightly_smiling:

[size=80]Bon et après j’imagine que c’est une question de goûts et d’habitudes, mais iptables me paraît largement plus clair que les tcpwrappers… Chacun son truc. :wink:[/size]

[quote=“syam”]
Oui ça a le même effet au final, mais c’est pas non plus exactement pareil. Le “cassage de tête avec iptables” c’est surtout à cause des IP dynamiques, pour faire la même chose dans hosts.allow c’est pas moins compliqué mais c’est surtout moins robuste (manipulation de fichier texte ; sed -i pour changer l’IP, sérieusement ?), de plus tout le monde ne conserve pas les tcpwrappers… donc moins générique aussi.
En fait je pense que ce que tu dis rentrerait plus dans le cas que j’ai résumé ainsi : (en IP fixe c’est facile, y’a pas besoin de s’emmerder comme ça) :033

Mais tu fais bien de le mentionner, ça peut intéresser des gens aussi. C’est clairement pas un problème où il n’y a qu’UNE solution correcte. :slightly_smiling:

[size=80]Bon et après j’imagine que c’est une question de goûts et d’habitudes, mais iptables me paraît largement plus clair que les tcpwrappers… Chacun son truc. :wink:[/size][/quote]
oui effectivement vu comme ça… j’y avais pas pensé :slightly_smiling:
par contre là où ça peut ajouter un petit plus pour les ip dynamique, c’est que les FAI ont des range ip qui varient très peu.
tu peux donc indiquer le range ip de ton FAI dans le hosts.allow
ça limite déjà pas mal
après intervient iptables pour finioler
bien que si utilisation d’iptables, hosts.allow/hosts.deny deviennent un peu inutiles

quoi qu’il en soit je prend le script aussi oui car très intéressant :slightly_smiling:
thx