Pas Tout A Fait

Aller au contenu | Aller au menu | Aller à la recherche

Le port-knocking ou comment cacher un service

Dernière mise à jour le 07 juin 2011

La technique du "port-knoking" consiste à insérer une règle préalablement définie dans un pare-feu en cas de réception, dans un délai donné, d'une séquence de paquets TCP et/ou UDP. Elle permet de cacher un service sur un serveur et de renforcer sa sécurité. Un petit daemon existe sous GNU/Linux pour mettre en place une telle porte dérobée, knockd.

286_8618b.jpg

Photographie de Jérôme Plano


Présentation du Port-Knocking

La page traitant du port-knocking sur WikiPédia est comme souvent fort bien réalisée, en voici un extrait :

« Un processus s'exécute en arrière-plan (daemon) et scrute le journal des connexions du pare-feu, ou une analyse de paquets passant par un port déjà ouvert, permet de détecter une séquence particulière. Le serveur garde une liste des ports sur lesquels ont été tentés des connexions en fonction de l'adresse IP de l'émetteur. À chaque tentative de connexion, le port est ajouté à la liste des ports pour cette adresse IP. Si la liste contient une séquence reconnue, les règles du pare-feu seront modifiées pour ouvrir un port défini à l'avance, et d'autres commandes peuvent être exécutées de cette manière. La complexité de la séquence peut varier de la simple liste (par exemple : TCP port 1000, TCP port 2000, UDP port 3000) à une vérification de la durée et à des données chiffrées.

La seule indication d'échec est de ne pas avoir de port nouvellement ouvert à la fin de la séquence. À aucun moment des informations sont envoyées au lanceur de séquence ; le système reste muet.

Lorsqu'un port a été ouvert par la séquence correcte, les règles du pare-feu n'autorisent que l'adresse IP ayant lancé la séquence à communiquer sur le port ouvert. Le port peut de nouveau être fermé après un délai prévu ou à la demande. »

Une petite série de schéma est disponible sur le site de l'université de Marne-la-Vallée.


Installation de knockd

Avant tout, sachez qu'il vous faut un firewall correctement configuré sur votre machine pour pouvoir utiliser knockd. Sous GNU/Linux, le firewall est NetFilter, associé à son principal outil de configuration : IPtables. Il existe une multitude d'outils graphiques pour configurer NetFilter simplement.

Knockd s'installe lui très simplement grâce à apt-get :

sudo apt-get install knockd

Une fois installé, le daemon se lance en employant la commande suivante :

/etc/init.d/knockd start

Comme souvent, on peut utiliser start, stop, restart, reload et force-reload pour contrôler le daemon.

Les options de lancement sont :

  • -i, --interface <int>

Permet de spécifier l'interface à écouter. Par défaut eth0.

  • -d, --daemon

Lancer en tant que daemon. Cette option est positionnée par défaut sous Ubuntu, directement dans le script de lancement de knockd.

  • -c, --config <file>

Permet de spécifier un fichier de configuration. Par défaut le fichier est /etc/knockd.conf.

  • -D, --debug

Active les messages de debug.

  • -l, --lookup

Réaliser une résolution de noms pour les lignes du fichier de logs. Activer cette option peut représenter un risque de sécurité !

  • -v, --verbose

Active le mode verbeux.

  • -V, --version

Affiche le numéro de version de knockd.

  • -h, --help

L'aide syntaxique des options de lancement.

Notez que sous Ubuntu, les options sont à indiquer dans le fichier /etc/default/knockd plutôt que directement dans le script /etc/init.d/knockd. Voici un exemple de ce fichier :

################################################
#
# knockd's default file, for generic sys config
#
################################################
# control if we start knockd at init or not
# 1 = start
# anything else = don't start
#
# PLEASE EDIT /etc/knockd.conf BEFORE ENABLING
START_KNOCKD=1
# command line options
KNOCKD_OPTS="-i eth0"

Dans l'exemple ci-dessus, on spécifie l'interface à écouter avec -i eth0. Il semble qu'en spécifier une en cas d'interfaces multiples soit obligatoire, puisque knockd refuse de démarrer sans cela.

C'est aussi dans ce fichier que l'on indique si le daemon doit être démarré au lancement du système, via l'option "START_KNOCKD=1".

L'option -d est quant à elle déjà positionnée dans le fichier de lancement /etc/init.d/knockd, il n'est donc pas utile de la mettre dans /etc/default/knockd.


Configuration

Sous Ubuntu, le fichier de configuration est /etc/knockd.conf. Il se présente ainsi par défaut :

[options]
UseSyslog
[openSSH]
sequence    = 7000,8000,9000
seq_timeout = 5
command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags    = syn
[closeSSH]
sequence    = 9000,8000,7000
seq_timeout = 5
command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags    = syn

C'est ce fichier qui permet de définir les séquences de ports à écouter et les actions à réaliser en cas de détection d'une séquence valide.

Les options

Elles sont peu nombreuses et se trouvent en dessous de [options] dans le fichier :

  • UseSyslog

Utiliser Syslog pour enregistrer les logs. Par défaut les enregistrements vont dans /var/log/messages.

  • LogFile = /chemin/vers/fichier

