Sélectionner une page

« Écouter » ?

Sous Linux (comme sous tout autre système d’exploitation), un service réseau écoute sur le réseau. L’expression anglaise est listen (on utilise aussi bind selon ce dont on parle).
Le protocole TCP, le plus utilisé sur Internet pour les services comme le web (HTTPS) et le mail (IMAP/SMTP) permet à un client de se connecter à un serveur. Pour cela il faut donc que le serveur écoute sur le réseau sur un port donné (443 pour le HTTPS, 25 ou 587 pour le SMTP etc.)
Sur un serveur normal, la machine a donc une adresse IP (comme 91.194.61.222) et le service écoute sur le port ad-hoc sur l’IP du serveur. On peut le voir à l’aide de l’outil ss :

ss -plnt nous montre les services qui écoutent sur le réseau, attendant les connexions des clients :

On remarque plusieurs informations intéressantes dans cette commande : ss nous dit (grace à l’option -p) quel processus écoute sur quel port, il nous dit aussi sur quelle adresse IP le service écoute. Il peut s’agir de 127.0.0.1 si le service ne doit être accessible que depuis la machine locale, d’une adresse IP publique comme 91.194.61.222, ou de 0.0.0.0, qui signifie « toutes les adresses IP de la machine, à tout moment« .

Ce 0.0.0.0 est très pratique dans le cas de serveurs disposant d’IP flottante, dites failover. Une IP flottante utilise généralement le protocole VRRP pour bouger d’un serveur à l’autre en cas de pépin. Cela signifie qu’en temps normal, le serveur secondaire ne porte pas l’IP flottante. Cependant, il faut que ce serveur secondaire fasse quand même tourner le service qui servira immédiatement en cas de bascule. On utilise donc 0.0.0.0 pour cela.

Et si on ne veut pas utiliser 0.0.0.0 ?

Il existe plusieurs bonnes raisons de vouloir ne pas utiliser 0.0.0.0 pour faire écouter un service : par exemple, sur un serveur disposant d’une IP publique et d’une IP privée (dans un réseau interne) on peut vouloir que le service n’écoute que sur l’un des deux réseaux mais ne soit pas accessible à l’autre. On pourrait dans ce cas utiliser le pare-feu de la machine, mais dans le cadre de la défense en profondeur, il est toujours conseillé de sécuriser chaque service de manière indépendante d’autres paramètres système.

Autre situation possible : dans le cas d’un serveur avec une IP flottante, le serveur a souvent une IP dans le même réseau que son IP flottante pour pouvoir discuter sur le réseau, et on pourrait ne pas vouloir faire écouter le service sur cette seconde IP.

Est-il possible de faire écouter un service sur une IP que le serveur ne porte pas (pour l’instant…) ? Sous Linux, c’est possible grace à la directive système ip_nonlocal_bind. Comme son nom l’indique, elle permet d’autoriser les services à demander à écouter sur une IP que la machine ne porte pas pour l’instant, mais qu’elle pourrait porter plus tard.

Pour autoriser ip_nonlocal_bind, on utilise les sysctl, des directives passant par le système de fichiers virtuel /proc, qui permettent d’échanger (lire ou écrire) des paramètres et valeurs avec le noyau en cours de fonctionnement.

Pour cela, on crée un fichier dans /etc/sysctl.d/, par exemple ip_nonlocal_bind.conf et on y met les lignes suivantes :

net.ipv4.ip_nonlocal_bind = 1
net.ipv6.ip_nonlocal_bind = 1

vous remarquerez qu’il existe 2 directives : une pour les IPv4, une pour les IPv6 (car si le service est fourni au public, on voudra disposer du même service en IPv4 et en IPv6 !).

Pour appliquer ce changement, sous Debian, on relance le service procps, qui est chargé d’appliquer ces paramètres

service procps restart

Peut-on faire cela à la main ?

Si l’on souhaite juste tester temporairement ce paramètre, on peut faire ce changement à la main, et on peut connaître l’état de ip_nonlocal_bind facilement. Pour cela on utilise echo ou cat sur /proc comme suit :

Pour connaître l’état de ip_nonlocal_bind :

# cat /proc/sys/net/ipv4/ip_nonlocal_bind
1

pour le modifier (ici le désactiver) :

# echo "0" > /proc/sys/net/ipv4/ip_nonlocal_bind

Un exemple de service ainsi configuré :

Voici un exemple de résultat de ss -plnt sur un serveur ne disposant pas des IP flottantes 91.194.61.222 et 10.0.20.17 à l’heure de ce post :

Dans cet exemple, dans /etc/redis/redis.conf, on a mis la directive :

bind 10.0.20.17

et dans /etc/haproxy/haproxy.cfg :

frontend https-in
     bind 91.194.61.222:443 ssl crt /etc/ssl/haproxy