Recherche…


Introduction

Cette rubrique explique comment limiter l'accès à vos conteneurs de docker du monde extérieur à l'aide d'iptables.

Pour les personnes impatientes, vous pouvez consulter les exemples. Pour les autres, veuillez lire la section des remarques pour comprendre comment construire de nouvelles règles.

Syntaxe

  • iptables -I DOCKER [RULE ...] [ACCEPT | DROP] // Pour ajouter une règle en haut de la table DOCKER
  • iptables -D DOCKER [RULE ...] [ACCEPT | DROP] // Pour supprimer une règle de la table DOCKER
  • ipset restore </etc/ipfriends.conf // Pour reconfigurer vos ipfriends ipset

Paramètres

Paramètres Détails
ext_if Votre interface externe sur l'hôte Docker.
XXX.XXX.XXX.XXX Une adresse IP particulière sur laquelle les conteneurs Docker doivent être accessibles.
AAAA.AAAA.AAAA.AAAA Une autre adresse IP sur laquelle les conteneurs Docker doivent être accessibles doit être fournie.
ipfriends Le nom de l'ipset définissant les adresses IP autorisées à accéder à vos conteneurs Docker.

Remarques

Le problème

La configuration des règles iptables pour les conteneurs Docker est un peu délicate. Au début, vous penseriez que les règles de pare-feu "classiques" devraient faire l'affaire.

Par exemple, supposons que vous avez configuré un conteneur nginx-proxy + plusieurs conteneurs de services pour exposer via HTTPS certains services Web personnels. Ensuite, une règle comme celle-ci devrait donner accès à vos services Web uniquement pour IP XXX.XXX.XXX.XXX.

$ iptables -A INPUT -i eth0 -p tcp -s XXX.XXX.XXX.XXX -j ACCEPT
$ iptables -P INPUT DROP

Cela ne marchera pas, vos conteneurs sont toujours accessibles pour tout le monde.

En effet, les conteneurs Docker ne sont pas des services hôtes. Ils s'appuient sur un réseau virtuel dans votre hôte et l'hôte agit comme une passerelle pour ce réseau. Et en ce qui concerne les passerelles, le trafic routé n'est pas géré par la table INPUT, mais par la table FORWARD, ce qui rend la règle affichée avant qu'elle soit inefficace.

Mais ce n'est pas tout. En fait, le démon Docker crée beaucoup de règles iptables quand il commence à faire sa magie concernant la connectivité réseau des conteneurs. En particulier, une table DOCKER est créée pour gérer les règles concernant les conteneurs en transférant le trafic de la table FORWARD vers cette nouvelle table.

$ iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain DOCKER (2 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:https
ACCEPT     tcp  --  anywhere             172.18.0.4           tcp dpt:http

Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere

La solution

Si vous consultez la documentation officielle ( https://docs.docker.com/v1.5/articles/networking/) , une première solution est proposée pour limiter l'accès du conteneur Docker à une adresse IP particulière.

$ iptables -I DOCKER -i ext_if ! -s 8.8.8.8 -j DROP

En effet, ajouter une règle en haut de la table DOCKER est une bonne idée. Cela n'interfère pas avec les règles configurées automatiquement par Docker, et c'est simple. Mais deux grands manques:

  • Tout d'abord, que faire si vous avez besoin d'accéder à deux adresses IP au lieu d'une seule? Ici, une seule IP src peut être acceptée, les autres seront supprimées sans aucun moyen de prévention.
  • Deuxièmement, que se passe-t-il si votre docker doit avoir accès à Internet? Dans la pratique, aucune requête ne réussira car seul le serveur 8.8.8.8 pourra y répondre.
  • Enfin, que faire si vous souhaitez ajouter d'autres logiques? Par exemple, donnez accès à n'importe quel utilisateur à votre serveur Web utilisant le protocole HTTP, mais limitez tout le reste à une adresse IP particulière.

Pour la première observation, nous pouvons utiliser ipset . Au lieu d'autoriser une IP dans la règle ci-dessus, nous autorisons toutes les IP de l'ipset prédéfini. En prime, l'ipset peut être mis à jour sans qu'il soit nécessaire de redéfinir la règle iptable.

$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP

Pour la seconde observation, il s'agit d'un problème canonique pour les pare-feu: si vous êtes autorisé à contacter un serveur via un pare-feu, le pare-feu doit autoriser le serveur à répondre à votre demande. Cela peut être fait en autorisant des paquets liés à une connexion établie. Pour la logique du docker, cela donne:

$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

La dernière observation porte sur un point: les règles iptables sont essentielles. En effet, une logique supplémentaire pour ACCEPTER certaines connexions (y compris celle concernant les connexions ESTABLISHED) doit être placée en haut de la table DOCKER, avant la règle DROP qui refuse toutes les connexions restantes ne correspondant pas à l'ipset.

Comme nous utilisons l'option -I d'iptable, qui insère des règles en haut de la table, les règles iptables précédentes doivent être insérées par ordre inverse:

// Drop rule for non matching IPs
$ iptables -I DOCKER -i ext_if -m set ! --match-set my-ipset src -j DROP
// Then Accept rules for established connections
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT 
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 3rd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 2nd custom accept rule
$ iptables -I DOCKER -i ext_if ... ACCEPT // Then 1st custom accept rule

En gardant cela à l'esprit, vous pouvez maintenant vérifier les exemples qui illustrent cette configuration.

Limiter l'accès aux conteneurs Docker à un ensemble d'IP

D'abord, installez ipset si nécessaire. Veuillez vous référer à votre distribution pour savoir comment le faire. À titre d'exemple, voici la commande pour les distributions de type Debian.

$ apt-get update
$ apt-get install ipset

Créez ensuite un fichier de configuration pour définir un ipset contenant les adresses IP pour lesquelles vous souhaitez ouvrir l'accès à vos conteneurs Docker.

$ vi /etc/ipfriends.conf
# Recreate the ipset if needed, and flush all entries
create -exist ipfriends hash:ip family inet hashsize 1024 maxelem 65536
flush
# Give access to specific ips
add ipfriends XXX.XXX.XXX.XXX
add ipfriends YYY.YYY.YYY.YYY

Chargez cet ipset.

$ ipset restore < /etc/ipfriends.conf

Assurez-vous que votre démon Docker est en cours d'exécution: aucune erreur ne doit apparaître après la saisie de la commande suivante.

$ docker ps

Vous êtes prêt à insérer vos règles iptables. Vous devez respecter la commande.

// All requests of src ips not matching the ones from ipset ipfriends will be dropped.
$ iptables -I DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
// Except for requests coming from a connection already established.
$ iptables -I DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Si vous souhaitez créer de nouvelles règles, vous devrez supprimer toutes les règles personnalisées que vous avez ajoutées avant d'insérer les nouvelles.

$ iptables -D DOCKER -i ext_if -m set ! --match-set ipfriends src -j DROP
$ iptables -D DOCKER -i ext_if -m state --state ESTABLISHED,RELATED -j ACCEPT

Configurez l'accès aux restrictions au démarrage du démon Docker

Travaux en cours

Quelques règles iptables personnalisées

Travaux en cours



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow