Utiliser TCP keepalive sous Linux

Linux intègre nativement le keepalive. Vous devez activer le réseau TCP/IP pour pouvoir l'utiliser. Vous avez aussi besoin du support de procfs et de sysctl pour pouvoir configurer les paramètre noyau au lancement.

Les fonctions impliquant keepalive utilisent trois variables manipulées par l'utilisateur :

tcp_keepalive_time

intervalle entre le dernier envoi de paquet (le simple ACK n'étant pas considéré comme de la donnée) et la première sonde keepalive; après que la connexion ait été marquée comme requérant un keepalive, ce compteur n'est plus utilisé.

tcp_keepalive_intvl

intervalle entre deux sondes keepalive, indépendamment de ce qui est échangé sur la connexion dans l'intervalle

tcp_keepalive_probes

nombre de sondes non acquittées à envoyer avant de considérer la connexion perdue et de notifier la couche applicative.

Rappelez-vous que le support du keepalive, même s'il est configuré dans le noyau, n'est pas le comportement par défaut de Linux. Les programmes doivent requérir le contrôle du keepalive pour que ses sockets puissent utiliser l'interface setsockopt. Relativement peu de programmes implémentent keepalive, mais vous pouvez facilement ajouter le support du keepalive pour la plupart d'entre eux en suivant les instructions détaillées plus avant dans ce document.

Il existe deux moyens de configurer les paramètres keepalive du noyau au travers de commandes utilisateur:

Nous aborderons essentiellement comment procéder au travers de l'interface procfs car elle est la plus utilisée, recommandée et la plus simple à appréhender. L'interface sysctl, particulièrement sous l'aspect de l'appel système (syscall) sysctl(2) et non de l'outil sysctl(8), n'est là qu'à titre informatif.

Cette interface nécessite quesysctl et procfs soient inclus au noayu, et que procfs soit monté quelque part dans le système de fichiers (habituellement /proc, comme dans l'exemple ci-dessous). Vous pouvez lire les valeurs des paramètres actuels en listant avec la commande « cat » les fichiers du répertoire /proc/sys/net/ipv4/ :

Les deux premiers paramètres sont exprimés en secondes, et le dernier est un nombre simple. Cela signifie que les routines keepalive attendent deux heures (7200 secs) avant d'adresser la première sonde keepalive, et en adressent une nouvelle toutes les 75 secondes. Si aucune réponse ACK n'est reçue après neuf tentatives consécutives, la connexion est considérée comme rompue.

La modification de ces valeurs est directe : il faut écrire de nouvelles valeurs dans les fichiers. Supposons que souhaitiez configurer la machine pour que le keepalive débute après dix minutes d'inactivité sur le lien, et que des sondes soient envoyées chaque minute. En raison de l'instabilité de ce brin de votre réseau et de la faible valeur de l'intervalle, supposons que vous vouliez augmenter le nombre de tentatives à 20.

Voici comment paramétrer ces valeurs :

  # echo 600 > /proc/sys/net/ipv4/tcp_keepalive_time

  # echo 60 > /proc/sys/net/ipv4/tcp_keepalive_intvl

  # echo 20 > /proc/sys/net/ipv4/tcp_keepalive_probes
        

Pour confirmer la prise en compte des nouvelles valeurs, affichez à nouveau le contenu des fichiers pour vérifier qu'ils présentent bien les valeurs souhaitées.

Il faut garder présent à l'esprit que procfs manipule des fichiers spéciaux, et vous ne pouvez pas tout faire sur ces fichiers qui ne sont qu'une interface vers l'environnement du noyau, non de véritables fichiers. Testez vos scripts avant de les utiliser et faites en sorte d'utiliser des modes d'accès simples comme dans les exemples ci-dessus.

Vous pouvez accéder à l'interface grâce à l'outil sysctl(8), en précisant ce que vos voulez lire ou écrire.

  # sysctl \
  > net.ipv4.tcp_keepalive_time \
  > net.ipv4.tcp_keepalive_intvl \
  > net.ipv4.tcp_keepalive_probes
  net.ipv4.tcp_keepalive_time = 7200
  net.ipv4.tcp_keepalive_intvl = 75
  net.ipv4.tcp_keepalive_probes = 9
        

Remarquez que les noms sysctl sont proches des chemins procfs. L'écriture se fait grâce à l'option -w de sysctl (8):

  # sysctl -w \
  > net.ipv4.tcp_keepalive_time=600 \
  > net.ipv4.tcp_keepalive_intvl=60 \
  > net.ipv4.tcp_keepalive_probes=20
  net.ipv4.tcp_keepalive_time = 600
  net.ipv4.tcp_keepalive_intvl = 60
  net.ipv4.tcp_keepalive_probes = 20
        

Remarquez que sysctl (8) n'utilise pas l'appel système (syscall)sysctl(2), mais lit et écrit directement dans l'arborescence procfs, donc procfs devra être activé dans le noyau et monté dans le système de fichiers, comme si vous accédiez directement aux fichiers via l'interface procfs. Sysctl(8) n'est qu'un moyen différent de faire la même chose.

Il existe différents moyens de paramétrer le système à chaque démarrage. Tout d'abord, souvenez vous que chaque distribution Linux possède son propre jeu de scripts d'initialisation appelé par init (8). Les configurations les plus courantes incluent soit le répertoire /etc/rc.d/ , soit /etc/init.d/ . Dans ce cas vous pouvez positionner les paramètres dans un script de démarrage quelconque, keepalive relisant les valeurs à chaque fois que ses routines en ont besoin. Donc si vous changez la valeur de tcp_keepalive_intvl alors que la connexion est encore active, le noyau utilisera la nouvelle valeur pour continuer.

Les commandes d'initialisation peuvent logiquement être placées en trois endroits différents : le premier est dans la configuration réseau, le second dans le script rc.local , habituellement inclus dans toutes les distributions, et connu comme étant le point de configuration utilisateur au démarrage. Le troisième point existe peut-être déjà sur votre système. En revenant à l'outil sysctl (8) , vous pouvez voir que l'option -p charge les paramètres du fichier de configuration /etc/sysctl.conf . Il est fréquent que votre script d'initialisation exécute déjà sysctl -p (un « grep » sur le répertoire de configuration le confirmera), et vous n'avez alors qu'à ajouter les lignes dans /etc/sysctl.conf pour qu'elles soient prises en compte à chaque démarrage. Pour davantage d'informations sur la syntaxe de sysctl.conf (5), reportez vous au manuel.