Page suivante Page précédente Table des matières

4. Configuration

La configuration de PERS s'effectue en espace utilisateur à l'aide de la commande iptables et d'une bibliothèque dynamique associée permettant de lui passer tous ses paramètres spécifiques. Cette bibliothèque ajoute à iptables de nouvelles options applicables à chaque règle dont la cible est PERS ; l'une de ces options permet l'utilisation d'un fichier de configuration détaillé regroupant l'ensemble des paramètres nécessaires à l'émulation d'un système d'exploitation particulier. Via l'utilisation de fichiers de configuration différents pour chaque règle différente on peut donc très librement choisir d'émuler un système particulier en fonction d'adresses sources et destinations, de l'interface, et autres critères de sélection dans les règles.

4.1 Options en ligne de commande

Les options de la ligne commande sont passées à la cible lors de l'ajout d'une règle l'utilisant par exemple avec une syntaxe du type :

iptables -A <chaine> -s <source> -d <destination> -j PERS <options>

[Se référer à la documentation d'iptables pour plus de détails sur la syntaxe globale]

Les options reconnues par la bibliothèque sont :

4.2 Fichier de configuration

Les paramètres concernant l'émulation d'un système particulier se définissent au sein d'un fichier. Ce fichier utilise une syntaxe proche de named.conf, inspirée du langage C. Les options de configuration sont regroupées dans des blocs (délimités par des { et }) et chaque bloc de configuration correspond à un type de réécriture différent. Chaque option est constituée d'un identifiant suivi d'un ou plusieurs arguments et terminée par un symbole ;. Les options et les blocs peuvent être spécifiés dans n'importe quel ordre.

Identification

Le premier élément d'un fichier de configuration est une identification du système qu'il décrit. Il s'agit d'une chaîne d'au plus 20 caractères décrivant le système. La syntaxe est la suivante :

 id "FakeOS";

Paramètres génériques TCP

Ces paramètres sont regroupés au sein d'une section nommée tcp. Exemple :

  tcp {
    incoming yes;
    outgoing no;
    max-window 65536;
  }

Le paramètre incoming définit si l'on souhaite activer les modifications opérant sur des connexions TCP (ISN, taille de fenêtre, et Options) pour les connexions entrantes vers la zone protégée. Il peut prendre les valeurs yes ou no.

Le paramètre outgoing est analogue pour les connexions sortantes de la zone protégée.

Le paramètre max-window contrôle la réécriture de la taille de fenêtre sur les paquets TCP des connexions correpondant aux réglages précédents. Si il est défini à une valeur non nulle, alors pour toute nouvelle connexion dont la taille de fenêtre lui est supérieure, un décalage est calculé et la taille de fenêtre est ramenée à une valeur inférieure à ce paramètre sur toute la durée de la connexion.

Paramètres de générateur de numéros de séquence

Ces paramètres sont regroupés au sein d'une section nommée tcp_isn. Exemple :

  tcp_isn {
    type random-inc 10000;
    initial-value 2600;
  }

Le paramètre type décrit le type de générateur à émuler ainsi qu'une éventuelle option de cet émulation. Les types suivants sont implémentés :

Le paramètre initial-value décrit la valeur initiale à utiliser pour le générateur de numéro de séquence. Il peut s'agir d'une valeur numérique ou bien du mot-clé random qui choisira une valeur aléatoire lors de l'insertion de la règle. Ce paramètre a peu d'importance pour les types de générateurs peu prédictibles.

Paramètres de générateur d'Identifiants IP

Ces paramètres sont regroupés au sein d'une section nommée ip_id. Exemple :

  ip_id {
    type broken-inc 1;
    initial-value 2600;
  }

Le paramètre type décrit le type de générateur à émuler ainsi qu'une éventuelle option de cet émulation. Les même types que pour les générateurs de numéros de séquences sont acceptés, et un choix supplémentaire, broken-inc number est disponible : il s'agit d'un compteur incrémenté de la valeur spécifiée à chaque utilisation, mais dont le résultat est stoqué dans le paquet au format "little endian", au lieu de l'ordre réseau.

Paramètres de rééordonnancement des options

Ces paramètres sont regroupés au sein d'une section nommée tcp_options. Exemple :

  tcp_options {
    keep-unknown yes;
    keep-unused no;
    isolated-packets yes;
    timestamp-scale 100;
    code {
      <code...>
    }
  }

Cette section définit comment les options TCP d'un paquet doivent être réécrites. La sous-section code contient un programme dans un langage proche du C (décrit par la suite) qui est compilé par le module libipt_PERS.so. Ce code est passé à la machine virtuelle qui remplit le buffer d'options constituant son état au fer et à mesure de l'exécution. Lorsque l'exécution est achevée, le buffer d'options résultant est utilisé pour remplacer les options initiales du paquet.

Le paramètre keep-unknown spécifie si les options "inconnues" présentes dans le paquet initial, et donc non manipulables par le programme de réécriture, doivent être rajoutées à la fin du buffer final afin d'être présentes dans le paquet final. Ce paramètre peut prendre les valeurs yes ou no.

Le paramètre keep-unused spécifie si les options du paquet original qui n'ont pas été utilisées (testées ou recopiées) pendant l'exécution du programme doivent être recopiées à la fin du buffer afin d'être présentes dans le paquet final. Ce paramètre peut prendre les valeurs yes ou no. Ceci permet d'utiliser un code assez simple pour réordonner seulement quelques options tout en conservant toutes les options du paquet original.

Le paramètre isolated-packets spécifie si la réécriture des options doit être appliquée aux paquets n'appartenant à aucune connexion connue. Ce paramètre peut prendre les valeurs yes ou no (valeur par défaut).

Le paramètre timestamp-scale spécifie si l'on souhaite changer la valeur des "timestamp" TCP dans les paquets communiquant avec la machine locale. Il prend en argument la fréquence à utiliser pour les nouveaux "timestamp". (si la valeur est nulle ou égale à la fréquence nominale, l'option est ignorée).

