web-dev-qa-db-fra.com

Ensemble de règles Iptables pour qu'un conteneur Docker puisse accéder à un service sur une adresse IP hôte

J'ai des problèmes pour accéder à une interface privée hôte (IP) à partir d'un conteneur Docker. Je suis assez certain que c'est lié à mes règles Iptables (ou peut-être au routage). Lorsque j'ajoute le --net=Host drapeau à docker run, tout fonctionne comme prévu. De même, lorsque je précise que la politique INPUT suit une politique libérale -P INPUT ACCEPT, les choses fonctionnent aussi comme je m'y attendais. Cependant, ce sont des options indésirables et dangereuses que j'aimerais éviter.

Étant donné que ce n'est pas spécifique à mes services (DNS), j'ai exclu cela du problème, car la recherche de cela en combinaison avec docker génère un problème différent (populaire), ajoutant du bruit aux résultats de la recherche.

La liaison de conteneurs Docker n'est pas non plus une option viable, car certains conteneurs doivent être exécutés avec l'option --net = Host, empêchant la liaison et je souhaite créer une situation cohérente dans la mesure du possible.

J'ai les règles Iptables suivantes. Une combinaison de CoreOS, Digital Ocean et Docker, je suppose.

-P INPUT DROP
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N DOCKER
-A INPUT -i lo -j ACCEPT
-A INPUT -i eth1 -j ACCEPT
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT

Mes interfaces hôtes (pertinentes):

3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    inet 10.129.112.210/16 brd 10.129.255.255 scope global eth1
       valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Et je lance un conteneur docker:

$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.

À ce stade, je veux pouvoir utiliser un service local, lié le 10.129.112.210:53. Pour que ce qui suit donne une réponse:

$ ping google.com
^C
$ ping user.skydns.local
^C

Lorsque j'exécute la même commande depuis mon hôte:

$ ping photo.skydns.localPING photo.skydns.local (10.129.112.206) 56(84) bytes of data.
64 bytes from 10.129.112.206: icmp_seq=1 ttl=64 time=0.790 ms
^C

Mon resolv.conf

$ cat /etc/resolv.conf
nameserver 10.129.112.210
nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4

Le point ici n'est pas d'accéder aux hôtes publics, mais plutôt aux hôtes internes, en utilisant le service DNS local disponible sur l'hôte (via une autre instance de docker).

Pour l'illustrer encore plus (mes compétences en conception d'art ascii dépassent mes fu iptables, donc cela devrait suffire à ce stade):

 ______________________________________________
|  __________________________           Host   |
| |   Docker DNS container   |                 |
|  ``````````````````````|```                  |
|                        |                     |
|     ,----------,---( private n. interface )  |
|     |          |                             |
|     |          |   ( public  n. interface )---
|     |          |                             |
|     |          |   ( loopbck n. interface )  |
|     |          |                             |
|     |          |                             |
|     |        __|_______________________      |
|     |       | Docker service container |     |
|     |        ``````````````````````````      |
|     |                                        |
|     |                                        |
| [ Local Host service using DNS. ]            |
|                                              |
|______________________________________________|

  private (Host) network interface: eth1 (10.129.0.0/16)
  Docker network interface: docker0 (172.17.0.0/16)

J'ai cherché, lu et appliqué différents exemples de configurations Iptables, mais je connais trop peu de règles Iptables plus "avancées" pour comprendre ce qui se passe et ainsi obtenir le résultat souhaité.

Sortie de iptables -t nat -nL:

Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0

Chain DOCKER (2 references)
target     prot opt source               destination

Sortie de cat /proc/sys/net/ipv4/ip_forward:

1
18
Dynom

Le conteneur communique avec l'hôte à l'aide de docker0 interface. Pour autoriser le trafic provenant du conteneur, ajoutez:

-A INPUT -i docker0 -j ACCEPT
15
Laurentiu Roescu

J'ai rencontré une situation très similaire mais en ajoutant -A INPUT -i docker0 -j ACCEPT ouvrira tous les accès sur mon interface eth0 de docker Host aux conteneurs, ce qui n'est absolument pas ce que je voulais.

Et comme j'ai remarqué que mon conteneur avait juste un accès limité (disons seulement le port 22) à l'interface hôte au lieu d'être totalement fermé du réseau hôte, j'ai passé en revue mes règles iptables et trouvé une règle dans la chaîne IN_public_allow qui devrait en être responsable. La règle est -A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT. J'ai donc ajouté des règles similaires pour permettre à mon conteneur d'accéder aux autres ports hôtes souhaités, ce qui, je pense, pourrait être un moyen un peu plus précis d'ouvrir l'accès au réseau hôte aux conteneurs.

0
L3w1s