Comment utiliser Port Knocking sur Linux (et pourquoi vous ne devriez pas)



Le *port knocking*, ou frappe de port, est une méthode permettant de renforcer la sécurité d’un serveur. Elle consiste à maintenir les ports du pare-feu fermés, même ceux qui sont utilisés régulièrement. Ces ports ne s’ouvrent que si la demande de connexion inclut une séquence spécifique, un « toc secret ».

Le « toc secret » du *port knocking*

Au temps de la prohibition, pour entrer dans un bar clandestin, il fallait connaître le mot de passe et le prononcer correctement. Le *port knocking* est une version moderne de ce principe. Si vous voulez donner accès à des services de votre ordinateur, mais sans exposer votre pare-feu à Internet, vous pouvez utiliser le *port knocking*. Il permet de fermer tous les ports d’entrée et de les ouvrir uniquement lorsqu’une suite prédéfinie de tentatives de connexion est effectuée. Cette séquence de tentatives de connexion devient alors le « toc secret ». Un autre « toc secret » permettra de refermer le port.

Bien que novateur, le *port knocking* est un exemple de « sécurité par l’obscurité », un concept qui présente des failles. La sécurité d’un système basé sur le secret d’accès est efficace tant que ce secret est connu uniquement d’un groupe restreint. Cependant, une fois ce secret dévoilé, que ce soit par divulgation, observation, déduction ou ingénierie inverse, la sécurité devient illusoire. Il est préférable de sécuriser votre serveur par des méthodes plus robustes, comme les connexions par clés pour les serveurs SSH.

Les stratégies de cybersécurité les plus solides sont multi-couches. Le *port knocking* pourrait donc être une couche supplémentaire, car l’accumulation de mesures de sécurité est bénéfique. Néanmoins, il est discutable de savoir si le *port knocking* apporte une valeur significative, voire aucune, à un système déjà correctement protégé.

La cybersécurité est un domaine complexe et vaste. Le *port knocking* ne devrait jamais être votre seule défense.

Installation de `knockd`

Pour illustrer le fonctionnement du *port knocking*, nous l’utiliserons pour contrôler le port 22, celui du SSH. Nous utiliserons l’outil `knockd`. Installez ce paquet avec `apt-get` si vous utilisez Ubuntu ou une autre distribution basée sur Debian. Pour les autres distributions, utilisez l’outil de gestion de paquets de votre système.

Entrez la commande suivante :

sudo apt-get install knockd

Le pare-feu `iptables` est probablement déjà installé. Vous devrez peut-être aussi installer le paquet `iptables-persistent` qui gère le chargement automatique des règles `iptables` sauvegardées.

Pour l’installer, tapez :

sudo apt-get install iptables-persistent

Quand l’écran de configuration IPV4 apparaît, pressez la barre espace pour accepter l’option « Oui ».

Appuyez de nouveau sur la barre espace dans l’écran de configuration IPv6 pour accepter « Oui » et continuer.

La commande suivante indique à `iptables` d’autoriser les connexions établies et en cours. Nous allons ensuite émettre une autre commande pour fermer le port SSH.

Il ne faut pas interrompre une éventuelle connexion SSH existante en émettant cette commande :

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Cette commande ajoute une règle au pare-feu, qui dit :

-A: ajouter la règle à la fin de la liste des règles de pare-feu.
INPUT: cette règle concerne les connexions entrantes.
-m conntrack: les règles de pare-feu traitent le trafic réseau (paquets) correspondant à certains critères. L’option -m demande à `iptables` d’utiliser des modules de correspondance de paquets supplémentaires. Ici, `conntrack` permet d’utiliser les fonctionnalités de suivi de connexion réseau du noyau.
–ctstate ESTABLISHED, RELATED: ceci indique le type de connexion concernée par la règle : les connexions ESTABLISHED (déjà en cours) et RELATED (établies à la suite d’une connexion existante). Par exemple, un téléchargement de fichier initié par une connexion établie peut se faire via une nouvelle connexion.
-j ACCEPT: si le trafic correspond à la règle, il est envoyé à la cible ACCEPT, c’est-à-dire qu’il est autorisé à traverser le pare-feu.

Nous pouvons maintenant émettre la commande qui ferme le port:

sudo iptables -A INPUT -p tcp --dport 22 -j REJECT

Cette commande ajoute une règle au pare-feu, qui dit :