Paramètres du leurre TCP

Ces paramètres sont regroupés au sein d'une section nommée tcp_decoy. Exemple :

  tcp_decoy {
    code {
      <code...>
    }
  }

Cette section se résume à une sous-section code analogue à celle de la section précédente, qui définit un certain nombre de tests à effectuer sur le paquet initial afin de reconnaître des paquets caractéristiques d'outils de détection et de répondre en conséquence. Le langage utilisé est le même que précédemment (décrit ci après).

Paramètres du leurre UDP

Ces paramètres sont regroupés au sein d'une section nommée udp_unreach. Exemple :

  udp_unreach {
    reply yes;
    df no;
    max-len 56;
    tos 0;
  
    mangle-original {
      ip-len 21;
      ip-id same;
      ip-csum zero;
      udp-len 308;
      udp-csum zero;
      udp-data same;
    }
  }

Le paramètre reply détermine si l'on souhaite émettre un message ICMP de type "port unreachable" lorsque l'on reçoit un message UDP pour un port non ouvert localement. Il peut être défini à yes ou à no. Les autres paramètres de cette section s'appliquent si il est activé.

Le paramètre df spécifie si le bit "Don't Fragment" de l'entête IP du paquet ICMP doit être activé ou non.

Le paramètre max-len spécifie la longueur maximum du message ICMP généré en réponse.

Le paramètre tos spécifie la valeur du champ "Type Of service" dans l'entête IP du paquet ICMP retourné.

Lors de l'envoi d'un message ICMP de type "port unreachable", une portion du paquet initial est retournée dans le message. La section mangle-original permet de définir des modifications de cette portion du message initial. Elle comprend les paramètres suivants :

4.3 Langage

Les sections tcp_options et tcp_decoy possèdent toutes deux un paramètre code pouvant contenir un programme. Comme vu précédemment, ce programme est compilé par la bibliothèque dynamique de iptables dans un pseudo-code interpété au sein du module noyau par une machine virtuelle simple. Celle-ci opère sur un paquet TCP en entrée et gère un état interne. Son état est composé de :

Le code de la section tcp_options est appliqué à un paquet TCP entrant, et en fin de programme, le buffer d'options dans l'état de la machine virtuelle est utilisé comme nouvelle liste d'options TCP pour le paquet.

Le code de la section tcp_decoy est également appliqué à un paquet TCP entrant, mais le paquet n'est pas modifié. En fonction du type de terminaison du programme, un nouveau paquet peut être construit à partir de l'état de la machine virtuelle et renvoyé à la source du paquet initial. Le paquet inital peut aussi être rejeté, ou continuer son cheminement normal au sein de la cible.

Ces programmes peuvent être décrits avec un langage de syntaxe proche du C. Des test conditionnels peuvent être effectués sur le paquet initial afin de gérer le comportement en fonction de son contenu.

Un test a l'allure générale suivante :

  if (test) {
    <action>
  }
ou
  if (test) {
    <action>
  } else {
    <action>
  }

Un test est constitué d'une ou plusieurs conditions, séparées par les opérateurs && et ||, et groupées par des parenthèses si besoin. Les conditions reconnues par le langage sont :

Le langage dispose de plusieurs instructions afin de manipuler l'état interne de la machine virtuelle :

Ce langage permet donc simplement de définir les comportements pour réordonnancer les options ainsi que pour générer des réponses sur mesure à des tests pathologiques pour tromper les outils de détection de systèmes d'exploitation.

On peut faire les remarques suivantes :


Page suivante Page précédente Table des matières