Ne pas utiliser Syslog et enregistrer directement les logs dans le fichier indiqué.

  • PidFile = /chemin/vers/fichier

Permet de spécifier le fichier pid, il s'agit par défaut de /var/run/knockd.pid.

  • Interface = <nom_interface>

L'interface à écouter, comme eth0 ou venet0 par exemple.

Les règles d'ouverture/fermeture

Il est possible d'en spécifier plusieurs, en les indiquant sous un nom placé entre crochets, par exemple [ouvrirFTP]. Voici la liste des directives utilisables :

  • Sequence = <port1>[:<tcp|udp>][,<port2>[:<tcp|udp>] ...]

Spécifie une séquence de ports. Si une erreur de port a lieu pendant la séquence, elle est entièrement invalidée. En option, il est possible de définir le protocole (TCP ou UDP) à utiliser pour chaque port (par défaut TCP).

  • One_Time_Sequences = /chemin/vers/lefichierdesequence

Spécifie le fichier contenant les séquences uniques à utiliser. Au lieu d'utiliser une séquence fixe, knockd va lire ce fichier pour y trouver un séquence. Après chaque séquence correctement réalisée, knock va désactiver cette séquence en la commentant avec un "#" placé en remplacement du premier caractère de la ligne de cette séquence. Cette séquence désactivée sera remplacée par la prochaine séquence contenue dans le fichier.

Puisque knockd va remplacer par un "#" le premier caractère, il est recommandé de laisser un espace au début de chaque ligne de ce fichier, sous peine de voir les séquences compromises par le "#".

Chaque ligne du fichier doit contenir une et une seul séquence, écrite dans le même format que pour l'option "Sequence". Les lignes commençant par "#" sont ignorées.

Note: Ne jamais éditer cette ligne lorsque knockd est en fonctionnement !

  • Seq_Timeout = <délai>

Le temps durant lequel une séquence doit être exécutée. Au delà de ce délai, la séquence est annulée et doit être recommencée depuis le début.

  • TCPFlags = fin|syn|rst|psh|ack|urg

Permet d'ignorer les paquets qui n'ont pas les flags TCP spécifiés. Si cette option est activée, knockd va ignorer les paquets TCP qui n'ont pas le-s bon-s flag-s, sans pour autant invalider la séquence en cours. C'est un comportement différent de la normale, où knockd invalide entièrement une séquence en cours si un mauvais port est frappé, obligeant le client à recommencer du début.

Utiliser "TCPFlags = syn" est utile si vous réalisez la séquence dans un tunnel SSH, puisque le trafic SSH risque d'interférer avec la séquence et donc d'invalider cette dernière.

Séparez de multiples flags avec une virgule (par exemple : "TCPFlags = syn,ack,urg"). Il est possible d'exclure des flags en utilisant le point d'exclamation "!" (par exemple, "TCPFlags = syn,!ack" correspond au flag "syn" sans flag "ack").

  • Start_Command = <commande>

C'est la commande à exécuter en cas de réception valide de la séquence. %IP% sera remplacé par l'adresse IP du client aillant correctement réalisé la séquence. La directive "command" est un alias vers "Start_Command"

  • Cmd_Timeout = <délai>

Le délai entre l'exécution de Start_Command et Stop_Command. Indiquer ce délai est optionnel, sauf si Stop_Command est utilisé.

  • Stop_Command = <commande>

C'est la commande qui sera exécutée une fois le délai spécifié avec Cmd_Timeout écoulé. %IP% sera remplacé par l'adresse IP du client ayant correctement réalisé la séquence. Cette directive est optionnelle.

Surveiller les logs

Le fichier de logs peut être choisi avec l'option "LogFile". Voici à quoi ressemble les enregistrements réalisés par knockd :

[2009-12-31 09:51] openSSH: running command: /sbin/iptables -D INPUT -s 192.168.36.3 -p tcp --dport 22316 -j ACCEPT
[2009-12-31 09:51] 192.168.36.3: openSSH: command timeout
[2009-12-31 09:51] openSSH: running command: /sbin/iptables -I INPUT -s 192.168.36.3 -p tcp --dport 22316 -j ACCEPT
[2009-12-31 09:51] 192.168.36.3: openSSH: OPEN SESAME
[2009-12-31 09:51] 192.168.36.3: openSSH: Stage 4
[2009-12-31 09:51] 192.168.36.3: openSSH: Stage 3
[2009-12-31 09:51] 192.168.36.3: openSSH: Stage 2
[2009-12-31 09:51] 192.168.36.3: openSSH: Stage 1
[2009-12-31 09:49] starting up, listening on eth0

Pensez à surveiller les échecs trop fréquents, qui se présentent sous cette forme :

[2009-12-19 14:52] 192.168.38.112: closeLightHTTP: sequence timeout (stage 2)
[2009-12-19 14:14] 192.168.38.112: closeLightHTTP: Stage 2
[2009-12-19 14:14] 192.168.38.112: closeLightHTTP: Stage 1

