Mam problemy z dostępem do prywatnego interfejsu hosta (ip) z kontenera dokowanego. Jestem całkiem pewien, że jest to związane z moimi regułami Iptables (a może routingiem). Po dodaniu --net=host
flagi docker run
wszystko działa zgodnie z oczekiwaniami. Podobnie, gdy sprecyzuję, że polityka INPUT podąża za liberałem -P INPUT ACCEPT
, rzeczy również działają tak, jakbym się spodziewał. Są to jednak niepożądane i niebezpieczne opcje, których chciałbym uniknąć.
Ponieważ nie jest to specyficzne dla moich usług (DNS), wykluczyłem to z problemu, ponieważ wyszukiwanie tego w połączeniu z dokerem daje w innym (popularnym) obszarze problemu, powodując hałas w wynikach wyszukiwania.
Również łączenie kontenerów Docker nie jest realną opcją, ponieważ niektóre kontenery muszą być uruchamiane z opcją --net = host, co zapobiega łączeniu, a ja chcę stworzyć spójną sytuację tam, gdzie to możliwe.
Mam następujące zasady Iptables. Zakładam, że połączenie CoreOS, Digital Ocean i Docker.
-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
Moje (odpowiednie) interfejsy hosta:
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
I prowadzę kontener dokerów:
$ docker run --rm -it --dns=10.129.112.210 debian:jessie # Specifying the DNS is so that the public DNS servers aren't used.
W tym momencie chcę móc korzystać z usługi lokalnej, związanej z 10.129.112.210:53. Tak więc poniższe powinny dać odpowiedź:
$ ping google.com
^C
$ ping user.skydns.local
^C
Po uruchomieniu tego samego polecenia z mojego hosta:
$ 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
Mój 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
Nie chodzi o to, aby uzyskać dostęp do hostów publicznych, ale wewnętrznych, za pomocą lokalnej usługi DNS dostępnej na hoście (za pośrednictwem innej instancji dokera).
Aby zilustrować to jeszcze bardziej (moje umiejętności projektowania ascii przewyższają moje iptables fu, więc w tym momencie powinno to powiedzieć dość):
______________________________________________
| __________________________ 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)
Przeszukałem, przeczytałem i zastosowałem różne przykładowe konfiguracje Iptables, ale zbyt mało znam bardziej „zaawansowanych” reguł Iptables, aby zrozumieć, co się dzieje, a tym samym uzyskać pożądany rezultat.
Wyjście 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
Wyjście cat /proc/sys/net/ipv4/ip_forward
:
1
iptables -t nat -nL
? Czy zrobiłeś jakąkolwiek analizę pakietu, powiedz, że wykonaj ping z kontenera źródłowego i użyj tcpdump, aby przechwycić pakiety na hoście.$ cat /proc/sys/net/ipv4/ip_forward -> 1
i-A INPUT -i eth1 -j ACCEPT
akceptuje wszystkie połączenia w interfejsie prywatnym . Jakich zasad brakuje?-A INPUT -i docker0 -j ACCEPT
Odpowiedzi:
Kontener komunikuje się z hostem za pomocą
docker0
interfejsu. Aby zezwolić na ruch z kontenera, dodaj:źródło
iptables -A INPUT -j LOG
. ZnaczekIN=docker0
byłby bardzo przydatny w ustaleniu, jakie ulepszenie reguły jest potrzebne. Nie odbierać pracy Laurentiu, która była doskonała - +1 ode mnie!Zetknąłem się z bardzo podobną sytuacją, ale dodanie
-A INPUT -i docker0 -j ACCEPT
spowoduje otwarcie wszystkich dostępów przez mój interfejs eth0 hosta dokującego do kontenerów, co absolutnie nie jest moim zamierzeniem.A ponieważ zauważyłem, że mój kontener ma po prostu ograniczony dostęp (powiedzmy tylko port 22) do interfejsu hosta zamiast całkowicie zamknąć sieć hosta, przejrzałem moje reguły iptables i znalazłem regułę w łańcuchu IN_public_allow, która powinna być za to odpowiedzialna. Zasada jest taka
-A IN_public_allow -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
. Dodałem więc podobne reguły, aby mój kontener mógł uzyskać dostęp do innych pożądanych portów hosta, co moim zdaniem może być nieco bardziej precyzyjnym sposobem otwarcia dostępu do kontenerów przez sieć hosta.źródło
-i docker0
powinien upewnić się, że nie wpłynie to na ruch, który nie dociera przez sieć docker0. Twoja gramatyka jest jednak niejasna. Być może mówiłeś, że dostęp wychodzący z hostów dokerów przez eth0 jest włączony, co może być prawdą. Zgadzam się, że bardziej ukierunkowane zasady można otwierać tylko tyle, ile potrzebujesz.