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 un libéral -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.
Puisqu'il n'est pas spécifique à mes services (DNS), j'ai exclu cela du problème, car la recherche de cela en combinaison avec docker donne un autre problème (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, ce qui devrait en dire assez à 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
$ cat /proc/sys/net/ipv4/ip_forward -> 1
et -A INPUT -i eth1 -j ACCEPT
accepte toutes les connexions sur l' interface privée . Quelles règles vous manquent?
-A INPUT -i docker0 -j ACCEPT
iptables -t nat -nL
? Avez-vous fait une analyse de paquet, disons faire un ping depuis le conteneur source et utiliser tcpdump pour capturer les paquets sur l'hôte.