Une multiplication d'enregistrements de ce genre avec la même IP source peut indiquer une tentative de découverte par brute force. Une règle d'interdiction ajoutée à votre firewall devrait suffire à refroidir la situation.


Comment réaliser une séquence

C'est bien gentil de mettre en place plein de séquences, mais il faudrait savoir comment les réussir sur le serveur depuis une machine distante maintenant !

Le plus simple est d'utiliser le petit outil nommé knock qui est installé en même temps que le daemon knockd. Il est donc aussi utile d'installer le paquet "knockd" sur les machines clientes, même si elles ne feront par tourner le daemon.

L'utilisation de knock est très simple :

knock -v 192.168.36.3 20000 30000:udp 40000 50000:udp

La commande ci-dessus va envoyer la séquence "TCP/20000" puis "UDP/30000" puis "TCP/40000" et enfin "UDP/50000" à la machine d'adresse IP 192.168.36.3.

Il est évidemment possible d'utiliser des outils plus évolués pour réaliser les séquences. Je vous recommande HPing, qui fait ça très bien et s'installe facilement sous Ubuntu :

sudo apt-get install hping3

HPing est un outil puissant et complexe, il faut donc prendre un peu le temps de comprendre comment il fonctionne. La page de manuel est superbe :

man hping3

Les outils pour forger des paquets TCP/UDP/etc sont nombreux, libre à vous de trouver celui qui vous convient. :-)


Exemples de configuration

Voici quelques exemples simples de configuration. Notez que dans tous les exemples donnés, les caractères %IP% seront remplacés par l'adresse IP de la machine ayant réussi une séquence.

Pour un serveur SSH

Il s'agit ici d'ouvrir un port pour s'y connecter. Une fois la connexion établie dans le cadre d'une connexion maintenue, il n'est pas nécessaire de garder ce port ouvert, il se refermera donc automatiquement après un délai choisi.

[openSSH]
sequence    = 5555:udp,6666,7777,8888:udp
seq_timeout = 8
command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags    = syn,urg
cmd_timeout   = 15
stop_command  = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

Ici, "seq_timeout" indique que la "sequence" doit être réalisée en moins de 8 secondes, il faut donc que les quatre ports indiqués soient frappés dans un délai de 8 secondes. Les paquets doivent avoir les flags "syn" et "urg" comme le précise "tcpflags".

Une fois la séquence correctement réalisée, la "command" sera exécutée (elle ouvre le port TCP/22 pour l'adresse IP qui a réalisé la séquence correctement), et elle restera active pendant 15 secondes grâce à "cmd_timeout". C'est à dire qu'au bout de 15 secondes, le port TCP/22 sera automatiquement refermé en utilisant la commande "stop_command", qui referme le port TCP/22.

Pour un serveur HTTP

Voilà un exemple de configuration en deux temps. La première séquence permet d'ouvrir le port, et la seconde de le refermer. C'est particulièrement utile pour les connexions HTTP et plus généralement pour les connexions non-maintenues, dans la mesure où l'on ne sait pas précisément combien de temps on va avoir besoin de l'accès au serveur.

[openHTTP]
sequence    = 17000,38000,29000
seq_timeout = 5
command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 80 -j ACCEPT
tcpflags    = syn
[closeHTTP]
sequence    = 49000,18000,37000
seq_timeout = 5
command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 80 -j ACCEPT
tcpflags    = syn

La première séquence, celle de "openHTTP" va donc ouvrir le port TCP/80 en cas de réussite. La réussite étant de frapper les ports TCP/17000 puis TCP/38000 et TCP/29000 avec des paquets ayant le flag "syn", le tout en moins de 5 secondes.

Puis la seconde séquence, celle de "closeHTTP" va fermer ce port TCP/80 une fois la besogne accomplie. Il faut bien sûr ne pas oublier de refermer le port, ou bien automatiser cette tâche via un script qui se lance par exemple à la fermeture du navigateur.


Pour finir

Le port knocking permet de protéger un service efficacement. La seule méthode force brute est utilisable pour découvrir une séquence, et une simple séquence de trois ports représente déjà un nombre astronomique de possibilités à tester pour un attaquant. Notez tout de même que le sniffing permet de découvrir autrement plus rapidement une séquence.

Notez aussi que si votre daemon knockd se termine anormalement pour une raison ou une autre, l'accès au serveur sera impossible via SSH, ce qui peut être très gênant... Il est néanmoins possible de mettre en place un script pour relancer le daemon si celui-ci disparaît sans raison.

Matthieu Patout

Auteur: Matthieu Patout

Restez au courant de l'actualité et abonnez-vous au Flux RSS

Soyez le premier à réagir sur cet article

Ajouter un commentaire Fil des commentaires de ce billet

aucune annexe



Voir Aussi

logo-debian.png

Mise à jour automatique avec Cron-APT

Maintenir à jour les logiciels d'un serveur est la première étape d'une bonne politique de sécurité....

Lire la suite

Présentation de Seeks et installation sous Debian Lenny

La recherche sur internet est l'affaire aujourd'hui de quelques grands groupes commerciaux, dominés...

Lire la suite


Découvrez le Nouveau « Pack Liberté »