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
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
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.