-A: ajouter la règle à la fin de la liste des règles de pare-feu.
INPUT: cette règle concerne les connexions entrantes.
-p tcp: cette règle s’applique au trafic utilisant le protocole TCP.
–dport 22: cette règle s’applique spécifiquement au trafic TCP ciblant le port 22 (port du SSH).
-j REJECT: si le trafic correspond à la règle, il est envoyé à la cible REJECT dans le pare-feu, et n’est donc pas autorisé à le traverser.

Nous devons maintenant démarrer le démon `netfilter-persistent` avec cette commande :

sudo systemctl start netfilter-persistent

Nous voulons que `netfilter-persistent` effectue une sauvegarde et un rechargement afin qu’il charge et contrôle les règles `iptables`.

Entrez les commandes suivantes :

sudo netfilter-persistent save

sudo netfilter-persistent reload

Les outils nécessaires sont maintenant installés et le port SSH est fermé (normalement sans avoir interrompu une connexion existante). Il est temps de configurer le « toc secret ».

Configuration de `knockd`

La configuration de `knockd` se fait en modifiant deux fichiers. Le premier est le fichier de configuration de `knockd` :

sudo gedit /etc/knockd.conf

L’éditeur `gedit` s’ouvre, affichant le fichier de configuration de `knockd`.

Nous allons modifier ce fichier selon nos besoins. Les sections importantes sont « openSSH » et « closeSSH ». Chacune de ces sections contient quatre entrées :

sequence: la séquence de ports qui doivent être atteints pour ouvrir ou fermer le port 22. Par défaut, ce sont les ports 7000, 8000 et 9000 pour ouvrir, et 9000, 8000 et 7000 pour fermer. Vous pouvez modifier ou ajouter des ports à cette liste. Nous allons garder les valeurs par défaut.
seq_timeout: le délai maximum durant lequel les ports doivent être atteints pour déclencher l’ouverture ou la fermeture.
command: la commande envoyée au pare-feu `iptables` lorsque l’action d’ouverture ou de fermeture est déclenchée. Ces commandes ajoutent (pour ouvrir le port) ou suppriment (pour fermer le port) une règle au pare-feu.
tcpflags: le type de paquet que chaque port doit recevoir dans la séquence secrète. Un paquet SYN (synchroniser) est le premier d’une demande de connexion TCP, appelée « handshake à trois voies ».

La section « openSSH » se lit comme suit: « une demande de connexion TCP doit être adressée aux ports 7000, 8000 et 9000 – dans cet ordre et en moins de 5 secondes – pour que la commande d’ouverture du port 22 soit envoyée au pare-feu. »

La section « closeSSH » se lit comme suit: « une demande de connexion TCP doit être adressée aux ports 9000, 8000 et 7000 – dans cet ordre et en moins de 5 secondes – pour que la commande de fermeture du port 22 soit envoyée au pare-feu. »

Règles du pare-feu

Les entrées « command » dans les sections `openSSH` et `closeSSH` sont les mêmes, à l’exception d’un paramètre. Voici leur composition :

-A: ajouter la règle à la fin de la liste des règles de pare-feu (pour la commande `openSSH`).
-D: supprimer la règle de la liste des règles de pare-feu (pour la commande `closeSSH`).
INPUT: cette règle concerne le trafic réseau entrant.
-s %IP%: l’adresse IP du périphérique demandant une connexion.
-p: protocole réseau; dans notre cas, TCP.
–dport: le port de destination; dans notre exemple, le port 22.
-j ACCEPT: saute vers la cible d’acceptation dans le pare-feu, autorisant le paquet à passer au reste des règles sans autre traitement.

Modifications du fichier de configuration `knockd`

Les modifications apportées au fichier sont surlignées en rouge ci-dessous :

Nous étendons le `seq_timeout` à 15 secondes. Ceci est généreux, mais utile si une personne entre manuellement les demandes de connexion.

Dans la section `openSSH`, nous modifions l’option `-A` (ajouter) de la commande en `-I` (insérer). Cette commande insère une nouvelle règle de pare-feu au début de la liste. Avec l’option `-A`, la règle serait ajoutée à la fin de la liste.

Le trafic entrant est vérifié par rapport à chaque règle de pare-feu, du haut vers le bas. Nous avons déjà une règle qui ferme le port 22. Par conséquent, si le trafic entrant est testé par rapport à cette règle avant la règle qui autorise le trafic, la connexion sera refusée. En revanche, s’il voit d’abord cette nouvelle règle, la connexion sera autorisée.

La commande `close` supprime la règle ajoutée par `openSSH` des règles du pare-feu. Le trafic SSH est donc de nouveau géré par la règle préexistante « le port 22 est fermé ».

Après ces modifications, enregistrez le fichier de configuration.

Modifications du fichier de contrôle `knockd`

Le fichier de contrôle de `knockd` est plus simple. Avant de le modifier, nous devons identifier le nom interne de notre connexion réseau. Pour ce faire, tapez la commande :

ip addr

La connexion utilisée pour cet exemple est appelée `enp0s3`. Notez le nom de votre connexion.

La commande suivante modifie le fichier de contrôle `knockd` :

sudo gedit /etc/default/knockd

Voici le fichier `knockd` dans `gedit` :

Les quelques modifications sont surlignées en rouge :

Nous avons remplacé la valeur de `START_KNOCKD =` de 0 à 1.

Nous avons aussi supprimé le `#` au début de l’entrée `KNOCKD_OPTS =` et remplacé `eth1` par le nom de notre connexion réseau, `enp0s3`. Évidemment, si votre connexion est `eth1`, vous n’aurez pas à la modifier.

Vérification

Il est temps de vérifier si tout fonctionne. Nous allons démarrer le démon `knockd` avec cette commande :

sudo systemctrl start knockd

Nous allons maintenant passer sur une autre machine et tenter de nous connecter. Nous avons aussi installé l’outil `knockd` sur cette machine, non pas pour configurer le *port knocking*, mais parce que le paquet `knockd` contient un autre outil appelé `knock`. Nous l’utiliserons pour envoyer notre séquence secrète et « frapper à la porte ».

Utilisez la commande suivante pour envoyer votre séquence secrète de demandes de connexion vers les ports de l’hôte à l’adresse IP 192.168.4.24 :

knock 192.168.4.24 7000 8000 9000 -d 500

Cela indique à `knock` de cibler l’ordinateur à l’adresse IP 192.168.4.24 et d’envoyer une demande de connexion aux ports 7000, 8000 et 9000, dans l’ordre, avec un délai (-d) de 500 millisecondes entre chaque.

Un utilisateur nommé « dave » tente ensuite une connexion SSH vers 192.168.4.24 :

ssh dave@192.168.4.24

Sa connexion est acceptée, il entre son mot de passe et sa session distante démarre. Son invite de commande passe de `dave@nostromo` à `dave@howtogeek`. Pour se déconnecter de l’ordinateur distant, il tape :

exit

Son invite revient sur son ordinateur local. Il utilise de nouveau `knock`, en ciblant cette fois-ci les ports dans l’ordre inverse pour fermer le port SSH sur l’ordinateur distant.

knock 192.168.4.24 9000 8000 7000 -d 500

Cette session distante n’a pas été très longue, mais elle a montré comment ouvrir et fermer le port par le *port knocking*, le tout dans une seule capture d’écran.

Que se passe-t-il du côté serveur ? L’administrateur système utilise la commande suivante pour afficher les nouvelles entrées du journal système :

tail -f /var/log/syslog

On voit trois entrées `openSSH`. Elles sont déclenchées lorsque chaque port est ciblé par l’utilitaire de *knocking* distant.
Lorsque les trois étapes de la séquence sont remplies, une entrée indiquant  » SÉSAME OUVRE-TOI » est enregistrée.
La commande permettant d’insérer la règle dans la liste des règles `iptables` est envoyée. Elle autorise l’accès par SSH sur le port 22 depuis l’adresse IP spécifique du PC qui a donné le bon « toc » (192.168.4.23).
L’utilisateur « dave » se connecte pendant quelques secondes, puis se déconnecte.
On voit trois entrées `closeSSH`. Celles-ci sont déclenchées lorsque chaque port est ciblé par l’utilitaire de *knocking* distant, indiquant à l’hôte de fermer le port 22.
Une fois les trois étapes déclenchées, nous avons de nouveau un message « SÉSAME OUVRE-TOI ». La commande est envoyée au pare-feu pour supprimer la règle. (Pourquoi pas « SÉSAME FERME-TOI » lors de la fermeture du port ? Allez savoir…)

Désormais, la seule règle concernant le port 22 dans la liste des règles `iptables` est celle que nous avons entrée au début pour fermer ce port. Le port 22 est donc de nouveau fermé.

Conclusion

Voilà comment fonctionne le *port knocking*. Considérez-le comme une diversion et évitez de l’utiliser en production. Ou, si vous y êtes contraint, n’en faites pas votre seule mesure de sécurité.